Hi! On Sun, Jul 05, 2020 at 09:17:57PM -0500, Xionghu Luo wrote: > For extracting high part element from DImode register like: > > {%1:SF=unspec[r122:DI>>0x20#0] 86;clobber scratch;} > > split it before reload with "and mask" to avoid generating shift right > 32 bit then shift left 32 bit. > > srdi 3,3,32 > sldi 9,3,32 > mtvsrd 1,9 > xscvspdpn 1,1 > > => > > rldicr 3,3,0,31 > mtvsrd 1,3 > xscvspdpn 1,1
Great :-) > +;; For extracting high part element from DImode register like: > +;; {%1:SF=unspec[r122:DI>>0x20#0] 86;clobber scratch;} > +;; split it before reload with "and mask" to avoid generating shift right > +;; 32 bit then shift left 32 bit. > +(define_insn_and_split "movsf_from_si2" > + [(set (match_operand:SF 0 "nonimmediate_operand" > + "=!r, f, v, wa, m, Z, > + Z, wa, ?r, !r") > + (unspec:SF [ > + (subreg:SI (ashiftrt:DI > + (match_operand:DI 1 "input_operand" > + "m, m, wY, Z, r, f, > + wa, r, wa, r") > + (const_int 32)) 0)] > + UNSPEC_SF_FROM_SI)) > + (clobber (match_scratch:DI 2 > + "=X, X, X, X, X, X, > + X, r, X, X"))] > + "TARGET_NO_SF_SUBREG > + && (register_operand (operands[0], SFmode) > + && register_operand (operands[1], DImode))" If the insn condition requires operands 0 and 1 to be register_operands, it can ask for that in the predicates, instead: not nonimmediate_operand and input_operand, but just gpc_reg_operand instead. You can leave out the impossible alternatives as well (0, 1, 2, 3, 4, 5, 6), leaving just (define_insn_and_split "movsf_from_si2" [(set (match_operand:SF 0 "gpc_reg_operand" "=wa,?r,!r") (unspec:SF [(subreg:SI (ashiftrt:DI (match_operand:DI 1 "input_operand" "r,wa,r") (const_int 32)) 0)] UNSPEC_SF_FROM_SI)))] "TARGET_NO_SF_SUBREG" "@ # mfvsrwz %0,%x1 mr %0,%1" "&& !reload_completed && vsx_reg_sfsubreg_ok (operands[0], SFmode)" [(const_int 0)] { rtx op0 = operands[0]; rtx op1 = operands[1]; rtx tmp = gen_reg_rtx (DImode); You cannot call gen_reg_rtx too late in the pass pipeline. What we usually do for such cases is put it as a match_scratch in the pattern, and then do code like if (GET_CODE (operands[2]) == SCRATCH) operands[2] = gen_reg_rtx (DImode); so that it will work both before and after reload. /* Avoid split {r155:SI#0=unspec[r133:DI>>0x20#0] 86;clobber scratch;} from PR42745. */ (This line is too long, btw.) if (!SUBREG_P (operands[0])) { rtx mask = GEN_INT (HOST_WIDE_INT_M1U << 32); emit_insn (gen_anddi3 (tmp, op1, mask)); emit_insn (gen_p8_mtvsrd_sf (op0, tmp)); emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0)); DONE; } else FAIL; } [(set_attr "length" "12,*,*") (set_attr "type" "vecfloat,mffgpr,*") (set_attr "isa" "p8v,p8v,*")]) I wonder what will happen if you actually do FAIL here... There then is no insn alternative that can match, so we ICE? In that case, just leave out the whole FAIL thing, it is useless? You can do a gcc_assert if you want to check something. Oh, and maybe you only want to handle GPRs here, not VSRs? So just the "r", not the "wa" at all? What code would it generate for vector regs? Lots of questions, sorry! Segher