aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2024-10-17 13:55:20 -0700
committerGitHub <noreply@github.com>2024-10-17 13:55:20 -0700
commitb060661da8b3b53db55644e5e358bb2dca8b56d7 (patch)
treefe3e2538530b9f8ea72473f24673047034569dac /llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
parente913a33fcfbd667e4e3a35919b6bd9c5876a90a3 (diff)
downloadllvm-b060661da8b3b53db55644e5e358bb2dca8b56d7.zip
llvm-b060661da8b3b53db55644e5e358bb2dca8b56d7.tar.gz
llvm-b060661da8b3b53db55644e5e358bb2dca8b56d7.tar.bz2
[SCEVExpander] Expand UDiv avoiding UB when in seq_min/max. (#92177)
Update SCEVExpander to introduce an SafeUDivMode, which is set when expanding operands of SCEVSequentialMinMaxExpr. In this mode, the expander will make sure that the divisor of the expanded UDiv is neither 0 nor poison. Fixes https://github.com/llvm/llvm-project/issues/89958. PR https://github.com/llvm/llvm-project/pull/92177
Diffstat (limited to 'llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp20
1 files changed, 19 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
index c412d03..39da38e 100644
--- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
+++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp
@@ -681,7 +681,21 @@ Value *SCEVExpander::visitUDivExpr(const SCEVUDivExpr *S) {
SCEV::FlagAnyWrap, /*IsSafeToHoist*/ true);
}
- Value *RHS = expand(S->getRHS());
+ const SCEV *RHSExpr = S->getRHS();
+ Value *RHS = expand(RHSExpr);
+ if (SafeUDivMode) {
+ bool GuaranteedNotPoison =
+ ScalarEvolution::isGuaranteedNotToBePoison(RHSExpr);
+ if (!GuaranteedNotPoison)
+ RHS = Builder.CreateFreeze(RHS);
+
+ // We need an umax if either RHSExpr is not known to be zero, or if it is
+ // not guaranteed to be non-poison. In the later case, the frozen poison may
+ // be 0.
+ if (!SE.isKnownNonZero(RHSExpr) || !GuaranteedNotPoison)
+ RHS = Builder.CreateIntrinsic(RHS->getType(), Intrinsic::umax,
+ {RHS, ConstantInt::get(RHS->getType(), 1)});
+ }
return InsertBinop(Instruction::UDiv, LHS, RHS, SCEV::FlagAnyWrap,
/*IsSafeToHoist*/ SE.isKnownNonZero(S->getRHS()));
}
@@ -1376,11 +1390,14 @@ Value *SCEVExpander::visitSignExtendExpr(const SCEVSignExtendExpr *S) {
Value *SCEVExpander::expandMinMaxExpr(const SCEVNAryExpr *S,
Intrinsic::ID IntrinID, Twine Name,
bool IsSequential) {
+ bool PrevSafeMode = SafeUDivMode;
+ SafeUDivMode |= IsSequential;
Value *LHS = expand(S->getOperand(S->getNumOperands() - 1));
Type *Ty = LHS->getType();
if (IsSequential)
LHS = Builder.CreateFreeze(LHS);
for (int i = S->getNumOperands() - 2; i >= 0; --i) {
+ SafeUDivMode = (IsSequential && i != 0) || PrevSafeMode;
Value *RHS = expand(S->getOperand(i));
if (IsSequential && i != 0)
RHS = Builder.CreateFreeze(RHS);
@@ -1395,6 +1412,7 @@ Value *SCEVExpander::expandMinMaxExpr(const SCEVNAryExpr *S,
}
LHS = Sel;
}
+ SafeUDivMode = PrevSafeMode;
return LHS;
}