mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-21 12:38:45 +00:00
Implement the "if (X == 6 || X == 4)" -> "if ((X|2) == 6)" optimization.
This currently only catches the most basic case, a two-case switch, but can be extended later. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119964 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b05099bf42
commit
ce750f0332
@ -1753,10 +1753,56 @@ bool SelectionDAGBuilder::handleSmallSwitchRange(CaseRec& CR,
|
|||||||
if (++BBI != FuncInfo.MF->end())
|
if (++BBI != FuncInfo.MF->end())
|
||||||
NextBlock = BBI;
|
NextBlock = BBI;
|
||||||
|
|
||||||
// TODO: If any two of the cases has the same destination, and if one value
|
// If any two of the cases has the same destination, and if one value
|
||||||
// is the same as the other, but has one bit unset that the other has set,
|
// is the same as the other, but has one bit unset that the other has set,
|
||||||
// use bit manipulation to do two compares at once. For example:
|
// use bit manipulation to do two compares at once. For example:
|
||||||
// "if (X == 6 || X == 4)" -> "if ((X|2) == 6)"
|
// "if (X == 6 || X == 4)" -> "if ((X|2) == 6)"
|
||||||
|
// TODO: This could be extended to merge any 2 cases in switches with 3 cases.
|
||||||
|
// TODO: Handle cases where CR.CaseBB != SwitchBB.
|
||||||
|
if (Size == 2 && CR.CaseBB == SwitchBB) {
|
||||||
|
Case &Small = *CR.Range.first;
|
||||||
|
Case &Big = *(CR.Range.second-1);
|
||||||
|
|
||||||
|
if (Small.Low == Small.High && Big.Low == Big.High && Small.BB == Big.BB) {
|
||||||
|
const APInt& SmallValue = cast<ConstantInt>(Small.Low)->getValue();
|
||||||
|
const APInt& BigValue = cast<ConstantInt>(Big.Low)->getValue();
|
||||||
|
|
||||||
|
// Check that there is only one bit different.
|
||||||
|
if (BigValue.countPopulation() == SmallValue.countPopulation() + 1 &&
|
||||||
|
(SmallValue | BigValue) == BigValue) {
|
||||||
|
// Isolate the common bit.
|
||||||
|
APInt CommonBit = BigValue & ~SmallValue;
|
||||||
|
assert((SmallValue | CommonBit) == BigValue &&
|
||||||
|
CommonBit.countPopulation() == 1 && "Not a common bit?");
|
||||||
|
|
||||||
|
SDValue CondLHS = getValue(SV);
|
||||||
|
EVT VT = CondLHS.getValueType();
|
||||||
|
DebugLoc DL = getCurDebugLoc();
|
||||||
|
|
||||||
|
SDValue Or = DAG.getNode(ISD::OR, DL, VT, CondLHS,
|
||||||
|
DAG.getConstant(CommonBit, VT));
|
||||||
|
SDValue Cond = DAG.getSetCC(DL, MVT::i1,
|
||||||
|
Or, DAG.getConstant(BigValue, VT),
|
||||||
|
ISD::SETEQ);
|
||||||
|
|
||||||
|
// Update successor info.
|
||||||
|
SwitchBB->addSuccessor(Small.BB);
|
||||||
|
SwitchBB->addSuccessor(Default);
|
||||||
|
|
||||||
|
// Insert the true branch.
|
||||||
|
SDValue BrCond = DAG.getNode(ISD::BRCOND, DL, MVT::Other,
|
||||||
|
getControlRoot(), Cond,
|
||||||
|
DAG.getBasicBlock(Small.BB));
|
||||||
|
|
||||||
|
// Insert the false branch.
|
||||||
|
BrCond = DAG.getNode(ISD::BR, DL, MVT::Other, BrCond,
|
||||||
|
DAG.getBasicBlock(Default));
|
||||||
|
|
||||||
|
DAG.setRoot(BrCond);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Rearrange the case blocks so that the last one falls through if possible.
|
// Rearrange the case blocks so that the last one falls through if possible.
|
||||||
if (NextBlock && Default != NextBlock && BackCase.BB != NextBlock) {
|
if (NextBlock && Default != NextBlock && BackCase.BB != NextBlock) {
|
||||||
|
@ -938,16 +938,6 @@ The expression should optimize to something like
|
|||||||
|
|
||||||
//===---------------------------------------------------------------------===//
|
//===---------------------------------------------------------------------===//
|
||||||
|
|
||||||
void a(int variable)
|
|
||||||
{
|
|
||||||
if (variable == 4 || variable == 6)
|
|
||||||
bar();
|
|
||||||
}
|
|
||||||
This should optimize to "if ((variable | 2) == 6)". Currently not
|
|
||||||
optimized with "clang -emit-llvm-bc | opt -std-compile-opts | llc".
|
|
||||||
|
|
||||||
//===---------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
unsigned int f(unsigned int i, unsigned int n) {++i; if (i == n) ++i; return
|
unsigned int f(unsigned int i, unsigned int n) {++i; if (i == n) ++i; return
|
||||||
i;}
|
i;}
|
||||||
unsigned int f2(unsigned int i, unsigned int n) {++i; i += i == n; return i;}
|
unsigned int f2(unsigned int i, unsigned int n) {++i; i += i == n; return i;}
|
||||||
|
22
test/CodeGen/X86/switch-or.ll
Normal file
22
test/CodeGen/X86/switch-or.ll
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
; RUN: llc -march=x86 -asm-verbose=false < %s | FileCheck %s
|
||||||
|
|
||||||
|
; Check that merging switch cases that differ in one bit works.
|
||||||
|
; CHECK: orl $2
|
||||||
|
; CHECK-NEXT: cmpl $6
|
||||||
|
|
||||||
|
define void @foo(i32 %variable) nounwind {
|
||||||
|
entry:
|
||||||
|
switch i32 %variable, label %if.end [
|
||||||
|
i32 4, label %if.then
|
||||||
|
i32 6, label %if.then
|
||||||
|
]
|
||||||
|
|
||||||
|
if.then:
|
||||||
|
%call = tail call i32 (...)* @bar() nounwind
|
||||||
|
ret void
|
||||||
|
|
||||||
|
if.end:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @bar(...) nounwind
|
Loading…
x
Reference in New Issue
Block a user