diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index fc0680c8fac3c..365ac7561255b 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -2687,11 +2687,8 @@ void InnerLoopVectorizer::fixNonInductionPHIs(VPTransformState &State) { PHINode *NewPhi = cast(State.get(VPPhi)); // Make sure the builder has a valid insert point. Builder.SetInsertPoint(NewPhi); - for (unsigned Idx = 0; Idx < VPPhi->getNumIncoming(); ++Idx) { - VPValue *Inc = VPPhi->getIncomingValue(Idx); - const VPBasicBlock *VPBB = VPPhi->getIncomingBlock(Idx); + for (const auto &[Inc, VPBB] : VPPhi->incoming_values_and_blocks()) NewPhi->addIncoming(State.get(Inc), State.CFG.VPBB2IRBB[VPBB]); - } } } } diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 5c3edee13020f..e13a9181e4daf 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -1230,6 +1230,31 @@ class VPPhiAccessors { return getAsRecipe()->getNumOperands(); } + /// Returns an interator range over the incoming values. + VPUser::const_operand_range incoming_values() const { + return make_range(getAsRecipe()->op_begin(), + getAsRecipe()->op_begin() + getNumIncoming()); + } + + using const_incoming_blocks_range = iterator_range>>; + + /// Returns an iterator range over the incoming blocks. + const_incoming_blocks_range incoming_blocks() const { + std::function GetBlock = [this](size_t Idx) { + return getIncomingBlock(Idx); + }; + return map_range(index_range(0, getNumIncoming()), GetBlock); + } + + /// Returns an iterator range over pairs of incoming values and corresponding + /// incoming blocks. + detail::zippy + incoming_values_and_blocks() const { + return zip_equal(incoming_values(), incoming_blocks()); + } + /// Removes the incoming value for \p IncomingBlock, which must be a /// predecessor. void removeIncomingValueFor(VPBlockBase *IncomingBlock) const; @@ -2301,6 +2326,11 @@ class VPReductionPHIRecipe : public VPHeaderPHIRecipe, VPSlotTracker &SlotTracker) const override; #endif + /// Returns the number of incoming values, also number of incoming blocks. + /// Note that at the moment, VPWidenPointerInductionRecipe only has a single + /// incoming value, its start value. + unsigned getNumIncoming() const override { return 2; } + /// Returns the recurrence kind of the reduction. RecurKind getRecurrenceKind() const { return Kind; } diff --git a/llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp b/llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp index 862b9301e8ca5..cdadc33e3088e 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp @@ -238,14 +238,11 @@ void VPPredicator::convertPhisToBlends(VPBasicBlock *VPBB) { // optimizations will clean it up. SmallVector OperandsWithMask; - unsigned NumIncoming = PhiR->getNumIncoming(); - for (unsigned In = 0; In < NumIncoming; In++) { - const VPBasicBlock *Pred = PhiR->getIncomingBlock(In); - OperandsWithMask.push_back(PhiR->getIncomingValue(In)); - VPValue *EdgeMask = getEdgeMask(Pred, VPBB); + for (const auto &[InVPV, InVPBB] : PhiR->incoming_values_and_blocks()) { + OperandsWithMask.push_back(InVPV); + VPValue *EdgeMask = getEdgeMask(InVPBB, VPBB); if (!EdgeMask) { - assert(In == 0 && "Both null and non-null edge masks found"); - assert(all_equal(PhiR->operands()) && + assert(all_equal(PhiR->incoming_values()) && "Distinct incoming values with one having a full mask"); break; } diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index e34cab117f321..56be0c18bb88a 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -1444,12 +1444,12 @@ void VPIRPhi::print(raw_ostream &O, const Twine &Indent, if (getNumOperands() != 0) { O << " (extra operand" << (getNumOperands() > 1 ? "s" : "") << ": "; - interleaveComma( - enumerate(operands()), O, [this, &O, &SlotTracker](auto Op) { - Op.value()->printAsOperand(O, SlotTracker); - O << " from "; - getParent()->getPredecessors()[Op.index()]->printAsOperand(O); - }); + interleaveComma(incoming_values_and_blocks(), O, + [&O, &SlotTracker](auto Op) { + std::get<0>(Op)->printAsOperand(O, SlotTracker); + O << " from "; + std::get<1>(Op)->printAsOperand(O); + }); O << ")"; } } diff --git a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp index 3417e1c8dc1ea..ef9ea73ba994e 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanVerifier.cpp @@ -250,17 +250,15 @@ bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) { for (const VPUser *U : V->users()) { auto *UI = cast(U); if (auto *Phi = dyn_cast(UI)) { - for (unsigned Idx = 0; Idx != Phi->getNumIncoming(); ++Idx) { - VPValue *IncomingVPV = Phi->getIncomingValue(Idx); + for (const auto &[IncomingVPV, IncomingVPBB] : + Phi->incoming_values_and_blocks()) { if (IncomingVPV != V) continue; - const VPBasicBlock *IncomingVPBB = Phi->getIncomingBlock(Idx); if (VPDT.dominates(VPBB, IncomingVPBB)) continue; - errs() << "Incoming def at index " << Idx - << " does not dominate incoming block!\n"; + errs() << "Incoming def does not dominate incoming block!\n"; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) VPSlotTracker Tracker(VPBB->getPlan()); IncomingVPV->getDefiningRecipe()->print(errs(), " ", Tracker); diff --git a/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp index b698b287178f7..c2f045bf524e9 100644 --- a/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPlanVerifierTest.cpp @@ -170,15 +170,14 @@ TEST_F(VPVerifierTest, VPPhiIncomingValueDoesntDominateIncomingBlock) { EXPECT_FALSE(verifyVPlanIsValid(Plan)); #if GTEST_HAS_STREAM_REDIRECTION #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - EXPECT_STREQ("Incoming def at index 0 does not dominate incoming block!\n" + EXPECT_STREQ("Incoming def does not dominate incoming block!\n" " EMIT vp<%2> = add ir<0>\n" " does not dominate preheader for\n" " EMIT-SCALAR vp<%1> = phi [ vp<%2>, preheader ]", ::testing::internal::GetCapturedStderr().c_str()); #else - EXPECT_STREQ("Incoming def at index 0 does not dominate incoming block!\n", :: - testing::internal::GetCapturedStderr() - .c_str()); + EXPECT_STREQ("Incoming def does not dominate incoming block!\n", + ::testing::internal::GetCapturedStderr().c_str()); #endif #endif }