OverflowingBinOp,
PossiblyExactOp,
FPMathOp,
+ GEPOp,
Other
};
struct WrapFlagsTy {
struct ExactFlagsTy {
char IsExact : 1;
};
+ struct GEPFlagsTy {
+ char IsInBounds : 1;
+ };
struct FastMathFlagsTy {
char AllowReassoc : 1;
char NoNaNs : 1;
union {
WrapFlagsTy WrapFlags;
ExactFlagsTy ExactFlags;
+ GEPFlagsTy GEPFlags;
FastMathFlagsTy FMFs;
unsigned char AllFlags;
};
} else if (auto *Op = dyn_cast<PossiblyExactOperator>(&I)) {
OpType = OperationType::PossiblyExactOp;
ExactFlags.IsExact = Op->isExact();
+ } else if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
+ OpType = OperationType::GEPOp;
+ GEPFlags.IsInBounds = GEP->isInBounds();
} else if (auto *Op = dyn_cast<FPMathOperator>(&I)) {
OpType = OperationType::FPMathOp;
FastMathFlags FMF = Op->getFastMathFlags();
}
static inline bool classof(const VPRecipeBase *R) {
- return R->getVPDefID() == VPRecipeBase::VPWidenSC;
+ return R->getVPDefID() == VPRecipeBase::VPWidenSC ||
+ R->getVPDefID() == VPRecipeBase::VPWidenGEPSC;
}
/// Drop all poison-generating flags.
case OperationType::PossiblyExactOp:
ExactFlags.IsExact = false;
break;
+ case OperationType::GEPOp:
+ GEPFlags.IsInBounds = false;
+ break;
case OperationType::FPMathOp:
FMFs.NoNaNs = false;
FMFs.NoInfs = false;
case OperationType::PossiblyExactOp:
I->setIsExact(ExactFlags.IsExact);
break;
+ case OperationType::GEPOp:
+ cast<GetElementPtrInst>(I)->setIsInBounds(GEPFlags.IsInBounds);
+ break;
case OperationType::FPMathOp:
I->setHasAllowReassoc(FMFs.AllowReassoc);
I->setHasNoNaNs(FMFs.NoNaNs);
};
/// A recipe for handling GEP instructions.
-class VPWidenGEPRecipe : public VPRecipeBase, public VPValue {
+class VPWidenGEPRecipe : public VPRecipeWithIRFlags, public VPValue {
bool isPointerLoopInvariant() const {
return getOperand(0)->isDefinedOutsideVectorRegions();
}
public:
template <typename IterT>
VPWidenGEPRecipe(GetElementPtrInst *GEP, iterator_range<IterT> Operands)
- : VPRecipeBase(VPDef::VPWidenGEPSC, Operands), VPValue(this, GEP) {}
+ : VPRecipeWithIRFlags(VPDef::VPWidenGEPSC, Operands, *GEP),
+ VPValue(this, GEP) {}
~VPWidenGEPRecipe() override = default;
// collectLoopScalars() and teach getVectorValue() to broadcast
// the lane-zero scalar value.
auto *Clone = State.Builder.Insert(GEP->clone());
+ setFlags(Clone);
for (unsigned Part = 0; Part < State.UF; ++Part) {
Value *EntryPart = State.Builder.CreateVectorSplat(State.VF, Clone);
State.set(this, EntryPart, Part);
Indices.push_back(State.get(Operand, Part));
}
- // If the GEP instruction is vectorized and was in a basic block that
- // needed predication, we can't propagate the poison-generating 'inbounds'
- // flag. The control flow has been linearized and the GEP is no longer
- // guarded by the predicate, which could make the 'inbounds' properties to
- // no longer hold.
- bool IsInBounds =
- GEP->isInBounds() && State.MayGeneratePoisonRecipes.count(this) == 0;
-
// Create the new GEP. Note that this GEP may be a scalar if VF == 1,
// but it should be a vector, otherwise.
auto *NewGEP = State.Builder.CreateGEP(GEP->getSourceElementType(), Ptr,
- Indices, "", IsInBounds);
+ Indices, "");
+ if (auto *I = dyn_cast<GetElementPtrInst>(NewGEP))
+ setFlags(I);
assert((State.VF.isScalar() || NewGEP->getType()->isVectorTy()) &&
"NewGEP is not a pointer vector");
State.set(this, NewGEP, Part);