[llvm] r291099 - [GlobalISel] Add support for switch statements
Kristof Beyls via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 5 03:28:51 PST 2017
Author: kbeyls
Date: Thu Jan 5 05:28:51 2017
New Revision: 291099
URL: http://llvm.org/viewvc/llvm-project?rev=291099&view=rev
Log:
[GlobalISel] Add support for switch statements
This commit does this using a trivial chain of conditional branches. In the
future, we probably want to reuse the optimized switch lowering used in
SelectionDAG.
Differential Revision: https://reviews.llvm.org/D28176
Modified:
llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h
llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp
llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h?rev=291099&r1=291098&r2=291099&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/IRTranslator.h Thu Jan 5 05:28:51 2017
@@ -180,6 +180,8 @@ private:
/// \pre \p U is a branch instruction.
bool translateBr(const User &U, MachineIRBuilder &MIRBuilder);
+ bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder);
+
bool translateExtractValue(const User &U, MachineIRBuilder &MIRBuilder);
bool translateInsertValue(const User &U, MachineIRBuilder &MIRBuilder);
@@ -292,12 +294,8 @@ private:
return translateBinaryOp(TargetOpcode::G_FREM, U, MIRBuilder);
}
-
// Stubs to keep the compiler happy while we implement the rest of the
// translation.
- bool translateSwitch(const User &U, MachineIRBuilder &MIRBuilder) {
- return false;
- }
bool translateIndirectBr(const User &U, MachineIRBuilder &MIRBuilder) {
return false;
}
Modified: llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp?rev=291099&r1=291098&r2=291099&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/IRTranslator.cpp Thu Jan 5 05:28:51 2017
@@ -195,6 +195,45 @@ bool IRTranslator::translateBr(const Use
return true;
}
+bool IRTranslator::translateSwitch(const User &U,
+ MachineIRBuilder &MIRBuilder) {
+ // For now, just translate as a chain of conditional branches.
+ // FIXME: could we share most of the logic/code in
+ // SelectionDAGBuilder::visitSwitch between SelectionDAG and GlobalISel?
+ // At first sight, it seems most of the logic in there is independent of
+ // SelectionDAG-specifics and a lot of work went in to optimize switch
+ // lowering in there.
+
+ const SwitchInst &SwInst = cast<SwitchInst>(U);
+ const unsigned SwCondValue = getOrCreateVReg(*SwInst.getCondition());
+
+ LLT LLTi1 = LLT(*Type::getInt1Ty(U.getContext()), *DL);
+ for (auto &CaseIt : SwInst.cases()) {
+ const unsigned CaseValueReg = getOrCreateVReg(*CaseIt.getCaseValue());
+ const unsigned Tst = MRI->createGenericVirtualRegister(LLTi1);
+ MIRBuilder.buildICmp(CmpInst::ICMP_EQ, Tst, CaseValueReg, SwCondValue);
+ MachineBasicBlock &CurBB = MIRBuilder.getMBB();
+ MachineBasicBlock &TrueBB = getOrCreateBB(*CaseIt.getCaseSuccessor());
+
+ MIRBuilder.buildBrCond(Tst, TrueBB);
+ CurBB.addSuccessor(&TrueBB);
+
+ MachineBasicBlock *FalseBB =
+ MF->CreateMachineBasicBlock(SwInst.getParent());
+ MF->push_back(FalseBB);
+ MIRBuilder.buildBr(*FalseBB);
+ CurBB.addSuccessor(FalseBB);
+
+ MIRBuilder.setMBB(*FalseBB);
+ }
+ // handle default case
+ MachineBasicBlock &DefaultBB = getOrCreateBB(*SwInst.getDefaultDest());
+ MIRBuilder.buildBr(DefaultBB);
+ MIRBuilder.getMBB().addSuccessor(&DefaultBB);
+
+ return true;
+}
+
bool IRTranslator::translateLoad(const User &U, MachineIRBuilder &MIRBuilder) {
const LoadInst &LI = cast<LoadInst>(U);
Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll?rev=291099&r1=291098&r2=291099&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll Thu Jan 5 05:28:51 2017
@@ -100,6 +100,75 @@ false:
ret void
}
+; Tests for switch.
+; This gets lowered to a very straightforward sequence of comparisons for now.
+; CHECK-LABEL: name: switch
+; CHECK: body:
+;
+; CHECK: {{bb.[0-9]+}}:
+; CHECK-NEXT: successors: %[[BB_CASE100:bb.[0-9]+]](0x40000000), %[[BB_NOTCASE100_CHECKNEXT:bb.[0-9]+.entry]](0x40000000)
+; CHECK: %0(s32) = COPY %w0
+; CHECK: %[[reg100:[0-9]+]](s32) = G_CONSTANT i32 100
+; CHECK: %[[reg200:[0-9]+]](s32) = G_CONSTANT i32 200
+; CHECK: %[[reg0:[0-9]+]](s32) = G_CONSTANT i32 0
+; CHECK: %[[reg1:[0-9]+]](s32) = G_CONSTANT i32 1
+; CHECK: %[[reg2:[0-9]+]](s32) = G_CONSTANT i32 2
+; CHECK: %[[regicmp100:[0-9]+]](s1) = G_ICMP intpred(eq), %[[reg100]](s32), %0
+; CHECK: G_BRCOND %[[regicmp100]](s1), %[[BB_CASE100]]
+; CHECK: G_BR %[[BB_NOTCASE100_CHECKNEXT]]
+;
+; CHECK: [[BB_CASE100]]:
+; CHECK-NEXT: successors: %[[BB_RET:bb.[0-9]+]](0x80000000)
+; CHECK: %[[regretc100:[0-9]+]](s32) = G_ADD %0, %[[reg1]]
+; CHECK: G_BR %[[BB_RET]]
+; CHECK: [[BB_NOTCASE100_CHECKNEXT]]:
+; CHECK-NEXT: successors: %[[BB_CASE200:bb.[0-9]+]](0x40000000), %[[BB_NOTCASE200_CHECKNEXT:bb.[0-9]+.entry]](0x40000000)
+; CHECK: %[[regicmp200:[0-9]+]](s1) = G_ICMP intpred(eq), %[[reg200]](s32), %0
+; CHECK: G_BRCOND %[[regicmp200]](s1), %[[BB_CASE200]]
+; CHECK: G_BR %[[BB_NOTCASE200_CHECKNEXT]]
+;
+; CHECK: [[BB_CASE200]]:
+; CHECK-NEXT: successors: %[[BB_RET:bb.[0-9]+]](0x80000000)
+; CHECK: %[[regretc200:[0-9]+]](s32) = G_ADD %0, %[[reg2]]
+; CHECK: G_BR %[[BB_RET]]
+; CHECK: [[BB_NOTCASE200_CHECKNEXT]]:
+; CHECK-NEXT: successors: %[[BB_DEFAULT:bb.[0-9]+]](0x80000000)
+; CHECK: G_BR %[[BB_DEFAULT]]
+;
+; CHECK: [[BB_DEFAULT]]:
+; CHECK-NEXT: successors: %[[BB_RET]](0x80000000)
+; CHECK: %[[regretdefault:[0-9]+]](s32) = G_ADD %0, %[[reg0]]
+; CHECK: G_BR %[[BB_RET]]
+;
+; CHECK: [[BB_RET]]:
+; CHECK-NEXT: %[[regret:[0-9]+]](s32) = PHI %[[regretdefault]](s32), %[[BB_DEFAULT]], %[[regretc100]](s32), %[[BB_CASE100]]
+; CHECK: %w0 = COPY %[[regret]](s32)
+; CHECK: RET_ReallyLR implicit %w0
+define i32 @switch(i32 %argc) {
+entry:
+ switch i32 %argc, label %default [
+ i32 100, label %case100
+ i32 200, label %case200
+ ]
+
+default:
+ %tmp0 = add i32 %argc, 0
+ br label %return
+
+case100:
+ %tmp1 = add i32 %argc, 1
+ br label %return
+
+case200:
+ %tmp2 = add i32 %argc, 2
+ br label %return
+
+return:
+ %res = phi i32 [ %tmp0, %default ], [ %tmp1, %case100 ], [ %tmp2, %case200 ]
+ ret i32 %res
+}
+
+
; Tests for or.
; CHECK-LABEL: name: ori64
; CHECK: [[ARG1:%[0-9]+]](s64) = COPY %x0
More information about the llvm-commits
mailing list