On Fri, 2012-08-17 at 22:32 +0200, Uros Bizjak wrote:
> Yes, x86_64 also has register passing convention. So, i.e.:
>
> --cut here--
> int foo (int a, int b, int c)
> {
> return a + b + c;
> }
> --cut here--
>
> expands to:
>
> (note 6 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
> (insn 2 6 3 2 (set (reg/v:SI 62 [ a ])
> (reg:SI 5 di [ a ])) t.c:2 -1
> (nil))
> (insn 3 2 4 2 (set (reg/v:SI 63 [ b ])
> (reg:SI 4 si [ b ])) t.c:2 -1
> (nil))
> (insn 4 3 5 2 (set (reg/v:SI 64 [ c ])
> (reg:SI 1 dx [ c ])) t.c:2 -1
> (nil))
> (note 5 4 8 2 NOTE_INSN_FUNCTION_BEG)
> (insn 8 5 9 2 (parallel [
> (set (reg:SI 66 [ D.1722 ])
> (plus:SI (reg/v:SI 62 [ a ])
> (reg/v:SI 63 [ b ])))
> (clobber (reg:CC 17 flags))
> ]) t.c:3 -1
> (nil))
> (...)
>
> So, we expand function arguments to pseudos first, and these survive
> up to the combine pass. If sh expanded func arguments to pseudos, then
> invalid hard register won't be propagated to insn pattern, leaving
> reload with much more freedom to choose correct register. I believe
> that code improvements you are seeing come from this added reload
> freedom.
It seems on SH func args are expanded to pseudos, sorry for not checking
this properly.
int test (uint8_t x)
{
return x & 15 ? -40 : -9;
}
expands to:
(note 1 0 7 NOTE_INSN_DELETED)
(note 7 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(insn 2 7 3 2 (set (reg:SI 164)
(reg:SI 4 r4 [ x ])) sh_tmp.cpp:9 -1
(nil))
(insn 3 2 4 2 (set (reg/v:SI 163 [ x ])
(zero_extend:SI (subreg:QI (reg:SI 164) 0))) sh_tmp.cpp:9 -1
(nil))
(note 4 3 9 2 NOTE_INSN_FUNCTION_BEG)
(insn 9 4 10 2 (set (reg:SI 165)
(and:SI (reg/v:SI 163 [ x ])
(const_int 15 [0xf]))) sh_tmp.cpp:10 -1
(nil))
...
Then in combine it goes like:
Successfully matched this instruction:
(set (reg/v:SI 163 [ x ])
(zero_extend:SI (reg:QI 4 r4 [ x ])))
deferring deletion of insn with uid = 2.
modifying insn i3 3 r163:SI=zero_extend(r4:QI)
REG_DEAD: r4:SI
deferring rescan insn with uid = 3.
[[note: the matched pattern above is "*zero_extendqisi2_compact" ]]
Trying 3 -> 9:
Successfully matched this instruction:
(set (reg:SI 165)
(and:SI (reg:SI 4 r4 [ x ])
(const_int 15 [0xf])))
deferring deletion of insn with uid = 3.
modifying insn i3 9 r165:SI=r4:SI&0xf
REG_DEAD: r4:SI
deferring rescan insn with uid = 9.
Trying 9 -> 11:
Successfully matched this instruction:
(set (reg:SI 167)
(and:SI (reg:SI 4 r4 [ x ])
(const_int 15 [0xf])))
deferring deletion of insn with uid = 9.
modifying insn i3 11 r167:SI=r4:SI&0xf
REG_DEAD: r4:SI
deferring rescan insn with uid = 11.
Trying 11 -> 12:
Successfully matched this instruction:
(set (reg:SI 147 t)
(eq:SI (zero_extract:SI (reg:SI 4 r4 [ x ])
(const_int 4 [0x4])
(const_int 0 [0]))
(const_int 0 [0])))
Operand failed to match constraints:
(reg:SI 4 r4 [ x ])
> Hm, I'd write this instruction as:
>
> (define_insn_and_split "nott"
> [(set (match_operand:SI 0 "t_reg_operand" "t")
> (xor:SI (match_operand:SI 1 "t_reg_operand" "0") (const_int 1)))]
> "TARGET_SH1"
> ...)
>
> This would match new combine limitation without problems, although
> empty constraint should be matched as well. Can you perhaps
> investigate a bit, why op_alt[j].anything.ok in
>
> + if (op_alt[j].anything_ok
> + || (op_alt[j].matches != -1
> + && rtx_equal_p (recog_data.operand[i],
> + recog_data.operand[op_alt[j].matches]))
> + || (reg_fits_class_p (op, op_alt[j].cl, offset, mode)))
>
> does not trigger for this operation? Maybe we need to add another
> condition to allow empty constraint.
It seems that in this case there are no alternatives in recog_data at
all. The 'for' never runs, 'win' remains 'false'.
Doing
- if (!win)
+ if (!win && recog_data.n_alternatives > 0)
seems to help.
> IMO, a patch like this that touches many targets won't be applied over
> night. Rest assured that there will be a discussion about it.
>
> Thanks for testing the patch, I look forward to comments.
Sure, no problem.
Cheers,
Oleg