@@ -504,9 +504,9 @@ Value *VPInstruction::generate(VPTransformState &State) {
504504 }
505505 case Instruction::ExtractElement: {
506506 assert (State.VF .isVector () && " Only extract elements from vectors" );
507- Value *Vec = State. get ( getOperand ( 0 ));
508- Value *Idx = State. get (getOperand (1 ), /* IsScalar= */ true );
509- return Builder. CreateExtractElement (Vec, Idx, Name );
507+ unsigned IdxToExtract =
508+ cast<ConstantInt> (getOperand (1 )-> getLiveInIRValue ())-> getZExtValue ( );
509+ return State. get ( getOperand ( 0 ), VPLane (IdxToExtract) );
510510 }
511511 case Instruction::Freeze: {
512512 Value *Op = State.get (getOperand (0 ), vputils::onlyFirstLaneUsed (this ));
@@ -617,6 +617,32 @@ Value *VPInstruction::generate(VPTransformState &State) {
617617 return Builder.CreateVectorSplat (
618618 State.VF , State.get (getOperand (0 ), /* IsScalar*/ true ), " broadcast" );
619619 }
620+ case VPInstruction::BuildStructVector: {
621+ // For struct types, we need to build a new 'wide' struct type, where each
622+ // element is widened, i.e. we crate a struct of vectors .
623+ auto *StructTy =
624+ cast<StructType>(State.TypeAnalysis .inferScalarType (getOperand (0 )));
625+ Value *Res = PoisonValue::get (toVectorizedTy (StructTy, State.VF ));
626+ for (const auto &[Idx, Op] : enumerate(operands ())) {
627+ for (unsigned I = 0 ; I != StructTy->getNumElements (); I++) {
628+ Value *ScalarValue = Builder.CreateExtractValue (State.get (Op, true ), I);
629+ Value *VectorValue = Builder.CreateExtractValue (Res, I);
630+ VectorValue =
631+ Builder.CreateInsertElement (VectorValue, ScalarValue, Idx);
632+ Res = Builder.CreateInsertValue (Res, VectorValue, I);
633+ }
634+ }
635+ return Res;
636+ }
637+ case VPInstruction::BuildVector: {
638+ auto *ScalarTy = State.TypeAnalysis .inferScalarType (getOperand (0 ));
639+ auto NumOfElements = ElementCount::getFixed (getNumOperands ());
640+ Value *Res = PoisonValue::get (toVectorizedTy (ScalarTy, NumOfElements));
641+ for (const auto &[Idx, Op] : enumerate(operands ()))
642+ Res = State.Builder .CreateInsertElement (Res, State.get (Op, true ),
643+ State.Builder .getInt32 (Idx));
644+ return Res;
645+ }
620646 case VPInstruction::ReductionStartVector: {
621647 if (State.VF .isScalar ())
622648 return State.get (getOperand (0 ), true );
@@ -935,6 +961,8 @@ bool VPInstruction::opcodeMayReadOrWriteFromMemory() const {
935961 case Instruction::ICmp:
936962 case Instruction::Select:
937963 case VPInstruction::AnyOf:
964+ case VPInstruction::BuildStructVector:
965+ case VPInstruction::BuildVector:
938966 case VPInstruction::CalculateTripCountMinusVF:
939967 case VPInstruction::CanonicalIVIncrementForPart:
940968 case VPInstruction::ExtractLastElement:
@@ -1059,6 +1087,12 @@ void VPInstruction::print(raw_ostream &O, const Twine &Indent,
10591087 case VPInstruction::Broadcast:
10601088 O << " broadcast" ;
10611089 break ;
1090+ case VPInstruction::BuildStructVector:
1091+ O << " buildstructvector" ;
1092+ break ;
1093+ case VPInstruction::BuildVector:
1094+ O << " buildvector" ;
1095+ break ;
10621096 case VPInstruction::ExtractLastElement:
10631097 O << " extract-last-element" ;
10641098 break ;
@@ -2660,37 +2694,30 @@ static void scalarizeInstruction(const Instruction *Instr,
26602694
26612695void VPReplicateRecipe::execute (VPTransformState &State) {
26622696 Instruction *UI = getUnderlyingInstr ();
2663- if (State.Lane ) { // Generate a single instance.
2664- assert ((State.VF .isScalar () || !isSingleScalar ()) &&
2665- " uniform recipe shouldn't be predicated" );
2666- assert (!State.VF .isScalable () && " Can't scalarize a scalable vector" );
2667- scalarizeInstruction (UI, this , *State.Lane , State);
2668- // Insert scalar instance packing it into a vector.
2669- if (State.VF .isVector () && shouldPack ()) {
2670- Value *WideValue;
2671- // If we're constructing lane 0, initialize to start from poison.
2672- if (State.Lane ->isFirstLane ()) {
2673- assert (!State.VF .isScalable () && " VF is assumed to be non scalable." );
2674- WideValue = PoisonValue::get (VectorType::get (UI->getType (), State.VF ));
2675- } else {
2676- WideValue = State.get (this );
2677- }
2678- State.set (this , State.packScalarIntoVectorizedValue (this , WideValue,
2679- *State.Lane ));
2680- }
2681- return ;
2682- }
26832697
2684- if (IsSingleScalar) {
2685- // Uniform within VL means we need to generate lane 0.
2698+ if (!State.Lane ) {
2699+ assert (IsSingleScalar &&
2700+ " VPReplicateRecipes outside replicate regions must be unrolled" );
26862701 scalarizeInstruction (UI, this , VPLane (0 ), State);
26872702 return ;
26882703 }
26892704
2690- // Generate scalar instances for all VF lanes.
2691- const unsigned EndLane = State.VF .getFixedValue ();
2692- for (unsigned Lane = 0 ; Lane < EndLane; ++Lane)
2693- scalarizeInstruction (UI, this , VPLane (Lane), State);
2705+ assert ((State.VF .isScalar () || !isSingleScalar ()) &&
2706+ " uniform recipe shouldn't be predicated" );
2707+ scalarizeInstruction (UI, this , *State.Lane , State);
2708+ // Insert scalar instance packing it into a vector.
2709+ if (State.VF .isVector () && shouldPack ()) {
2710+ Value *WideValue;
2711+ // If we're constructing lane 0, initialize to start from poison.
2712+ if (State.Lane ->isFirstLane ()) {
2713+ assert (!State.VF .isScalable () && " VF is assumed to be non scalable." );
2714+ WideValue = PoisonValue::get (VectorType::get (UI->getType (), State.VF ));
2715+ } else {
2716+ WideValue = State.get (this );
2717+ }
2718+ State.set (this , State.packScalarIntoVectorizedValue (this , WideValue,
2719+ *State.Lane ));
2720+ }
26942721}
26952722
26962723bool VPReplicateRecipe::shouldPack () const {
0 commit comments