Commit fdc54db7 by Andrew Scull

Implement ARM32 switch lowering.

A naive implementation of switch lowering using sequential tests for each of the cases. BUG= none TEST=switch-opt.ll R=jvoung@chromium.org Review URL: https://codereview.chromium.org/1213593002.
parent a509e1d8
...@@ -2037,8 +2037,36 @@ void TargetARM32::doAddressOptStore() { ...@@ -2037,8 +2037,36 @@ void TargetARM32::doAddressOptStore() {
} }
void TargetARM32::lowerSwitch(const InstSwitch *Inst) { void TargetARM32::lowerSwitch(const InstSwitch *Inst) {
(void)Inst; // This implements the most naive possible lowering.
UnimplementedError(Func->getContext()->getFlags()); // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default
Operand *Src0 = Inst->getComparison();
SizeT NumCases = Inst->getNumCases();
if (Src0->getType() == IceType_i64) {
// TODO(jvoung): handle and test undef for Src0
Variable *Src0Lo = legalizeToVar(loOperand(Src0));
Variable *Src0Hi = legalizeToVar(hiOperand(Src0));
for (SizeT I = 0; I < NumCases; ++I) {
Operand *ValueLo = Ctx->getConstantInt32(Inst->getValue(I));
Operand *ValueHi = Ctx->getConstantInt32(Inst->getValue(I) >> 32);
ValueLo = legalize(ValueLo, Legal_Reg | Legal_Flex);
ValueHi = legalize(ValueHi, Legal_Reg | Legal_Flex);
_cmp(Src0Lo, ValueLo);
_cmp(Src0Hi, ValueHi, CondARM32::EQ);
_br(Inst->getLabel(I), CondARM32::EQ);
}
_br(Inst->getLabelDefault());
return;
}
// 32 bit integer
Variable *Src0Var = legalizeToVar(Src0);
for (SizeT I = 0; I < NumCases; ++I) {
Operand *Value = Ctx->getConstantInt32(Inst->getValue(I));
Value = legalize(Value, Legal_Reg | Legal_Flex);
_cmp(Src0Var, Value);
_br(Inst->getLabel(I), CondARM32::EQ);
}
_br(Inst->getLabelDefault());
} }
void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) {
......
...@@ -183,6 +183,9 @@ protected: ...@@ -183,6 +183,9 @@ protected:
void _br(CfgNode *Target) { void _br(CfgNode *Target) {
Context.insert(InstARM32Br::create(Func, Target)); Context.insert(InstARM32Br::create(Func, Target));
} }
void _br(CfgNode *Target, CondARM32::Cond Condition) {
Context.insert(InstARM32Br::create(Func, Target, Condition));
}
void _cmp(Variable *Src0, Operand *Src1, void _cmp(Variable *Src0, Operand *Src1,
CondARM32::Cond Pred = CondARM32::AL) { CondARM32::Cond Pred = CondARM32::AL) {
Context.insert(InstARM32Cmp::create(Func, Src0, Src1, Pred)); Context.insert(InstARM32Cmp::create(Func, Src0, Src1, Pred));
......
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 | FileCheck %s ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 | FileCheck %s
; TODO(jvoung): Update to -02 once the phi assignments is done for ARM
; RUN: %if --need=target_ARM32 --command %p2i --filetype=asm --assemble \
; RUN: --disassemble --target arm32 -i %s --args -Om1 --skip-unimplemented \
; RUN: | %if --need=target_ARM32 --command FileCheck --check-prefix ARM32 %s
define i32 @testSwitch(i32 %a) { define i32 @testSwitch(i32 %a) {
entry: entry:
switch i32 %a, label %sw.default [ switch i32 %a, label %sw.default [
...@@ -49,6 +54,11 @@ sw.default: ...@@ -49,6 +54,11 @@ sw.default:
; CHECK-LABEL: testSwitchImm ; CHECK-LABEL: testSwitchImm
; CHECK-NOT: cmp 0x{{[0-9a-f]*}}, ; CHECK-NOT: cmp 0x{{[0-9a-f]*}},
; ARM32-LABEL: testSwitchImm
; ARM32: cmp {{r[0-9]+}}, #1
; ARM32-NEXT: beq
; ARM32-NEXT: b
; Test for correct 64-bit lowering. ; Test for correct 64-bit lowering.
define internal i32 @testSwitch64(i64 %a) { define internal i32 @testSwitch64(i64 %a) {
entry: entry:
...@@ -93,6 +103,24 @@ return: ; preds = %sw.default, %sw.bb3 ...@@ -93,6 +103,24 @@ return: ; preds = %sw.default, %sw.bb3
; CHECK-NEXT: cmp {{.*}},0x12 ; CHECK-NEXT: cmp {{.*}},0x12
; CHECK-NEXT: je ; CHECK-NEXT: je
; ARM32-LABEL: testSwitch64
; ARM32: cmp {{r[0-9]+}}, #123
; ARM32-NEXT: cmpeq {{r[0-9]+}}, #0
; ARM32-NEXT: beq
; ARM32: cmp {{r[0-9]+}}, #234
; ARM32-NEXT: cmpeq {{r[0-9]+}}, #0
; ARM32-NEXT: beq
; ARM32: movw [[REG:r[0-9]+]], #345
; ARM32-NEXT: cmp {{r[0-9]+}}, [[REG]]
; ARM32-NEXT: cmpeq {{r[0-9]+}}, #0
; ARM32-NEXT: beq
; ARM32: movw [[REG:r[0-9]+]], #30864
; ARM32-NEXT: movt [[REG]], #13398
; ARM32-NEXT: cmp {{r[0-9]+}}, [[REG]]
; ARM32-NEXT: cmpeq {{r[0-9]+}}, #18
; ARM32-NEXT: beq
; ARM32-NEXT: b
; Similar to testSwitchImm, make sure proper addressing modes are ; Similar to testSwitchImm, make sure proper addressing modes are
; used. In reality, this is tested by running the output through the ; used. In reality, this is tested by running the output through the
; assembler. ; assembler.
...@@ -110,3 +138,10 @@ sw.default: ...@@ -110,3 +138,10 @@ sw.default:
; CHECK-NEXT: jne ; CHECK-NEXT: jne
; CHECK-NEXT: cmp {{.*}},0x0 ; CHECK-NEXT: cmp {{.*}},0x0
; CHECK-NEXT: je ; CHECK-NEXT: je
; ARM32-LABEL: testSwitchImm64
; ARM32: cmp {{r[0-9]+}}, #1
; ARM32-NEXT: cmpeq {{r[0-9]+}}, #0
; ARM32-NEXT: beq [[ADDR:[0-9a-f]+]]
; ARM32-NEXT: b [[ADDR]]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment