[llvm] [ValueTracking] Analyze `Select` in `isKnownNonEqual`. (PR #68427)
Mikhail Gudim via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 7 12:27:20 PDT 2023
https://github.com/mgudim updated https://github.com/llvm/llvm-project/pull/68427
>From e8956e69ce44ae73b013885ff16936156339f26d Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at gmail.com>
Date: Tue, 3 Oct 2023 11:56:50 -0400
Subject: [PATCH 1/2] [ValueTracking] Analyze `Select` in `isKnownNonEqual`.
Basic way to recursively analyze `select` in `isKnownNonEqual`: `select %c, %t, %f` is
non-equal to `%x` if `%t` is non-equal to `%x` and `%f` is non-equal to
`%x`.
---
llvm/lib/Analysis/ValueTracking.cpp | 20 +++++++++++
.../test/Analysis/BasicAA/non-equal-select.ll | 33 +++++++++++++++++++
2 files changed, 53 insertions(+)
create mode 100644 llvm/test/Analysis/BasicAA/non-equal-select.ll
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 3af5a6d9a167de4..1c284e8d85ca417 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3112,6 +3112,23 @@ static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
return true;
}
+static bool isNonEqualSELECT(const Value *V1, const Value *V2, unsigned Depth,
+ const SimplifyQuery &Q) {
+ const SelectInst *SI1 = dyn_cast<SelectInst>(V1);
+ if (!SI1)
+ return false;
+
+ if (const SelectInst *SI2 = dyn_cast<SelectInst>(V2)) {
+ if (SI1->getCondition() == SI2->getCondition())
+ return isKnownNonEqual(SI1->getTrueValue(), SI2->getTrueValue(),
+ Depth + 1, Q) &&
+ isKnownNonEqual(SI1->getFalseValue(), SI2->getFalseValue(),
+ Depth + 1, Q);
+ }
+ return isKnownNonEqual(SI1->getTrueValue(), V2, Depth + 1, Q) &&
+ isKnownNonEqual(SI1->getFalseValue(), V2, Depth + 1, Q);
+}
+
/// Return true if it is known that V1 != V2.
static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
const SimplifyQuery &Q) {
@@ -3142,6 +3159,9 @@ 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 (isAddOfNonZero(V1, V2, Depth, Q) || isAddOfNonZero(V2, V1, Depth, Q))
return true;
diff --git a/llvm/test/Analysis/BasicAA/non-equal-select.ll b/llvm/test/Analysis/BasicAA/non-equal-select.ll
new file mode 100644
index 000000000000000..1af37245c6d85a6
--- /dev/null
+++ b/llvm/test/Analysis/BasicAA/non-equal-select.ll
@@ -0,0 +1,33 @@
+; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+ at G = global [10 x i32] zeroinitializer, align 4
+
+; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: none, inaccessiblemem: none) uwtable
+define void @select_in_gep1(i1 %c, i64 noundef %x) {
+entry:
+; CHECK: Function: select_in_gep1
+; CHECK: NoAlias: i32* %arrayidx1, i32* %arrayidx2
+ %add1_ = add nsw i64 %x, 1
+ %add2_ = add nsw i64 %x, 2
+ %select_ = select i1 %c, i64 %add1_, i64 %add2_
+ %arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select_
+ store i32 42, ptr %arrayidx1, align 4
+ %arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %x
+ store i32 43, ptr %arrayidx2, align 4
+ ret void
+}
+
+define void @select_in_gep2(i1 %c, i64 noundef %x) {
+entry:
+ ; TODO: should be "NoAlias" here as well.
+; CHECK: Function: select_in_gep2
+; CHECK: MayAlias: i32* %arrayidx1, i32* %arrayidx2
+ %add1_ = add nsw i64 %x, 1
+ %add2_ = add nsw i64 %x, 2
+ %add3_ = add nsw i64 %x, 3
+ %select_ = select i1 %c, i64 %add1_, i64 %add2_
+ %arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select_
+ store i32 42, ptr %arrayidx1, align 4
+ %arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %add3_
+ store i32 43, ptr %arrayidx2, align 4
+ ret void
+}
>From 7d2b482967e1b03dfd05a0fc634b311ff94c4433 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at gmail.com>
Date: Sat, 7 Oct 2023 15:26:09 -0400
Subject: [PATCH 2/2] Addressed review comments
---
llvm/lib/Analysis/ValueTracking.cpp | 30 +++++--
.../test/Analysis/BasicAA/non-equal-select.ll | 86 ++++++++++++++++++-
2 files changed, 105 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 1c284e8d85ca417..b42b9f85efd2136 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3112,18 +3112,34 @@ static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
return true;
}
-static bool isNonEqualSELECT(const Value *V1, const Value *V2, unsigned Depth,
+static bool isNonEqualSelect(const Value *V1, const Value *V2, unsigned Depth,
const SimplifyQuery &Q) {
const SelectInst *SI1 = dyn_cast<SelectInst>(V1);
if (!SI1)
return false;
if (const SelectInst *SI2 = dyn_cast<SelectInst>(V2)) {
- if (SI1->getCondition() == SI2->getCondition())
- return isKnownNonEqual(SI1->getTrueValue(), SI2->getTrueValue(),
- Depth + 1, Q) &&
- isKnownNonEqual(SI1->getFalseValue(), SI2->getFalseValue(),
- Depth + 1, Q);
+ const Value *TVal1 = nullptr;
+ const Value *TVal2 = nullptr;
+ const Value *FVal1 = nullptr;
+ const Value *FVal2 = nullptr;
+ const Value *Cond1 = SI1->getCondition();
+ const Value *Cond2 = SI2->getCondition();
+ if (Cond1 == Cond2) {
+ TVal1 = SI1->getTrueValue();
+ TVal2 = SI2->getTrueValue();
+ FVal1 = SI1->getFalseValue();
+ FVal2 = SI2->getFalseValue();
+ }
+ if (match(Cond1, m_Not(m_Specific(Cond2)))) {
+ TVal1 = SI1->getFalseValue();
+ TVal2 = SI2->getTrueValue();
+ FVal1 = SI1->getTrueValue();
+ FVal2 = SI2->getFalseValue();
+ }
+ if (TVal1)
+ return isKnownNonEqual(TVal1, TVal2, Depth + 1, Q) &&
+ isKnownNonEqual(FVal1, FVal2, Depth + 1, Q);
}
return isKnownNonEqual(SI1->getTrueValue(), V2, Depth + 1, Q) &&
isKnownNonEqual(SI1->getFalseValue(), V2, Depth + 1, Q);
@@ -3159,7 +3175,7 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
};
}
- if (isNonEqualSELECT(V1, V2, Depth, Q) || isNonEqualSELECT(V2, V1, Depth, Q))
+ if (isNonEqualSelect(V1, V2, Depth, Q) || isNonEqualSelect(V2, V1, Depth, Q))
return true;
if (isAddOfNonZero(V1, V2, Depth, Q) || isAddOfNonZero(V2, V1, Depth, Q))
diff --git a/llvm/test/Analysis/BasicAA/non-equal-select.ll b/llvm/test/Analysis/BasicAA/non-equal-select.ll
index 1af37245c6d85a6..1ee78535a09986a 100644
--- a/llvm/test/Analysis/BasicAA/non-equal-select.ll
+++ b/llvm/test/Analysis/BasicAA/non-equal-select.ll
@@ -1,10 +1,9 @@
; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
@G = global [10 x i32] zeroinitializer, align 4
-; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(readwrite, argmem: none, inaccessiblemem: none) uwtable
-define void @select_in_gep1(i1 %c, i64 noundef %x) {
+define void @select_in_gep1(i1 %c, i64 %x) {
entry:
-; CHECK: Function: select_in_gep1
+; CHECK-LABEL: Function: select_in_gep1
; CHECK: NoAlias: i32* %arrayidx1, i32* %arrayidx2
%add1_ = add nsw i64 %x, 1
%add2_ = add nsw i64 %x, 2
@@ -19,7 +18,7 @@ entry:
define void @select_in_gep2(i1 %c, i64 noundef %x) {
entry:
; TODO: should be "NoAlias" here as well.
-; CHECK: Function: select_in_gep2
+; CHECK-LABEL: Function: select_in_gep2
; CHECK: MayAlias: i32* %arrayidx1, i32* %arrayidx2
%add1_ = add nsw i64 %x, 1
%add2_ = add nsw i64 %x, 2
@@ -31,3 +30,82 @@ entry:
store i32 43, ptr %arrayidx2, align 4
ret void
}
+
+define void @two_selects_in_gep_same_cond(i1 %c, i64 %x) {
+entry:
+; CHECK-LABEL: Function: two_selects_in_gep_same_cond
+; CHECK: NoAlias: i32* %arrayidx1, i32* %arrayidx2
+ %add1_ = add nsw i64 %x, 1
+ %add2_ = add nsw i64 %x, 2
+ %select1_ = select i1 %c, i64 %x, i64 %add1_
+ %select2_ = select i1 %c, i64 %add2_, i64 %x
+ %arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select1_
+ store i32 42, ptr %arrayidx1, align 4
+ %arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select2_
+ store i32 43, ptr %arrayidx2, align 4
+ ret void
+}
+
+define void @two_selects_in_gep_opposite_cond1(i1 %c, i64 %x) {
+entry:
+; CHECK-LABEL: Function: two_selects_in_gep_opposite_cond1
+; CHECK: NoAlias: i32* %arrayidx1, i32* %arrayidx2 blah
+ %add1_ = add nsw i64 %x, 1
+ %add2_ = add nsw i64 %x, 2
+ %not_c = xor i1 %c, -1
+ %select1_ = select i1 %c, i64 %x, i64 %add1_
+ %select2_ = select i1 %not_c, i64 %x, i64 %add2_
+ %arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select1_
+ store i32 42, ptr %arrayidx1, align 4
+ %arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select2_
+ store i32 43, ptr %arrayidx2, align 4
+ ret void
+}
+
+define void @two_selects_in_gep_opposite_cond2(i1 %c, i64 %x) {
+entry:
+; CHECK-LABEL: Function: two_selects_in_gep_opposite_cond2
+; CHECK: NoAlias: i32* %arrayidx1, i32* %arrayidx2
+ %add1_ = add nsw i64 %x, 1
+ %add2_ = add nsw i64 %x, 2
+ %not_c = xor i1 %c, -1
+ %select1_ = select i1 %not_c, i64 %x, i64 %add1_
+ %select2_ = select i1 %c, i64 %x, i64 %add2_
+ %arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select1_
+ store i32 42, ptr %arrayidx1, align 4
+ %arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select2_
+ store i32 43, ptr %arrayidx2, align 4
+ ret void
+}
+
+define void @two_selects_in_gep_different_cond1(i1 %c1, i1 %c2, i64 %x) {
+entry:
+; CHECK-LABEL: Function: two_selects_in_gep_different_cond1
+; CHECK: NoAlias: i32* %arrayidx1, i32* %arrayidx2
+ %add1_ = add nsw i64 %x, 1
+ %add2_ = add nsw i64 %x, 2
+ %add3_ = add nsw i64 %x, 3
+ %add4_ = add nsw i64 %x, 4
+ %select1_ = select i1 %c1, i64 %add1_, i64 %add2_
+ %select2_ = select i1 %c2, i64 %add3_, i64 %add4_
+ %arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select1_
+ store i32 42, ptr %arrayidx1, align 4
+ %arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select2_
+ store i32 43, ptr %arrayidx2, align 4
+ ret void
+}
+
+define void @two_selects_in_gep_different_cond2(i1 %c1, i1 %c2, i64 %x) {
+entry:
+; CHECK-LABEL: Function: two_selects_in_gep_different_cond2
+; CHECK: MayAlias: i32* %arrayidx1, i32* %arrayidx2
+ %add1_ = add nsw i64 %x, 1
+ %add2_ = add nsw i64 %x, 2
+ %select1_ = select i1 %c1, i64 %x, i64 %add1_
+ %select2_ = select i1 %c2, i64 %x, i64 %add2_
+ %arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select1_
+ store i32 42, ptr %arrayidx1, align 4
+ %arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select2_
+ store i32 43, ptr %arrayidx2, align 4
+ ret void
+}
More information about the llvm-commits
mailing list