summaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
diff options
context:
space:
mode:
authorNikita Popov <npopov@redhat.com>2024-04-26 10:53:03 +0900
committerGitHub <noreply@github.com>2024-04-26 10:53:03 +0900
commitcbe1760f02882328c91e5764648f97fe644f44c9 (patch)
treec8edaf332938feb3106c21b0a650aa4806b3cec6 /llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
parente21d89eb8b0798d842b1240cc992cb979d54809c (diff)
[InstCombine] Allow multi-use OptimizePointerDifference() with two GEPs (#90017)
Currently, the OptimizePointerDifference fold does not trigger when working on the sub of two geps where one of the geps has multiple uses, to avoid duplicating the offset arithmetic too much. However, there are cases where performing it would still be clearly profitable, e.g. test_sub_ptradd_multiuse. This patch drops the one-use restriction using the same strategy we use in GEP comparison folds: If there are multiple uses, we rewrite the GEP to use the expanded offset arithmetic instead (effectively canonicalizing it into ptradd representation). Fixes https://github.com/llvm/llvm-project/issues/88231.
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp28
1 files changed, 6 insertions, 22 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index ea2cdadc84f1..a3775fa6f369 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2001,29 +2001,13 @@ Value *InstCombinerImpl::OptimizePointerDifference(Value *LHS, Value *RHS,
if (!GEP1)
return nullptr;
- if (GEP2) {
- // (gep X, ...) - (gep X, ...)
- //
- // Avoid duplicating the arithmetic if there are more than one non-constant
- // indices between the two GEPs and either GEP has a non-constant index and
- // multiple users. If zero non-constant index, the result is a constant and
- // there is no duplication. If one non-constant index, the result is an add
- // or sub with a constant, which is no larger than the original code, and
- // there's no duplicated arithmetic, even if either GEP has multiple
- // users. If more than one non-constant indices combined, as long as the GEP
- // with at least one non-constant index doesn't have multiple users, there
- // is no duplication.
- unsigned NumNonConstantIndices1 = GEP1->countNonConstantIndices();
- unsigned NumNonConstantIndices2 = GEP2->countNonConstantIndices();
- if (NumNonConstantIndices1 + NumNonConstantIndices2 > 1 &&
- ((NumNonConstantIndices1 > 0 && !GEP1->hasOneUse()) ||
- (NumNonConstantIndices2 > 0 && !GEP2->hasOneUse()))) {
- return nullptr;
- }
- }
+ // To avoid duplicating the offset arithmetic, rewrite the GEP to use the
+ // computed offset.
+ // TODO: We should probably do this even if there is only one GEP.
+ bool RewriteGEPs = GEP2 != nullptr;
// Emit the offset of the GEP and an intptr_t.
- Value *Result = EmitGEPOffset(GEP1);
+ Value *Result = EmitGEPOffset(GEP1, RewriteGEPs);
// If this is a single inbounds GEP and the original sub was nuw,
// then the final multiplication is also nuw.
@@ -2035,7 +2019,7 @@ Value *InstCombinerImpl::OptimizePointerDifference(Value *LHS, Value *RHS,
// 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.
if (GEP2) {
- Value *Offset = EmitGEPOffset(GEP2);
+ Value *Offset = EmitGEPOffset(GEP2, RewriteGEPs);
Result = Builder.CreateSub(Result, Offset, "gepdiff", /* NUW */ false,
GEP1->isInBounds() && GEP2->isInBounds());
}