assert(Instr->getParent() && "Predicated instruction not in any basic block");
auto *BOMRecipe = new VPBranchOnMaskRecipe(BlockInMask);
auto *Entry = new VPBasicBlock(Twine(RegionName) + ".entry", BOMRecipe);
- auto *PHIRecipe =
- Instr->getType()->isVoidTy() ? nullptr : new VPPredInstPHIRecipe(Instr);
+ auto *PHIRecipe = Instr->getType()->isVoidTy()
+ ? nullptr
+ : new VPPredInstPHIRecipe(Plan->getOrAddVPValue(Instr));
auto *Exit = new VPBasicBlock(Twine(RegionName) + ".continue", PHIRecipe);
auto *Pred = new VPBasicBlock(Twine(RegionName) + ".if", PredRecipe);
VPRegionBlock *Region = new VPRegionBlock(Entry, Exit, RegionName, true);
void VPPredInstPHIRecipe::execute(VPTransformState &State) {
assert(State.Instance && "Predicated instruction PHI works per instance.");
- Instruction *ScalarPredInst = cast<Instruction>(
- State.ValueMap.getScalarValue(PredInst, *State.Instance));
+ Instruction *ScalarPredInst =
+ cast<Instruction>(State.get(getOperand(0), *State.Instance));
BasicBlock *PredicatedBB = ScalarPredInst->getParent();
BasicBlock *PredicatingBB = PredicatedBB->getSinglePredecessor();
assert(PredicatingBB && "Predicated block has no single predecessor.");
// also do that packing, thereby "hoisting" the insert-element sequence.
// Otherwise, a phi node for the scalar value is needed.
unsigned Part = State.Instance->Part;
+ Instruction *PredInst =
+ cast<Instruction>(getOperand(0)->getUnderlyingValue());
if (State.ValueMap.hasVectorValue(PredInst, Part)) {
Value *VectorValue = State.ValueMap.getVectorValue(PredInst, Part);
InsertElementInst *IEI = cast<InsertElementInst>(VectorValue);
return U;
if (auto *U = dyn_cast<VPReductionRecipe>(this))
return U;
+ if (auto *U = dyn_cast<VPPredInstPHIRecipe>(this))
+ return U;
return nullptr;
}
void VPPredInstPHIRecipe::print(raw_ostream &O, const Twine &Indent,
VPSlotTracker &SlotTracker) const {
- O << "\"PHI-PREDICATED-INSTRUCTION " << VPlanIngredient(PredInst);
+ O << "\"PHI-PREDICATED-INSTRUCTION ";
+ printOperands(O, SlotTracker);
}
void VPWidenMemoryInstructionRecipe::print(raw_ostream &O, const Twine &Indent,
/// order to merge values that are set under such a branch and feed their uses.
/// The phi nodes can be scalar or vector depending on the users of the value.
/// This recipe works in concert with VPBranchOnMaskRecipe.
-class VPPredInstPHIRecipe : public VPRecipeBase {
- Instruction *PredInst;
+class VPPredInstPHIRecipe : public VPRecipeBase, public VPUser {
public:
/// Construct a VPPredInstPHIRecipe given \p PredInst whose value needs a phi
/// nodes after merging back from a Branch-on-Mask.
- VPPredInstPHIRecipe(Instruction *PredInst)
- : VPRecipeBase(VPPredInstPHISC), PredInst(PredInst) {}
+ VPPredInstPHIRecipe(VPValue *PredV)
+ : VPRecipeBase(VPPredInstPHISC), VPUser(PredV) {}
~VPPredInstPHIRecipe() override = default;
/// Method to support type inquiry through isa, cast, and dyn_cast.
class VPSlotTracker;
class VPUser;
class VPRecipeBase;
+class VPPredInstPHIRecipe;
// This is the base class of the VPlan Def/Use graph, used for modeling the data
// flow into, within and out of the VPlan. VPValues can stand for live-ins
friend class VPInterleavedAccessInfo;
friend class VPSlotTracker;
friend class VPRecipeBase;
+ friend class VPPredInstPHIRecipe;
const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast).
ret float %red.next
}
+define void @print_replicate_predicated_phi(i64 %n, i64* %x) {
+; CHECK: N0 [label =
+; CHECK-NEXT: "for.body:\n" +
+; CHECK-NEXT: "WIDEN-INDUCTION %i = phi 0, %i.next\l" +
+; CHECK-NEXT: "WIDEN ir<%cmp> = icmp ir<%i>, ir<5>\l"
+; CHECK-NEXT: ]
+;
+; CHECK: N2 [label =
+; CHECK-NEXT: "pred.udiv.entry:\n" +
+; CHECK-NEXT: +
+; CHECK-NEXT: "BRANCH-ON-MASK ir<%cmp>\l"\l
+; CHECK-NEXT: "CondBit: ir<%cmp>"
+; CHECK-NEXT: ]
+;
+; CHECK: N4 [label =
+; CHECK-NEXT: "pred.udiv.if:\n" +
+; CHECK-NEXT: "REPLICATE ir<%tmp4> = udiv ir<%n>, ir<%i> (S->V)\l"
+; CHECK-NEXT: ]
+;
+; CHECK: N5 [label =
+; CHECK-NEXT: "pred.udiv.continue:\n" +
+; CHECK-NEXT: "PHI-PREDICATED-INSTRUCTION ir<%tmp4>\l"
+; CHECK-NEXT: ]
+;
+; CHECK: N7 [label =
+; CHECK-NEXT: "for.inc:\n" +
+; CHECK-NEXT: "EMIT vp<%0> = not ir<%cmp>\l" +
+; CHECK-NEXT: "BLEND %d = ir<0>/vp<%0> ir<%tmp4>/ir<%cmp>\l" +
+; CHECK-NEXT: "CLONE ir<%idx> = getelementptr ir<%x>, ir<%i>\l" +
+; CHECK-NEXT: "WIDEN store ir<%idx>, ir<%d>\l"
+; CHECK-NEXT: ]
+;
+entry:
+ br label %for.body
+
+for.body: ; preds = %for.inc, %entry
+ %i = phi i64 [ 0, %entry ], [ %i.next, %for.inc ]
+ %cmp = icmp ult i64 %i, 5
+ br i1 %cmp, label %if.then, label %for.inc
+
+if.then: ; preds = %for.body
+ %tmp4 = udiv i64 %n, %i
+ br label %for.inc
+
+for.inc: ; preds = %if.then, %for.body
+ %d = phi i64 [ 0, %for.body ], [ %tmp4, %if.then ]
+ %idx = getelementptr i64, i64* %x, i64 %i
+ store i64 %d, i64* %idx
+ %i.next = add nuw nsw i64 %i, 1
+ %cond = icmp slt i64 %i.next, %n
+ br i1 %cond, label %for.body, label %for.end
+
+for.end: ; preds = %for.inc
+ ret void
+}
+
declare float @llvm.sqrt.f32(float) nounwind readnone