aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorbipmis <102525366+bipmis@users.noreply.github.com>2023-12-15 10:02:57 +0000
committerGitHub <noreply@github.com>2023-12-15 10:02:57 +0000
commit6df63203749200e09199577a7646442f77fc67ce (patch)
tree0393a6b775c5c66ce740f1bcd1c40d121445f8e3 /llvm/lib/Analysis/ValueTracking.cpp
parent08b306dc8e7c0b2498f4f194a3c51686d56dbd20 (diff)
downloadllvm-6df63203749200e09199577a7646442f77fc67ce.zip
llvm-6df63203749200e09199577a7646442f77fc67ce.tar.gz
llvm-6df63203749200e09199577a7646442f77fc67ce.tar.bz2
[ValueTracking] isNonEqual Pointers with with a recursive GEP (#70459)
Handles canonical icmp eq(ptr1, ptr2) -> where ptr1/ptr2 is a recursive GEP. Can helps scenarios where InstCombineCompares folds icmp eq(sub(ptr2int, ptr2int), 0) -> icmp eq(ptr1, ptr2) and icmp eq(phi(sub(ptr2int, ptr2int), ...)) -> phi i1 (icmp eq(sub(ptr2int, ptr2int), 0), ....)
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8f32a1ba..9ae05a4 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3096,6 +3096,58 @@ static bool isNonEqualSelect(const Value *V1, const Value *V2, unsigned Depth,
isKnownNonEqual(SI1->getFalseValue(), V2, Depth + 1, Q);
}
+// Check to see if A is both a GEP and is the incoming value for a PHI in the
+// loop, and B is either a ptr or another GEP. If the PHI has 2 incoming values,
+// one of them being the recursive GEP A and the other a ptr at same base and at
+// the same/higher offset than B we are only incrementing the pointer further in
+// loop if offset of recursive GEP is greater than 0.
+static bool isNonEqualPointersWithRecursiveGEP(const Value *A, const Value *B,
+ const SimplifyQuery &Q) {
+ if (!A->getType()->isPointerTy() || !B->getType()->isPointerTy())
+ return false;
+
+ auto *GEPA = dyn_cast<GEPOperator>(A);
+ if (!GEPA || GEPA->getNumIndices() != 1 || !isa<Constant>(GEPA->idx_begin()))
+ return false;
+
+ // Handle 2 incoming PHI values with one being a recursive GEP.
+ auto *PN = dyn_cast<PHINode>(GEPA->getPointerOperand());
+ if (!PN || PN->getNumIncomingValues() != 2)
+ return false;
+
+ // Search for the recursive GEP as an incoming operand, and record that as
+ // Step.
+ Value *Start = nullptr;
+ Value *Step = const_cast<Value *>(A);
+ if (PN->getIncomingValue(0) == Step)
+ Start = PN->getIncomingValue(1);
+ else if (PN->getIncomingValue(1) == Step)
+ Start = PN->getIncomingValue(0);
+ else
+ return false;
+
+ // Other incoming node base should match the B base.
+ // StartOffset >= OffsetB && StepOffset > 0?
+ // StartOffset <= OffsetB && StepOffset < 0?
+ // Is non-equal if above are true.
+ // We use stripAndAccumulateInBoundsConstantOffsets to restrict the
+ // optimisation to inbounds GEPs only.
+ unsigned IndexWidth = Q.DL.getIndexTypeSizeInBits(Start->getType());
+ APInt StartOffset(IndexWidth, 0);
+ Start = Start->stripAndAccumulateInBoundsConstantOffsets(Q.DL, StartOffset);
+ APInt StepOffset(IndexWidth, 0);
+ Step = Step->stripAndAccumulateInBoundsConstantOffsets(Q.DL, StepOffset);
+
+ // Check if Base Pointer of Step matches the PHI.
+ if (Step != PN)
+ return false;
+ APInt OffsetB(IndexWidth, 0);
+ B = B->stripAndAccumulateInBoundsConstantOffsets(Q.DL, OffsetB);
+ return Start == B &&
+ ((StartOffset.sge(OffsetB) && StepOffset.isStrictlyPositive()) ||
+ (StartOffset.sle(OffsetB) && StepOffset.isNegative()));
+}
+
/// Return true if it is known that V1 != V2.
static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
const SimplifyQuery &Q) {
@@ -3149,6 +3201,10 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
if (isNonEqualSelect(V1, V2, Depth, Q) || isNonEqualSelect(V2, V1, Depth, Q))
return true;
+ if (isNonEqualPointersWithRecursiveGEP(V1, V2, Q) ||
+ isNonEqualPointersWithRecursiveGEP(V2, V1, Q))
+ return true;
+
return false;
}