Skip to content

Commit 5c54367

Browse files
committed
[VPlan] Add VPResultType mixing to manage recipe result types.
1 parent b0ddcb9 commit 5c54367

File tree

3 files changed

+50
-11
lines changed

3 files changed

+50
-11
lines changed

llvm/lib/Transforms/Vectorize/VPlan.h

+45-7
Original file line numberDiff line numberDiff line change
@@ -1030,17 +1030,25 @@ class VPInstruction : public VPRecipeWithIRFlags,
10301030
}
10311031
};
10321032

1033-
/// A specialization of VPInstruction augmenting it with a dedicated result
1034-
/// type, to be used when the opcode and operands of the VPInstruction don't
1035-
/// directly determine the result type.
1036-
class VPInstructionWithType : public VPInstruction {
1033+
class VPResultType {
10371034
/// Scalar result type produced by the recipe.
10381035
Type *ResultTy;
10391036

1037+
public:
1038+
VPResultType(Type *ResultTy) : ResultTy(ResultTy) {}
1039+
virtual ~VPResultType() = default;
1040+
1041+
Type *getResultType() const { return ResultTy; }
1042+
};
1043+
1044+
/// A specialization of VPInstruction augmenting it with a dedicated result
1045+
/// type, to be used when the opcode and operands of the VPInstruction don't
1046+
/// directly determine the result type.
1047+
class VPInstructionWithType : public VPInstruction, public VPResultType {
10401048
public:
10411049
VPInstructionWithType(unsigned Opcode, ArrayRef<VPValue *> Operands,
10421050
Type *ResultTy, DebugLoc DL, const Twine &Name = "")
1043-
: VPInstruction(Opcode, Operands, DL, Name), ResultTy(ResultTy) {}
1051+
: VPInstruction(Opcode, Operands, DL, Name), VPResultType(ResultTy) {}
10441052

10451053
static inline bool classof(const VPRecipeBase *R) { return isCast(R); }
10461054

@@ -1065,15 +1073,45 @@ class VPInstructionWithType : public VPInstruction {
10651073
return 0;
10661074
}
10671075

1068-
Type *getResultType() const { return ResultTy; }
1069-
10701076
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
10711077
/// Print the recipe.
10721078
void print(raw_ostream &O, const Twine &Indent,
10731079
VPSlotTracker &SlotTracker) const override;
10741080
#endif
10751081
};
10761082

1083+
template <> struct CastIsPossible<VPResultType, const VPRecipeBase *> {
1084+
static inline bool isPossible(const VPRecipeBase *f) {
1085+
return isa<VPInstructionWithType>(f);
1086+
}
1087+
};
1088+
1089+
template <>
1090+
struct CastInfo<VPResultType, const VPRecipeBase *>
1091+
: public CastIsPossible<VPResultType, const VPRecipeBase *> {
1092+
using Self = CastInfo<VPResultType, const VPRecipeBase *>;
1093+
1094+
using CastReturnType =
1095+
typename cast_retty<VPResultType, VPRecipeBase *>::ret_type;
1096+
1097+
static inline VPResultType *doCast(const VPRecipeBase *f) {
1098+
auto *VPI =
1099+
const_cast<VPInstructionWithType *>(dyn_cast<VPInstructionWithType>(f));
1100+
return VPI;
1101+
}
1102+
1103+
// This assumes that you can construct the cast return type from `nullptr`.
1104+
// This is largely to support legacy use cases - if you don't want this
1105+
// behavior you should specialize CastInfo for your use case.
1106+
static inline VPResultType *castFailed() { return nullptr; }
1107+
1108+
static inline VPResultType *doCastIfPossible(const VPRecipeBase *f) {
1109+
if (!Self::isPossible(f))
1110+
return castFailed();
1111+
return doCast(f);
1112+
}
1113+
};
1114+
10771115
/// A recipe to wrap on original IR instruction not to be modified during
10781116
/// execution, except for PHIs. PHIs are modeled via the VPIRPhi subclass.
10791117
/// Expect PHIs, VPIRInstructions cannot have any operands.

llvm/lib/Transforms/Vectorize/VPlanAnalysis.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,10 @@ Type *VPTypeAnalysis::inferScalarType(const VPValue *V) {
261261
VPPartialReductionRecipe>([this](const VPRecipeBase *R) {
262262
return inferScalarType(R->getOperand(0));
263263
})
264-
// VPInstructionWithType must be handled before VPInstruction.
265-
.Case<VPInstructionWithType, VPWidenIntrinsicRecipe>(
264+
// VPResultType must be handled before VPInstruction.
265+
.Case<VPResultType, VPWidenIntrinsicRecipe>(
266266
[](const auto *R) { return R->getResultType(); })
267+
267268
.Case<VPBlendRecipe, VPInstruction, VPWidenRecipe, VPReplicateRecipe,
268269
VPWidenCallRecipe, VPWidenMemoryRecipe, VPWidenSelectRecipe>(
269270
[this](const auto *R) { return inferScalarTypeForRecipe(R); })

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1078,7 +1078,7 @@ void VPInstructionWithType::execute(VPTransformState &State) {
10781078
case Instruction::Trunc: {
10791079
Value *Op = State.get(getOperand(0), VPLane(0));
10801080
Value *Cast = State.Builder.CreateCast(Instruction::CastOps(getOpcode()),
1081-
Op, ResultTy);
1081+
Op, getResultType());
10821082
State.set(this, Cast, VPLane(0));
10831083
break;
10841084
}
@@ -1094,7 +1094,7 @@ void VPInstructionWithType::print(raw_ostream &O, const Twine &Indent,
10941094
printAsOperand(O, SlotTracker);
10951095
O << " = " << Instruction::getOpcodeName(getOpcode()) << " ";
10961096
printOperands(O, SlotTracker);
1097-
O << " to " << *ResultTy;
1097+
O << " to " << *getResultType();
10981098
}
10991099
#endif
11001100

0 commit comments

Comments
 (0)