Hi,

I am supporting custom 32-bit backend for gcc 4.6.2, and I want to
implement DI to DF conversion. Earlier it was through libgcc. Specific
of backend is, that DF may be represented as one register, but source
DI must be splitted into two SI to be used.

So overall insn pattern (actual splitting is performed inside expand
pattern) is:

;; splitted 64-bit integer to double float
(define_insn "floatdidf2_32_internal"
  [(parallel
     [(set (subreg:SI (match_operand:DF 0 "register_operand" "=r") 4)
           (subreg:SI (float:DF (match_operand:SI 1 "register_operand" "r")) 4))
      (set (subreg:SI (match_dup 0) 0)
           (subreg:SI (float:DF (match_operand:SI 2 "register_operand"
"r")) 0))])]
  "TARGET_32BIT"
  {
    return output_pseudo_didf(operands);
  }
  [(set_attr "predicable" "no")]
)

output_pseudo_didf is function, that outputs non-trivial instruction
sequence, using operands[0], operands[1], operands[2].

And everything works just fine on -O2, but on -O2 -frename-registers
behaves strange:

Before renaming:

(insn 20 19 8 3 (set:DF (reg:DF 3 %r10 [74])
        (const_double:DF 0.0 [0x0.0p+0])) test.c:4 11 {movdf_internal_vec}
     (expr_list:REG_EQUAL (const_double:DF 0.0 [0x0.0p+0])
        (nil)))

(insn 8 20 13 3 (parallel [
            (set (subreg:SI (reg:DF 3 %r10 [74]) 4)
                (subreg:SI (float:DF (reg:SI 7 %r2 [ s ])) 4))
            (set (subreg:SI (reg:DF 3 %r10 [74]) 0)
                (subreg:SI (float:DF (reg:SI 8 %r3 [ s+4 ])) 0))
        ]) test.c:4 160 {floatdidf2_32_internal}
     (expr_list:REG_DEAD (reg:SI 8 %r3 [ s+4 ])
        (expr_list:REG_DEAD (reg:SI 7 %r2 [ s ])
            (nil))))

(insn 13 8 16 3 (set:DF (reg/i:DF 7 %r2)
        (reg:DF 3 %r10 [74])) test.c:5 11 {movdf_internal_vec}
     (expr_list:REG_DEAD (reg:DF 3 %r10 [74])
        (nil)))

After renaming:

(insn 20 19 8 3 (set:DF (reg:DF 3 %r10 [74])
        (const_double:DF 0.0 [0x0.0p+0])) test.c:4 11 {movdf_internal_vec}
     (expr_list:REG_EQUAL (const_double:DF 0.0 [0x0.0p+0])
        (nil)))

(insn 8 20 13 3 (parallel [
            (set (subreg:SI (reg:DF 3 %r10 [74]) 4)
                (subreg:SI (float:DF (reg:SI 7 %r2 [ s ])) 4))
            (set (subreg:SI (reg:DF 4 %r11 [74]) 0)
<------ here %r10 was renamed to be %r11, that is senseless
                (subreg:SI (float:DF (reg:SI 8 %r3 [ s+4 ])) 0))
        ]) test.c:4 160 {floatdidf2_32_internal}
     (expr_list:REG_DEAD (reg:SI 8 %r3 [ s+4 ])
        (expr_list:REG_DEAD (reg:SI 7 %r2 [ s ])
            (nil))))

(insn 13 8 16 3 (set:DF (reg/i:DF 7 %r2)
        (reg:DF 4 %r11 [74])) test.c:5 11 {movdf_internal_vec}
     (expr_list:REG_DEAD (reg:DF 4 %r11 [74])
        (nil)))

It seems, that register renaming in gcc 4.6.2 doesn't know how to
preserve match_dup, and breaks it. How can I rewrite my pattern to
explain, that I mean exactly that: "synchronously updating higher and
lower part of the same register, no renaming please"? Or may be I can
somehow patch renaming pass itself (I don't want to do it and prefer
to change everything only in my backend code, but in the last resort
it is a solution).

---
With best regards, Konstantin

Reply via email to