-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[VPlan] Add VPInstruction::StepVector and use it in VPWidenIntOrFpInductionRecipe #129508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
68bbf28
5d307e4
83fafe3
2b7ee27
e73e994
c7d9d75
6759922
9937480
6626037
e994900
c2d8fb8
8201fa2
f813502
912883b
4158c96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -902,6 +902,8 @@ class VPInstruction : public VPRecipeWithIRFlags, | |
| /// Scale the first operand (vector step) by the second operand | ||
| /// (scalar-step). Casts both operands to the result type if needed. | ||
| WideIVStep, | ||
| // Creates a step vector starting from 0 to VF with a step of 1. | ||
| StepVector, | ||
|
|
||
| }; | ||
|
|
||
|
|
@@ -1072,7 +1074,15 @@ class VPInstructionWithType : public VPInstruction { | |
| if (R->isScalarCast()) | ||
| return true; | ||
| auto *VPI = dyn_cast<VPInstruction>(R); | ||
| return VPI && VPI->getOpcode() == VPInstruction::WideIVStep; | ||
| if (!VPI) | ||
| return false; | ||
| switch (VPI->getOpcode()) { | ||
| case VPInstruction::WideIVStep: | ||
lukel97 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| case VPInstruction::StepVector: | ||
| return true; | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| static inline bool classof(const VPUser *R) { | ||
|
|
@@ -1869,7 +1879,7 @@ class VPWidenIntOrFpInductionRecipe : public VPWidenInductionRecipe { | |
| TruncInst *Trunc; | ||
|
|
||
| // If this recipe is unrolled it will have 2 additional operands. | ||
| bool isUnrolled() const { return getNumOperands() == 5; } | ||
| bool isUnrolled() const { return getNumOperands() == 6; } | ||
|
|
||
| public: | ||
| VPWidenIntOrFpInductionRecipe(PHINode *IV, VPValue *Start, VPValue *Step, | ||
|
|
@@ -1918,6 +1928,18 @@ class VPWidenIntOrFpInductionRecipe : public VPWidenInductionRecipe { | |
| VPValue *getVFValue() { return getOperand(2); } | ||
| const VPValue *getVFValue() const { return getOperand(2); } | ||
|
|
||
| // TODO: Remove once VPWidenIntOrFpInduction is fully expanded in | ||
| // convertToConcreteRecipes. | ||
| VPValue *getStepVector() { return getOperand(3); } | ||
|
||
| const VPValue *getStepVector() const { return getOperand(3); } | ||
|
||
| void setStepVector(VPValue *V) { | ||
| assert(cast<VPInstructionWithType>(getStepVector()->getDefiningRecipe()) | ||
| ->getOpcode() == VPInstruction::StepVector && | ||
| cast<VPInstructionWithType>(V->getDefiningRecipe())->getOpcode() == | ||
| VPInstruction::StepVector); | ||
| setOperand(3, V); | ||
| } | ||
|
|
||
| VPValue *getSplatVFValue() { | ||
| // If the recipe has been unrolled return the VPValue for the induction | ||
| // increment. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -934,6 +934,7 @@ bool VPInstruction::opcodeMayReadOrWriteFromMemory() const { | |
| case VPInstruction::Not: | ||
| case VPInstruction::PtrAdd: | ||
| case VPInstruction::WideIVStep: | ||
| case VPInstruction::StepVector: | ||
| return false; | ||
| default: | ||
| return true; | ||
|
|
@@ -1085,8 +1086,6 @@ void VPInstruction::print(raw_ostream &O, const Twine &Indent, | |
|
|
||
| void VPInstructionWithType::execute(VPTransformState &State) { | ||
| State.setDebugLocFrom(getDebugLoc()); | ||
| assert(vputils::onlyFirstLaneUsed(this) && | ||
| "Codegen only implemented for first lane."); | ||
| switch (getOpcode()) { | ||
| case Instruction::ZExt: | ||
| case Instruction::Trunc: { | ||
|
|
@@ -1096,6 +1095,12 @@ void VPInstructionWithType::execute(VPTransformState &State) { | |
| State.set(this, Cast, VPLane(0)); | ||
| break; | ||
| } | ||
| case VPInstruction::StepVector: { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to add this to VPInstruction::computeCost?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's currently costed as zero for now since we don't want to change the overall cost of VPWidenIntOrFpInductionRecipe. Once we expand VPWidenIntOrFpInductionRecipe in #118638 I think it should be safe to add a cost to it then? Since the expansion will happen just before execution, after any costing. |
||
| Value *StepVector = | ||
| State.Builder.CreateStepVector(VectorType::get(ResultTy, State.VF)); | ||
| State.set(this, StepVector); | ||
| break; | ||
| } | ||
| default: | ||
| llvm_unreachable("opcode not implemented yet"); | ||
| } | ||
|
|
@@ -1113,6 +1118,9 @@ void VPInstructionWithType::print(raw_ostream &O, const Twine &Indent, | |
| O << "wide-iv-step "; | ||
| printOperands(O, SlotTracker); | ||
| break; | ||
| case VPInstruction::StepVector: | ||
| O << "step-vector " << *ResultTy; | ||
| break; | ||
| default: | ||
| assert(Instruction::isCast(getOpcode()) && "unhandled opcode"); | ||
| O << Instruction::getOpcodeName(getOpcode()) << " "; | ||
|
|
@@ -1880,7 +1888,8 @@ InstructionCost VPHeaderPHIRecipe::computeCost(ElementCount VF, | |
| /// (0 * Step, 1 * Step, 2 * Step, ...) | ||
| /// to each vector element of Val. | ||
| /// \p Opcode is relevant for FP induction variable. | ||
| static Value *getStepVector(Value *Val, Value *Step, | ||
| /// \p InitVec is an integer step vector from 0 with a step of 1. | ||
| static Value *getStepVector(Value *Val, Value *Step, Value *InitVec, | ||
| Instruction::BinaryOps BinOp, ElementCount VF, | ||
| IRBuilderBase &Builder) { | ||
| assert(VF.isVector() && "only vector VFs are supported"); | ||
|
|
@@ -1894,15 +1903,6 @@ static Value *getStepVector(Value *Val, Value *Step, | |
| "Induction Step must be an integer or FP"); | ||
| assert(Step->getType() == STy && "Step has wrong type"); | ||
|
|
||
| // Create a vector of consecutive numbers from zero to VF. | ||
| VectorType *InitVecValVTy = ValVTy; | ||
| if (STy->isFloatingPointTy()) { | ||
| Type *InitVecValSTy = | ||
| IntegerType::get(STy->getContext(), STy->getScalarSizeInBits()); | ||
| InitVecValVTy = VectorType::get(InitVecValSTy, VLen); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps we should assert that
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They might not always have the same type as step might be a float or an integer, whereas InitVec is always an integer. Hopefully the calls to |
||
| } | ||
| Value *InitVec = Builder.CreateStepVector(InitVecValVTy); | ||
|
|
||
| if (STy->isIntegerTy()) { | ||
| Step = Builder.CreateVectorSplat(VLen, Step); | ||
| assert(Step->getType() == Val->getType() && "Invalid step vec"); | ||
|
|
@@ -1969,8 +1969,12 @@ void VPWidenIntOrFpInductionRecipe::execute(VPTransformState &State) { | |
| } | ||
|
|
||
| Value *SplatStart = Builder.CreateVectorSplat(State.VF, Start); | ||
| Value *SteppedStart = getStepVector(SplatStart, Step, ID.getInductionOpcode(), | ||
| State.VF, State.Builder); | ||
| assert(cast<VPInstruction>(getStepVector())->getOpcode() == | ||
|
||
| VPInstruction::StepVector && | ||
| "step vector operand must be a VPInstruction::StepVector"); | ||
| Value *SteppedStart = | ||
| ::getStepVector(SplatStart, Step, State.get(getStepVector()), | ||
| ID.getInductionOpcode(), State.VF, State.Builder); | ||
|
|
||
| // We create vector phi nodes for both integer and floating-point induction | ||
| // variables. Here, we determine the kind of arithmetic we will perform. | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -1223,6 +1223,15 @@ static bool optimizeVectorInductionWidthForTCAndVFUF(VPlan &Plan, | |||||
| WideIV->setStartValue(NewStart); | ||||||
| auto *NewStep = Plan.getOrAddLiveIn(ConstantInt::get(NewIVTy, 1)); | ||||||
| WideIV->setStepValue(NewStep); | ||||||
| // TODO: Remove once VPWidenIntOrFpInductionRecipe is fully expanded. | ||||||
| auto *OldStepVector = cast<VPInstructionWithType>( | ||||||
| WideIV->getStepVector()->getDefiningRecipe()); | ||||||
| assert(OldStepVector->getOpcode() == VPInstruction::StepVector); | ||||||
| auto *NewStepVector = new VPInstructionWithType( | ||||||
| VPInstruction::StepVector, {}, NewIVTy, OldStepVector->getDebugLoc()); | ||||||
| NewStepVector->insertAfter(WideIV->getStepVector()->getDefiningRecipe()); | ||||||
| WideIV->setStepVector(NewStepVector); | ||||||
|
||||||
| OldStepVector->eraseFromParent(); | ||||||
|
|
||||||
| auto *NewBTC = new VPWidenCastRecipe( | ||||||
| Instruction::Trunc, Plan.getOrCreateBackedgeTakenCount(), NewIVTy); | ||||||
|
|
@@ -2586,6 +2595,29 @@ void VPlanTransforms::handleUncountableEarlyExit( | |||||
| LatchExitingBranch->eraseFromParent(); | ||||||
| } | ||||||
|
|
||||||
| void VPlanTransforms::materializeStepVectors(VPlan &Plan) { | ||||||
| for (auto &Phi : Plan.getVectorLoopRegion()->getEntryBasicBlock()->phis()) { | ||||||
| auto *IVR = dyn_cast<VPWidenIntOrFpInductionRecipe>(&Phi); | ||||||
| if (!IVR) | ||||||
| continue; | ||||||
|
|
||||||
| // Infer an up-to-date type since | ||||||
| // optimizeVectorInductionWidthForTCAndVFUF may have truncated the start | ||||||
| // and step values. | ||||||
| Type *Ty = IVR->getPHINode()->getType(); | ||||||
| if (TruncInst *Trunc = IVR->getTruncInst()) | ||||||
| Ty = Trunc->getType(); | ||||||
| if (Ty->isFloatingPointTy()) | ||||||
| Ty = IntegerType::get(Ty->getContext(), Ty->getScalarSizeInBits()); | ||||||
|
||||||
|
|
||||||
| VPBuilder Builder(Plan.getVectorPreheader()); | ||||||
| VPInstruction *StepVector = Builder.createNaryOp( | ||||||
| VPInstruction::StepVector, {}, Ty, {}, IVR->getDebugLoc()); | ||||||
| assert(IVR->getNumOperands() == 3); | ||||||
|
||||||
| assert(IVR->getNumOperands() == 3); | |
| assert(IVR->getNumOperands() == 3 && "can only add step vector before unrolling"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this empty file was added by accident? please remove before landing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woops, will remove. This sometimes gets left around when calling update_test_checks.py on files that check the stderr output, e.g.
; RUN: opt -S < %s -p loop-vectorize -debug-only=loop-vectorize -mattr=+sve 2>%t. Not sure if UTC could be taught to redirect that