http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46098
Michael Matz <matz at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |hubicka at gcc dot gnu.org, | |uros at gcc dot gnu.org --- Comment #2 from Michael Matz <matz at gcc dot gnu.org> 2010-10-21 14:33:15 UTC --- Well, that's a problem of the target. The pattern that is supposed to match is: (define_insn "<sse>_movu<ssemodesuffix>" [(set (match_operand:SSEMODEF2P 0 "nonimmediate_operand" "=x,m") (unspec:SSEMODEF2P [(match_operand:SSEMODEF2P 1 "nonimmediate_operand" "xm,x")] UNSPEC_MOVU))] "SSE_VEC_FLOAT_MODE_P (<MODE>mode) && !(MEM_P (operands[0]) && MEM_P (operands[1]))" ... So, the predicates are nonimmediate_operand for both. The additional matching condition is that not both arguments are memory. They are here, hence nothing matches. But if this is the only pattern that could match the RTL code then the builtin expander has the obligation to create patterns that are matchable. But that's not what ix86_expand_special_args_builtin is doing here. In particular it detects that nargs=1, klass=load, memory=0. That means the first (and only) argument has to be memory. Nothing is said about the target. The routine then proceeds to not change the target, because: if (klass == store) ... else { arg_adjust = 0; if (optimize || target == 0 || GET_MODE (target) != tmode || !insn_p->operand[0].predicate (target, tmode)) target = gen_reg_rtx (tmode); } target is (mem/c/i:V2DF (plus:DI (reg/f:DI 54 virtual-stack-vars) (const_int -16 [0xfffffffffffffff0])) [0 D.2706+0 S16 A128]) The target _does_ match the predicate, hence no change occurs. Furthermore in the loop over arguments: for (i = 0; i < nargs; i++) { if (last_arg_constant && (i + 1) == nargs) ... else { if (i == memory) { /* This must be the memory operand. */ op = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, op)); gcc_assert (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode); } ... } Here we would explicitely construct a memory argument, even if it isn't already, irrespective if the predicate matches or not. Hence, no matter what this does it will end up with a pattern where target and argument are both MEM. This is never matchable --> boom. I don't know enough about the intention of the ix86_builtin expanders to suggest where to fix this. One alternative seems to be to adjust the pattern to only accept register_operand in the destination (which also means removing one alternative and the matching condition). Another alternative would be only removing the !(MEM && MEM) part of the matching condition, because reload will fix up the non-matching constraints. The third alternative would be to fix ix86_expand_special_args_builtin to emit the correct patterns from the start. Whatever is done, it probably also needs to be done for some other patterns. FWIW the second alternative would look like so: Index: config/i386/sse.md =================================================================== --- config/i386/sse.md (revision 165503) +++ config/i386/sse.md (working copy) @@ -412,8 +412,7 @@ (define_insn "<sse>_movu<ssemodesuffix>" (unspec:SSEMODEF2P [(match_operand:SSEMODEF2P 1 "nonimmediate_operand" "xm,x")] UNSPEC_MOVU))] - "SSE_VEC_FLOAT_MODE_P (<MODE>mode) - && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "SSE_VEC_FLOAT_MODE_P (<MODE>mode)" "movu<ssemodesuffix>\t{%1, %0|%0, %1}" [(set_attr "type" "ssemov") (set_attr "movu" "1") and fixes the bug.