Skip to content

Commit a7d992c

Browse files
committed
[ValueTracking] Allow context-sensitive nullness check for non-pointers
Summary: Same as D60846 and D69571 but with a fix for the problem encountered after them. Both times it was a missing context adjustment in the handling of PHI nodes. The reproducers created from the bugs that caused the old commits to be reverted are included. Reviewers: nikic, nlopes, mkazantsev, spatel, dlrobertson, uabelho, hakzsam, hans Subscribers: hiraditya, bollu, asbirlea, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D71181
1 parent 1164d43 commit a7d992c

File tree

6 files changed

+89
-24
lines changed

6 files changed

+89
-24
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,10 +543,16 @@ static Value *ThreadCmpOverPHI(CmpInst::Predicate Pred, Value *LHS, Value *RHS,
543543

544544
// Evaluate the BinOp on the incoming phi values.
545545
Value *CommonValue = nullptr;
546-
for (Value *Incoming : PI->incoming_values()) {
546+
for (unsigned u = 0, e = PI->getNumIncomingValues(); u < e; ++u) {
547+
Value *Incoming = PI->getIncomingValue(u);
548+
Instruction *InTI = PI->getIncomingBlock(u)->getTerminator();
547549
// If the incoming value is the phi node itself, it can safely be skipped.
548550
if (Incoming == PI) continue;
549-
Value *V = SimplifyCmpInst(Pred, Incoming, RHS, Q, MaxRecurse);
551+
// Change the context instruction to the "edge" that flows into the phi.
552+
// This is important because that is where incoming is actually "evaluated"
553+
// even though it is used later somewhere else.
554+
Value *V = SimplifyCmpInst(Pred, Incoming, RHS, Q.getWithInstruction(InTI),
555+
MaxRecurse);
550556
// If the operation failed to simplify, or simplified to a different value
551557
// to previously, then give up.
552558
if (!V || (CommonValue && V != CommonValue))

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,8 @@ static void computeKnownBitsFromOperator(const Operator *I, KnownBits &Known,
13531353
for (unsigned i = 0; i != 2; ++i) {
13541354
Value *L = P->getIncomingValue(i);
13551355
Value *R = P->getIncomingValue(!i);
1356+
Instruction *RInst = P->getIncomingBlock(!i)->getTerminator();
1357+
Instruction *LInst = P->getIncomingBlock(i)->getTerminator();
13561358
Operator *LU = dyn_cast<Operator>(L);
13571359
if (!LU)
13581360
continue;
@@ -1374,13 +1376,22 @@ static void computeKnownBitsFromOperator(const Operator *I, KnownBits &Known,
13741376
L = LL;
13751377
else
13761378
continue; // Check for recurrence with L and R flipped.
1379+
1380+
// Change the context instruction to the "edge" that flows into the
1381+
// phi. This is important because that is where the value is actually
1382+
// "evaluated" even though it is used later somewhere else. (see also
1383+
// D69571).
1384+
Query RecQ = Q;
1385+
13771386
// Ok, we have a PHI of the form L op= R. Check for low
13781387
// zero bits.
1379-
computeKnownBits(R, Known2, Depth + 1, Q);
1388+
RecQ.CxtI = RInst;
1389+
computeKnownBits(R, Known2, Depth + 1, RecQ);
13801390

13811391
// We need to take the minimum number of known bits
13821392
KnownBits Known3(Known);
1383-
computeKnownBits(L, Known3, Depth + 1, Q);
1393+
RecQ.CxtI = LInst;
1394+
computeKnownBits(L, Known3, Depth + 1, RecQ);
13841395

13851396
Known.Zero.setLowBits(std::min(Known2.countMinTrailingZeros(),
13861397
Known3.countMinTrailingZeros()));
@@ -1436,14 +1447,22 @@ static void computeKnownBitsFromOperator(const Operator *I, KnownBits &Known,
14361447

14371448
Known.Zero.setAllBits();
14381449
Known.One.setAllBits();
1439-
for (Value *IncValue : P->incoming_values()) {
1450+
for (unsigned u = 0, e = P->getNumIncomingValues(); u < e; ++u) {
1451+
Value *IncValue = P->getIncomingValue(u);
14401452
// Skip direct self references.
14411453
if (IncValue == P) continue;
14421454

1455+
// Change the context instruction to the "edge" that flows into the
1456+
// phi. This is important because that is where the value is actually
1457+
// "evaluated" even though it is used later somewhere else. (see also
1458+
// D69571).
1459+
Query RecQ = Q;
1460+
RecQ.CxtI = P->getIncomingBlock(u)->getTerminator();
1461+
14431462
Known2 = KnownBits(BitWidth);
14441463
// Recurse, but cap the recursion to one level, because we don't
14451464
// want to waste time spinning around in loops.
1446-
computeKnownBits(IncValue, Known2, MaxDepth - 1, Q);
1465+
computeKnownBits(IncValue, Known2, MaxDepth - 1, RecQ);
14471466
Known.Zero &= Known2.Zero;
14481467
Known.One &= Known2.One;
14491468
// If all bits have been ruled out, there's no need to check
@@ -1902,8 +1921,8 @@ static bool isGEPKnownNonNull(const GEPOperator *GEP, unsigned Depth,
19021921
static bool isKnownNonNullFromDominatingCondition(const Value *V,
19031922
const Instruction *CtxI,
19041923
const DominatorTree *DT) {
1905-
assert(V->getType()->isPointerTy() && "V must be pointer type");
1906-
assert(!isa<ConstantData>(V) && "Did not expect ConstantPointerNull");
1924+
if (isa<Constant>(V))
1925+
return false;
19071926

19081927
if (!CtxI || !DT)
19091928
return false;
@@ -2078,12 +2097,11 @@ bool isKnownNonZero(const Value *V, unsigned Depth, const Query &Q) {
20782097
}
20792098
}
20802099

2100+
if (isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
2101+
return true;
20812102

20822103
// Check for recursive pointer simplifications.
20832104
if (V->getType()->isPointerTy()) {
2084-
if (isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
2085-
return true;
2086-
20872105
// Look through bitcast operations, GEPs, and int2ptr instructions as they
20882106
// do not alter the value, or at least not the nullness property of the
20892107
// value, e.g., int2ptr is allowed to zero/sign extend the value.

llvm/test/Transforms/Attributor/nonnull.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ define void @PR43833_simple(i32* %0, i32 %1) {
789789
; ATTRIBUTOR_NPM-NEXT: ret void
790790
; ATTRIBUTOR_NPM: 8:
791791
; ATTRIBUTOR_NPM-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
792-
; ATTRIBUTOR_NPM-NEXT: tail call void @sink(i32* [[TMP6]])
792+
; ATTRIBUTOR_NPM-NEXT: tail call void @sink(i32* nonnull [[TMP6]])
793793
; ATTRIBUTOR_NPM-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
794794
; ATTRIBUTOR_NPM-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
795795
; ATTRIBUTOR_NPM-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]

llvm/test/Transforms/InstCombine/known-non-zero.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ define i32 @test0(i64 %x) {
1313
; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[X:%.*]], 0
1414
; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]]
1515
; CHECK: non_zero:
16-
; CHECK-NEXT: [[CTZ:%.*]] = call i64 @llvm.cttz.i64(i64 [[X]], i1 false), !range !0
16+
; CHECK-NEXT: [[CTZ:%.*]] = call i64 @llvm.cttz.i64(i64 [[X]], i1 true), !range !0
1717
; CHECK-NEXT: [[CTZ32:%.*]] = trunc i64 [[CTZ]] to i32
1818
; CHECK-NEXT: br label [[EXIT]]
1919
; CHECK: exit:
@@ -40,7 +40,7 @@ define i32 @test1(i64 %x) {
4040
; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[X:%.*]], 0
4141
; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]]
4242
; CHECK: non_zero:
43-
; CHECK-NEXT: [[CTZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[X]], i1 false), !range !0
43+
; CHECK-NEXT: [[CTZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[X]], i1 true), !range !0
4444
; CHECK-NEXT: [[CTZ32:%.*]] = trunc i64 [[CTZ]] to i32
4545
; CHECK-NEXT: br label [[EXIT]]
4646
; CHECK: exit:

llvm/test/Transforms/InstSimplify/known-non-zero.ll

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ define i64 @test0(i64 %x) {
77
; CHECK-NEXT: [[A:%.*]] = icmp eq i64 [[X:%.*]], 0
88
; CHECK-NEXT: br i1 [[A]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]]
99
; CHECK: non_zero:
10-
; CHECK-NEXT: [[B:%.*]] = icmp eq i64 [[X]], 0
11-
; CHECK-NEXT: br i1 [[B]], label [[UNREACHABLE:%.*]], label [[EXIT]]
10+
; CHECK-NEXT: br i1 false, label [[UNREACHABLE:%.*]], label [[EXIT]]
1211
; CHECK: unreachable:
1312
; CHECK-NEXT: br label [[EXIT]]
1413
; CHECK: exit:
@@ -37,8 +36,7 @@ define i64 @test1(i64 %x) {
3736
; CHECK-NEXT: [[A:%.*]] = icmp eq i64 [[X:%.*]], 0
3837
; CHECK-NEXT: br i1 [[A]], label [[EXIT:%.*]], label [[NON_ZERO:%.*]]
3938
; CHECK: non_zero:
40-
; CHECK-NEXT: [[B:%.*]] = icmp ugt i64 [[X]], 0
41-
; CHECK-NEXT: br i1 [[B]], label [[EXIT]], label [[UNREACHABLE:%.*]]
39+
; CHECK-NEXT: br i1 true, label [[EXIT]], label [[UNREACHABLE:%.*]]
4240
; CHECK: unreachable:
4341
; CHECK-NEXT: br label [[EXIT]]
4442
; CHECK: exit:
@@ -73,11 +71,9 @@ define i1 @test2(i64 %x, i1 %y) {
7371
; CHECK: two:
7472
; CHECK-NEXT: br label [[MAINBLOCK]]
7573
; CHECK: mainblock:
76-
; CHECK-NEXT: [[P:%.*]] = phi i64 [ [[X]], [[ONE]] ], [ 42, [[TWO]] ]
77-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[P]], 0
7874
; CHECK-NEXT: br label [[EXIT]]
7975
; CHECK: exit:
80-
; CHECK-NEXT: [[RES:%.*]] = phi i1 [ [[CMP]], [[MAINBLOCK]] ], [ true, [[START:%.*]] ]
76+
; CHECK-NEXT: [[RES:%.*]] = phi i1 [ false, [[MAINBLOCK]] ], [ true, [[START:%.*]] ]
8177
; CHECK-NEXT: ret i1 [[RES]]
8278
;
8379
start:
@@ -102,3 +98,50 @@ exit:
10298
%res = phi i1 [ %cmp, %mainblock ], [ 1, %start ]
10399
ret i1 %res
104100
}
101+
102+
103+
; The code below exposed a bug similar to the one exposed by D60846, see the commit 6ea477590085.
104+
; In a nutshell, we should not replace %result.0 with 0 here.
105+
106+
define zeroext i8 @update_phi_query_loc_in_recursive_call(i8* nocapture readonly %p){
107+
; CHECK-LABEL: @update_phi_query_loc_in_recursive_call(
108+
; CHECK-NEXT: entry:
109+
; CHECK-NEXT: br label [[FOR_COND:%.*]]
110+
; CHECK: for.cond:
111+
; CHECK-NEXT: [[RESULT_0:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[CONV2:%.*]], [[FOR_BODY:%.*]] ]
112+
; CHECK-NEXT: [[SHIFT_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ 1, [[FOR_BODY]] ]
113+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[SHIFT_0]], 0
114+
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]
115+
; CHECK: for.cond.cleanup:
116+
; CHECK-NEXT: ret i8 [[RESULT_0]]
117+
; CHECK: for.body:
118+
; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[P:%.*]], align 1
119+
; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[TMP0]] to i32
120+
; CHECK-NEXT: [[MUL:%.*]] = shl nuw nsw i32 [[SHIFT_0]], 3
121+
; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[CONV]], [[MUL]]
122+
; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[SHL]] to i8
123+
; CHECK-NEXT: [[CONV2]] = or i8 [[RESULT_0]], [[TMP1]]
124+
; CHECK-NEXT: br label [[FOR_COND]]
125+
;
126+
entry:
127+
br label %for.cond
128+
129+
for.cond: ; preds = %for.body, %entry
130+
%result.0 = phi i8 [ 0, %entry ], [ %conv2, %for.body ]
131+
%shift.0 = phi i32 [ 0, %entry ], [ 1, %for.body ]
132+
%cmp = icmp eq i32 %shift.0, 0
133+
br i1 %cmp, label %for.body, label %for.cond.cleanup
134+
135+
for.cond.cleanup: ; preds = %for.cond
136+
ret i8 %result.0
137+
138+
for.body: ; preds = %for.cond
139+
%0 = load i8, i8* %p, align 1
140+
%conv = zext i8 %0 to i32
141+
%mul = shl nuw nsw i32 %shift.0, 3
142+
%shl = shl nuw nsw i32 %conv, %mul
143+
%1 = trunc i32 %shl to i8
144+
%conv2 = or i8 %result.0, %1
145+
%inc = add nuw nsw i32 %shift.0, 1
146+
br label %for.cond
147+
}

llvm/test/Transforms/LICM/hoist-mustexec.ll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,23 +129,21 @@ fail:
129129
}
130130

131131
; requires fact length is non-zero
132-
; TODO: IsKnownNonNullFromDominatingConditions is currently only be done for
133-
; pointers; should handle integers too
134132
define i32 @test4(i32* noalias nocapture readonly %a) nounwind uwtable {
135133
; CHECK-LABEL: @test4(
136134
; CHECK-NEXT: entry:
137135
; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[A:%.*]], align 4, !range !0
138136
; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0
139137
; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]]
140138
; CHECK: preheader:
139+
; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[A]], align 4
141140
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
142141
; CHECK: for.body:
143142
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]
144143
; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ]
145144
; CHECK-NEXT: [[R_CHK:%.*]] = icmp ult i32 [[IV]], [[LEN]]
146145
; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]]
147146
; CHECK: continue:
148-
; CHECK-NEXT: [[I1:%.*]] = load i32, i32* [[A]], align 4
149147
; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
150148
; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1
151149
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000

0 commit comments

Comments
 (0)