This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] rs6000: Fix the shift patterns, and add test


Firstly, it adds back the split conditions that I accidentally removed.
Without it the dot insns are never generated, or rather, always split
back to a separate compare instruction.

Secondly, the shift amount should be SI always, not GPR, or GCC will
insert a zero-extend at expand time that it cannot get rid of later.

The test tests whether dot-form instructions are generated for both
"dot" and "dot2" cases, that is, with just a CC output or also a GPR
output; for all four basic shifts, with a register amount or an
immediate amount.  It also tests for superfluous zero-extends.  This
also tests if combine "simplifies" the rotates to right-rotates, which
it shouldn't do anymore.

Bootstrapped and tested as usual.  Okay to commit?


Segher


2014-07-02  Segher Boessenkool  <segher@kernel.crashing.org>

gcc/
	* config/rs6000/rs6000.md (rotl<mode>3, ashl<mode>3, lshr<mode>3,
	ashr<mode>3): Correct mode of operands[2].
	(rotl<mode>3_dot, rotl<mode>3_dot2, ashl<mode>3_dot, ashl<mode>3_dot2,
	lshr<mode>3_dot, lshr<mode>3_dot2, ashr<mode>3_dot, ashr<mode>3_dot2):
	Correct mode of operands[2].  Fix split condition.

gcc/testsuite/
	* gcc.target/powerpc/shift-dot.c: New test.

---
 gcc/config/rs6000/rs6000.md                  | 42 ++++++++++++------------
 gcc/testsuite/gcc.target/powerpc/shift-dot.c | 49 ++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+), 21 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/shift-dot.c

diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 8e9039e..83aaa58 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -3874,7 +3874,7 @@ (define_insn "*extzvdi_internal2"
 (define_insn "rotl<mode>3"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
 	(rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
-		    (match_operand:GPR 2 "reg_or_cint_operand" "rn")))]
+		    (match_operand:SI 2 "reg_or_cint_operand" "rn")))]
   ""
   "rotl<wd>%I2 %0,%1,%<hH>2"
   [(set_attr "type" "shift")
@@ -3893,14 +3893,14 @@ (define_insn "*rotlsi3_64"
 (define_insn_and_split "*rotl<mode>3_dot"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
 	(compare:CC (rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
-				(match_operand:GPR 2 "reg_or_cint_operand" "rn,rn"))
+				(match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
 		    (const_int 0)))
    (clobber (match_scratch:GPR 0 "=r,r"))]
   "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
    rotl<wd>%I2. %0,%1,%<hH>2
    #"
-  "&& reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
 	(rotate:GPR (match_dup 1)
 		    (match_dup 2)))
@@ -3916,7 +3916,7 @@ (define_insn_and_split "*rotl<mode>3_dot"
 (define_insn_and_split "*rotl<mode>3_dot2"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
 	(compare:CC (rotate:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
-				(match_operand:GPR 2 "reg_or_cint_operand" "rn,rn"))
+				(match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
 		    (const_int 0)))
    (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
 	(rotate:GPR (match_dup 1)
@@ -3925,7 +3925,7 @@ (define_insn_and_split "*rotl<mode>3_dot2"
   "@
    rotl<wd>%I2. %0,%1,%<hH>2
    #"
-  "&& reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
 	(rotate:GPR (match_dup 1)
 		    (match_dup 2)))
@@ -4353,7 +4353,7 @@ (define_split
 (define_insn "ashl<mode>3"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
 	(ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
-		    (match_operand:GPR 2 "reg_or_cint_operand" "rn")))]
+		    (match_operand:SI 2 "reg_or_cint_operand" "rn")))]
   ""
   "sl<wd>%I2 %0,%1,%<hH>2"
   [(set_attr "type" "shift")
@@ -4372,14 +4372,14 @@ (define_insn "*ashlsi3_64"
 (define_insn_and_split "*ashl<mode>3_dot"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
 	(compare:CC (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
-				(match_operand:GPR 2 "reg_or_cint_operand" "rn,rn"))
+				(match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
 		    (const_int 0)))
    (clobber (match_scratch:GPR 0 "=r,r"))]
   "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
    sl<wd>%I2. %0,%1,%<hH>2
    #"
-  "&& reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
 	(ashift:GPR (match_dup 1)
 		    (match_dup 2)))
@@ -4395,7 +4395,7 @@ (define_insn_and_split "*ashl<mode>3_dot"
 (define_insn_and_split "*ashl<mode>3_dot2"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
 	(compare:CC (ashift:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
-				(match_operand:GPR 2 "reg_or_cint_operand" "rn,rn"))
+				(match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
 		    (const_int 0)))
    (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
 	(ashift:GPR (match_dup 1)
@@ -4404,7 +4404,7 @@ (define_insn_and_split "*ashl<mode>3_dot2"
   "@
    sl<wd>%I2. %0,%1,%<hH>2
    #"
-  "&& reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
 	(ashift:GPR (match_dup 1)
 		    (match_dup 2)))
@@ -4498,7 +4498,7 @@ (define_split
 (define_insn "lshr<mode>3"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
 	(lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
-		      (match_operand:GPR 2 "reg_or_cint_operand" "rn")))]
+		      (match_operand:SI 2 "reg_or_cint_operand" "rn")))]
   ""
   "sr<wd>%I2 %0,%1,%<hH>2"
   [(set_attr "type" "shift")
@@ -4517,14 +4517,14 @@ (define_insn "*lshrsi3_64"
 (define_insn_and_split "*lshr<mode>3_dot"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
 	(compare:CC (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
-				  (match_operand:GPR 2 "reg_or_cint_operand" "rn,rn"))
+				  (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
 		    (const_int 0)))
    (clobber (match_scratch:GPR 0 "=r,r"))]
   "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
    sr<wd>%I2. %0,%1,%<hH>2
    #"
-  "&& reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
 	(lshiftrt:GPR (match_dup 1)
 		      (match_dup 2)))
@@ -4540,7 +4540,7 @@ (define_insn_and_split "*lshr<mode>3_dot"
 (define_insn_and_split "*lshr<mode>3_dot2"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
 	(compare:CC (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
-				  (match_operand:GPR 2 "reg_or_cint_operand" "rn,rn"))
+				  (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
 		    (const_int 0)))
    (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
 	(lshiftrt:GPR (match_dup 1)
@@ -4549,7 +4549,7 @@ (define_insn_and_split "*lshr<mode>3_dot2"
   "@
    sr<wd>%I2. %0,%1,%<hH>2
    #"
-  "&& reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
 	(lshiftrt:GPR (match_dup 1)
 		      (match_dup 2)))
@@ -4971,7 +4971,7 @@ (define_split
 (define_expand "ashr<mode>3"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "")
 	(ashiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
-		      (match_operand:GPR 2 "reg_or_cint_operand" "")))]
+		      (match_operand:SI 2 "reg_or_cint_operand" "")))]
   ""
 {
   /* The generic code does not generate optimal code for the low word
@@ -4993,7 +4993,7 @@ (define_expand "ashr<mode>3"
 (define_insn "*ashr<mode>3"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
 	(ashiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
-		      (match_operand:GPR 2 "reg_or_cint_operand" "rn")))]
+		      (match_operand:SI 2 "reg_or_cint_operand" "rn")))]
   ""
   "sra<wd>%I2 %0,%1,%<hH>2"
   [(set_attr "type" "shift")
@@ -5012,14 +5012,14 @@ (define_insn "*ashrsi3_64"
 (define_insn_and_split "*ashr<mode>3_dot"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
 	(compare:CC (ashiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
-				  (match_operand:GPR 2 "reg_or_cint_operand" "rn,rn"))
+				  (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
 		    (const_int 0)))
    (clobber (match_scratch:GPR 0 "=r,r"))]
   "<MODE>mode == Pmode && rs6000_gen_cell_microcode"
   "@
    sra<wd>%I2. %0,%1,%<hH>2
    #"
-  "&& reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
 	(ashiftrt:GPR (match_dup 1)
 		      (match_dup 2)))
@@ -5035,7 +5035,7 @@ (define_insn_and_split "*ashr<mode>3_dot"
 (define_insn_and_split "*ashr<mode>3_dot2"
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
 	(compare:CC (ashiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "r,r")
-				  (match_operand:GPR 2 "reg_or_cint_operand" "rn,rn"))
+				  (match_operand:SI 2 "reg_or_cint_operand" "rn,rn"))
 		    (const_int 0)))
    (set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
 	(ashiftrt:GPR (match_dup 1)
@@ -5044,7 +5044,7 @@ (define_insn_and_split "*ashr<mode>3_dot2"
   "@
    sra<wd>%I2. %0,%1,%<hH>2
    #"
-  "&& reload_completed"
+  "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)"
   [(set (match_dup 0)
 	(ashiftrt:GPR (match_dup 1)
 		      (match_dup 2)))
diff --git a/gcc/testsuite/gcc.target/powerpc/shift-dot.c b/gcc/testsuite/gcc.target/powerpc/shift-dot.c
new file mode 100644
index 0000000..002948c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/shift-dot.c
@@ -0,0 +1,49 @@
+/* Check that record-form instructions are used.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -mgen-cell-microcode" } */
+
+/* { dg-final { scan-assembler-times {\mrotl[wd]\.} 2 } } */
+/* { dg-final { scan-assembler-times {\msl[wd]\.} 2 } } */
+/* { dg-final { scan-assembler-times {\msr[wd]\.} 2 } } */
+/* { dg-final { scan-assembler-times {\msra[wd]\.} 2 } } */
+
+/* { dg-final { scan-assembler-times {\mrotl[wd]i\.} 2 } } */
+/* { dg-final { scan-assembler-times {\msl[wd]i\.} 2 } } */
+/* { dg-final { scan-assembler-times {\msr[wd]i\.} 2 } } */
+/* Combine converts the arith shift right compares to a (more expensive)
+   direct compare.  Luckily not the other shifts.  XFAIL for now.  */
+/* { dg-final { scan-assembler-times {\msra[wd]i\.} 2 { xfail *-*-* } } } */
+
+/* There should not be any extends of the shift amount (or anything else).  */
+/* { dg-final { scan-assembler-not {\mextsw\M} } } */
+/* { dg-final { scan-assembler-not {\mrldicl\M} } } */
+/* { dg-final { scan-assembler-not {\mclrldi\M} } } */
+/* { dg-final { scan-assembler-not {\mrlwinm\M} } } */
+
+
+typedef unsigned long u;
+typedef long s;
+#define M(n) (8 * sizeof(long) - (n))
+#define T1 if ((s)x > 0) g();
+#define T2 if ((s)x > 0) g(); return x;
+
+void g(void);
+
+void rot1(u x, u n) { x = (x << M(n)) | (x >> n); T1 }
+   u rot2(u x, u n) { x = (x << M(n)) | (x >> n); T2 }
+void shl1(u x, u n) { x <<= n; T1 }
+   u shl2(u x, u n) { x <<= n; T2 }
+void shr1(u x, u n) { x >>= n; T1 }
+   u shr2(u x, u n) { x >>= n; T2 }
+void asr1(s x, u n) { x >>= n; T1 }
+   s asr2(s x, u n) { x >>= n; T2 }
+
+void rot1i(u x) { x = (x << M(23)) | (x >> 23); T1 }
+   u rot2i(u x) { x = (x << M(23)) | (x >> 23); T2 }
+void shl1i(u x) { x <<= 23; T1 }
+   u shl2i(u x) { x <<= 23; T2 }
+void shr1i(u x) { x >>= 23; T1 }
+   u shr2i(u x) { x >>= 23; T2 }
+void asr1i(s x) { x >>= 23; T1 }
+   s asr2i(s x) { x >>= 23; T2 }
-- 
1.8.1.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]