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