http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60763
--- Comment #11 from rsandifo at gcc dot gnu.org <rsandifo at gcc dot gnu.org> --- (In reply to David Edelsohn from comment #10) > I'm not questioning the analysis, I'm questioning the solution. Directly > generating a register and jamming in the REGNO in this pattern seems sort of > crude. > > gen_rtx_REG (DImode, REGNO (op0)); > > I don't doubt that this is the RTL that eventually is produced, I am > surprised that there is no existing wrapper function in simplify-rtx.c or > rtlanal.c that can be used. > > If this is the necessary implementation, I think it deserves some, brief > comment. I think the reason there's no wrapper function is that it's very dangerous to change the mode of a register when the target has explicitly said that that shouldn't happen. Maybe it's an easier sell if I say that this op0_di is really a secondary temporary value that just happens to use the same register as the output. I think: (define_insn_and_split "reload_vsx_from_gprsf" [(set (match_operand:SF 0 "register_operand" "=wa") (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_P8V_RELOAD_FROM_GPR)) (clobber (match_operand:DI 2 "register_operand" "=r")) (clobber (match_operand:DI 3 "register_operand" "=wa"))] "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" "#" "&& reload_completed" [(const_int 0)] { rtx op0 = operands[0]; rtx op1 = operands[1]; rtx op2 = operands[2]; rtx op3 = operands[3]; rtx op1_di = simplify_gen_subreg (DImode, op1, SFmode, 0); /* Move SF value to upper 32-bits for xscvspdpn. */ emit_insn (gen_ashldi3 (op2, op1_di, GEN_INT (32))); emit_move_insn (op3, op2); emit_insn (gen_vsx_xscvspdpn_directmove (op0, op3)); DONE; } [(set_attr "length" "8") (set_attr "type" "two")]) would work too. The difference is that the above would always allocate two separate FPRs, which is wasteful, so the pattern is trying to use the same register for both the temporary value and the final result. But I suppose it just doesn't seem that crude to me.