Skip to content

Commit afbb6d9

Browse files
committed
[CVP] Simplify and generalize switch handling
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.
1 parent a5c65de commit afbb6d9

File tree

2 files changed

+6
-53
lines changed

2 files changed

+6
-53
lines changed

llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp

+3-38
Original file line numberDiff line numberDiff line change
@@ -330,15 +330,6 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI,
330330
Value *Cond = I->getCondition();
331331
BasicBlock *BB = I->getParent();
332332

333-
// If the condition was defined in same block as the switch then LazyValueInfo
334-
// currently won't say anything useful about it, though in theory it could.
335-
if (isa<Instruction>(Cond) && cast<Instruction>(Cond)->getParent() == BB)
336-
return false;
337-
338-
// If the switch is unreachable then trying to improve it is a waste of time.
339-
pred_iterator PB = pred_begin(BB), PE = pred_end(BB);
340-
if (PB == PE) return false;
341-
342333
// Analyse each switch case in turn.
343334
bool Changed = false;
344335
DenseMap<BasicBlock*, int> SuccessorsCount;
@@ -351,35 +342,9 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI,
351342

352343
for (auto CI = SI->case_begin(), CE = SI->case_end(); CI != CE;) {
353344
ConstantInt *Case = CI->getCaseValue();
354-
355-
// Check to see if the switch condition is equal to/not equal to the case
356-
// value on every incoming edge, equal/not equal being the same each time.
357-
LazyValueInfo::Tristate State = LazyValueInfo::Unknown;
358-
for (pred_iterator PI = PB; PI != PE; ++PI) {
359-
// Is the switch condition equal to the case value?
360-
LazyValueInfo::Tristate Value = LVI->getPredicateOnEdge(CmpInst::ICMP_EQ,
361-
Cond, Case, *PI,
362-
BB, SI);
363-
// Give up on this case if nothing is known.
364-
if (Value == LazyValueInfo::Unknown) {
365-
State = LazyValueInfo::Unknown;
366-
break;
367-
}
368-
369-
// If this was the first edge to be visited, record that all other edges
370-
// need to give the same result.
371-
if (PI == PB) {
372-
State = Value;
373-
continue;
374-
}
375-
376-
// If this case is known to fire for some edges and known not to fire for
377-
// others then there is nothing we can do - give up.
378-
if (Value != State) {
379-
State = LazyValueInfo::Unknown;
380-
break;
381-
}
382-
}
345+
LazyValueInfo::Tristate State =
346+
LVI->getPredicateAt(CmpInst::ICMP_EQ, Cond, Case, I,
347+
/* UseBlockValue */ true);
383348

384349
if (State == LazyValueInfo::False) {
385350
// This case never fires - remove it.

llvm/test/Transforms/CorrelatedValuePropagation/basic.ll

+3-15
Original file line numberDiff line numberDiff line change
@@ -285,11 +285,7 @@ define void @switch_nonzero_zext(i8 %s) {
285285
; CHECK-NEXT: br i1 [[CMP]], label [[SWITCH:%.*]], label [[EXIT:%.*]]
286286
; CHECK: switch:
287287
; CHECK-NEXT: [[S_EXT:%.*]] = zext i8 [[S]] to i32
288-
; CHECK-NEXT: switch i32 [[S_EXT]], label [[EXIT]] [
289-
; CHECK-NEXT: i32 0, label [[UNREACHABLE:%.*]]
290-
; CHECK-NEXT: i32 1, label [[EXIT]]
291-
; CHECK-NEXT: i32 -1, label [[EXIT]]
292-
; CHECK-NEXT: ]
288+
; CHECK-NEXT: br label [[EXIT]]
293289
; CHECK: exit:
294290
; CHECK-NEXT: ret void
295291
; CHECK: unreachable:
@@ -319,11 +315,7 @@ define void @switch_assume_nonzero(i32 %s) {
319315
; CHECK-NEXT: entry:
320316
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[S:%.*]], 0
321317
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
322-
; CHECK-NEXT: switch i32 [[S]], label [[EXIT:%.*]] [
323-
; CHECK-NEXT: i32 0, label [[UNREACHABLE:%.*]]
324-
; CHECK-NEXT: i32 1, label [[EXIT]]
325-
; CHECK-NEXT: i32 -1, label [[EXIT]]
326-
; CHECK-NEXT: ]
318+
; CHECK-NEXT: br label [[EXIT:%.*]]
327319
; CHECK: exit:
328320
; CHECK-NEXT: ret void
329321
; CHECK: unreachable:
@@ -355,11 +347,7 @@ define void @switch_nonzero_phi(i1 %cond) {
355347
; CHECK-NEXT: br label [[SWITCH]]
356348
; CHECK: switch:
357349
; CHECK-NEXT: [[S:%.*]] = phi i32 [ 1, [[IF]] ], [ -1, [[ELSE]] ]
358-
; CHECK-NEXT: switch i32 [[S]], label [[EXIT:%.*]] [
359-
; CHECK-NEXT: i32 0, label [[UNREACHABLE:%.*]]
360-
; CHECK-NEXT: i32 1, label [[EXIT]]
361-
; CHECK-NEXT: i32 -1, label [[EXIT]]
362-
; CHECK-NEXT: ]
350+
; CHECK-NEXT: br label [[EXIT:%.*]]
363351
; CHECK: exit:
364352
; CHECK-NEXT: ret void
365353
; CHECK: unreachable:

0 commit comments

Comments
 (0)