Skip to content

Commit

Permalink
[ValueTracking] Don't use CondContext in dataflow analysis of phi nod…
Browse files Browse the repository at this point in the history
…es (llvm#100316)

See the following case:
```
define i16 @pr100298() {
entry:
  br label %for.inc

for.inc:
  %indvar = phi i32 [ -15, %entry ], [ %mask, %for.inc ]
  %add = add nsw i32 %indvar, 9
  %mask = and i32 %add, 65535
  %cmp1 = icmp ugt i32 %mask, 5
  br i1 %cmp1, label %for.inc, label %for.end

for.end:
  %conv = trunc i32 %add to i16
  %cmp2 = icmp ugt i32 %mask, 3
  %shl = shl nuw i16 %conv, 14
  %res = select i1 %cmp2, i16 %conv, i16 %shl
  ret i16 %res
}
```

When computing knownbits of `%shl` with `%cmp2=false`, we cannot use
this condition in the analysis of `%mask (%for.inc -> %for.inc)`.
 
Fixes llvm#100298.
  • Loading branch information
dtcxzyw authored Jul 24, 2024
1 parent 559be8e commit 59eae91
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 11 deletions.
6 changes: 6 additions & 0 deletions llvm/include/llvm/Analysis/SimplifyQuery.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ struct SimplifyQuery {
Copy.CC = &CC;
return Copy;
}

SimplifyQuery getWithoutCondContext() const {
SimplifyQuery Copy(*this);
Copy.CC = nullptr;
return Copy;
}
};

} // end namespace llvm
Expand Down
22 changes: 11 additions & 11 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1435,7 +1435,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
// inferred hold at original context instruction. TODO: It may be
// correct to use the original context. IF warranted, explore and
// add sufficient tests to cover.
SimplifyQuery RecQ = Q;
SimplifyQuery RecQ = Q.getWithoutCondContext();
RecQ.CxtI = P;
computeKnownBits(R, DemandedElts, Known2, Depth + 1, RecQ);
switch (Opcode) {
Expand Down Expand Up @@ -1468,7 +1468,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
// phi. This is important because that is where the value is actually
// "evaluated" even though it is used later somewhere else. (see also
// D69571).
SimplifyQuery RecQ = Q;
SimplifyQuery RecQ = Q.getWithoutCondContext();

unsigned OpNum = P->getOperand(0) == R ? 0 : 1;
Instruction *RInst = P->getIncomingBlock(OpNum)->getTerminator();
Expand Down Expand Up @@ -1546,7 +1546,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
// phi. This is important because that is where the value is actually
// "evaluated" even though it is used later somewhere else. (see also
// D69571).
SimplifyQuery RecQ = Q;
SimplifyQuery RecQ = Q.getWithoutCondContext();
RecQ.CxtI = P->getIncomingBlock(u)->getTerminator();

Known2 = KnownBits(BitWidth);
Expand Down Expand Up @@ -2329,7 +2329,7 @@ bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero, unsigned Depth,
// it is an induction variable where in each step its value is a power of
// two.
auto *PN = cast<PHINode>(I);
SimplifyQuery RecQ = Q;
SimplifyQuery RecQ = Q.getWithoutCondContext();

// Check if it is an induction variable and always power of two.
if (isPowerOfTwoRecurrence(PN, OrZero, Depth, RecQ))
Expand Down Expand Up @@ -2943,7 +2943,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
return true;

// Check if all incoming values are non-zero using recursion.
SimplifyQuery RecQ = Q;
SimplifyQuery RecQ = Q.getWithoutCondContext();
unsigned NewDepth = std::max(Depth, MaxAnalysisRecursionDepth - 1);
return llvm::all_of(PN->operands(), [&](const Use &U) {
if (U.get() == PN)
Expand Down Expand Up @@ -3509,7 +3509,7 @@ static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
if (UsedFullRecursion)
return false;

SimplifyQuery RecQ = Q;
SimplifyQuery RecQ = Q.getWithoutCondContext();
RecQ.CxtI = IncomBB->getTerminator();
if (!isKnownNonEqual(IV1, IV2, DemandedElts, Depth + 1, RecQ))
return false;
Expand Down Expand Up @@ -4001,7 +4001,7 @@ static unsigned ComputeNumSignBitsImpl(const Value *V,

// Take the minimum of all incoming values. This can't infinitely loop
// because of our depth threshold.
SimplifyQuery RecQ = Q;
SimplifyQuery RecQ = Q.getWithoutCondContext();
Tmp = TyBits;
for (unsigned i = 0, e = NumIncomingValues; i != e; ++i) {
if (Tmp == 1) return Tmp;
Expand Down Expand Up @@ -5909,10 +5909,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
// Recurse, but cap the recursion to two levels, because we don't want
// to waste time spinning around in loops. We need at least depth 2 to
// detect known sign bits.
computeKnownFPClass(
IncValue, DemandedElts, InterestedClasses, KnownSrc,
PhiRecursionLimit,
Q.getWithInstruction(P->getIncomingBlock(U)->getTerminator()));
computeKnownFPClass(IncValue, DemandedElts, InterestedClasses, KnownSrc,
PhiRecursionLimit,
Q.getWithoutCondContext().getWithInstruction(
P->getIncomingBlock(U)->getTerminator()));

if (First) {
Known = KnownSrc;
Expand Down
39 changes: 39 additions & 0 deletions llvm/test/Transforms/InstCombine/pr100298.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S -passes=instcombine < %s | FileCheck %s

; Make sure that the result of computeKnownBits for %indvar is correct.

define i16 @pr100298() {
; CHECK-LABEL: define i16 @pr100298() {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[FOR_INC:.*]]
; CHECK: [[FOR_INC]]:
; CHECK-NEXT: [[INDVAR:%.*]] = phi i32 [ -15, %[[ENTRY]] ], [ [[MASK:%.*]], %[[FOR_INC]] ]
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[INDVAR]], 9
; CHECK-NEXT: [[MASK]] = and i32 [[ADD]], 65535
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i32 [[MASK]], 5
; CHECK-NEXT: br i1 [[CMP1]], label %[[FOR_INC]], label %[[FOR_END:.*]]
; CHECK: [[FOR_END]]:
; CHECK-NEXT: [[CONV:%.*]] = trunc i32 [[ADD]] to i16
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[MASK]], 3
; CHECK-NEXT: [[SHL:%.*]] = shl nuw i16 [[CONV]], 14
; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP2]], i16 [[CONV]], i16 [[SHL]]
; CHECK-NEXT: ret i16 [[RES]]
;
entry:
br label %for.inc

for.inc:
%indvar = phi i32 [ -15, %entry ], [ %mask, %for.inc ]
%add = add nsw i32 %indvar, 9
%mask = and i32 %add, 65535
%cmp1 = icmp ugt i32 %mask, 5
br i1 %cmp1, label %for.inc, label %for.end

for.end:
%conv = trunc i32 %add to i16
%cmp2 = icmp ugt i32 %mask, 3
%shl = shl nuw i16 %conv, 14
%res = select i1 %cmp2, i16 %conv, i16 %shl
ret i16 %res
}

0 comments on commit 59eae91

Please sign in to comment.