mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
Teach SimplifyCFG that (switch (select cond, X, Y)) is better expressed as a branch.
Based on a patch by Alistair Lynn. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126647 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
da834093b7
commit
f7b2a9d7df
@ -1800,6 +1800,26 @@ static bool SimplifyTerminatorOnSelect(TerminatorInst *OldTerm, Value *Cond,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SimplifySwitchOnSelect - Replaces
|
||||||
|
// (switch (select cond, X, Y)) on constant X, Y
|
||||||
|
// with a branch - conditional if X and Y lead to distinct BBs,
|
||||||
|
// unconditional otherwise.
|
||||||
|
static bool SimplifySwitchOnSelect(SwitchInst *SI, SelectInst *Select) {
|
||||||
|
// Check for constant integer values in the select.
|
||||||
|
ConstantInt *TrueVal = dyn_cast<ConstantInt>(Select->getTrueValue());
|
||||||
|
ConstantInt *FalseVal = dyn_cast<ConstantInt>(Select->getFalseValue());
|
||||||
|
if (!TrueVal || !FalseVal)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Find the relevant condition and destinations.
|
||||||
|
Value *Condition = Select->getCondition();
|
||||||
|
BasicBlock *TrueBB = SI->getSuccessor(SI->findCaseValue(TrueVal));
|
||||||
|
BasicBlock *FalseBB = SI->getSuccessor(SI->findCaseValue(FalseVal));
|
||||||
|
|
||||||
|
// Perform the actual simplification.
|
||||||
|
return SimplifyTerminatorOnSelect(SI, Condition, TrueBB, FalseBB);
|
||||||
|
}
|
||||||
|
|
||||||
// SimplifyIndirectBrOnSelect - Replaces
|
// SimplifyIndirectBrOnSelect - Replaces
|
||||||
// (indirectbr (select cond, blockaddress(@fn, BlockA),
|
// (indirectbr (select cond, blockaddress(@fn, BlockA),
|
||||||
// blockaddress(@fn, BlockB)))
|
// blockaddress(@fn, BlockB)))
|
||||||
@ -2310,6 +2330,11 @@ bool SimplifyCFGOpt::SimplifySwitch(SwitchInst *SI) {
|
|||||||
if (SimplifyEqualityComparisonWithOnlyPredecessor(SI, OnlyPred))
|
if (SimplifyEqualityComparisonWithOnlyPredecessor(SI, OnlyPred))
|
||||||
return SimplifyCFG(BB) | true;
|
return SimplifyCFG(BB) | true;
|
||||||
|
|
||||||
|
Value *Cond = SI->getCondition();
|
||||||
|
if (SelectInst *Select = dyn_cast<SelectInst>(Cond))
|
||||||
|
if (SimplifySwitchOnSelect(SI, Select))
|
||||||
|
return SimplifyCFG(BB) | true;
|
||||||
|
|
||||||
// If the block only contains the switch, see if we can fold the block
|
// If the block only contains the switch, see if we can fold the block
|
||||||
// away into any preds.
|
// away into any preds.
|
||||||
BasicBlock::iterator BBI = BB->begin();
|
BasicBlock::iterator BBI = BB->begin();
|
||||||
|
138
test/Transforms/SimplifyCFG/switch-on-const-select.ll
Normal file
138
test/Transforms/SimplifyCFG/switch-on-const-select.ll
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
; RUN: opt < %s -simplifycfg -S | FileCheck %s
|
||||||
|
|
||||||
|
; Test basic folding to a conditional branch.
|
||||||
|
define i32 @foo(i64 %x, i64 %y) nounwind {
|
||||||
|
; CHECK: @foo
|
||||||
|
entry:
|
||||||
|
%eq = icmp eq i64 %x, %y
|
||||||
|
br i1 %eq, label %b, label %switch
|
||||||
|
switch:
|
||||||
|
%lt = icmp slt i64 %x, %y
|
||||||
|
; CHECK: br i1 %lt, label %a, label %b
|
||||||
|
%qux = select i1 %lt, i32 0, i32 2
|
||||||
|
switch i32 %qux, label %bees [
|
||||||
|
i32 0, label %a
|
||||||
|
i32 1, label %b
|
||||||
|
i32 2, label %b
|
||||||
|
]
|
||||||
|
a:
|
||||||
|
tail call void @bees.a() nounwind
|
||||||
|
ret i32 1
|
||||||
|
; CHECK: b:
|
||||||
|
; CHECK-NEXT: %retval = phi i32 [ 0, %switch ], [ 2, %entry ]
|
||||||
|
b:
|
||||||
|
%retval = phi i32 [0, %switch], [0, %switch], [2, %entry]
|
||||||
|
tail call void @bees.b() nounwind
|
||||||
|
ret i32 %retval
|
||||||
|
; CHECK-NOT: bees:
|
||||||
|
bees:
|
||||||
|
tail call void @llvm.trap() nounwind
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
; Test basic folding to an unconditional branch.
|
||||||
|
define i32 @bar(i64 %x, i64 %y) nounwind {
|
||||||
|
; CHECK: @bar
|
||||||
|
entry:
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: tail call void @bees.a() nounwind
|
||||||
|
; CHECK-NEXT: ret i32 0
|
||||||
|
%lt = icmp slt i64 %x, %y
|
||||||
|
%qux = select i1 %lt, i32 0, i32 2
|
||||||
|
switch i32 %qux, label %bees [
|
||||||
|
i32 0, label %a
|
||||||
|
i32 1, label %b
|
||||||
|
i32 2, label %a
|
||||||
|
]
|
||||||
|
a:
|
||||||
|
%retval = phi i32 [0, %entry], [0, %entry], [1, %b]
|
||||||
|
tail call void @bees.a() nounwind
|
||||||
|
ret i32 0
|
||||||
|
b:
|
||||||
|
tail call void @bees.b() nounwind
|
||||||
|
br label %a
|
||||||
|
bees:
|
||||||
|
tail call void @llvm.trap() nounwind
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
; Test the edge case where both values from the select are the default case.
|
||||||
|
define void @bazz(i64 %x, i64 %y) nounwind {
|
||||||
|
; CHECK: @bazz
|
||||||
|
entry:
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: tail call void @bees.b() nounwind
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
%lt = icmp slt i64 %x, %y
|
||||||
|
%qux = select i1 %lt, i32 10, i32 12
|
||||||
|
switch i32 %qux, label %b [
|
||||||
|
i32 0, label %a
|
||||||
|
i32 1, label %bees
|
||||||
|
i32 2, label %bees
|
||||||
|
]
|
||||||
|
a:
|
||||||
|
tail call void @bees.a() nounwind
|
||||||
|
ret void
|
||||||
|
b:
|
||||||
|
tail call void @bees.b() nounwind
|
||||||
|
ret void
|
||||||
|
bees:
|
||||||
|
tail call void @llvm.trap()
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
; Test the edge case where both values from the select are equal.
|
||||||
|
define void @quux(i64 %x, i64 %y) nounwind {
|
||||||
|
; CHECK: @quux
|
||||||
|
entry:
|
||||||
|
; CHECK-NEXT: entry:
|
||||||
|
; CHECK-NEXT: tail call void @bees.a() nounwind
|
||||||
|
; CHECK-NEXT: ret void
|
||||||
|
%lt = icmp slt i64 %x, %y
|
||||||
|
%qux = select i1 %lt, i32 0, i32 0
|
||||||
|
switch i32 %qux, label %b [
|
||||||
|
i32 0, label %a
|
||||||
|
i32 1, label %bees
|
||||||
|
i32 2, label %bees
|
||||||
|
]
|
||||||
|
a:
|
||||||
|
tail call void @bees.a() nounwind
|
||||||
|
ret void
|
||||||
|
b:
|
||||||
|
tail call void @bees.b() nounwind
|
||||||
|
ret void
|
||||||
|
bees:
|
||||||
|
tail call void @llvm.trap()
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
; A final test, for phi node munging.
|
||||||
|
define i32 @xyzzy(i64 %x, i64 %y) {
|
||||||
|
; CHECK: @xyzzy
|
||||||
|
entry:
|
||||||
|
%eq = icmp eq i64 %x, %y
|
||||||
|
br i1 %eq, label %r, label %cont
|
||||||
|
cont:
|
||||||
|
; CHECK: %lt = icmp slt i64 %x, %y
|
||||||
|
%lt = icmp slt i64 %x, %y
|
||||||
|
; CHECK-NEXT: br i1 %lt, label %a, label %r
|
||||||
|
%qux = select i1 %lt, i32 0, i32 2
|
||||||
|
switch i32 %qux, label %bees [
|
||||||
|
i32 0, label %a
|
||||||
|
i32 1, label %r
|
||||||
|
i32 2, label %r
|
||||||
|
]
|
||||||
|
r:
|
||||||
|
%val = phi i32 [0, %entry], [1, %cont], [1, %cont]
|
||||||
|
ret i32 %val
|
||||||
|
a:
|
||||||
|
ret i32 -1
|
||||||
|
; CHECK-NOT: bees:
|
||||||
|
bees:
|
||||||
|
tail call void @llvm.trap()
|
||||||
|
unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.trap() nounwind noreturn
|
||||||
|
declare void @bees.a() nounwind
|
||||||
|
declare void @bees.b() nounwind
|
Loading…
Reference in New Issue
Block a user