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


Reply via email to