forked from OSchip/llvm-project
[Attributor][FIX] Sanitize queries to LVI and ScalarEvolution
When we talk to outside analyse, e.g., LVI and ScalarEvolution, we need to be careful with the query. The particular error occurred because we folded a PHI node before the LVI query but the context location was now not dominated by the value anymore. This is not supported by LVI so we have to filter these situations before we query the outside analyses.
This commit is contained in:
parent
c1d53a316d
commit
4761d29633
|
@ -7134,11 +7134,42 @@ struct AAValueConstantRangeImpl : AAValueConstantRange {
|
|||
const_cast<Instruction *>(CtxI));
|
||||
}
|
||||
|
||||
/// Return true if \p CtxI is valid for querying outside analyses.
|
||||
/// This basically makes sure we do not ask intra-procedural analysis
|
||||
/// about a context in the wrong function or a context that violates
|
||||
/// dominance assumptions they might have. The \p AllowAACtxI flag indicates
|
||||
/// if the original context of this AA is OK or should be considered invalid.
|
||||
bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,
|
||||
const Instruction *CtxI,
|
||||
bool AllowAACtxI) const {
|
||||
if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
|
||||
return false;
|
||||
|
||||
// Our context might be in a different function, neither intra-procedural
|
||||
// analysis (ScalarEvolution nor LazyValueInfo) can handle that.
|
||||
if (!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))
|
||||
return false;
|
||||
|
||||
// If the context is not dominated by the value there are paths to the
|
||||
// context that do not define the value. This cannot be handled by
|
||||
// LazyValueInfo so we need to bail.
|
||||
if (auto *I = dyn_cast<Instruction>(&getAssociatedValue())) {
|
||||
InformationCache &InfoCache = A.getInfoCache();
|
||||
const DominatorTree *DT =
|
||||
InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
|
||||
*I->getFunction());
|
||||
return DT && DT->dominates(I, CtxI);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// See AAValueConstantRange::getKnownConstantRange(..).
|
||||
ConstantRange
|
||||
getKnownConstantRange(Attributor &A,
|
||||
const Instruction *CtxI = nullptr) const override {
|
||||
if (!CtxI || CtxI == getCtxI())
|
||||
if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
|
||||
/* AllowAACtxI */ false))
|
||||
return getKnown();
|
||||
|
||||
ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
|
||||
|
@ -7154,9 +7185,8 @@ struct AAValueConstantRangeImpl : AAValueConstantRange {
|
|||
// We may be able to bound a variable range via assumptions in
|
||||
// Attributor. ex.) If x is assumed to be in [1, 3] and y is known to
|
||||
// evolve to x^2 + x, then we can say that y is in [2, 12].
|
||||
|
||||
if (!CtxI || CtxI == getCtxI() ||
|
||||
!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))
|
||||
if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
|
||||
/* AllowAACtxI */ false))
|
||||
return getAssumed();
|
||||
|
||||
ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
|
||||
|
|
|
@ -1224,15 +1224,19 @@ declare i8* @m()
|
|||
define i32 @test(i1 %c) {
|
||||
; CHECK-LABEL: define {{[^@]+}}@test
|
||||
; CHECK-SAME: (i1 [[C:%.*]]) {
|
||||
; CHECK-NEXT: [[R:%.*]] = call i32 @ctx_test(i1 [[C]])
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
; CHECK-NEXT: [[R1:%.*]] = call i32 @ctx_test1(i1 [[C]])
|
||||
; CHECK-NEXT: [[R2:%.*]] = call i32 @ctx_test2(i1 [[C]]), !range [[RNG0:![0-9]+]]
|
||||
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[R1]], [[R2]]
|
||||
; CHECK-NEXT: ret i32 [[ADD]]
|
||||
;
|
||||
%r = call i32 @ctx_test(i1 %c)
|
||||
ret i32 %r
|
||||
%r1 = call i32 @ctx_test1(i1 %c)
|
||||
%r2 = call i32 @ctx_test2(i1 %c)
|
||||
%add = add i32 %r1, %r2
|
||||
ret i32 %add
|
||||
}
|
||||
|
||||
define internal i32 @ctx_test(i1 %c) {
|
||||
; CHECK-LABEL: define {{[^@]+}}@ctx_test
|
||||
define internal i32 @ctx_test1(i1 %c) {
|
||||
; CHECK-LABEL: define {{[^@]+}}@ctx_test1
|
||||
; CHECK-SAME: (i1 [[C:%.*]]) {
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[JOIN:%.*]]
|
||||
|
@ -1259,6 +1263,36 @@ join:
|
|||
ret i32 %ret
|
||||
}
|
||||
|
||||
define internal i32 @ctx_test2(i1 %c) {
|
||||
; CHECK-LABEL: define {{[^@]+}}@ctx_test2
|
||||
; CHECK-SAME: (i1 [[C:%.*]]) {
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[C]], label [[THEN:%.*]], label [[JOIN:%.*]]
|
||||
; CHECK: then:
|
||||
; CHECK-NEXT: [[M:%.*]] = tail call i8* @m()
|
||||
; CHECK-NEXT: [[I:%.*]] = ptrtoint i8* [[M]] to i32
|
||||
; CHECK-NEXT: br label [[JOIN]]
|
||||
; CHECK: join:
|
||||
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[I]], [[THEN]] ], [ undef, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: [[RET:%.*]] = lshr i32 [[PHI]], 1
|
||||
; CHECK-NEXT: ret i32 [[RET]]
|
||||
;
|
||||
entry:
|
||||
br i1 %c, label %then, label %join
|
||||
|
||||
then:
|
||||
%m = tail call i8* @m()
|
||||
%i = ptrtoint i8* %m to i32
|
||||
br label %join
|
||||
|
||||
join:
|
||||
%phi = phi i32 [ %i, %then ], [ undef, %entry ]
|
||||
%ret = lshr i32 %phi, 1
|
||||
ret i32 %ret
|
||||
|
||||
uselistorder label %join, { 1, 0 }
|
||||
}
|
||||
|
||||
;.
|
||||
; IS__TUNIT_OPM: attributes #[[ATTR0]] = { nofree nosync nounwind willreturn }
|
||||
; IS__TUNIT_OPM: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
|
||||
|
@ -1298,3 +1332,5 @@ join:
|
|||
; IS__CGSCC_NPM: attributes #[[ATTR7]] = { readonly willreturn }
|
||||
; IS__CGSCC_NPM: attributes #[[ATTR8]] = { nofree nosync nounwind readnone }
|
||||
;.
|
||||
; CHECK: [[RNG0]] = !{i32 0, i32 -2147483648}
|
||||
;.
|
||||
|
|
Loading…
Reference in New Issue