BasicBlock *createVectorizedLoopSkeleton();
/// Widen a single instruction within the innermost loop.
- void widenInstruction(Instruction &I);
+ void widenInstruction(Instruction &I, VPUser &Operands,
+ VPTransformState &State);
/// Widen a single call instruction within the innermost loop.
void widenCallInstruction(CallInst &I, VPUser &ArgOperands,
return !CInt || CInt->isZero();
}
-void InnerLoopVectorizer::widenInstruction(Instruction &I) {
+void InnerLoopVectorizer::widenInstruction(Instruction &I, VPUser &User,
+ VPTransformState &State) {
switch (I.getOpcode()) {
case Instruction::Call:
case Instruction::Br:
for (unsigned Part = 0; Part < UF; ++Part) {
SmallVector<Value *, 2> Ops;
- for (Value *Op : I.operands())
- Ops.push_back(getOrCreateVectorValue(Op, Part));
+ for (VPValue *VPOp : User.operands())
+ Ops.push_back(State.get(VPOp, Part));
Value *V = Builder.CreateNAryOp(I.getOpcode(), Ops);
auto *Cmp = cast<CmpInst>(&I);
setDebugLocFromInst(Builder, Cmp);
for (unsigned Part = 0; Part < UF; ++Part) {
- Value *A = getOrCreateVectorValue(Cmp->getOperand(0), Part);
- Value *B = getOrCreateVectorValue(Cmp->getOperand(1), Part);
+ Value *A = State.get(User.getOperand(0), Part);
+ Value *B = State.get(User.getOperand(1), Part);
Value *C = nullptr;
if (FCmp) {
// Propagate fast math flags.
(VF == 1) ? CI->getType() : VectorType::get(CI->getType(), VF);
for (unsigned Part = 0; Part < UF; ++Part) {
- Value *A = getOrCreateVectorValue(CI->getOperand(0), Part);
+ Value *A = State.get(User.getOperand(0), Part);
Value *Cast = Builder.CreateCast(CI->getOpcode(), A, DestTy);
VectorLoopValueMap.setVectorValue(&I, Part, Cast);
addMetadata(Cast, &I);
if (!LoopVectorizationPlanner::getDecisionAndClampRange(willWiden, Range))
return nullptr;
- // Success: widen this call.
- auto VPValues = map_range(CI->arg_operands(), [&Plan](Value *Op) {
- return Plan.getOrAddVPValue(Op);
- });
-
- return new VPWidenCallRecipe(*CI, VPValues);
+ return new VPWidenCallRecipe(*CI, Plan.mapToVPValues(CI->arg_operands()));
}
bool VPRecipeBuilder::shouldWiden(Instruction *I, VFRange &Range) const {
return nullptr;
// Success: widen this instruction.
- return new VPWidenRecipe(*I);
+ return new VPWidenRecipe(*I, Plan.mapToVPValues(I->operands()));
}
VPBasicBlock *VPRecipeBuilder::handleReplication(
}
void VPWidenRecipe::execute(VPTransformState &State) {
- State.ILV->widenInstruction(Ingredient);
+ State.ILV->widenInstruction(Ingredient, User, State);
}
void VPWidenGEPRecipe::execute(VPTransformState &State) {
/// Hold the instruction to be widened.
Instruction &Ingredient;
+ /// Hold VPValues for the operands of the ingredient.
+ VPUser User;
+
public:
- VPWidenRecipe(Instruction &I) : VPRecipeBase(VPWidenSC), Ingredient(I) {}
+ template <typename IterT>
+ VPWidenRecipe(Instruction &I, iterator_range<IterT> Operands)
+ : VPRecipeBase(VPWidenSC), Ingredient(I), User(Operands) {}
~VPWidenRecipe() override = default;
/// Dump the plan to stderr (for debugging).
void dump() const;
+ /// Returns a range mapping the values the range \p Operands to their
+ /// corresponding VPValues.
+ iterator_range<mapped_iterator<Use *, std::function<VPValue *(Value *)>>>
+ mapToVPValues(User::op_range Operands) {
+ std::function<VPValue *(Value *)> Fn = [this](Value *Op) {
+ return getOrAddVPValue(Op);
+ };
+ return map_range(Operands, Fn);
+ }
+
private:
/// Add to the given dominator tree the header block and every new basic block
/// that was created between it and the latch block, inclusive.
%tmp4 = phi i32 [ %tmp3, %for.body ]
ret i32 %tmp4
}
+
+; Check for crash exposed by D76992.
+; CHECK: N0 [label =
+; CHECK-NEXT: "loop:\n" +
+; CHECK-NEXT: "WIDEN-INDUCTION %iv = phi 0, %iv.next\l" +
+; CHECK-NEXT: "WIDEN\l"" %cond0 = icmp %iv, 13\l" +
+; CHECK-NEXT: "WIDEN-SELECT%s = select %cond0, 10, 20\l" +
+; CHECK-NEXT: "EMIT vp<%1> = icmp ule ir<%iv> vp<%0>\l"
+; CHECK-NEXT: ]
+define void @test() {
+entry:
+ br label %loop
+
+loop: ; preds = %loop, %entry
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %cond0 = icmp ult i64 %iv, 13
+ %s = select i1 %cond0, i32 10, i32 20
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond = icmp eq i64 %iv.next, 14
+ br i1 %exitcond, label %exit, label %loop
+
+exit: ; preds = %loop
+ ret void
+}