[PATCH] Fix ppc LTU/GTU sCC splitters (PR target/20196)

Jakub Jelinek jakub@redhat.com
Thu Feb 24 22:46:00 GMT 2005


Hi!

Before the http://gcc.gnu.org/ml/gcc-patches/2004-11/msg00672.html
change these patterns were plain instructions with earlyclobbers, but
that patch changed them to splitters so that they get better scheduled
and the earlyclobbers got lost.
On the testcase below, this leads to:
(insn 116 74 117 8 (set (reg:CCUNS 153)
        (compare:CCUNS (reg/v:SI 123 [ g ])
            (reg:SI 125 [ f.3 ]))) 378 {*cmpsi_internal2} (nil)
    (nil))
(insn 117 116 118 8 (set (reg:SI 152)
        (ltu:SI (reg:CCUNS 153)
            (const_int 0 [0x0]))) 385 {*rs6000.md:11461} (insn_list:REG_DEP_TRUE 116 (nil))
    (expr_list:REG_DEAD (reg:CCUNS 153)
        (nil)))
(insn 118 117 82 8 (set (reg/v:SI 121 [ i ])
        (plus:SI (reg/v:SI 121 [ i ])
            (reg:SI 152))) 48 {*addsi3_internal1} (insn_list:REG_DEP_TRUE 117 (nil))
    (expr_list:REG_DEAD (reg:SI 152)
        (nil)))
being combined into:
(insn 118 117 82 8 (set (reg/v:SI 121 [ i ])
        (plus:SI (ltu:SI (reg/v:SI 123 [ g ])
                (reg:SI 125 [ f.3 ]))
            (reg/v:SI 121 [ i ]))) 420 {*rs6000.md:12672} (nil)
    (nil))
and at .sched time split into:
(insn 131 117 132 8 (set (reg/v:SI 121 [ i ])
        (neg:SI (ltu:SI (reg/v:SI 123 [ g ])
                (reg:SI 125 [ f.3 ])))) 424 {*rs6000.md:12765} (nil)
    (nil))
(insn 132 131 82 8 (set (reg/v:SI 121 [ i ])
        (minus:SI (reg/v:SI 121 [ i ])
            (reg/v:SI 121 [ i ]))) 55 {*rs6000.md:1174} (insn_list:REG_DEP_TRUE 131 (nil))
    (nil))
which is wrong, as the first instruction clobbers a register that
is then used in the second one.
Adding an earlyclobber is not enough, since if the instruction is split already
before reload, then the earlyclobber will not be looked at and the problem will
persist.  But adding && reload_completed could lead to less efficient scheduling
for cases where operands 0 and 3 don't overlap (be it operand 3 a constant or
a different register from the output one).

With the patch below we split even before reload if there is no overlap, and
the earlyclobber ensures that there will be no overlap after reload.

Ok to commit if bootstrap/testing succeeds?

2005-02-24  Jakub Jelinek  <jakub@redhat.com>

	PR target/20196
	* config/rs6000/rs6000.md (LTU, GTU sCC splitters): Add earlyclobber,
	allow splitting only if operands 0 and 3 don't overlap.

	* gcc.c-torture/execute/20050224-1.c: New test.

--- gcc/config/rs6000/rs6000.md.jj	2005-02-24 17:46:32.763086019 +0100
+++ gcc/config/rs6000/rs6000.md	2005-02-24 18:38:14.633421677 +0100
@@ -12670,25 +12670,25 @@
   "")
 
 (define_insn_and_split ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,r")
 	(plus:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
 			 (match_operand:SI 2 "reg_or_neg_short_operand" "r,P"))
 		 (match_operand:SI 3 "reg_or_short_operand" "rI,rI")))]
   "TARGET_32BIT"
   "#"
-  "TARGET_32BIT"
+  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
   [(set (match_dup 0) (neg:SI (ltu:SI (match_dup 1) (match_dup 2))))
    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 0)))]
   "")
 
 (define_insn_and_split ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
 	(plus:DI (ltu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
 			 (match_operand:DI 2 "reg_or_neg_short_operand" "r,P"))
 		 (match_operand:DI 3 "reg_or_short_operand" "rI,rI")))]
   "TARGET_64BIT"
   "#"
-  "TARGET_64BIT"
+  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
   [(set (match_dup 0) (neg:DI (ltu:DI (match_dup 1) (match_dup 2))))
    (set (match_dup 0) (minus:DI (match_dup 3) (match_dup 0)))]
   "")
@@ -13628,25 +13628,25 @@
   "")
 
 (define_insn_and_split ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
         (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                          (match_operand:SI 2 "reg_or_short_operand" "rI"))
                  (match_operand:SI 3 "reg_or_short_operand" "rI")))]
   "TARGET_32BIT"
   "#"
-  "TARGET_32BIT"
+  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
   [(set (match_dup 0) (neg:SI (gtu:SI (match_dup 1) (match_dup 2))))
    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 0)))]
   "")
 
 (define_insn_and_split ""
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
         (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r")
                          (match_operand:DI 2 "reg_or_short_operand" "rI"))
                  (match_operand:DI 3 "reg_or_short_operand" "rI")))]
   "TARGET_64BIT"
   "#"
-  "TARGET_64BIT"
+  "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
   [(set (match_dup 0) (neg:DI (gtu:DI (match_dup 1) (match_dup 2))))
    (set (match_dup 0) (minus:DI (match_dup 3) (match_dup 0)))]
   "")
--- gcc/testsuite/gcc.c-torture/execute/20050224-1.c.jj	2005-02-24 18:16:00.054384897 +0100
+++ gcc/testsuite/gcc.c-torture/execute/20050224-1.c	2005-02-24 18:17:03.962039493 +0100
@@ -0,0 +1,33 @@
+/* Origin: Mikael Pettersson <mikpe@csd.uu.se> and the Linux kernel.  */
+
+extern void abort (void);
+unsigned long a = 0xc0000000, b = 0xd0000000;
+unsigned long c = 0xc01bb958, d = 0xc0264000;
+unsigned long e = 0xc0288000, f = 0xc02d4378;
+
+void
+foo (int x, int y, int z)
+{
+  if (x != 245 || y != 36 || z != 444)
+    abort ();
+}
+
+int
+main (void)
+{
+  unsigned long g;
+  int h = 0, i = 0, j = 0;
+
+  if (sizeof (unsigned long) < 4)
+    return 0;
+
+  for (g = a; g < b; g += 0x1000)
+    if (g < c)
+      h++;
+    else if (g >= d && g < e)
+      j++;
+    else if (g < f)
+      i++;
+  foo (i, j, h);
+  return 0;
+}

	Jakub



More information about the Gcc-patches mailing list