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