Skip to content

Commit

Permalink
[CVP] Simplify and generalize switch handling
Browse files Browse the repository at this point in the history
CVP currently handles switches by checking an equality predicate
on all edges from predecessor blocks. Of course, this can only
work if the value being switched over is defined in a different block.

Replace this implementation with a call to getPredicateAt(), which
also does the predecessor edge predicate check (if not defined in
the same block), but can also do quite a bit more: It can reason
about phi-nodes by checking edge predicates for incoming values,
it can reason about assumes, and it can reason about block values.

As such, this makes the implementation both simpler and more
powerful. The compile-time impact on CTMark is in the noise.
  • Loading branch information
nikic committed Dec 12, 2020
1 parent a5c65de commit afbb6d9
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 53 deletions.
41 changes: 3 additions & 38 deletions llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,15 +330,6 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI,
Value *Cond = I->getCondition();
BasicBlock *BB = I->getParent();

// If the condition was defined in same block as the switch then LazyValueInfo
// currently won't say anything useful about it, though in theory it could.
if (isa<Instruction>(Cond) && cast<Instruction>(Cond)->getParent() == BB)
return false;

// If the switch is unreachable then trying to improve it is a waste of time.
pred_iterator PB = pred_begin(BB), PE = pred_end(BB);
if (PB == PE) return false;

// Analyse each switch case in turn.
bool Changed = false;
DenseMap<BasicBlock*, int> SuccessorsCount;
Expand All @@ -351,35 +342,9 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI,

for (auto CI = SI->case_begin(), CE = SI->case_end(); CI != CE;) {
ConstantInt *Case = CI->getCaseValue();

// Check to see if the switch condition is equal to/not equal to the case
// value on every incoming edge, equal/not equal being the same each time.
LazyValueInfo::Tristate State = LazyValueInfo::Unknown;
for (pred_iterator PI = PB; PI != PE; ++PI) {
// Is the switch condition equal to the case value?
LazyValueInfo::Tristate Value = LVI->getPredicateOnEdge(CmpInst::ICMP_EQ,
Cond, Case, *PI,
BB, SI);
// Give up on this case if nothing is known.
if (Value == LazyValueInfo::Unknown) {
State = LazyValueInfo::Unknown;
break;
}

// If this was the first edge to be visited, record that all other edges
// need to give the same result.
if (PI == PB) {
State = Value;
continue;
}

// If this case is known to fire for some edges and known not to fire for
// others then there is nothing we can do - give up.
if (Value != State) {
State = LazyValueInfo::Unknown;
break;
}
}
LazyValueInfo::Tristate State =
LVI->getPredicateAt(CmpInst::ICMP_EQ, Cond, Case, I,
/* UseBlockValue */ true);

if (State == LazyValueInfo::False) {
// This case never fires - remove it.
Expand Down
18 changes: 3 additions & 15 deletions llvm/test/Transforms/CorrelatedValuePropagation/basic.ll
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,7 @@ define void @switch_nonzero_zext(i8 %s) {
; CHECK-NEXT: br i1 [[CMP]], label [[SWITCH:%.*]], label [[EXIT:%.*]]
; CHECK: switch:
; CHECK-NEXT: [[S_EXT:%.*]] = zext i8 [[S]] to i32
; CHECK-NEXT: switch i32 [[S_EXT]], label [[EXIT]] [
; CHECK-NEXT: i32 0, label [[UNREACHABLE:%.*]]
; CHECK-NEXT: i32 1, label [[EXIT]]
; CHECK-NEXT: i32 -1, label [[EXIT]]
; CHECK-NEXT: ]
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: ret void
; CHECK: unreachable:
Expand Down Expand Up @@ -319,11 +315,7 @@ define void @switch_assume_nonzero(i32 %s) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[S:%.*]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: switch i32 [[S]], label [[EXIT:%.*]] [
; CHECK-NEXT: i32 0, label [[UNREACHABLE:%.*]]
; CHECK-NEXT: i32 1, label [[EXIT]]
; CHECK-NEXT: i32 -1, label [[EXIT]]
; CHECK-NEXT: ]
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
; CHECK: unreachable:
Expand Down Expand Up @@ -355,11 +347,7 @@ define void @switch_nonzero_phi(i1 %cond) {
; CHECK-NEXT: br label [[SWITCH]]
; CHECK: switch:
; CHECK-NEXT: [[S:%.*]] = phi i32 [ 1, [[IF]] ], [ -1, [[ELSE]] ]
; CHECK-NEXT: switch i32 [[S]], label [[EXIT:%.*]] [
; CHECK-NEXT: i32 0, label [[UNREACHABLE:%.*]]
; CHECK-NEXT: i32 1, label [[EXIT]]
; CHECK-NEXT: i32 -1, label [[EXIT]]
; CHECK-NEXT: ]
; CHECK-NEXT: br label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret void
; CHECK: unreachable:
Expand Down

0 comments on commit afbb6d9

Please sign in to comment.