diff options
author | Nikita Popov <npopov@redhat.com> | 2024-06-20 14:39:03 +0200 |
---|---|---|
committer | Nikita Popov <npopov@redhat.com> | 2024-06-20 14:45:02 +0200 |
commit | 7f09aa9e3670778217a3d61702a4cf3343e6449d (patch) | |
tree | a89770f371015f48dc5fa29ebfc781106b53d649 /llvm/lib/Analysis/ScalarEvolution.cpp | |
parent | 3808ba78dea8ef81b108862d795ff21cb463bdb1 (diff) | |
download | llvm-7f09aa9e3670778217a3d61702a4cf3343e6449d.zip llvm-7f09aa9e3670778217a3d61702a4cf3343e6449d.tar.gz llvm-7f09aa9e3670778217a3d61702a4cf3343e6449d.tar.bz2 |
[SCEV] Transfer gep nusw and nuw flags
nusw implies nsw offset and nuw base+offset arithmetic if offset
is non-negative. nuw implies nuw offset and base+offset arithmetic.
As usual, we can only transfer is poison implies UB.
Diffstat (limited to 'llvm/lib/Analysis/ScalarEvolution.cpp')
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 7d3e3f4..8d90530 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -3746,21 +3746,23 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP, // getSCEV(Base)->getType() has the same address space as Base->getType() // because SCEV::getType() preserves the address space. Type *IntIdxTy = getEffectiveSCEVType(BaseExpr->getType()); - const bool AssumeInBoundsFlags = [&]() { - if (!GEP->isInBounds()) - return false; - + GEPNoWrapFlags NW = GEP->getNoWrapFlags(); + if (NW != GEPNoWrapFlags::none()) { // We'd like to propagate flags from the IR to the corresponding SCEV nodes, // but to do that, we have to ensure that said flag is valid in the entire // defined scope of the SCEV. - auto *GEPI = dyn_cast<Instruction>(GEP); // TODO: non-instructions have global scope. We might be able to prove // some global scope cases - return GEPI && isSCEVExprNeverPoison(GEPI); - }(); + auto *GEPI = dyn_cast<Instruction>(GEP); + if (!GEPI || !isSCEVExprNeverPoison(GEPI)) + NW = GEPNoWrapFlags::none(); + } - SCEV::NoWrapFlags OffsetWrap = - AssumeInBoundsFlags ? SCEV::FlagNSW : SCEV::FlagAnyWrap; + SCEV::NoWrapFlags OffsetWrap = SCEV::FlagAnyWrap; + if (NW.hasNoUnsignedSignedWrap()) + OffsetWrap = setFlags(OffsetWrap, SCEV::FlagNSW); + if (NW.hasNoUnsignedWrap()) + OffsetWrap = setFlags(OffsetWrap, SCEV::FlagNUW); Type *CurTy = GEP->getType(); bool FirstIter = true; @@ -3806,8 +3808,9 @@ ScalarEvolution::getGEPExpr(GEPOperator *GEP, // 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. - SCEV::NoWrapFlags BaseWrap = AssumeInBoundsFlags && isKnownNonNegative(Offset) - ? SCEV::FlagNUW : SCEV::FlagAnyWrap; + bool NUW = NW.hasNoUnsignedWrap() || + (NW.hasNoUnsignedSignedWrap() && isKnownNonNegative(Offset)); + SCEV::NoWrapFlags BaseWrap = NUW ? SCEV::FlagNUW : SCEV::FlagAnyWrap; auto *GEPExpr = getAddExpr(BaseExpr, Offset, BaseWrap); assert(BaseExpr->getType() == GEPExpr->getType() && "GEP should not change type mid-flight."); |