Bernd Schmidt wrote: > On 07/11/11 18:42, Bernd Schmidt wrote: >> On 07/11/11 18:12, Georg-Johann Lay wrote: >>> The reason is that IRA (or reload, don't see it from the dumps) >>> combines the insns again to: >>> >>> (insn 29 31 24 2 (parallel [ >>> (set (reg:HI 24 r24 [49]) >>> (mult:HI (reg:HI 18 r18) >>> (const_int 15 [0xf]))) >>> (clobber (reg:QI 20 r20)) >>> ]) wmul.c:71 46 {*mulhi3.uconst} >>> (nil)) >> Find out where it does that (breakpoint on make_insn_raw if the insn is >> newly created; watchpoint on its PATTERN (insn->u.fld[4].rt_rtx I think) >> otherwise. > > Ok, so I'm guessing it's the validate_replace_rtx call in > update_equiv_regs. If I understand correctly, you're doing this to get > the constant CSEd - is that right? If so, have you tried using an > expander rather than a split (no CSE passes after combine)? > > Bernd
Ya, it's to get potential duplicate constants CSEd out. I see now. In this particular case I could use an expander because it's a standard insn. However, I have also cases where it is not a standard insn like (define_insn_and_split "*mulsqihi3.sconst" [(set (match_operand:HI 0 "register_operand" "=r") (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "r")) (match_operand:HI 2 "s8_operand" "Cs8"))) (clobber (match_scratch:QI 3 "=&d"))] I started some hacking: avr.c: #include "tree-pass.h" bool avr_gate_split1 (void) { if (current_pass->static_pass_number < pass_match_asm_constraints.pass.static_pass_number) return true; return false; } And the splitter: (define_insn_and_split "*mulsqihi3.sconst" [(set (match_operand:HI 0 "register_operand" "=&r") (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d")) (match_operand:HI 2 "s8_operand" "Cs8"))) (clobber (match_scratch:QI 3 "=&d"))] "AVR_HAVE_MUL && avr_gate_split1()" "#" "&& 1" [(set (match_dup 3) (match_dup 2)) ; *muls (set (match_dup 0) (mult:HI (sign_extend:HI (match_dup 1)) (sign_extend:HI (match_dup 3))))] { operands[2] = GEN_INT (trunc_int_for_mode (INTVAL (operands[2]), QImode)); if (SCRATCH == GET_CODE (operands[3])) operands[3] = gen_reg_rtx (QImode); }) It works! Test case: int y15; int x15; void cmul_15 (char x, char y) { y15 = y * 15; x15 = x * 15; } Without the gate, the 15 is loaded 2 times and with the gate just once. So the question is: Can this be done without the hack? Or is avr_gate_split1 something that is ok to commit? Johann