-
Notifications
You must be signed in to change notification settings - Fork 15.5k
[VPlan] Extract reverse operation for reverse accesses #146525
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 all commits
f7ce0a3
69d8820
1b31f74
63ab793
f66fcea
c276d02
b451dc7
033b703
1bcfc52
1b1deb7
2dd5a2f
590ad95
c4feade
e7af9d5
398854c
82460e9
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 |
|---|---|---|
|
|
@@ -444,6 +444,7 @@ unsigned VPInstruction::getNumOperandsForOpcode(unsigned Opcode) { | |
| case VPInstruction::ExtractPenultimateElement: | ||
| case VPInstruction::Not: | ||
| case VPInstruction::ResumeForEpilogue: | ||
| case VPInstruction::Reverse: | ||
| case VPInstruction::Unpack: | ||
| return 1; | ||
| case Instruction::ICmp: | ||
|
|
@@ -901,6 +902,8 @@ Value *VPInstruction::generate(VPTransformState &State) { | |
| } | ||
| case VPInstruction::ResumeForEpilogue: | ||
| return State.get(getOperand(0), true); | ||
| case VPInstruction::Reverse: | ||
| return Builder.CreateVectorReverse(State.get(getOperand(0)), "reverse"); | ||
| default: | ||
| llvm_unreachable("Unsupported opcode for instruction"); | ||
| } | ||
|
|
@@ -1087,6 +1090,14 @@ InstructionCost VPInstruction::computeCost(ElementCount VF, | |
| I32Ty, {Arg0Ty, I32Ty, I1Ty}); | ||
| return Ctx.TTI.getIntrinsicInstrCost(Attrs, Ctx.CostKind); | ||
| } | ||
| case VPInstruction::Reverse: { | ||
| assert(VF.isVector() && "Reverse operation must be vector type"); | ||
| auto *VectorTy = cast<VectorType>( | ||
| toVectorTy(Ctx.Types.inferScalarType(getOperand(0)), VF)); | ||
| return Ctx.TTI.getShuffleCost(TargetTransformInfo::SK_Reverse, VectorTy, | ||
| VectorTy, /*Mask=*/{}, Ctx.CostKind, | ||
| /*Index=*/0); | ||
| } | ||
| case VPInstruction::ExtractLastLane: { | ||
| // Add on the cost of extracting the element. | ||
| auto *VecTy = toVectorTy(Ctx.Types.inferScalarType(getOperand(0)), VF); | ||
|
|
@@ -1189,6 +1200,7 @@ bool VPInstruction::opcodeMayReadOrWriteFromMemory() const { | |
| case VPInstruction::WidePtrAdd: | ||
| case VPInstruction::StepVector: | ||
| case VPInstruction::ReductionStartVector: | ||
| case VPInstruction::Reverse: | ||
| case VPInstruction::VScale: | ||
| case VPInstruction::Unpack: | ||
| return false; | ||
|
|
@@ -1366,6 +1378,9 @@ void VPInstruction::printRecipe(raw_ostream &O, const Twine &Indent, | |
| case VPInstruction::ResumeForEpilogue: | ||
| O << "resume-for-epilogue"; | ||
| break; | ||
| case VPInstruction::Reverse: | ||
| O << "reverse"; | ||
| break; | ||
| case VPInstruction::Unpack: | ||
| O << "unpack"; | ||
| break; | ||
|
|
@@ -2244,18 +2259,32 @@ InstructionCost VPWidenCastRecipe::computeCost(ElementCount VF, | |
| VPValue *Operand = getOperand(0); | ||
| TTI::CastContextHint CCH = TTI::CastContextHint::None; | ||
| // For Trunc/FPTrunc, get the context from the only user. | ||
| if ((Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) && | ||
| !hasMoreThanOneUniqueUser() && getNumUsers() > 0) { | ||
| if (auto *StoreRecipe = dyn_cast<VPRecipeBase>(*user_begin())) | ||
| CCH = ComputeCCH(StoreRecipe); | ||
| if (Opcode == Instruction::Trunc || Opcode == Instruction::FPTrunc) { | ||
| auto GetOnlyUser = [](const VPSingleDefRecipe *R) -> VPRecipeBase * { | ||
| if (R->getNumUsers() == 0 || R->hasMoreThanOneUniqueUser()) | ||
| return nullptr; | ||
| return dyn_cast<VPRecipeBase>(*R->user_begin()); | ||
| }; | ||
|
|
||
| if (VPRecipeBase *Recipe = GetOnlyUser(this)) { | ||
| if (match(Recipe, m_Reverse(m_VPValue()))) | ||
| Recipe = GetOnlyUser(cast<VPInstruction>(Recipe)); | ||
| if (Recipe) | ||
| CCH = ComputeCCH(Recipe); | ||
| } | ||
| } | ||
| // For Z/Sext, get the context from the operand. | ||
| else if (Opcode == Instruction::ZExt || Opcode == Instruction::SExt || | ||
| Opcode == Instruction::FPExt) { | ||
|
Comment on lines
2277
to
2278
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. Not sure I understand why the code is guarded by Trunc, FPTrunc, FPExt, ZExt, or SExt opcodes?
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. This code is used to determine TTI::CastContextHint. Perhaps for other cast opcodes, there isn’t currently a situation that requires this hint. But I think that’s a separate issue. The change here is just to ensure that CastContextHint::Reversed is still correctly propagated after the reverse operation is separated out. |
||
| if (Operand->isLiveIn()) | ||
| CCH = TTI::CastContextHint::Normal; | ||
| else if (Operand->getDefiningRecipe()) | ||
| CCH = ComputeCCH(Operand->getDefiningRecipe()); | ||
| else if (auto *Recipe = Operand->getDefiningRecipe()) { | ||
| VPValue *ReverseOp; | ||
| if (match(Recipe, m_Reverse(m_VPValue(ReverseOp)))) | ||
| Recipe = ReverseOp->getDefiningRecipe(); | ||
| if (Recipe) | ||
| CCH = ComputeCCH(Recipe); | ||
| } | ||
| } | ||
|
|
||
| auto *SrcTy = | ||
|
|
@@ -3500,12 +3529,7 @@ InstructionCost VPWidenMemoryRecipe::computeCost(ElementCount VF, | |
| Cost += Ctx.TTI.getMemoryOpCost(Opcode, Ty, Alignment, AS, Ctx.CostKind, | ||
| OpInfo, &Ingredient); | ||
| } | ||
| if (!Reverse) | ||
| return Cost; | ||
|
|
||
| return Cost += Ctx.TTI.getShuffleCost( | ||
| TargetTransformInfo::SK_Reverse, cast<VectorType>(Ty), | ||
| cast<VectorType>(Ty), {}, Ctx.CostKind, 0); | ||
| return Cost; | ||
| } | ||
|
|
||
| void VPWidenLoadRecipe::execute(VPTransformState &State) { | ||
|
|
@@ -3536,8 +3560,6 @@ void VPWidenLoadRecipe::execute(VPTransformState &State) { | |
| NewLI = Builder.CreateAlignedLoad(DataTy, Addr, Alignment, "wide.load"); | ||
| } | ||
| applyMetadata(*cast<Instruction>(NewLI)); | ||
| if (Reverse) | ||
| NewLI = Builder.CreateVectorReverse(NewLI, "reverse"); | ||
| State.set(this, NewLI); | ||
| } | ||
|
|
||
|
|
@@ -3592,8 +3614,6 @@ void VPWidenLoadEVLRecipe::execute(VPTransformState &State) { | |
| 0, Attribute::getWithAlignment(NewLI->getContext(), Alignment)); | ||
| applyMetadata(*NewLI); | ||
| Instruction *Res = NewLI; | ||
| if (isReverse()) | ||
| Res = createReverseEVL(Builder, Res, EVL, "vp.reverse"); | ||
| State.set(this, Res); | ||
| } | ||
|
|
||
|
|
@@ -3610,15 +3630,9 @@ InstructionCost VPWidenLoadEVLRecipe::computeCost(ElementCount VF, | |
| Type *Ty = toVectorTy(getLoadStoreType(&Ingredient), VF); | ||
| unsigned AS = cast<PointerType>(Ctx.Types.inferScalarType(getAddr())) | ||
| ->getAddressSpace(); | ||
| InstructionCost Cost = Ctx.TTI.getMemIntrinsicInstrCost( | ||
| return Ctx.TTI.getMemIntrinsicInstrCost( | ||
| MemIntrinsicCostAttributes(Intrinsic::vp_load, Ty, Alignment, AS), | ||
| Ctx.CostKind); | ||
| if (!Reverse) | ||
| return Cost; | ||
|
|
||
| return Cost + Ctx.TTI.getShuffleCost( | ||
| TargetTransformInfo::SK_Reverse, cast<VectorType>(Ty), | ||
| cast<VectorType>(Ty), {}, Ctx.CostKind, 0); | ||
| } | ||
|
|
||
| #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||
|
|
@@ -3647,13 +3661,6 @@ void VPWidenStoreRecipe::execute(VPTransformState &State) { | |
| } | ||
|
|
||
| Value *StoredVal = State.get(StoredVPValue); | ||
| if (isReverse()) { | ||
| // If we store to reverse consecutive memory locations, then we need | ||
| // to reverse the order of elements in the stored value. | ||
| StoredVal = Builder.CreateVectorReverse(StoredVal, "reverse"); | ||
| // We don't want to update the value in the map as it might be used in | ||
| // another expression. So don't call resetVectorValue(StoredVal). | ||
| } | ||
| Value *Addr = State.get(getAddr(), /*IsScalar*/ !CreateScatter); | ||
| Instruction *NewSI = nullptr; | ||
| if (CreateScatter) | ||
|
|
@@ -3682,8 +3689,6 @@ void VPWidenStoreEVLRecipe::execute(VPTransformState &State) { | |
| CallInst *NewSI = nullptr; | ||
| Value *StoredVal = State.get(StoredValue); | ||
| Value *EVL = State.get(getEVL(), VPLane(0)); | ||
| if (isReverse()) | ||
| StoredVal = createReverseEVL(Builder, StoredVal, EVL, "vp.reverse"); | ||
| Value *Mask = nullptr; | ||
| if (VPValue *VPMask = getMask()) { | ||
| Mask = State.get(VPMask); | ||
|
|
@@ -3720,15 +3725,9 @@ InstructionCost VPWidenStoreEVLRecipe::computeCost(ElementCount VF, | |
| Type *Ty = toVectorTy(getLoadStoreType(&Ingredient), VF); | ||
| unsigned AS = cast<PointerType>(Ctx.Types.inferScalarType(getAddr())) | ||
| ->getAddressSpace(); | ||
| InstructionCost Cost = Ctx.TTI.getMemIntrinsicInstrCost( | ||
| return Ctx.TTI.getMemIntrinsicInstrCost( | ||
| MemIntrinsicCostAttributes(Intrinsic::vp_store, Ty, Alignment, AS), | ||
| Ctx.CostKind); | ||
| if (!Reverse) | ||
| return Cost; | ||
|
|
||
| return Cost + Ctx.TTI.getShuffleCost( | ||
| TargetTransformInfo::SK_Reverse, cast<VectorType>(Ty), | ||
| cast<VectorType>(Ty), {}, Ctx.CostKind, 0); | ||
| } | ||
|
|
||
| #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||
|
|
||
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.
the only addition here is the stored value, right? can we unify to a single constructor, and clarify that
VPWidenStoreRecipeis only used for other fields?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.
92733e9
Unify them, thank.