forked from OSchip/llvm-project
[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.
This commit is contained in:
parent
a5c65de295
commit
afbb6d97b5
|
@ -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;
|
||||
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue