Skip to content

Commit d77067d

Browse files
authored
[ValueTracking] Add dominating condition support in computeKnownBits() (#73662)
This adds support for using dominating conditions in computeKnownBits() when called from InstCombine. The implementation uses a DomConditionCache, which stores which branches may provide information that is relevant for a given value. DomConditionCache is similar to AssumptionCache, but does not try to do any kind of automatic tracking. Relevant branches have to be explicitly registered and invalidated values explicitly removed. The necessary tracking is done inside InstCombine. The reason why this doesn't just do exactly the same thing as AssumptionCache is that a lot more transforms touch branches and branch conditions than assumptions. AssumptionCache is an immutable analysis and mostly gets away with this because only a handful of places have to register additional assumptions (mostly as a result of cloning). This is very much not the case for branches. This change regresses compile-time by about ~0.2%. It also improves stage2-O0-g builds by about ~0.2%, which indicates that this change results in additional optimizations inside clang itself. Fixes #74242.
1 parent a1b9736 commit d77067d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+372
-208
lines changed

clang/test/CodeGenCXX/RelativeVTablesABI/member-function-pointer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
// The loading of the virtual function here should be replaced with a llvm.load.relative() call.
1616
// CHECK-NEXT: [[vtable:%.+]] = load ptr, ptr [[this_adj]], align 8
17-
// CHECK-NEXT: [[offset:%.+]] = add i64 [[fn_ptr]], -1
17+
// CHECK-NEXT: [[offset:%.+]] = add nsw i64 [[fn_ptr]], -1
1818
// CHECK-NEXT: [[ptr:%.+]] = tail call ptr @llvm.load.relative.i64(ptr [[vtable]], i64 [[offset]])
1919
// CHECK-NEXT: br label %[[memptr_end:.+]]
2020
// CHECK: [[nonvirt]]:

clang/test/Headers/__clang_hip_math.hip

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ typedef unsigned long long uint64_t;
4343
// CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_THEN_I:%.*]], label [[CLEANUP_I]]
4444
// CHECK: if.then.i:
4545
// CHECK-NEXT: [[MUL_I:%.*]] = shl i64 [[__R_0_I]], 3
46-
// CHECK-NEXT: [[CONV5_I:%.*]] = sext i8 [[TMP0]] to i64
46+
// CHECK-NEXT: [[CONV5_I:%.*]] = zext nneg i8 [[TMP0]] to i64
4747
// CHECK-NEXT: [[ADD_I:%.*]] = add i64 [[MUL_I]], -48
4848
// CHECK-NEXT: [[SUB_I:%.*]] = add i64 [[ADD_I]], [[CONV5_I]]
4949
// CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I]], i64 1
@@ -75,7 +75,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base8(const char *p) {
7575
// CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_THEN_I:%.*]], label [[CLEANUP_I]]
7676
// CHECK: if.then.i:
7777
// CHECK-NEXT: [[MUL_I:%.*]] = mul i64 [[__R_0_I]], 10
78-
// CHECK-NEXT: [[CONV5_I:%.*]] = sext i8 [[TMP0]] to i64
78+
// CHECK-NEXT: [[CONV5_I:%.*]] = zext nneg i8 [[TMP0]] to i64
7979
// CHECK-NEXT: [[ADD_I:%.*]] = add i64 [[MUL_I]], -48
8080
// CHECK-NEXT: [[SUB_I:%.*]] = add i64 [[ADD_I]], [[CONV5_I]]
8181
// CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I]], i64 1
@@ -116,7 +116,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base10(const char *p) {
116116
// CHECK: if.end31.i:
117117
// CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I]] ], [ -87, [[IF_ELSE_I]] ], [ -55, [[IF_ELSE17_I]] ]
118118
// CHECK-NEXT: [[MUL24_I:%.*]] = shl i64 [[__R_0_I]], 4
119-
// CHECK-NEXT: [[CONV25_I:%.*]] = sext i8 [[TMP0]] to i64
119+
// CHECK-NEXT: [[CONV25_I:%.*]] = zext nneg i8 [[TMP0]] to i64
120120
// CHECK-NEXT: [[ADD26_I:%.*]] = add i64 [[MUL24_I]], [[DOTSINK]]
121121
// CHECK-NEXT: [[ADD28_I:%.*]] = add i64 [[ADD26_I]], [[CONV25_I]]
122122
// CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I]], i64 1
@@ -169,7 +169,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) {
169169
// CHECK: if.end31.i.i:
170170
// CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I]] ], [ -87, [[IF_ELSE_I_I]] ], [ -55, [[IF_ELSE17_I_I]] ]
171171
// CHECK-NEXT: [[MUL24_I_I:%.*]] = shl i64 [[__R_0_I32_I]], 4
172-
// CHECK-NEXT: [[CONV25_I_I:%.*]] = sext i8 [[TMP2]] to i64
172+
// CHECK-NEXT: [[CONV25_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64
173173
// CHECK-NEXT: [[ADD26_I_I:%.*]] = add i64 [[MUL24_I_I]], [[DOTSINK]]
174174
// CHECK-NEXT: [[ADD28_I_I:%.*]] = add i64 [[ADD26_I_I]], [[CONV25_I_I]]
175175
// CHECK-NEXT: [[INCDEC_PTR_I40_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I31_I]], i64 1
@@ -191,7 +191,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) {
191191
// CHECK-NEXT: br i1 [[OR_COND_I_I]], label [[IF_THEN_I_I:%.*]], label [[CLEANUP_I_I]]
192192
// CHECK: if.then.i.i:
193193
// CHECK-NEXT: [[MUL_I_I:%.*]] = shl i64 [[__R_0_I_I]], 3
194-
// CHECK-NEXT: [[CONV5_I_I:%.*]] = sext i8 [[TMP6]] to i64
194+
// CHECK-NEXT: [[CONV5_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64
195195
// CHECK-NEXT: [[ADD_I_I:%.*]] = add i64 [[MUL_I_I]], -48
196196
// CHECK-NEXT: [[SUB_I_I:%.*]] = add i64 [[ADD_I_I]], [[CONV5_I_I]]
197197
// CHECK-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I_I]], i64 1
@@ -212,7 +212,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) {
212212
// CHECK-NEXT: br i1 [[OR_COND_I19_I]], label [[IF_THEN_I24_I:%.*]], label [[CLEANUP_I20_I]]
213213
// CHECK: if.then.i24.i:
214214
// CHECK-NEXT: [[MUL_I25_I:%.*]] = mul i64 [[__R_0_I16_I]], 10
215-
// CHECK-NEXT: [[CONV5_I26_I:%.*]] = sext i8 [[TMP8]] to i64
215+
// CHECK-NEXT: [[CONV5_I26_I:%.*]] = zext nneg i8 [[TMP8]] to i64
216216
// CHECK-NEXT: [[ADD_I27_I:%.*]] = add i64 [[MUL_I25_I]], -48
217217
// CHECK-NEXT: [[SUB_I28_I:%.*]] = add i64 [[ADD_I27_I]], [[CONV5_I26_I]]
218218
// CHECK-NEXT: [[INCDEC_PTR_I29_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I15_I]], i64 1
@@ -2395,7 +2395,7 @@ extern "C" __device__ double test_modf(double x, double* y) {
23952395
// CHECK: if.end31.i.i.i:
23962396
// CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ]
23972397
// CHECK-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4
2398-
// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = sext i8 [[TMP2]] to i64
2398+
// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64
23992399
// CHECK-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]]
24002400
// CHECK-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]]
24012401
// CHECK-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1
@@ -2417,7 +2417,7 @@ extern "C" __device__ double test_modf(double x, double* y) {
24172417
// CHECK-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]]
24182418
// CHECK: if.then.i.i.i:
24192419
// CHECK-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3
2420-
// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = sext i8 [[TMP6]] to i64
2420+
// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64
24212421
// CHECK-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48
24222422
// CHECK-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]]
24232423
// CHECK-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1
@@ -2438,7 +2438,7 @@ extern "C" __device__ double test_modf(double x, double* y) {
24382438
// CHECK-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]]
24392439
// CHECK: if.then.i24.i.i:
24402440
// CHECK-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10
2441-
// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = sext i8 [[TMP8]] to i64
2441+
// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64
24422442
// CHECK-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48
24432443
// CHECK-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]]
24442444
// CHECK-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1
@@ -2494,7 +2494,7 @@ extern "C" __device__ float test_nanf(const char *tag) {
24942494
// CHECK: if.end31.i.i.i:
24952495
// CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ]
24962496
// CHECK-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4
2497-
// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = sext i8 [[TMP2]] to i64
2497+
// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64
24982498
// CHECK-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]]
24992499
// CHECK-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]]
25002500
// CHECK-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1
@@ -2516,7 +2516,7 @@ extern "C" __device__ float test_nanf(const char *tag) {
25162516
// CHECK-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]]
25172517
// CHECK: if.then.i.i.i:
25182518
// CHECK-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3
2519-
// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = sext i8 [[TMP6]] to i64
2519+
// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64
25202520
// CHECK-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48
25212521
// CHECK-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]]
25222522
// CHECK-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1
@@ -2537,7 +2537,7 @@ extern "C" __device__ float test_nanf(const char *tag) {
25372537
// CHECK-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]]
25382538
// CHECK: if.then.i24.i.i:
25392539
// CHECK-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10
2540-
// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = sext i8 [[TMP8]] to i64
2540+
// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64
25412541
// CHECK-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48
25422542
// CHECK-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]]
25432543
// CHECK-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//===- llvm/Analysis/DomConditionCache.h ------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// Cache for branch conditions that affect a certain value for use by
10+
// ValueTracking. Unlike AssumptionCache, this class does not perform any
11+
// automatic analysis or invalidation. The caller is responsible for registering
12+
// all relevant branches (and re-registering them if they change), and for
13+
// removing invalidated values from the cache.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef LLVM_ANALYSIS_DOMCONDITIONCACHE_H
18+
#define LLVM_ANALYSIS_DOMCONDITIONCACHE_H
19+
20+
#include "llvm/ADT/ArrayRef.h"
21+
#include "llvm/ADT/DenseMap.h"
22+
#include "llvm/ADT/DenseMapInfo.h"
23+
#include "llvm/ADT/SmallVector.h"
24+
#include "llvm/IR/ValueHandle.h"
25+
26+
namespace llvm {
27+
28+
class Value;
29+
class BranchInst;
30+
31+
class DomConditionCache {
32+
private:
33+
/// A map of values about which a branch might be providing information.
34+
using AffectedValuesMap = DenseMap<Value *, SmallVector<BranchInst *, 1>>;
35+
AffectedValuesMap AffectedValues;
36+
37+
public:
38+
/// Add a branch condition to the cache.
39+
void registerBranch(BranchInst *BI);
40+
41+
/// Remove a value from the cache, e.g. because it will be erased.
42+
void removeValue(Value *V) { AffectedValues.erase(V); }
43+
44+
/// Access the list of branches which affect this value.
45+
ArrayRef<BranchInst *> conditionsFor(const Value *V) const {
46+
auto AVI = AffectedValues.find_as(const_cast<Value *>(V));
47+
if (AVI == AffectedValues.end())
48+
return ArrayRef<BranchInst *>();
49+
50+
return AVI->second;
51+
}
52+
};
53+
54+
} // end namespace llvm
55+
56+
#endif // LLVM_ANALYSIS_DOMCONDITIONCACHE_H

llvm/include/llvm/Analysis/SimplifyQuery.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace llvm {
1515

1616
class AssumptionCache;
17+
class DomConditionCache;
1718
class DominatorTree;
1819
class TargetLibraryInfo;
1920

@@ -62,6 +63,7 @@ struct SimplifyQuery {
6263
const DominatorTree *DT = nullptr;
6364
AssumptionCache *AC = nullptr;
6465
const Instruction *CxtI = nullptr;
66+
const DomConditionCache *DC = nullptr;
6567

6668
// Wrapper to query additional information for instructions like metadata or
6769
// keywords like nsw, which provides conservative results if those cannot
@@ -80,8 +82,8 @@ struct SimplifyQuery {
8082
const DominatorTree *DT = nullptr,
8183
AssumptionCache *AC = nullptr,
8284
const Instruction *CXTI = nullptr, bool UseInstrInfo = true,
83-
bool CanUseUndef = true)
84-
: DL(DL), TLI(TLI), DT(DT), AC(AC), CxtI(CXTI), IIQ(UseInstrInfo),
85+
bool CanUseUndef = true, const DomConditionCache *DC = nullptr)
86+
: DL(DL), TLI(TLI), DT(DT), AC(AC), CxtI(CXTI), DC(DC), IIQ(UseInstrInfo),
8587
CanUseUndef(CanUseUndef) {}
8688

8789
SimplifyQuery(const DataLayout &DL, const DominatorTree *DT,

llvm/include/llvm/Transforms/InstCombine/InstCombiner.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#ifndef LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINER_H
1919
#define LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINER_H
2020

21+
#include "llvm/Analysis/DomConditionCache.h"
2122
#include "llvm/Analysis/InstructionSimplify.h"
2223
#include "llvm/Analysis/TargetFolder.h"
2324
#include "llvm/Analysis/ValueTracking.h"
@@ -72,10 +73,11 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
7273
TargetLibraryInfo &TLI;
7374
DominatorTree &DT;
7475
const DataLayout &DL;
75-
const SimplifyQuery SQ;
76+
SimplifyQuery SQ;
7677
OptimizationRemarkEmitter &ORE;
7778
BlockFrequencyInfo *BFI;
7879
ProfileSummaryInfo *PSI;
80+
DomConditionCache DC;
7981

8082
// Optional analyses. When non-null, these can both be used to do better
8183
// combining and will be updated to reflect any changes.
@@ -98,7 +100,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
98100
const DataLayout &DL, LoopInfo *LI)
99101
: TTI(TTI), Builder(Builder), Worklist(Worklist),
100102
MinimizeSize(MinimizeSize), AA(AA), AC(AC), TLI(TLI), DT(DT), DL(DL),
101-
SQ(DL, &TLI, &DT, &AC), ORE(ORE), BFI(BFI), PSI(PSI), LI(LI) {}
103+
SQ(DL, &TLI, &DT, &AC, nullptr, /*UseInstrInfo*/ true,
104+
/*CanUseUndef*/ true, &DC),
105+
ORE(ORE), BFI(BFI), PSI(PSI), LI(LI) {}
102106

103107
virtual ~InstCombiner() = default;
104108

llvm/lib/Analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ add_llvm_component_library(LLVMAnalysis
5555
DependenceAnalysis.cpp
5656
DependenceGraphBuilder.cpp
5757
DevelopmentModeInlineAdvisor.cpp
58+
DomConditionCache.cpp
5859
DomPrinter.cpp
5960
DomTreeUpdater.cpp
6061
DominanceFrontier.cpp
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//===- DomConditionCache.cpp ----------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "llvm/Analysis/DomConditionCache.h"
10+
#include "llvm/IR/PatternMatch.h"
11+
12+
using namespace llvm;
13+
using namespace llvm::PatternMatch;
14+
15+
// TODO: This code is very similar to findAffectedValues() in
16+
// AssumptionCache, but currently specialized to just the patterns that
17+
// computeKnownBits() supports, and without the notion of result elem indices
18+
// that are AC specific. Deduplicate this code once we have a clearer picture
19+
// of how much they can be shared.
20+
static void findAffectedValues(Value *Cond,
21+
SmallVectorImpl<Value *> &Affected) {
22+
auto AddAffected = [&Affected](Value *V) {
23+
if (isa<Argument>(V) || isa<GlobalValue>(V)) {
24+
Affected.push_back(V);
25+
} else if (auto *I = dyn_cast<Instruction>(V)) {
26+
Affected.push_back(I);
27+
28+
// Peek through unary operators to find the source of the condition.
29+
Value *Op;
30+
if (match(I, m_PtrToInt(m_Value(Op)))) {
31+
if (isa<Instruction>(Op) || isa<Argument>(Op))
32+
Affected.push_back(Op);
33+
}
34+
}
35+
};
36+
37+
ICmpInst::Predicate Pred;
38+
Value *A;
39+
Constant *C;
40+
if (match(Cond, m_ICmp(Pred, m_Value(A), m_Constant(C)))) {
41+
AddAffected(A);
42+
43+
if (ICmpInst::isEquality(Pred)) {
44+
Value *X;
45+
// (X & C) or (X | C) or (X ^ C).
46+
// (X << C) or (X >>_s C) or (X >>_u C).
47+
if (match(A, m_BitwiseLogic(m_Value(X), m_ConstantInt())) ||
48+
match(A, m_Shift(m_Value(X), m_ConstantInt())))
49+
AddAffected(X);
50+
} else {
51+
Value *X;
52+
// Handle (A + C1) u< C2, which is the canonical form of A > C3 && A < C4.
53+
if (match(A, m_Add(m_Value(X), m_ConstantInt())))
54+
AddAffected(X);
55+
}
56+
}
57+
}
58+
59+
void DomConditionCache::registerBranch(BranchInst *BI) {
60+
assert(BI->isConditional() && "Must be conditional branch");
61+
SmallVector<Value *, 16> Affected;
62+
findAffectedValues(BI->getCondition(), Affected);
63+
for (Value *V : Affected) {
64+
auto &AV = AffectedValues[V];
65+
if (!is_contained(AV, BI))
66+
AV.push_back(BI);
67+
}
68+
}

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "llvm/Analysis/AssumeBundleQueries.h"
2727
#include "llvm/Analysis/AssumptionCache.h"
2828
#include "llvm/Analysis/ConstantFolding.h"
29+
#include "llvm/Analysis/DomConditionCache.h"
2930
#include "llvm/Analysis/GuardUtils.h"
3031
#include "llvm/Analysis/InstructionSimplify.h"
3132
#include "llvm/Analysis/Loads.h"
@@ -706,9 +707,33 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred,
706707

707708
void llvm::computeKnownBitsFromContext(const Value *V, KnownBits &Known,
708709
unsigned Depth, const SimplifyQuery &Q) {
709-
// Use of assumptions is context-sensitive. If we don't have a context, we
710-
// cannot use them!
711-
if (!Q.AC || !Q.CxtI)
710+
if (!Q.CxtI)
711+
return;
712+
713+
if (Q.DC && Q.DT) {
714+
// Handle dominating conditions.
715+
for (BranchInst *BI : Q.DC->conditionsFor(V)) {
716+
auto *Cmp = dyn_cast<ICmpInst>(BI->getCondition());
717+
if (!Cmp)
718+
continue;
719+
720+
BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
721+
if (Q.DT->dominates(Edge0, Q.CxtI->getParent()))
722+
computeKnownBitsFromCmp(V, Cmp->getPredicate(), Cmp->getOperand(0),
723+
Cmp->getOperand(1), Known, Depth, Q);
724+
725+
BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
726+
if (Q.DT->dominates(Edge1, Q.CxtI->getParent()))
727+
computeKnownBitsFromCmp(V, Cmp->getInversePredicate(),
728+
Cmp->getOperand(0), Cmp->getOperand(1), Known,
729+
Depth, Q);
730+
}
731+
732+
if (Known.hasConflict())
733+
Known.resetAll();
734+
}
735+
736+
if (!Q.AC)
712737
return;
713738

714739
unsigned BitWidth = Known.getBitWidth();

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "InstCombineInternal.h"
1414
#include "llvm/ADT/APSInt.h"
15+
#include "llvm/ADT/ScopeExit.h"
1516
#include "llvm/ADT/SetVector.h"
1617
#include "llvm/ADT/Statistic.h"
1718
#include "llvm/Analysis/CaptureTracking.h"
@@ -6113,13 +6114,19 @@ Instruction *InstCombinerImpl::foldICmpUsingKnownBits(ICmpInst &I) {
61136114
KnownBits Op0Known(BitWidth);
61146115
KnownBits Op1Known(BitWidth);
61156116

6116-
if (SimplifyDemandedBits(&I, 0,
6117-
getDemandedBitsLHSMask(I, BitWidth),
6118-
Op0Known, 0))
6119-
return &I;
6117+
{
6118+
// Don't use dominating conditions when folding icmp using known bits. This
6119+
// may convert signed into unsigned predicates in ways that other passes
6120+
// (especially IndVarSimplify) may not be able to reliably undo.
6121+
SQ.DC = nullptr;
6122+
auto _ = make_scope_exit([&]() { SQ.DC = &DC; });
6123+
if (SimplifyDemandedBits(&I, 0, getDemandedBitsLHSMask(I, BitWidth),
6124+
Op0Known, 0))
6125+
return &I;
61206126

6121-
if (SimplifyDemandedBits(&I, 1, APInt::getAllOnes(BitWidth), Op1Known, 0))
6122-
return &I;
6127+
if (SimplifyDemandedBits(&I, 1, APInt::getAllOnes(BitWidth), Op1Known, 0))
6128+
return &I;
6129+
}
61236130

61246131
// Given the known and unknown bits, compute a range that the LHS could be
61256132
// in. Compute the Min, Max and RHS values based on the known bits. For the

llvm/lib/Transforms/InstCombine/InstCombineInternal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
459459
// use counts.
460460
SmallVector<Value *> Ops(I.operands());
461461
Worklist.remove(&I);
462+
DC.removeValue(&I);
462463
I.eraseFromParent();
463464
for (Value *Op : Ops)
464465
Worklist.handleUseCountDecrement(Op);

0 commit comments

Comments
 (0)