Patchwork [SH] PR 51244 - Improve conditional branches

login
register
mail settings
Submitter Oleg Endo
Date March 8, 2012, 8:31 a.m.
Message ID <1331195493.1876.14.camel@yam-132-YW-E178-FTW>
Download mbox | patch
Permalink /patch/145468/
State New
Headers show

Comments

Oleg Endo - March 8, 2012, 8:31 a.m.
On Tue, 2012-03-06 at 08:13 +0900, Kaz Kojima wrote:
> > Oleg Endo <oleg.endo@t-online.de> wrote:
> >> The attached patch is the same as the last one proposed in the PR.
> >> Tested against rev 184877 with
> >> 
> >> make -k check RUNTESTFLAGS="--target_board=sh-sim
> >> \{-m2/-ml,-m2/-mb,-m2a-single/-mb,
> >> -m4-single/-ml,-m4-single/-mb,
> >> -m4a-single/-ml,-m4a-single/-mb}"
> >> 
> >> and no new failures.
> >> OK?
> > 
> > OK.
> 
> I've tested your latest patch on sh4-unknown-linux-gnu with trunk
> revision 184872.  It looks that some new failures are poping up:
> 
> New tests that FAIL:
> 
> 22_locale/ctype/is/char/3.cc execution test
> 27_io/basic_filebuf/underflow/wchar_t/9178.cc execution test
> gfortran.dg/widechar_intrinsics_6.f90  -Os  execution test
> 
> Pehaps failures might be ones you've suggested in #10 in
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51244
> 

This is the patch for the patch, as attached in the PR.
Tested against rev 184966 as before and no changes in the test results
for me (i.e. no new failures).

ChangeLog:

	PR target/51244
	* config/sh/sh.md (movnegt): Expand into respective insns 
	immediately.  Use movrt_negc instead of negc pattern for
	non-SH2A.
	(*movnegt): Remove.
	(*movrt_negc, *negnegt, *movtt, *movt_qi): New insns and splits.

testsuite/ChangeLog:

	PR target/51244
	* gcc.target/sh/pr51244-1.c: Fix thinkos.

Patch

Index: gcc/testsuite/gcc.target/sh/pr51244-1.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr51244-1.c	(revision 184966)
+++ gcc/testsuite/gcc.target/sh/pr51244-1.c	(working copy)
@@ -13,20 +13,20 @@ 
 }
 
 int
-testfunc_01 (int a, char* p, int b, int c)
+testfunc_01 (int a, int b, int c, int d)
 {
-  return (a == b && a == c) ? b : c;
+  return (a == b || a == d) ? b : c;
 }
 
 int
-testfunc_02 (int a, char* p, int b, int c)
+testfunc_02 (int a, int b, int c, int d)
 {
-  return (a == b && a == c) ? b : c;
+  return (a == b && a == d) ? b : c;
 }
 
 int
-testfunc_03 (int a, char* p, int b, int c)
+testfunc_03 (int a, int b, int c, int d)
 {
-  return (a != b && a != c) ? b : c;
+  return (a != b && a != d) ? b : c;
 }
 
Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md	(revision 184966)
+++ gcc/config/sh/sh.md	(working copy)
@@ -9679,39 +9679,90 @@ 
 ;; If the constant -1 can be CSE-ed or lifted out of a loop it effectively
 ;; becomes a one instruction operation.  Moreover, care must be taken that
 ;; the insn can still be combined with inverted compare and branch code
-;; around it.
-;; The expander will reserve the constant -1, the insn makes the whole thing
-;; combinable, the splitter finally emits the insn if it was not combined 
-;; away.
-;; Notice that when using the negc variant the T bit also gets inverted.
+;; around it.  On the other hand, if a function returns the complement of
+;; a previous comparison result in the T bit, the xor #1,r0 approach might
+;; lead to better code.
 
 (define_expand "movnegt"
-  [(set (match_dup 1) (const_int -1))
-   (parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
-		   (xor:SI (reg:SI T_REG) (const_int 1)))
-   (use (match_dup 1))])]
+  [(set (match_operand:SI 0 "arith_reg_dest" "")
+       (xor:SI (reg:SI T_REG) (const_int 1)))]
   ""
 {
-  operands[1] = gen_reg_rtx (SImode);
+  if (TARGET_SH2A)
+    emit_insn (gen_movrt (operands[0]));
+  else
+    {
+      rtx val = force_reg (SImode, gen_int_mode (-1, SImode));
+      emit_insn (gen_movrt_negc (operands[0], val));
+    }
+  DONE;
 })
 
-(define_insn_and_split "*movnegt"
+(define_insn "movrt_negc"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
 	(xor:SI (reg:SI T_REG) (const_int 1)))
+   (set (reg:SI T_REG) (xor:SI (reg:SI T_REG) (const_int 1)))
    (use (match_operand:SI 1 "arith_reg_operand" "r"))]
   "TARGET_SH1"
+  "negc	%1,%0"
+  [(set_attr "type" "arith")])
+
+;; The *negnegt patterns help the combine pass to figure out how to fold 
+;; an explicit double T bit negation.
+(define_insn_and_split "*negnegt"
+  [(set (reg:SI T_REG)
+	(eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 3)
+        (const_int 0)))]
+  "! TARGET_LITTLE_ENDIAN"
   "#"
-  "&& 1"
-  [(const_int 0)]
-{
-  if (TARGET_SH2A)
-    emit_insn (gen_movrt (operands[0]));
-  else
-    emit_insn (gen_negc (operands[0], operands[1]));
-  DONE;
-}
+  ""
+  [(const_int 0)])
+
+(define_insn_and_split "*negnegt"
+  [(set (reg:SI T_REG)
+	(eq:SI (subreg:QI (xor:SI (reg:SI T_REG) (const_int 1)) 0)
+        (const_int 0)))]
+  "TARGET_LITTLE_ENDIAN"
+  "#"
+  ""
+  [(const_int 0)])
+
+;; The *movtt patterns improve code at -O1.
+(define_insn_and_split "*movtt"
+  [(set (reg:SI T_REG)
+	(eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 3))
+        (const_int 1)))]
+  "! TARGET_LITTLE_ENDIAN"
+  "#"
+  ""
+  [(const_int 0)])
+
+(define_insn_and_split "*movtt"
+  [(set (reg:SI T_REG)
+	(eq:SI (zero_extend:SI (subreg:QI (reg:SI T_REG) 0))
+        (const_int 1)))]
+  "TARGET_LITTLE_ENDIAN"
+  "#"
+  ""
+  [(const_int 0)])
+
+;; The *movt_qi patterns help the combine pass convert a movrt_negc pattern
+;; into a movt Rn, xor #1 Rn pattern.  This can happen when e.g. a function
+;; returns the inverted T bit value.
+(define_insn "*movt_qi"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+	(zero_extend:SI (subreg:QI (reg:SI T_REG) 3)))]
+  "! TARGET_LITTLE_ENDIAN"
+  "movt	%0"
   [(set_attr "type" "arith")])
 
+(define_insn "*movt_qi"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+	(zero_extend:SI (subreg:QI (reg:SI T_REG) 0)))]
+  "TARGET_LITTLE_ENDIAN"
+  "movt	%0"
+  [(set_attr "type" "arith")])
+
 (define_expand "cstoresf4"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(match_operator:SI 1 "sh_float_comparison_operator"