aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
diff options
context:
space:
mode:
authorYingwei Zheng <dtcxzyw2333@gmail.com>2025-07-04 23:34:33 +0800
committerGitHub <noreply@github.com>2025-07-04 23:34:33 +0800
commit2472cdcb69d2fe0ff3573403be1bd49eb2d62dd8 (patch)
tree3a793383b3d22685fb6d9ab0e606dd6b124ef4a5 /llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
parentfd5ed046fdca42603fef1cbc6f4e7e0f536dcff3 (diff)
downloadllvm-2472cdcb69d2fe0ff3573403be1bd49eb2d62dd8.zip
llvm-2472cdcb69d2fe0ff3573403be1bd49eb2d62dd8.tar.gz
llvm-2472cdcb69d2fe0ff3573403be1bd49eb2d62dd8.tar.bz2
[InstCombine] Refine nuw propagation in `OptimizePointerDifference` (#147059)
After https://github.com/llvm/llvm-project/pull/146100, the offset may be generated by a previous call to `EmitGEPOffsets`, causing the nuw flag on shl to be lost. This patch handles the `shl+ptradd` case as well. It also fixes a miscompilation in the case of `mul + ptradd`. Alive2: https://alive2.llvm.org/ce/z/BeaNzE This patch removes many unnecessary masking operations in Rust programs with the `ptr_offset_from_unsigned` intrinsic : https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2538/files
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp10
1 files changed, 7 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index f727eb0..1ba548b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2164,10 +2164,14 @@ Value *InstCombinerImpl::OptimizePointerDifference(Value *LHS, Value *RHS,
// If this is a single inbounds GEP and the original sub was nuw,
// then the final multiplication is also nuw.
- if (auto *I = dyn_cast<Instruction>(Result))
+ if (auto *I = dyn_cast<OverflowingBinaryOperator>(Result))
if (IsNUW && match(Offset2, m_Zero()) && Base.LHSNW.isInBounds() &&
- I->getOpcode() == Instruction::Mul)
- I->setHasNoUnsignedWrap();
+ (I->use_empty() || I->hasOneUse()) && I->hasNoSignedWrap() &&
+ !I->hasNoUnsignedWrap() &&
+ ((I->getOpcode() == Instruction::Mul &&
+ match(I->getOperand(1), m_NonNegative())) ||
+ I->getOpcode() == Instruction::Shl))
+ cast<Instruction>(I)->setHasNoUnsignedWrap();
// If we have a 2nd GEP of the same base pointer, subtract the offsets.
// If both GEPs are inbounds, then the subtract does not have signed overflow.