Hi! On Thu, Jun 18, 2020 at 03:20:18PM -0700, Carl Love wrote: > * config/rs6000/altivec.md (UNSPEC_XXSPLTIW, UNSPEC_XXSPLTID, > UNSPEC_XXSPLTI32DX): New. > (vxxspltiw_v4si, vxxspltiw_v4sf_inst, vxxspltidp_v2df_inst, > vxxsplti32dx_v4si_inst, vxxsplti32dx_v4sf_inst): New define_insn. > (vxxspltiw_v4sf, vxxspltidp_v2df, vxxsplti32dx_v4si, > vxxsplti32dx_v4sf.): New define_expands.
A whole bunch of these could be done with iterators (but that is then a future improvement, no need to do it now). > +(define_expand "xxsplti32dx_v4si" > + [(set (match_operand:V4SI 0 "register_operand" "=wa") > + (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "wa") > + (match_operand:QI 2 "u1bit_cint_operand" "n") > + (match_operand:SI 3 "s32bit_cint_operand" "n")] > + UNSPEC_XXSPLTI32DX))] > + "TARGET_FUTURE" > +{ > + int index = INTVAL (operands[2]); > + > + if (!BYTES_BIG_ENDIAN) > + index = 1 - index; > + > + /* Instruction uses destination as a source. Do not overwrite source. */ > + emit_move_insn (operands[0], operands[1]); > + > + emit_insn (gen_xxsplti32dx_v4si_inst (operands[0], GEN_INT (index), > + operands[3])); > + DONE; > +} > + [(set_attr "type" "vecsimple")]) > + > +(define_insn "xxsplti32dx_v4si_inst" > + [(set (match_operand:V4SI 0 "register_operand" "+wa") > + (unspec:V4SI [(match_operand:QI 1 "u1bit_cint_operand" "n") > + (match_operand:SI 2 "s32bit_cint_operand" "n")] > + UNSPEC_XXSPLTI32DX))] > + "TARGET_FUTURE" > + "xxsplti32dx %x0,%1,%2" > + [(set_attr "type" "vecsimple")]) Hrm. Can we not just use two operands for that, the second with a "0" constraint? Then register allocation will sort it all out (compare to other instructions with this problem, rl[wd]imi is classical). > +;; Return 1 if op is a 32-bit constant signed integer > +(define_predicate "s32bit_cint_operand" > + (and (match_code "const_int") > + (match_test "(unsigned HOST_WIDE_INT) > + (0x80000000 + UINTVAL (op)) >> 32 == 0"))) You don't need the cast here: UINTVAL returns that type already, and that cascades to everything else in the expression. > +;; Return 1 if op is a constant 32-bit floating point value > +(define_predicate "f32bit_const_operand" > + (match_code "const_double") > +{ > + if (GET_MODE (op) == SFmode) > + return 1; > + > + else if ((GET_MODE (op) == DFmode) && ((UINTVAL (op) >> 32) == 0)) > + { > + /* Value fits in 32-bits */ > + return 1; > + } > + else > + /* Not the expected mode. */ > + return 0; > +}) I don't think this is the correct test. What you want to see is if the number in "op" can be converted to an IEEE single-precision number, and back again, losslessly. (And subnormal SP numbers aren't allowed either, but NaNs and infinities are). Rest looks fine. Sorry it took me so long to spot this. Segher