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

Reply via email to