Skip to content

Commit

Permalink
[ValueTracking] Add dominating condition support in computeKnownBits() (
Browse files Browse the repository at this point in the history
#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.
  • Loading branch information
nikic committed Dec 6, 2023
1 parent a1b9736 commit d77067d
Show file tree
Hide file tree
Showing 44 changed files with 372 additions and 208 deletions.
Expand Up @@ -14,7 +14,7 @@

// The loading of the virtual function here should be replaced with a llvm.load.relative() call.
// CHECK-NEXT: [[vtable:%.+]] = load ptr, ptr [[this_adj]], align 8
// CHECK-NEXT: [[offset:%.+]] = add i64 [[fn_ptr]], -1
// CHECK-NEXT: [[offset:%.+]] = add nsw i64 [[fn_ptr]], -1
// CHECK-NEXT: [[ptr:%.+]] = tail call ptr @llvm.load.relative.i64(ptr [[vtable]], i64 [[offset]])
// CHECK-NEXT: br label %[[memptr_end:.+]]
// CHECK: [[nonvirt]]:
Expand Down
24 changes: 12 additions & 12 deletions clang/test/Headers/__clang_hip_math.hip
Expand Up @@ -43,7 +43,7 @@ typedef unsigned long long uint64_t;
// CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_THEN_I:%.*]], label [[CLEANUP_I]]
// CHECK: if.then.i:
// CHECK-NEXT: [[MUL_I:%.*]] = shl i64 [[__R_0_I]], 3
// CHECK-NEXT: [[CONV5_I:%.*]] = sext i8 [[TMP0]] to i64
// CHECK-NEXT: [[CONV5_I:%.*]] = zext nneg i8 [[TMP0]] to i64
// CHECK-NEXT: [[ADD_I:%.*]] = add i64 [[MUL_I]], -48
// CHECK-NEXT: [[SUB_I:%.*]] = add i64 [[ADD_I]], [[CONV5_I]]
// CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I]], i64 1
Expand Down Expand Up @@ -75,7 +75,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base8(const char *p) {
// CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_THEN_I:%.*]], label [[CLEANUP_I]]
// CHECK: if.then.i:
// CHECK-NEXT: [[MUL_I:%.*]] = mul i64 [[__R_0_I]], 10
// CHECK-NEXT: [[CONV5_I:%.*]] = sext i8 [[TMP0]] to i64
// CHECK-NEXT: [[CONV5_I:%.*]] = zext nneg i8 [[TMP0]] to i64
// CHECK-NEXT: [[ADD_I:%.*]] = add i64 [[MUL_I]], -48
// CHECK-NEXT: [[SUB_I:%.*]] = add i64 [[ADD_I]], [[CONV5_I]]
// CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I]], i64 1
Expand Down Expand Up @@ -116,7 +116,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base10(const char *p) {
// CHECK: if.end31.i:
// CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I]] ], [ -87, [[IF_ELSE_I]] ], [ -55, [[IF_ELSE17_I]] ]
// CHECK-NEXT: [[MUL24_I:%.*]] = shl i64 [[__R_0_I]], 4
// CHECK-NEXT: [[CONV25_I:%.*]] = sext i8 [[TMP0]] to i64
// CHECK-NEXT: [[CONV25_I:%.*]] = zext nneg i8 [[TMP0]] to i64
// CHECK-NEXT: [[ADD26_I:%.*]] = add i64 [[MUL24_I]], [[DOTSINK]]
// CHECK-NEXT: [[ADD28_I:%.*]] = add i64 [[ADD26_I]], [[CONV25_I]]
// CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I]], i64 1
Expand Down Expand Up @@ -169,7 +169,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) {
// CHECK: if.end31.i.i:
// CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I]] ], [ -87, [[IF_ELSE_I_I]] ], [ -55, [[IF_ELSE17_I_I]] ]
// CHECK-NEXT: [[MUL24_I_I:%.*]] = shl i64 [[__R_0_I32_I]], 4
// CHECK-NEXT: [[CONV25_I_I:%.*]] = sext i8 [[TMP2]] to i64
// CHECK-NEXT: [[CONV25_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64
// CHECK-NEXT: [[ADD26_I_I:%.*]] = add i64 [[MUL24_I_I]], [[DOTSINK]]
// CHECK-NEXT: [[ADD28_I_I:%.*]] = add i64 [[ADD26_I_I]], [[CONV25_I_I]]
// CHECK-NEXT: [[INCDEC_PTR_I40_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I31_I]], i64 1
Expand All @@ -191,7 +191,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) {
// CHECK-NEXT: br i1 [[OR_COND_I_I]], label [[IF_THEN_I_I:%.*]], label [[CLEANUP_I_I]]
// CHECK: if.then.i.i:
// CHECK-NEXT: [[MUL_I_I:%.*]] = shl i64 [[__R_0_I_I]], 3
// CHECK-NEXT: [[CONV5_I_I:%.*]] = sext i8 [[TMP6]] to i64
// CHECK-NEXT: [[CONV5_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64
// CHECK-NEXT: [[ADD_I_I:%.*]] = add i64 [[MUL_I_I]], -48
// CHECK-NEXT: [[SUB_I_I:%.*]] = add i64 [[ADD_I_I]], [[CONV5_I_I]]
// CHECK-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I_I]], i64 1
Expand All @@ -212,7 +212,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) {
// CHECK-NEXT: br i1 [[OR_COND_I19_I]], label [[IF_THEN_I24_I:%.*]], label [[CLEANUP_I20_I]]
// CHECK: if.then.i24.i:
// CHECK-NEXT: [[MUL_I25_I:%.*]] = mul i64 [[__R_0_I16_I]], 10
// CHECK-NEXT: [[CONV5_I26_I:%.*]] = sext i8 [[TMP8]] to i64
// CHECK-NEXT: [[CONV5_I26_I:%.*]] = zext nneg i8 [[TMP8]] to i64
// CHECK-NEXT: [[ADD_I27_I:%.*]] = add i64 [[MUL_I25_I]], -48
// CHECK-NEXT: [[SUB_I28_I:%.*]] = add i64 [[ADD_I27_I]], [[CONV5_I26_I]]
// CHECK-NEXT: [[INCDEC_PTR_I29_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I15_I]], i64 1
Expand Down Expand Up @@ -2395,7 +2395,7 @@ extern "C" __device__ double test_modf(double x, double* y) {
// CHECK: if.end31.i.i.i:
// CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ]
// CHECK-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4
// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = sext i8 [[TMP2]] to i64
// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64
// CHECK-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]]
// CHECK-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]]
// CHECK-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1
Expand All @@ -2417,7 +2417,7 @@ extern "C" __device__ double test_modf(double x, double* y) {
// CHECK-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]]
// CHECK: if.then.i.i.i:
// CHECK-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3
// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = sext i8 [[TMP6]] to i64
// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64
// CHECK-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48
// CHECK-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]]
// CHECK-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1
Expand All @@ -2438,7 +2438,7 @@ extern "C" __device__ double test_modf(double x, double* y) {
// CHECK-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]]
// CHECK: if.then.i24.i.i:
// CHECK-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10
// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = sext i8 [[TMP8]] to i64
// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64
// CHECK-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48
// CHECK-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]]
// CHECK-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1
Expand Down Expand Up @@ -2494,7 +2494,7 @@ extern "C" __device__ float test_nanf(const char *tag) {
// CHECK: if.end31.i.i.i:
// CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ]
// CHECK-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4
// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = sext i8 [[TMP2]] to i64
// CHECK-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64
// CHECK-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]]
// CHECK-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]]
// CHECK-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1
Expand All @@ -2516,7 +2516,7 @@ extern "C" __device__ float test_nanf(const char *tag) {
// CHECK-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]]
// CHECK: if.then.i.i.i:
// CHECK-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3
// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = sext i8 [[TMP6]] to i64
// CHECK-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64
// CHECK-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48
// CHECK-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]]
// CHECK-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1
Expand All @@ -2537,7 +2537,7 @@ extern "C" __device__ float test_nanf(const char *tag) {
// CHECK-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]]
// CHECK: if.then.i24.i.i:
// CHECK-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10
// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = sext i8 [[TMP8]] to i64
// CHECK-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64
// CHECK-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48
// CHECK-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]]
// CHECK-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1
Expand Down
56 changes: 56 additions & 0 deletions llvm/include/llvm/Analysis/DomConditionCache.h
@@ -0,0 +1,56 @@
//===- llvm/Analysis/DomConditionCache.h ------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Cache for branch conditions that affect a certain value for use by
// ValueTracking. Unlike AssumptionCache, this class does not perform any
// automatic analysis or invalidation. The caller is responsible for registering
// all relevant branches (and re-registering them if they change), and for
// removing invalidated values from the cache.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_ANALYSIS_DOMCONDITIONCACHE_H
#define LLVM_ANALYSIS_DOMCONDITIONCACHE_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/ValueHandle.h"

namespace llvm {

class Value;
class BranchInst;

class DomConditionCache {
private:
/// A map of values about which a branch might be providing information.
using AffectedValuesMap = DenseMap<Value *, SmallVector<BranchInst *, 1>>;
AffectedValuesMap AffectedValues;

public:
/// Add a branch condition to the cache.
void registerBranch(BranchInst *BI);

/// Remove a value from the cache, e.g. because it will be erased.
void removeValue(Value *V) { AffectedValues.erase(V); }

/// Access the list of branches which affect this value.
ArrayRef<BranchInst *> conditionsFor(const Value *V) const {
auto AVI = AffectedValues.find_as(const_cast<Value *>(V));
if (AVI == AffectedValues.end())
return ArrayRef<BranchInst *>();

return AVI->second;
}
};

} // end namespace llvm

#endif // LLVM_ANALYSIS_DOMCONDITIONCACHE_H
6 changes: 4 additions & 2 deletions llvm/include/llvm/Analysis/SimplifyQuery.h
Expand Up @@ -14,6 +14,7 @@
namespace llvm {

class AssumptionCache;
class DomConditionCache;
class DominatorTree;
class TargetLibraryInfo;

Expand Down Expand Up @@ -62,6 +63,7 @@ struct SimplifyQuery {
const DominatorTree *DT = nullptr;
AssumptionCache *AC = nullptr;
const Instruction *CxtI = nullptr;
const DomConditionCache *DC = nullptr;

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

SimplifyQuery(const DataLayout &DL, const DominatorTree *DT,
Expand Down
8 changes: 6 additions & 2 deletions llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
Expand Up @@ -18,6 +18,7 @@
#ifndef LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINER_H
#define LLVM_TRANSFORMS_INSTCOMBINE_INSTCOMBINER_H

#include "llvm/Analysis/DomConditionCache.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/TargetFolder.h"
#include "llvm/Analysis/ValueTracking.h"
Expand Down Expand Up @@ -72,10 +73,11 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner {
TargetLibraryInfo &TLI;
DominatorTree &DT;
const DataLayout &DL;
const SimplifyQuery SQ;
SimplifyQuery SQ;
OptimizationRemarkEmitter &ORE;
BlockFrequencyInfo *BFI;
ProfileSummaryInfo *PSI;
DomConditionCache DC;

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

virtual ~InstCombiner() = default;

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Analysis/CMakeLists.txt
Expand Up @@ -55,6 +55,7 @@ add_llvm_component_library(LLVMAnalysis
DependenceAnalysis.cpp
DependenceGraphBuilder.cpp
DevelopmentModeInlineAdvisor.cpp
DomConditionCache.cpp
DomPrinter.cpp
DomTreeUpdater.cpp
DominanceFrontier.cpp
Expand Down
68 changes: 68 additions & 0 deletions llvm/lib/Analysis/DomConditionCache.cpp
@@ -0,0 +1,68 @@
//===- DomConditionCache.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DomConditionCache.h"
#include "llvm/IR/PatternMatch.h"

using namespace llvm;
using namespace llvm::PatternMatch;

// TODO: This code is very similar to findAffectedValues() in
// AssumptionCache, but currently specialized to just the patterns that
// computeKnownBits() supports, and without the notion of result elem indices
// that are AC specific. Deduplicate this code once we have a clearer picture
// of how much they can be shared.
static void findAffectedValues(Value *Cond,
SmallVectorImpl<Value *> &Affected) {
auto AddAffected = [&Affected](Value *V) {
if (isa<Argument>(V) || isa<GlobalValue>(V)) {
Affected.push_back(V);
} else if (auto *I = dyn_cast<Instruction>(V)) {
Affected.push_back(I);

// Peek through unary operators to find the source of the condition.
Value *Op;
if (match(I, m_PtrToInt(m_Value(Op)))) {
if (isa<Instruction>(Op) || isa<Argument>(Op))
Affected.push_back(Op);
}
}
};

ICmpInst::Predicate Pred;
Value *A;
Constant *C;
if (match(Cond, m_ICmp(Pred, m_Value(A), m_Constant(C)))) {
AddAffected(A);

if (ICmpInst::isEquality(Pred)) {
Value *X;
// (X & C) or (X | C) or (X ^ C).
// (X << C) or (X >>_s C) or (X >>_u C).
if (match(A, m_BitwiseLogic(m_Value(X), m_ConstantInt())) ||
match(A, m_Shift(m_Value(X), m_ConstantInt())))
AddAffected(X);
} else {
Value *X;
// Handle (A + C1) u< C2, which is the canonical form of A > C3 && A < C4.
if (match(A, m_Add(m_Value(X), m_ConstantInt())))
AddAffected(X);
}
}
}

void DomConditionCache::registerBranch(BranchInst *BI) {
assert(BI->isConditional() && "Must be conditional branch");
SmallVector<Value *, 16> Affected;
findAffectedValues(BI->getCondition(), Affected);
for (Value *V : Affected) {
auto &AV = AffectedValues[V];
if (!is_contained(AV, BI))
AV.push_back(BI);
}
}
31 changes: 28 additions & 3 deletions llvm/lib/Analysis/ValueTracking.cpp
Expand Up @@ -26,6 +26,7 @@
#include "llvm/Analysis/AssumeBundleQueries.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/DomConditionCache.h"
#include "llvm/Analysis/GuardUtils.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/Loads.h"
Expand Down Expand Up @@ -706,9 +707,33 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred,

void llvm::computeKnownBitsFromContext(const Value *V, KnownBits &Known,
unsigned Depth, const SimplifyQuery &Q) {
// Use of assumptions is context-sensitive. If we don't have a context, we
// cannot use them!
if (!Q.AC || !Q.CxtI)
if (!Q.CxtI)
return;

if (Q.DC && Q.DT) {
// Handle dominating conditions.
for (BranchInst *BI : Q.DC->conditionsFor(V)) {
auto *Cmp = dyn_cast<ICmpInst>(BI->getCondition());
if (!Cmp)
continue;

BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
if (Q.DT->dominates(Edge0, Q.CxtI->getParent()))
computeKnownBitsFromCmp(V, Cmp->getPredicate(), Cmp->getOperand(0),
Cmp->getOperand(1), Known, Depth, Q);

BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
if (Q.DT->dominates(Edge1, Q.CxtI->getParent()))
computeKnownBitsFromCmp(V, Cmp->getInversePredicate(),
Cmp->getOperand(0), Cmp->getOperand(1), Known,
Depth, Q);
}

if (Known.hasConflict())
Known.resetAll();
}

if (!Q.AC)
return;

unsigned BitWidth = Known.getBitWidth();
Expand Down
19 changes: 13 additions & 6 deletions llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
Expand Up @@ -12,6 +12,7 @@

#include "InstCombineInternal.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/CaptureTracking.h"
Expand Down Expand Up @@ -6113,13 +6114,19 @@ Instruction *InstCombinerImpl::foldICmpUsingKnownBits(ICmpInst &I) {
KnownBits Op0Known(BitWidth);
KnownBits Op1Known(BitWidth);

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

if (SimplifyDemandedBits(&I, 1, APInt::getAllOnes(BitWidth), Op1Known, 0))
return &I;
if (SimplifyDemandedBits(&I, 1, APInt::getAllOnes(BitWidth), Op1Known, 0))
return &I;
}

// Given the known and unknown bits, compute a range that the LHS could be
// in. Compute the Min, Max and RHS values based on the known bits. For the
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineInternal.h
Expand Up @@ -459,6 +459,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
// use counts.
SmallVector<Value *> Ops(I.operands());
Worklist.remove(&I);
DC.removeValue(&I);
I.eraseFromParent();
for (Value *Op : Ops)
Worklist.handleUseCountDecrement(Op);
Expand Down

0 comments on commit d77067d

Please sign in to comment.