-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[VPlan] Extend getSCEVForVPV, use to compute VPReplicateRecipe cost. #161276
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 7 commits
4e58117
85d4624
032c1c0
295ff44
b055e83
5698517
2c115ca
8d54b4d
0f1f329
deeceea
fffd8b1
c16c8b3
6f84e6a
172407a
1a92250
aebc291
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 |
|---|---|---|
|
|
@@ -77,7 +77,8 @@ bool vputils::isHeaderMask(const VPValue *V, const VPlan &Plan) { | |
| B == Plan.getBackedgeTakenCount(); | ||
| } | ||
|
|
||
| const SCEV *vputils::getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE) { | ||
| const SCEV *vputils::getSCEVExprForVPValue(const VPValue *V, | ||
| ScalarEvolution &SE, const Loop *L) { | ||
| if (V->isLiveIn()) { | ||
| if (Value *LiveIn = V->getLiveInIRValue()) | ||
| return SE.getSCEV(LiveIn); | ||
|
|
@@ -88,6 +89,85 @@ const SCEV *vputils::getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE) { | |
| return TypeSwitch<const VPRecipeBase *, const SCEV *>(V->getDefiningRecipe()) | ||
| .Case<VPExpandSCEVRecipe>( | ||
| [](const VPExpandSCEVRecipe *R) { return R->getSCEV(); }) | ||
| .Case<VPCanonicalIVPHIRecipe>([&SE, L](const VPCanonicalIVPHIRecipe *R) { | ||
| if (!L) | ||
| return SE.getCouldNotCompute(); | ||
artagnon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const SCEV *Start = getSCEVExprForVPValue(R->getOperand(0), SE, L); | ||
| return SE.getAddRecExpr(Start, SE.getOne(Start->getType()), L, | ||
| SCEV::FlagAnyWrap); | ||
| }) | ||
| .Case<VPDerivedIVRecipe>([&SE, L](const VPDerivedIVRecipe *R) { | ||
| const SCEV *Start = getSCEVExprForVPValue(R->getOperand(0), SE, L); | ||
| const SCEV *IV = getSCEVExprForVPValue(R->getOperand(1), SE, L); | ||
| const SCEV *Scale = getSCEVExprForVPValue(R->getOperand(2), SE, L); | ||
| if (any_of(ArrayRef({Start, IV, Scale}), IsaPred<SCEVCouldNotCompute>)) | ||
| return SE.getCouldNotCompute(); | ||
|
|
||
| return SE.getAddExpr(SE.getTruncateOrSignExtend(Start, IV->getType()), | ||
| SE.getMulExpr(IV, SE.getTruncateOrSignExtend( | ||
| Scale, IV->getType()))); | ||
artagnon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }) | ||
| .Case<VPScalarIVStepsRecipe>([&SE, L](const VPScalarIVStepsRecipe *R) { | ||
| return getSCEVExprForVPValue(R->getOperand(0), SE, L); | ||
| }) | ||
| .Case<VPReplicateRecipe>([&SE, L](const VPReplicateRecipe *R) { | ||
| if (R->getOpcode() != Instruction::GetElementPtr) | ||
| return SE.getCouldNotCompute(); | ||
|
|
||
| const SCEV *Base = getSCEVExprForVPValue(R->getOperand(0), SE, L); | ||
| if (isa<SCEVCouldNotCompute>(Base)) | ||
| return SE.getCouldNotCompute(); | ||
|
|
||
| Type *IntIdxTy = SE.getEffectiveSCEVType(Base->getType()); | ||
| Type *CurTy = IntIdxTy; | ||
| bool FirstIter = true; | ||
| SmallVector<const SCEV *, 4> Offsets; | ||
| for (VPValue *Index : drop_begin(R->operands())) { | ||
| const SCEV *IndexExpr = getSCEVExprForVPValue(Index, SE, L); | ||
| if (isa<SCEVCouldNotCompute>(IndexExpr)) | ||
| return SE.getCouldNotCompute(); | ||
| // Compute the (potentially symbolic) offset in bytes for this index. | ||
| if (StructType *STy = dyn_cast<StructType>(CurTy)) { | ||
|
||
| // For a struct, add the member offset. | ||
| ConstantInt *Index = cast<SCEVConstant>(IndexExpr)->getValue(); | ||
| unsigned FieldNo = Index->getZExtValue(); | ||
| const SCEV *FieldOffset = | ||
| SE.getOffsetOfExpr(IntIdxTy, STy, FieldNo); | ||
| Offsets.push_back(FieldOffset); | ||
|
|
||
| // Update CurTy to the type of the field at Index. | ||
| CurTy = STy->getTypeAtIndex(Index); | ||
| } else { | ||
| // Update CurTy to its element type. | ||
| if (FirstIter) { | ||
| CurTy = cast<GetElementPtrInst>(R->getUnderlyingInstr()) | ||
| ->getSourceElementType(); | ||
| FirstIter = false; | ||
| } else { | ||
| CurTy = GetElementPtrInst::getTypeAtIndex(CurTy, (uint64_t)0); | ||
| } | ||
| // For an array, add the element offset, explicitly scaled. | ||
| const SCEV *ElementSize = SE.getSizeOfExpr(IntIdxTy, CurTy); | ||
| // Getelementptr indices are signed. | ||
| IndexExpr = SE.getTruncateOrSignExtend(IndexExpr, IntIdxTy); | ||
|
|
||
| // Multiply the index by the element size to compute the element | ||
| // offset. | ||
| const SCEV *LocalOffset = SE.getMulExpr(IndexExpr, ElementSize); | ||
| Offsets.push_back(LocalOffset); | ||
| } | ||
| } | ||
| // Handle degenerate case of GEP without offsets. | ||
| if (Offsets.empty()) | ||
| return Base; | ||
|
|
||
| // Add the offsets together, assuming nsw if inbounds. | ||
| const SCEV *Offset = SE.getAddExpr(Offsets); | ||
| // Add the base address and the offset. We cannot use the nsw flag, as | ||
| // the base address is unsigned. However, if we know that the offset is | ||
| // non-negative, we can use nuw. | ||
| return SE.getAddExpr(Base, Offset); | ||
| }) | ||
artagnon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .Default([&SE](const VPRecipeBase *) { return SE.getCouldNotCompute(); }); | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.