diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -735,6 +735,26 @@ return Opcode == Instruction::Store || Opcode == Instruction::Call || Opcode == Instruction::Invoke || Opcode == SLPStore; } + + bool hasResult() const { + // CallInst may or may not have a result, depending on the called function. + // Conservatively return calls have results for now. + switch (getOpcode()) { + case Instruction::Ret: + case Instruction::Br: + case Instruction::Store: + case Instruction::Switch: + case Instruction::IndirectBr: + case Instruction::Resume: + case Instruction::CatchRet: + case Instruction::Unreachable: + case Instruction::Fence: + case Instruction::AtomicRMW: + return false; + default: + return true; + } + } }; /// VPWidenRecipe is a recipe for producing a copy of vector type for each diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp --- a/llvm/lib/Transforms/Vectorize/VPlan.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp @@ -404,8 +404,10 @@ } void VPInstruction::print(raw_ostream &O, VPSlotTracker &SlotTracker) const { - printAsOperand(O, SlotTracker); - O << " = "; + if (hasResult()) { + printAsOperand(O, SlotTracker); + O << " = "; + } switch (getOpcode()) { case VPInstruction::Not: @@ -814,11 +816,18 @@ } void VPValue::printAsOperand(raw_ostream &OS, VPSlotTracker &Tracker) const { + if (const Value *UV = getUnderlyingValue()) { + OS << "ir<"; + UV->printAsOperand(OS, false); + OS << ">"; + return; + } + unsigned Slot = Tracker.getSlot(this); if (Slot == unsigned(-1)) OS << ""; else - OS << "%vp" << Tracker.getSlot(this); + OS << "vp<%" << Tracker.getSlot(this) << ">"; } void VPInterleavedAccessInfo::visitRegion(VPRegionBlock *Region, @@ -869,6 +878,13 @@ void VPSlotTracker::assignSlot(const VPValue *V) { assert(Slots.find(V) == Slots.end() && "VPValue already has a slot!"); + const Value *UV = V->getUnderlyingValue(); + if (UV) + return; + const auto *VPI = dyn_cast(V); + if (VPI && !VPI->hasResult()) + return; + Slots[V] = NextSlot++; } diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h --- a/llvm/lib/Transforms/Vectorize/VPlanValue.h +++ b/llvm/lib/Transforms/Vectorize/VPlanValue.h @@ -42,6 +42,7 @@ friend class VPlanTransforms; friend class VPBasicBlock; friend class VPInterleavedAccessInfo; + friend class VPSlotTracker; private: const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast). @@ -64,6 +65,7 @@ /// Return the underlying Value attached to this VPValue. Value *getUnderlyingValue() { return UnderlyingVal; } + const Value *getUnderlyingValue() const { return UnderlyingVal; } // Set \p Val as the underlying Value of this VPValue. void setUnderlyingValue(Value *Val) { diff --git a/llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp --- a/llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp @@ -10,6 +10,7 @@ #include "../lib/Transforms/Vectorize/VPlanTransforms.h" #include "VPlanTestBase.h" #include "gtest/gtest.h" +#include namespace llvm { namespace { @@ -88,6 +89,42 @@ EXPECT_EQ(IndvarAdd, ICmp->getOperand(0)); EXPECT_EQ(VecBB->getCondBit(), ICmp); + std::string FullDump; + raw_string_ostream(FullDump) << *Plan; + EXPECT_EQ(R"(digraph VPlan { +graph [labelloc=t, fontsize=30; label="Vectorization Plan"] +node [shape=rect, fontname=Courier, fontsize=30] +edge [fontname=Courier, fontsize=30] +compound=true + subgraph cluster_N0 { + fontname=Courier + label="\ TopRegion" + N1 [label = + "entry:\n" + ] + N1 -> N2 [ label=""] + N2 [label = + "for.body:\n" + + "EMIT ir<%indvars.iv> = phi ir<0> ir<%indvars.iv.next>\l" + + "EMIT ir<%arr.idx> = getelementptr ir<%A> ir<%indvars.iv>\l" + + "EMIT ir<%l1> = load ir<%arr.idx>\l" + + "EMIT ir<%res> = add ir<%l1> ir<10>\l" + + "EMIT store ir<%res> ir<%arr.idx>\l" + + "EMIT ir<%indvars.iv.next> = add ir<%indvars.iv> ir<1>\l" + + "EMIT ir<%exitcond> = icmp ir<%indvars.iv.next> ir<%N>\l" + + "CondBit: ir<%exitcond> (for.body)\l" + ] + N2 -> N2 [ label="T"] + N2 -> N3 [ label="F"] + N3 [label = + "for.end:\n" + + "EMIT ret\l" + ] + } +} +)", + FullDump); + LoopVectorizationLegality::InductionList Inductions; SmallPtrSet DeadInstructions; VPlanTransforms::VPInstructionsToVPRecipes(LI->getLoopFor(LoopHeader), Plan, diff --git a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp --- a/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp +++ b/llvm/unittests/Transforms/Vectorize/VPlanTest.cpp @@ -178,17 +178,17 @@ } TEST(VPBasicBlockTest, print) { - VPInstruction *I1 = new VPInstruction(10, {}); - VPInstruction *I2 = new VPInstruction(1, {I1}); - VPInstruction *I3 = new VPInstruction(2, {I1, I2}); + VPInstruction *I1 = new VPInstruction(Instruction::Add, {}); + VPInstruction *I2 = new VPInstruction(Instruction::Sub, {I1}); + VPInstruction *I3 = new VPInstruction(Instruction::Br, {I1, I2}); VPBasicBlock *VPBB1 = new VPBasicBlock(); VPBB1->appendRecipe(I1); VPBB1->appendRecipe(I2); VPBB1->appendRecipe(I3); - VPInstruction *I4 = new VPInstruction(4, {I3, I2}); - VPInstruction *I5 = new VPInstruction(5, {I1}); + VPInstruction *I4 = new VPInstruction(Instruction::Mul, {I2, I1}); + VPInstruction *I5 = new VPInstruction(Instruction::Ret, {I4}); VPBasicBlock *VPBB2 = new VPBasicBlock(); VPBB2->appendRecipe(I4); VPBB2->appendRecipe(I5); @@ -201,7 +201,7 @@ raw_string_ostream OS(I3Dump); I3->print(OS); OS.flush(); - EXPECT_EQ(" = br ", I3Dump); + EXPECT_EQ("br ", I3Dump); } VPlan Plan; @@ -216,15 +216,15 @@ compound=true N0 [label = ":\n" + - "EMIT %vp0 = catchswitch\l" + - "EMIT %vp1 = ret %vp0\l" + - "EMIT %vp2 = br %vp0 %vp1\l" + "EMIT vp<%0> = add\l" + + "EMIT vp<%1> = sub vp<%0>\l" + + "EMIT br vp<%0> vp<%1>\l" ] N0 -> N1 [ label=""] N1 [label = ":\n" + - "EMIT %vp3 = indirectbr %vp2 %vp1\l" + - "EMIT %vp4 = invoke %vp0\l" + "EMIT vp<%2> = mul vp<%1> vp<%0>\l" + + "EMIT ret vp<%2>\l" ] } )", @@ -235,15 +235,15 @@ raw_string_ostream OS(I3Dump); I3->print(OS); OS.flush(); - EXPECT_EQ("%vp2 = br %vp0 %vp1", I3Dump); + EXPECT_EQ("br vp<%0> vp<%1>", I3Dump); } { - std::string I2Dump; - raw_string_ostream OS(I2Dump); - OS << *I2; + std::string I4Dump; + raw_string_ostream OS(I4Dump); + OS << *I4; OS.flush(); - EXPECT_EQ("%vp1 = ret %vp0", I2Dump); + EXPECT_EQ("vp<%2> = mul vp<%1> vp<%0>", I4Dump); } }