@@ -863,6 +863,31 @@ Value *VPInstruction::generate(VPTransformState &State) {
863
863
Res = Builder.CreateOr (Res, State.get (Op));
864
864
return State.VF .isScalar () ? Res : Builder.CreateOrReduce (Res);
865
865
}
866
+ case VPInstruction::ExtractLane: {
867
+ Value *LaneToExtract = State.get (getOperand (0 ), true );
868
+ Type *IdxTy = State.TypeAnalysis .inferScalarType (getOperand (0 ));
869
+ Value *Res = nullptr ;
870
+ Value *RuntimeVF = getRuntimeVF (State.Builder , IdxTy, State.VF );
871
+
872
+ for (unsigned Idx = 1 ; Idx != getNumOperands (); ++Idx) {
873
+ Value *VectorStart =
874
+ Builder.CreateMul (RuntimeVF, ConstantInt::get (IdxTy, Idx - 1 ));
875
+ Value *VectorIdx = Idx == 1
876
+ ? LaneToExtract
877
+ : Builder.CreateSub (LaneToExtract, VectorStart);
878
+ Value *Ext = State.VF .isScalar ()
879
+ ? State.get (getOperand (Idx))
880
+ : Builder.CreateExtractElement (
881
+ State.get (getOperand (Idx)), VectorIdx);
882
+ if (Res) {
883
+ Value *Cmp = Builder.CreateICmpUGE (LaneToExtract, VectorStart);
884
+ Res = Builder.CreateSelect (Cmp, Ext, Res);
885
+ } else {
886
+ Res = Ext;
887
+ }
888
+ }
889
+ return Res;
890
+ }
866
891
case VPInstruction::FirstActiveLane: {
867
892
if (getNumOperands () == 1 ) {
868
893
Value *Mask = State.get (getOperand (0 ));
@@ -921,7 +946,8 @@ InstructionCost VPInstruction::computeCost(ElementCount VF,
921
946
}
922
947
923
948
switch (getOpcode ()) {
924
- case Instruction::ExtractElement: {
949
+ case Instruction::ExtractElement:
950
+ case VPInstruction::ExtractLane: {
925
951
// Add on the cost of extracting the element.
926
952
auto *VecTy = toVectorTy (Ctx.Types .inferScalarType (getOperand (0 )), VF);
927
953
return Ctx.TTI .getVectorInstrCost (Instruction::ExtractElement, VecTy,
@@ -983,6 +1009,7 @@ bool VPInstruction::isVectorToScalar() const {
983
1009
return getOpcode () == VPInstruction::ExtractLastElement ||
984
1010
getOpcode () == VPInstruction::ExtractPenultimateElement ||
985
1011
getOpcode () == Instruction::ExtractElement ||
1012
+ getOpcode () == VPInstruction::ExtractLane ||
986
1013
getOpcode () == VPInstruction::FirstActiveLane ||
987
1014
getOpcode () == VPInstruction::ComputeAnyOfResult ||
988
1015
getOpcode () == VPInstruction::ComputeFindIVResult ||
@@ -1048,6 +1075,7 @@ bool VPInstruction::opcodeMayReadOrWriteFromMemory() const {
1048
1075
case VPInstruction::BuildVector:
1049
1076
case VPInstruction::CalculateTripCountMinusVF:
1050
1077
case VPInstruction::CanonicalIVIncrementForPart:
1078
+ case VPInstruction::ExtractLane:
1051
1079
case VPInstruction::ExtractLastElement:
1052
1080
case VPInstruction::ExtractPenultimateElement:
1053
1081
case VPInstruction::FirstActiveLane:
@@ -1097,6 +1125,8 @@ bool VPInstruction::onlyFirstLaneUsed(const VPValue *Op) const {
1097
1125
case VPInstruction::ComputeAnyOfResult:
1098
1126
case VPInstruction::ComputeFindIVResult:
1099
1127
return Op == getOperand (1 );
1128
+ case VPInstruction::ExtractLane:
1129
+ return Op == getOperand (0 );
1100
1130
};
1101
1131
llvm_unreachable (" switch should return" );
1102
1132
}
@@ -1176,6 +1206,9 @@ void VPInstruction::print(raw_ostream &O, const Twine &Indent,
1176
1206
case VPInstruction::BuildVector:
1177
1207
O << " buildvector" ;
1178
1208
break ;
1209
+ case VPInstruction::ExtractLane:
1210
+ O << " extract-lane" ;
1211
+ break ;
1179
1212
case VPInstruction::ExtractLastElement:
1180
1213
O << " extract-last-element" ;
1181
1214
break ;
0 commit comments