[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:
Florian Hahn 2021-09-21 16:54:47 +01:00
parent 5fb3ae525f
commit 5131037ea9
No known key found for this signature in database
GPG Key ID: 61D7554B5CECDC0D
6 changed files with 14 additions and 11 deletions

View File

@ -549,6 +549,7 @@ constexpr unsigned MaxAnalysisRecursionDepth = 6;
ConstantRange computeConstantRange(const Value *V, bool UseInstrInfo = true,
AssumptionCache *AC = nullptr,
const Instruction *CtxI = nullptr,
const DominatorTree *DT = nullptr,
unsigned Depth = 0);
/// Return true if this function can prove that the instruction I will

View File

@ -7031,6 +7031,7 @@ static void setLimitsForSelectPattern(const SelectInst &SI, APInt &Lower,
ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo,
AssumptionCache *AC,
const Instruction *CtxI,
const DominatorTree *DT,
unsigned Depth) {
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 &&
"must be an assume intrinsic");
if (!isValidAssumeForContext(I, CtxI, nullptr))
if (!isValidAssumeForContext(I, CtxI, DT))
continue;
Value *Arg = I->getArgOperand(0);
ICmpInst *Cmp = dyn_cast<ICmpInst>(Arg);
@ -7077,7 +7078,7 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo,
if (!Cmp || Cmp->getOperand(0) != V)
continue;
ConstantRange RHS = computeConstantRange(Cmp->getOperand(1), UseInstrInfo,
AC, I, Depth + 1);
AC, I, DT, Depth + 1);
CR = CR.intersectWith(
ConstantRange::makeAllowedICmpRegion(Cmp->getPredicate(), RHS));
}

View File

@ -827,7 +827,8 @@ public:
/// Idx. \p Idx must access a valid vector element.
static ScalarizationResult canScalarizeAccess(FixedVectorType *VecTy,
Value *Idx, Instruction *CtxI,
AssumptionCache &AC) {
AssumptionCache &AC,
const DominatorTree &DT) {
if (auto *C = dyn_cast<ConstantInt>(Idx)) {
if (C->getValue().ult(VecTy->getNumElements()))
return ScalarizationResult::safe();
@ -841,7 +842,7 @@ static ScalarizationResult canScalarizeAccess(FixedVectorType *VecTy,
ConstantRange IdxRange(IntWidth, true);
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::unsafe();
}
@ -909,7 +910,7 @@ bool VectorCombine::foldSingleElementStore(Instruction &I) {
SrcAddr != SI->getPointerOperand()->stripPointerCasts())
return false;
auto ScalarizableIdx = canScalarizeAccess(VecTy, Idx, Load, AC);
auto ScalarizableIdx = canScalarizeAccess(VecTy, Idx, Load, AC, DT);
if (ScalarizableIdx.isUnsafe() ||
isMemModifiedBetween(Load->getIterator(), SI->getIterator(),
MemoryLocation::get(SI), AA))
@ -987,7 +988,7 @@ bool VectorCombine::scalarizeLoadExtract(Instruction &I) {
else if (LastCheckedInst->comesBefore(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()) {
// TODO: Freeze index if it is safe to do so.
return false;

View File

@ -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: [[EXT_1:%.*]] = extractelement <225 x double> [[LV]], i64 [[IDX_2]]
; CHECK-NEXT: [[SUB:%.*]] = fsub double [[EXT_1]], [[MUL]]
; CHECK-NEXT: [[INS:%.*]] = insertelement <225 x double> [[LV]], double [[SUB]], i64 [[IDX_1]]
; CHECK-NEXT: store <225 x double> [[INS]], <225 x double>* [[A]], align 8
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds <225 x double>, <225 x double>* [[A]], i64 0, i64 [[IDX_1]]
; CHECK-NEXT: store double [[SUB]], double* [[TMP0]], align 8
; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond()
; CHECK-NEXT: br i1 [[C_2]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:

View File

@ -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: br i1 [[C_1:%.*]], label [[LOOP:%.*]], label [[EXIT:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[LV:%.*]] = load <4 x i32>, <4 x i32>* [[X:%.*]], align 16
; 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: br i1 [[C_2]], label [[LOOP]], label [[EXIT]]
; CHECK: exit:

View File

@ -2103,7 +2103,7 @@ TEST_F(ValueTrackingTest, ComputeConstantRange) {
// Check the depth cutoff results in a conservative result (full set) by
// 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());
}
{