trouble emilinating redundant compares

Paul S pauls@dataworx.com.au
Mon Jan 16 01:02:00 GMT 2012


In the port I'm working on I have used the newer CC tracking technique 
(i.e. not cc0). I have followed the directions at the top of 
compare-elim.c and have the following pattern for addhi3

(define_insn "addhi3"
   [
     (set (match_operand:WORD 0 "register_operand" "=r,r,r")
                 (plus:WORD (match_operand:WORD 1 "register_operand" 
"0,0,0")
                                    (match_operand:WORD 2 "rhs_operand" 
"m,r,i")))
     (set (reg:CC CC_REGNUM)
             (compare:CC
                 (plus:WORD
                     (match_dup 1)
                     (match_dup 2))
                 (const_int 0)))
   ]
   ""
   "@
    add\t\t%0,[%2]
    add\t\t%0,%2
    add\t\t%0,#%2"
   [(set_attr "length" "4,2,2")]
)

the following code snippet

int x, y;
char ch1 = 1, ch2 = -2;
...
     if( --x )
     {
         ch1 =  ch2;
     }

produces the following rtl

(insn 5 2 6 2 (set (reg:HI 0 r0 [orig:17 x ] [17])
         (mem/c/i:HI (symbol_ref:HI ("x") <var_decl 0xb76fe0c0 x>) [0 
x+0 S2 A16])) t.c:6 60 {*movhihi}
      (expr_list:REG_EQUIV (mem/c/i:HI (symbol_ref:HI ("x") <var_decl 
0xb76fe0c0 x>) [0 x+0 S2 A16])
         (nil)))
+(insn 6 5 7 2 (parallel [
+            (set (reg:HI 0 r0 [orig:15 x.1 ] [15])
+                (plus:HI (reg:HI 0 r0 [orig:17 x ] [17])
+                    (const_int -1 [0xffffffff])))
+            (set (reg:CC 6 flags)
+                (compare:CC (plus:HI (reg:HI 0 r0 [orig:17 x ] [17])
+                        (const_int -1 [0xffffffff]))
+                    (const_int 0 [0])))
+        ]) t.c:6 20 {addhi3}
+     (nil))
(insn 7 6 8 2 (set (mem/c/i:HI (symbol_ref:HI ("x") <var_decl 0xb76fe0c0 
x>) [0 x+0 S2 A16])
         (reg:HI 0 r0 [orig:15 x.1 ] [15])) t.c:6 61 {*storehihi}
      (nil))
?(insn 8 7 9 2 (set (reg:CC 6 flags)
?        (compare:CC (reg:HI 0 r0 [orig:15 x.1 ] [15])
?            (const_int 0 [0]))) t.c:6 53 {comparehi3}
?     (nil))
(jump_insn 9 8 10 2 (set (pc)
         (if_then_else (eq (reg:CC 6 flags)
                 (const_int 0 [0]))
             (label_ref:HI 15)
             (pc))) t.c:6 73 {cbranchcc4}
      (expr_list:REG_BR_PROB (const_int 3900 [0xf3c])
         (nil))
  -> 15)
(insn 18 11 12 3 (set (reg:QI 0 r0)
         (mem/v/c/i:QI (symbol_ref:HI ("ch2") [flags 0x2] <var_decl 
0xb76fe240 ch2>) [0 ch2+0 S1 A8])) t.c:8 62 {*movqiqi}
      (nil))
(insn 12 18 15 3 (set (mem/v/c/i:QI (symbol_ref:HI ("ch1") [flags 0x2] 
<var_decl 0xb76fe1e0 ch1>) [0 ch1+0 S1 A8])
         (reg:QI 0 r0)) t.c:8 62 {*movqiqi}
      (nil))

I've marked the (plus-1) operation with + in the left border and the 
subsequent compare the duplicates the CC_REG setting with ? in the left 
border.

As you can see, the redundant compare hasn't been eliminated and there 
are no clobbers that should require a re-compare.

I've used gdb to trace through compare-elim.c and discovered that the 
problem is

conforming_compare (rtx insn)

calling

set = single_set (insn);

on the parallel [plus:compare] operation and not finding the compare:CC 
sub-operation because the plus::HI operation doesn't include a DEAD_REG 
note (and I can't see that it should).

I'm clearly missing something... can anyone provide a hint ?

Paul S




More information about the Gcc mailing list