forked from OSchip/llvm-project
[ValueTracking,VectorCombine] Allow passing DT to computeConstantRange.
isValidAssumeForContext can provide better results with access to the dominator tree in some cases. This patch adjusts computeConstantRange to allow passing through a dominator tree. The use VectorCombine is updated to pass through the DT to enable additional scalarization. Note that similar APIs like computeKnownBits already accept optional dominator tree arguments. Reviewed By: lebedev.ri Differential Revision: https://reviews.llvm.org/D110175
This commit is contained in:
parent
5fb3ae525f
commit
5131037ea9
|
@ -549,6 +549,7 @@ constexpr unsigned MaxAnalysisRecursionDepth = 6;
|
||||||
ConstantRange computeConstantRange(const Value *V, bool UseInstrInfo = true,
|
ConstantRange computeConstantRange(const Value *V, bool UseInstrInfo = true,
|
||||||
AssumptionCache *AC = nullptr,
|
AssumptionCache *AC = nullptr,
|
||||||
const Instruction *CtxI = nullptr,
|
const Instruction *CtxI = nullptr,
|
||||||
|
const DominatorTree *DT = nullptr,
|
||||||
unsigned Depth = 0);
|
unsigned Depth = 0);
|
||||||
|
|
||||||
/// Return true if this function can prove that the instruction I will
|
/// Return true if this function can prove that the instruction I will
|
||||||
|
|
|
@ -7031,6 +7031,7 @@ static void setLimitsForSelectPattern(const SelectInst &SI, APInt &Lower,
|
||||||
ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo,
|
ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo,
|
||||||
AssumptionCache *AC,
|
AssumptionCache *AC,
|
||||||
const Instruction *CtxI,
|
const Instruction *CtxI,
|
||||||
|
const DominatorTree *DT,
|
||||||
unsigned Depth) {
|
unsigned Depth) {
|
||||||
assert(V->getType()->isIntOrIntVectorTy() && "Expected integer instruction");
|
assert(V->getType()->isIntOrIntVectorTy() && "Expected integer instruction");
|
||||||
|
|
||||||
|
@ -7069,7 +7070,7 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo,
|
||||||
assert(I->getCalledFunction()->getIntrinsicID() == Intrinsic::assume &&
|
assert(I->getCalledFunction()->getIntrinsicID() == Intrinsic::assume &&
|
||||||
"must be an assume intrinsic");
|
"must be an assume intrinsic");
|
||||||
|
|
||||||
if (!isValidAssumeForContext(I, CtxI, nullptr))
|
if (!isValidAssumeForContext(I, CtxI, DT))
|
||||||
continue;
|
continue;
|
||||||
Value *Arg = I->getArgOperand(0);
|
Value *Arg = I->getArgOperand(0);
|
||||||
ICmpInst *Cmp = dyn_cast<ICmpInst>(Arg);
|
ICmpInst *Cmp = dyn_cast<ICmpInst>(Arg);
|
||||||
|
@ -7077,7 +7078,7 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo,
|
||||||
if (!Cmp || Cmp->getOperand(0) != V)
|
if (!Cmp || Cmp->getOperand(0) != V)
|
||||||
continue;
|
continue;
|
||||||
ConstantRange RHS = computeConstantRange(Cmp->getOperand(1), UseInstrInfo,
|
ConstantRange RHS = computeConstantRange(Cmp->getOperand(1), UseInstrInfo,
|
||||||
AC, I, Depth + 1);
|
AC, I, DT, Depth + 1);
|
||||||
CR = CR.intersectWith(
|
CR = CR.intersectWith(
|
||||||
ConstantRange::makeAllowedICmpRegion(Cmp->getPredicate(), RHS));
|
ConstantRange::makeAllowedICmpRegion(Cmp->getPredicate(), RHS));
|
||||||
}
|
}
|
||||||
|
|
|
@ -827,7 +827,8 @@ public:
|
||||||
/// Idx. \p Idx must access a valid vector element.
|
/// Idx. \p Idx must access a valid vector element.
|
||||||
static ScalarizationResult canScalarizeAccess(FixedVectorType *VecTy,
|
static ScalarizationResult canScalarizeAccess(FixedVectorType *VecTy,
|
||||||
Value *Idx, Instruction *CtxI,
|
Value *Idx, Instruction *CtxI,
|
||||||
AssumptionCache &AC) {
|
AssumptionCache &AC,
|
||||||
|
const DominatorTree &DT) {
|
||||||
if (auto *C = dyn_cast<ConstantInt>(Idx)) {
|
if (auto *C = dyn_cast<ConstantInt>(Idx)) {
|
||||||
if (C->getValue().ult(VecTy->getNumElements()))
|
if (C->getValue().ult(VecTy->getNumElements()))
|
||||||
return ScalarizationResult::safe();
|
return ScalarizationResult::safe();
|
||||||
|
@ -841,7 +842,7 @@ static ScalarizationResult canScalarizeAccess(FixedVectorType *VecTy,
|
||||||
ConstantRange IdxRange(IntWidth, true);
|
ConstantRange IdxRange(IntWidth, true);
|
||||||
|
|
||||||
if (isGuaranteedNotToBePoison(Idx, &AC)) {
|
if (isGuaranteedNotToBePoison(Idx, &AC)) {
|
||||||
if (ValidIndices.contains(computeConstantRange(Idx, true, &AC, CtxI, 0)))
|
if (ValidIndices.contains(computeConstantRange(Idx, true, &AC, CtxI, &DT)))
|
||||||
return ScalarizationResult::safe();
|
return ScalarizationResult::safe();
|
||||||
return ScalarizationResult::unsafe();
|
return ScalarizationResult::unsafe();
|
||||||
}
|
}
|
||||||
|
@ -909,7 +910,7 @@ bool VectorCombine::foldSingleElementStore(Instruction &I) {
|
||||||
SrcAddr != SI->getPointerOperand()->stripPointerCasts())
|
SrcAddr != SI->getPointerOperand()->stripPointerCasts())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto ScalarizableIdx = canScalarizeAccess(VecTy, Idx, Load, AC);
|
auto ScalarizableIdx = canScalarizeAccess(VecTy, Idx, Load, AC, DT);
|
||||||
if (ScalarizableIdx.isUnsafe() ||
|
if (ScalarizableIdx.isUnsafe() ||
|
||||||
isMemModifiedBetween(Load->getIterator(), SI->getIterator(),
|
isMemModifiedBetween(Load->getIterator(), SI->getIterator(),
|
||||||
MemoryLocation::get(SI), AA))
|
MemoryLocation::get(SI), AA))
|
||||||
|
@ -987,7 +988,7 @@ bool VectorCombine::scalarizeLoadExtract(Instruction &I) {
|
||||||
else if (LastCheckedInst->comesBefore(UI))
|
else if (LastCheckedInst->comesBefore(UI))
|
||||||
LastCheckedInst = UI;
|
LastCheckedInst = UI;
|
||||||
|
|
||||||
auto ScalarIdx = canScalarizeAccess(FixedVT, UI->getOperand(1), &I, AC);
|
auto ScalarIdx = canScalarizeAccess(FixedVT, UI->getOperand(1), &I, AC, DT);
|
||||||
if (!ScalarIdx.isSafe()) {
|
if (!ScalarIdx.isSafe()) {
|
||||||
// TODO: Freeze index if it is safe to do so.
|
// TODO: Freeze index if it is safe to do so.
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -74,8 +74,8 @@ define void @load_extract_insert_store_var_idx_assume_valid_in_dominating_block(
|
||||||
; CHECK-NEXT: [[MUL:%.*]] = fmul double 2.000000e+01, [[EXT_0]]
|
; CHECK-NEXT: [[MUL:%.*]] = fmul double 2.000000e+01, [[EXT_0]]
|
||||||
; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <225 x double> [[LV]], i64 [[IDX_2]]
|
; CHECK-NEXT: [[EXT_1:%.*]] = extractelement <225 x double> [[LV]], i64 [[IDX_2]]
|
||||||
; CHECK-NEXT: [[SUB:%.*]] = fsub double [[EXT_1]], [[MUL]]
|
; CHECK-NEXT: [[SUB:%.*]] = fsub double [[EXT_1]], [[MUL]]
|
||||||
; CHECK-NEXT: [[INS:%.*]] = insertelement <225 x double> [[LV]], double [[SUB]], i64 [[IDX_1]]
|
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <225 x double>, <225 x double>* [[A]], i64 0, i64 [[IDX_1]]
|
||||||
; CHECK-NEXT: store <225 x double> [[INS]], <225 x double>* [[A]], align 8
|
; CHECK-NEXT: store double [[SUB]], double* [[TMP0]], align 8
|
||||||
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
|
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
|
||||||
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP]], label [[EXIT]]
|
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP]], label [[EXIT]]
|
||||||
; CHECK: exit:
|
; CHECK: exit:
|
||||||
|
|
|
@ -114,9 +114,9 @@ define i32 @load_extract_idx_var_i64_known_valid_by_assume_in_dominating_block(<
|
||||||
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
|
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
|
||||||
; CHECK-NEXT: br i1 [[C_1:%.*]], label [[LOOP:%.*]], label [[EXIT:%.*]]
|
; CHECK-NEXT: br i1 [[C_1:%.*]], label [[LOOP:%.*]], label [[EXIT:%.*]]
|
||||||
; CHECK: loop:
|
; CHECK: loop:
|
||||||
; CHECK-NEXT: [[LV:%.*]] = load <4 x i32>, <4 x i32>* [[X:%.*]], align 16
|
|
||||||
; CHECK-NEXT: call void @maythrow()
|
; CHECK-NEXT: call void @maythrow()
|
||||||
; CHECK-NEXT: [[R:%.*]] = extractelement <4 x i32> [[LV]], i64 [[IDX]]
|
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <4 x i32>, <4 x i32>* [[X:%.*]], i32 0, i64 [[IDX]]
|
||||||
|
; CHECK-NEXT: [[R:%.*]] = load i32, i32* [[TMP0]], align 4
|
||||||
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
|
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
|
||||||
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP]], label [[EXIT]]
|
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP]], label [[EXIT]]
|
||||||
; CHECK: exit:
|
; CHECK: exit:
|
||||||
|
|
|
@ -2103,7 +2103,7 @@ TEST_F(ValueTrackingTest, ComputeConstantRange) {
|
||||||
|
|
||||||
// Check the depth cutoff results in a conservative result (full set) by
|
// Check the depth cutoff results in a conservative result (full set) by
|
||||||
// passing Depth == MaxDepth == 6.
|
// passing Depth == MaxDepth == 6.
|
||||||
ConstantRange CR3 = computeConstantRange(X2, true, &AC, I, 6);
|
ConstantRange CR3 = computeConstantRange(X2, true, &AC, I, nullptr, 6);
|
||||||
EXPECT_TRUE(CR3.isFullSet());
|
EXPECT_TRUE(CR3.isFullSet());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue