@@ -74,6 +74,8 @@ bool VETargetLowering::CanLowerReturn(
74
74
static const MVT AllVectorVTs[] = {MVT::v256i32, MVT::v512i32, MVT::v256i64,
75
75
MVT::v256f32, MVT::v512f32, MVT::v256f64};
76
76
77
+ static const MVT AllPackedVTs[] = {MVT::v512i32, MVT::v512f32};
78
+
77
79
void VETargetLowering::initRegisterClasses () {
78
80
// Set up the register classes.
79
81
addRegisterClass (MVT::i32 , &VE::I32RegClass);
@@ -292,6 +294,8 @@ void VETargetLowering::initSPUActions() {
292
294
void VETargetLowering::initVPUActions () {
293
295
for (MVT LegalVecVT : AllVectorVTs) {
294
296
setOperationAction (ISD::BUILD_VECTOR, LegalVecVT, Custom);
297
+ setOperationAction (ISD::INSERT_VECTOR_ELT, LegalVecVT, Legal);
298
+ setOperationAction (ISD::EXTRACT_VECTOR_ELT, LegalVecVT, Legal);
295
299
// Translate all vector instructions with legal element types to VVP_*
296
300
// nodes.
297
301
// TODO We will custom-widen into VVP_* nodes in the future. While we are
@@ -301,6 +305,11 @@ void VETargetLowering::initVPUActions() {
301
305
setOperationAction (ISD::ISD_NAME, LegalVecVT, Custom);
302
306
#include " VVPNodes.def"
303
307
}
308
+
309
+ for (MVT LegalPackedVT : AllPackedVTs) {
310
+ setOperationAction (ISD::INSERT_VECTOR_ELT, LegalPackedVT, Custom);
311
+ setOperationAction (ISD::EXTRACT_VECTOR_ELT, LegalPackedVT, Custom);
312
+ }
304
313
}
305
314
306
315
SDValue
@@ -1662,6 +1671,11 @@ SDValue VETargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
1662
1671
case ISD::VAARG:
1663
1672
return lowerVAARG (Op, DAG);
1664
1673
1674
+ case ISD::INSERT_VECTOR_ELT:
1675
+ return lowerINSERT_VECTOR_ELT (Op, DAG);
1676
+ case ISD::EXTRACT_VECTOR_ELT:
1677
+ return lowerEXTRACT_VECTOR_ELT (Op, DAG);
1678
+
1665
1679
#define ADD_BINARY_VVP_OP (VVP_NAME, ISD_NAME ) case ISD::ISD_NAME:
1666
1680
#include " VVPNodes.def"
1667
1681
return lowerToVVP (Op, DAG);
@@ -2661,3 +2675,100 @@ SDValue VETargetLowering::lowerToVVP(SDValue Op, SelectionDAG &DAG) const {
2661
2675
}
2662
2676
llvm_unreachable (" lowerToVVP called for unexpected SDNode." );
2663
2677
}
2678
+
2679
+ SDValue VETargetLowering::lowerEXTRACT_VECTOR_ELT (SDValue Op,
2680
+ SelectionDAG &DAG) const {
2681
+ assert (Op.getOpcode () == ISD::EXTRACT_VECTOR_ELT && " Unknown opcode!" );
2682
+ MVT VT = Op.getOperand (0 ).getSimpleValueType ();
2683
+
2684
+ // Special treatment for packed V64 types.
2685
+ assert (VT == MVT::v512i32 || VT == MVT::v512f32);
2686
+ // Example of codes:
2687
+ // %packed_v = extractelt %vr, %idx / 2
2688
+ // %v = %packed_v >> (%idx % 2 * 32)
2689
+ // %res = %v & 0xffffffff
2690
+
2691
+ SDValue Vec = Op.getOperand (0 );
2692
+ SDValue Idx = Op.getOperand (1 );
2693
+ SDLoc DL (Op);
2694
+ SDValue Result = Op;
2695
+ if (0 /* Idx->isConstant() */ ) {
2696
+ // TODO: optimized implementation using constant values
2697
+ } else {
2698
+ SDValue Const1 = DAG.getConstant (1 , DL, MVT::i64 );
2699
+ SDValue HalfIdx = DAG.getNode (ISD::SRL, DL, MVT::i64 , {Idx, Const1});
2700
+ SDValue PackedElt =
2701
+ SDValue (DAG.getMachineNode (VE::LVSvr, DL, MVT::i64 , {Vec, HalfIdx}), 0 );
2702
+ SDValue AndIdx = DAG.getNode (ISD::AND, DL, MVT::i64 , {Idx, Const1});
2703
+ SDValue Shift = DAG.getNode (ISD::XOR, DL, MVT::i64 , {AndIdx, Const1});
2704
+ SDValue Const5 = DAG.getConstant (5 , DL, MVT::i64 );
2705
+ Shift = DAG.getNode (ISD::SHL, DL, MVT::i64 , {Shift, Const5});
2706
+ PackedElt = DAG.getNode (ISD::SRL, DL, MVT::i64 , {PackedElt, Shift});
2707
+ SDValue Mask = DAG.getConstant (0xFFFFFFFFL , DL, MVT::i64 );
2708
+ PackedElt = DAG.getNode (ISD::AND, DL, MVT::i64 , {PackedElt, Mask});
2709
+ SDValue SubI32 = DAG.getTargetConstant (VE::sub_i32, DL, MVT::i32 );
2710
+ Result = SDValue (DAG.getMachineNode (TargetOpcode::EXTRACT_SUBREG, DL,
2711
+ MVT::i32 , PackedElt, SubI32),
2712
+ 0 );
2713
+
2714
+ if (Op.getSimpleValueType () == MVT::f32 ) {
2715
+ Result = DAG.getBitcast (MVT::f32 , Result);
2716
+ } else {
2717
+ assert (Op.getSimpleValueType () == MVT::i32 );
2718
+ }
2719
+ }
2720
+ return Result;
2721
+ }
2722
+
2723
+ SDValue VETargetLowering::lowerINSERT_VECTOR_ELT (SDValue Op,
2724
+ SelectionDAG &DAG) const {
2725
+ assert (Op.getOpcode () == ISD::INSERT_VECTOR_ELT && " Unknown opcode!" );
2726
+ MVT VT = Op.getOperand (0 ).getSimpleValueType ();
2727
+
2728
+ // Special treatment for packed V64 types.
2729
+ assert (VT == MVT::v512i32 || VT == MVT::v512f32);
2730
+ // The v512i32 and v512f32 starts from upper bits (0..31). This "upper
2731
+ // bits" required `val << 32` from C implementation's point of view.
2732
+ //
2733
+ // Example of codes:
2734
+ // %packed_elt = extractelt %vr, (%idx >> 1)
2735
+ // %shift = ((%idx & 1) ^ 1) << 5
2736
+ // %packed_elt &= 0xffffffff00000000 >> shift
2737
+ // %packed_elt |= (zext %val) << shift
2738
+ // %vr = insertelt %vr, %packed_elt, (%idx >> 1)
2739
+
2740
+ SDLoc DL (Op);
2741
+ SDValue Vec = Op.getOperand (0 );
2742
+ SDValue Val = Op.getOperand (1 );
2743
+ SDValue Idx = Op.getOperand (2 );
2744
+ if (Idx.getSimpleValueType () == MVT::i32 )
2745
+ Idx = DAG.getNode (ISD::ZERO_EXTEND, DL, MVT::i64 , Idx);
2746
+ if (Val.getSimpleValueType () == MVT::f32 )
2747
+ Val = DAG.getBitcast (MVT::i32 , Val);
2748
+ assert (Val.getSimpleValueType () == MVT::i32 );
2749
+ Val = DAG.getNode (ISD::ZERO_EXTEND, DL, MVT::i64 , Val);
2750
+
2751
+ SDValue Result = Op;
2752
+ if (0 /* Idx->isConstant()*/ ) {
2753
+ // TODO: optimized implementation using constant values
2754
+ } else {
2755
+ SDValue Const1 = DAG.getConstant (1 , DL, MVT::i64 );
2756
+ SDValue HalfIdx = DAG.getNode (ISD::SRL, DL, MVT::i64 , {Idx, Const1});
2757
+ SDValue PackedElt =
2758
+ SDValue (DAG.getMachineNode (VE::LVSvr, DL, MVT::i64 , {Vec, HalfIdx}), 0 );
2759
+ SDValue AndIdx = DAG.getNode (ISD::AND, DL, MVT::i64 , {Idx, Const1});
2760
+ SDValue Shift = DAG.getNode (ISD::XOR, DL, MVT::i64 , {AndIdx, Const1});
2761
+ SDValue Const5 = DAG.getConstant (5 , DL, MVT::i64 );
2762
+ Shift = DAG.getNode (ISD::SHL, DL, MVT::i64 , {Shift, Const5});
2763
+ SDValue Mask = DAG.getConstant (0xFFFFFFFF00000000L , DL, MVT::i64 );
2764
+ Mask = DAG.getNode (ISD::SRL, DL, MVT::i64 , {Mask, Shift});
2765
+ PackedElt = DAG.getNode (ISD::AND, DL, MVT::i64 , {PackedElt, Mask});
2766
+ Val = DAG.getNode (ISD::SHL, DL, MVT::i64 , {Val, Shift});
2767
+ PackedElt = DAG.getNode (ISD::OR, DL, MVT::i64 , {PackedElt, Val});
2768
+ Result =
2769
+ SDValue (DAG.getMachineNode (VE::LSVrr_v, DL, Vec.getSimpleValueType (),
2770
+ {HalfIdx, PackedElt, Vec}),
2771
+ 0 );
2772
+ }
2773
+ return Result;
2774
+ }
0 commit comments