aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2022-06-19 14:13:27 -0400
committerSanjay Patel <spatel@rotateright.com>2022-06-19 15:12:19 -0400
commit4022551a154e01ca5347629fd429ca04b36801e0 (patch)
treedf62de92410fbf72475f074cde2ef66c880358ec /llvm/lib/Analysis/ValueTracking.cpp
parentbfb915ec8bd057c566772b6f620a5ad3f55e9e17 (diff)
downloadllvm-4022551a154e01ca5347629fd429ca04b36801e0.zip
llvm-4022551a154e01ca5347629fd429ca04b36801e0.tar.gz
llvm-4022551a154e01ca5347629fd429ca04b36801e0.tar.bz2
[ValueTracking] recognize sub X, (X -nuw Y) as not overflowing
This extends a similar pattern from D125500 and D127754. If we know that operand 1 (RHS) of a subtract is itself a non-overflowing subtract from operand 0 (LHS), then the final/outer subtract is also non-overflowing: https://alive2.llvm.org/ce/z/Bqan8v InstCombine uses this analysis to trigger a narrowing optimization, so that is what the first changed test shows. The last test models a motivating case from issue #48013. In that example, we determine 'nuw' on the first sub from the urem, then we determine that the 2nd sub can be narrowed, and that leads to eliminating both subtracts. here are still several missing subtract narrowing optimizations demonstrated in the tests above the diffs shown here - those should be handled in InstCombine with another set of patches.
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp13
1 files changed, 10 insertions, 3 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index a6c256f..4ae1c6d 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -4955,11 +4955,18 @@ OverflowResult llvm::computeOverflowForUnsignedSub(const Value *LHS,
// X - (X % ?)
// The remainder of a value can't have greater magnitude than itself,
// so the subtraction can't overflow.
+
+ // X - (X -nuw ?)
+ // In the minimal case, this would simplify to "?", so there's no subtract
+ // at all. But if this analysis is used to peek through casts, for example,
+ // then determining no-overflow may allow other transforms.
+
// TODO: There are other patterns like this.
// See simplifyICmpWithBinOpOnLHS() for candidates.
- if (match(RHS, m_URem(m_Specific(LHS), m_Value())) &&
- isGuaranteedNotToBeUndefOrPoison(LHS, AC, CxtI, DT))
- return OverflowResult::NeverOverflows;
+ if (match(RHS, m_URem(m_Specific(LHS), m_Value())) ||
+ match(RHS, m_NUWSub(m_Specific(LHS), m_Value())))
+ if (isGuaranteedNotToBeUndefOrPoison(LHS, AC, CxtI, DT))
+ return OverflowResult::NeverOverflows;
// Checking for conditions implied by dominating conditions may be expensive.
// Limit it to usub_with_overflow calls for now.