[GuardWidening] Fix widening possibility check (#66064)

In the 0e0ff8573d was introduced
inconsistency between condition widening and checking if it's possible
to widen. We check the possibility to hoist checks parsed from the
condition, but hoist entire condition.

This patch returns testing that a condition can be hoisted rather than
the checks parsed from that condition.

Co-authored-by: Aleksander Popov <apopov@azul.com>
This commit is contained in:
Aleksandr Popov
2023-09-12 14:49:14 +02:00
committed by GitHub
parent 0528dbfe5c
commit ec0f678744
2 changed files with 54 additions and 5 deletions

View File

@@ -184,6 +184,7 @@ class GuardWideningImpl {
/// Compute the score for widening the condition in \p DominatedInstr
/// into \p WideningPoint.
WideningScore computeWideningScore(Instruction *DominatedInstr,
Instruction *ToWiden,
Instruction *WideningPoint,
SmallVectorImpl<Value *> &ChecksToHoist,
SmallVectorImpl<Value *> &ChecksToWiden);
@@ -423,8 +424,8 @@ bool GuardWideningImpl::eliminateInstrViaWidening(
continue;
SmallVector<Value *> CandidateChecks;
parseWidenableGuard(Candidate, CandidateChecks);
auto Score = computeWideningScore(Instr, WideningPoint, ChecksToHoist,
CandidateChecks);
auto Score = computeWideningScore(Instr, Candidate, WideningPoint,
ChecksToHoist, CandidateChecks);
LLVM_DEBUG(dbgs() << "Score between " << *Instr << " and " << *Candidate
<< " is " << scoreTypeToString(Score) << "\n");
if (Score > BestScoreSoFar) {
@@ -456,8 +457,8 @@ bool GuardWideningImpl::eliminateInstrViaWidening(
}
GuardWideningImpl::WideningScore GuardWideningImpl::computeWideningScore(
Instruction *DominatedInstr, Instruction *WideningPoint,
SmallVectorImpl<Value *> &ChecksToHoist,
Instruction *DominatedInstr, Instruction *ToWiden,
Instruction *WideningPoint, SmallVectorImpl<Value *> &ChecksToHoist,
SmallVectorImpl<Value *> &ChecksToWiden) {
Loop *DominatedInstrLoop = LI.getLoopFor(DominatedInstr->getParent());
Loop *DominatingGuardLoop = LI.getLoopFor(WideningPoint->getParent());
@@ -475,7 +476,10 @@ GuardWideningImpl::WideningScore GuardWideningImpl::computeWideningScore(
if (!canBeHoistedTo(ChecksToHoist, WideningPoint))
return WS_IllegalOrNegative;
if (!canBeHoistedTo(ChecksToWiden, WideningPoint))
// Further in the GuardWideningImpl::hoistChecks the entire condition might be
// widened, not the parsed list of checks. So we need to check the possibility
// of that condition hoisting.
if (!canBeHoistedTo(getCondition(ToWiden), WideningPoint))
return WS_IllegalOrNegative;
// If the guard was conditional executed, it may never be reached

View File

@@ -0,0 +1,45 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=guard-widening < %s | FileCheck %s
declare void @llvm.experimental.deoptimize.isVoid(...)
declare i1 @llvm.experimental.widenable.condition()
; In the current scheme we widen `br i1 %and1`, so we try to build
; `and i1 poison, %and1` using `%call0` as insertion point.
; That's not possible, so widening will not occur in the case.
; TODO: Widen `%call0` in the test case, not a branch.
define void @test() {
; CHECK-LABEL: @test(
; CHECK-NEXT: bb0:
; CHECK-NEXT: [[CALL0:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[AND0:%.*]] = and i1 false, [[CALL0]]
; CHECK-NEXT: [[AND1:%.*]] = and i1 false, [[AND0]]
; CHECK-NEXT: br i1 [[AND1]], label [[BB1:%.*]], label [[DEOPT:%.*]]
; CHECK: bb1:
; CHECK-NEXT: [[CALL1:%.*]] = call i1 @llvm.experimental.widenable.condition()
; CHECK-NEXT: [[AND2:%.*]] = and i1 poison, [[CALL1]]
; CHECK-NEXT: br i1 [[AND2]], label [[UNREACH:%.*]], label [[DEOPT]]
; CHECK: unreach:
; CHECK-NEXT: unreachable
; CHECK: deopt:
; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid(i32 0) [ "deopt"(i32 0) ]
; CHECK-NEXT: ret void
;
bb0:
%call0 = call i1 @llvm.experimental.widenable.condition()
%and0 = and i1 false, %call0
%and1 = and i1 false, %and0
br i1 %and1, label %bb1, label %deopt
bb1:
%call1 = call i1 @llvm.experimental.widenable.condition()
%and2 = and i1 poison, %call1
br i1 %and2, label %unreach, label %deopt
unreach:
unreachable
deopt:
call void (...) @llvm.experimental.deoptimize.isVoid(i32 0) [ "deopt"(i32 0) ]
ret void
}