Skip to content

Commit 9abf3df

Browse files
authored
[ValueTracking] Analyze Select in isKnownNonEqual. (#68427)
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`.
1 parent f2441a0 commit 9abf3df

File tree

2 files changed

+102
-0
lines changed

2 files changed

+102
-0
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3122,6 +3122,25 @@ static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
31223122
return true;
31233123
}
31243124

3125+
static bool isNonEqualSelect(const Value *V1, const Value *V2, unsigned Depth,
3126+
const SimplifyQuery &Q) {
3127+
const SelectInst *SI1 = dyn_cast<SelectInst>(V1);
3128+
if (!SI1)
3129+
return false;
3130+
3131+
if (const SelectInst *SI2 = dyn_cast<SelectInst>(V2)) {
3132+
const Value *Cond1 = SI1->getCondition();
3133+
const Value *Cond2 = SI2->getCondition();
3134+
if (Cond1 == Cond2)
3135+
return isKnownNonEqual(SI1->getTrueValue(), SI2->getTrueValue(),
3136+
Depth + 1, Q) &&
3137+
isKnownNonEqual(SI1->getFalseValue(), SI2->getFalseValue(),
3138+
Depth + 1, Q);
3139+
}
3140+
return isKnownNonEqual(SI1->getTrueValue(), V2, Depth + 1, Q) &&
3141+
isKnownNonEqual(SI1->getFalseValue(), V2, Depth + 1, Q);
3142+
}
3143+
31253144
/// Return true if it is known that V1 != V2.
31263145
static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
31273146
const SimplifyQuery &Q) {
@@ -3171,6 +3190,10 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
31713190
Known2.Zero.intersects(Known1.One))
31723191
return true;
31733192
}
3193+
3194+
if (isNonEqualSelect(V1, V2, Depth, Q) || isNonEqualSelect(V2, V1, Depth, Q))
3195+
return true;
3196+
31743197
return false;
31753198
}
31763199

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
2+
@G = global [10 x i32] zeroinitializer, align 4
3+
4+
define void @select_in_gep1(i1 %c, i64 %x) {
5+
entry:
6+
; CHECK-LABEL: Function: select_in_gep1
7+
; CHECK: NoAlias: i32* %arrayidx1, i32* %arrayidx2
8+
%add1_ = add nsw i64 %x, 1
9+
%add2_ = add nsw i64 %x, 2
10+
%select_ = select i1 %c, i64 %add1_, i64 %add2_
11+
%arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select_
12+
store i32 42, ptr %arrayidx1, align 4
13+
%arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %x
14+
store i32 43, ptr %arrayidx2, align 4
15+
ret void
16+
}
17+
18+
define void @select_in_gep2(i1 %c, i64 %x) {
19+
entry:
20+
; TODO: should be "NoAlias" here as well.
21+
; CHECK-LABEL: Function: select_in_gep2
22+
; CHECK: MayAlias: i32* %arrayidx1, i32* %arrayidx2
23+
%add1_ = add nsw i64 %x, 1
24+
%add2_ = add nsw i64 %x, 2
25+
%add3_ = add nsw i64 %x, 3
26+
%select_ = select i1 %c, i64 %add1_, i64 %add2_
27+
%arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select_
28+
store i32 42, ptr %arrayidx1, align 4
29+
%arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %add3_
30+
store i32 43, ptr %arrayidx2, align 4
31+
ret void
32+
}
33+
34+
define void @two_selects_in_gep_same_cond(i1 %c, i64 %x) {
35+
entry:
36+
; CHECK-LABEL: Function: two_selects_in_gep_same_cond
37+
; CHECK: NoAlias: i32* %arrayidx1, i32* %arrayidx2
38+
%add1_ = add nsw i64 %x, 1
39+
%add2_ = add nsw i64 %x, 2
40+
%select1_ = select i1 %c, i64 %x, i64 %add1_
41+
%select2_ = select i1 %c, i64 %add2_, i64 %x
42+
%arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select1_
43+
store i32 42, ptr %arrayidx1, align 4
44+
%arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select2_
45+
store i32 43, ptr %arrayidx2, align 4
46+
ret void
47+
}
48+
49+
define void @two_selects_in_gep_different_cond1(i1 %c1, i1 %c2, i64 %x) {
50+
entry:
51+
; CHECK-LABEL: Function: two_selects_in_gep_different_cond1
52+
; CHECK: NoAlias: i32* %arrayidx1, i32* %arrayidx2
53+
%add1_ = add nsw i64 %x, 1
54+
%add2_ = add nsw i64 %x, 2
55+
%add3_ = add nsw i64 %x, 3
56+
%add4_ = add nsw i64 %x, 4
57+
%select1_ = select i1 %c1, i64 %add1_, i64 %add2_
58+
%select2_ = select i1 %c2, i64 %add3_, i64 %add4_
59+
%arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select1_
60+
store i32 42, ptr %arrayidx1, align 4
61+
%arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select2_
62+
store i32 43, ptr %arrayidx2, align 4
63+
ret void
64+
}
65+
66+
define void @two_selects_in_gep_different_cond2(i1 %c1, i1 %c2, i64 %x) {
67+
entry:
68+
; CHECK-LABEL: Function: two_selects_in_gep_different_cond2
69+
; CHECK: MayAlias: i32* %arrayidx1, i32* %arrayidx2
70+
%add1_ = add nsw i64 %x, 1
71+
%add2_ = add nsw i64 %x, 2
72+
%select1_ = select i1 %c1, i64 %x, i64 %add1_
73+
%select2_ = select i1 %c2, i64 %x, i64 %add2_
74+
%arrayidx1 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select1_
75+
store i32 42, ptr %arrayidx1, align 4
76+
%arrayidx2 = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select2_
77+
store i32 43, ptr %arrayidx2, align 4
78+
ret void
79+
}

0 commit comments

Comments
 (0)