ARM: lowerSelect for integers.
No bool-folding optimization, just the straightforward
compare followed by mov and conditional mov.
BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/1211243005.
diff --git a/src/IceConditionCodesX8664.h b/src/IceConditionCodesX8664.h
index 297b54b..59a1493 100644
--- a/src/IceConditionCodesX8664.h
+++ b/src/IceConditionCodesX8664.h
@@ -19,14 +19,14 @@
namespace Ice {
-namespace CondX8664 {
+namespace CondX8664 {
// An enum of condition codes used for branches and cmov. The enum value
// should match the value used to encode operands in binary instructions.
enum BrCond {
#define X(tag, encode, opp, dump, emit) tag encode,
- ICEINSTX8664BR_TABLE
+ ICEINSTX8664BR_TABLE
#undef X
- Br_None
+ Br_None
};
// An enum of condition codes relevant to the CMPPS instruction. The enum
@@ -34,9 +34,9 @@
// instructions.
enum CmppsCond {
#define X(tag, emit) tag,
- ICEINSTX8664CMPPS_TABLE
+ ICEINSTX8664CMPPS_TABLE
#undef X
- Cmpps_Invalid
+ Cmpps_Invalid
};
} // end of namespace CondX8664
diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp
index 450fbba..3473b8c 100644
--- a/src/IceGlobalContext.cpp
+++ b/src/IceGlobalContext.cpp
@@ -31,8 +31,8 @@
#pragma clang diagnostic pop
#include <algorithm> // max()
-#include <cctype> // isdigit(), isupper()
-#include <locale> // locale
+#include <cctype> // isdigit(), isupper()
+#include <locale> // locale
#include <unordered_map>
namespace std {
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp
index 25e013b..33a914d 100644
--- a/src/IceTargetLowering.cpp
+++ b/src/IceTargetLowering.cpp
@@ -519,8 +519,9 @@
Var.getInitializers()) {
switch (Init->getKind()) {
case VariableDeclaration::Initializer::DataInitializerKind: {
- const auto &Data = llvm::cast<VariableDeclaration::DataInitializer>(
- Init.get())->getContents();
+ const auto &Data =
+ llvm::cast<VariableDeclaration::DataInitializer>(Init.get())
+ ->getContents();
for (SizeT i = 0; i < Init->getNumBytes(); ++i) {
Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n";
}
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp
index b1081b3..fad9bcf 100644
--- a/src/IceTargetLoweringARM32.cpp
+++ b/src/IceTargetLoweringARM32.cpp
@@ -2009,8 +2009,51 @@
}
void TargetARM32::lowerSelect(const InstSelect *Inst) {
- (void)Inst;
- UnimplementedError(Func->getContext()->getFlags());
+ Variable *Dest = Inst->getDest();
+ Type DestTy = Dest->getType();
+ Operand *SrcT = Inst->getTrueOperand();
+ Operand *SrcF = Inst->getFalseOperand();
+ Operand *Condition = Inst->getCondition();
+
+ if (isVectorType(DestTy)) {
+ UnimplementedError(Func->getContext()->getFlags());
+ return;
+ }
+ if (isFloatingType(DestTy)) {
+ UnimplementedError(Func->getContext()->getFlags());
+ return;
+ }
+ // TODO(jvoung): handle folding opportunities.
+ // cmp cond, #0; mov t, SrcF; mov_cond t, SrcT; mov dest, t
+ Variable *CmpOpnd0 = legalizeToVar(Condition);
+ Operand *CmpOpnd1 = Ctx->getConstantZero(IceType_i32);
+ _cmp(CmpOpnd0, CmpOpnd1);
+ CondARM32::Cond Cond = CondARM32::NE;
+ if (DestTy == IceType_i64) {
+ // Set the low portion.
+ Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
+ Variable *TLo = nullptr;
+ Operand *SrcFLo = legalize(loOperand(SrcF), Legal_Reg | Legal_Flex);
+ _mov(TLo, SrcFLo);
+ Operand *SrcTLo = legalize(loOperand(SrcT), Legal_Reg | Legal_Flex);
+ _mov_nonkillable(TLo, SrcTLo, Cond);
+ _mov(DestLo, TLo);
+ // Set the high portion.
+ Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
+ Variable *THi = nullptr;
+ Operand *SrcFHi = legalize(hiOperand(SrcF), Legal_Reg | Legal_Flex);
+ _mov(THi, SrcFHi);
+ Operand *SrcTHi = legalize(hiOperand(SrcT), Legal_Reg | Legal_Flex);
+ _mov_nonkillable(THi, SrcTHi, Cond);
+ _mov(DestHi, THi);
+ return;
+ }
+ Variable *T = nullptr;
+ SrcF = legalize(SrcF, Legal_Reg | Legal_Flex);
+ _mov(T, SrcF);
+ SrcT = legalize(SrcT, Legal_Reg | Legal_Flex);
+ _mov_nonkillable(T, SrcT, Cond);
+ _mov(Dest, T);
}
void TargetARM32::lowerStore(const InstStore *Inst) {
@@ -2057,7 +2100,7 @@
_br(Inst->getLabelDefault());
return;
}
-
+
// 32 bit integer
Variable *Src0Var = legalizeToVar(Src0);
for (SizeT I = 0; I < NumCases; ++I) {
diff --git a/tests_lit/llvm2ice_tests/64bit.pnacl.ll b/tests_lit/llvm2ice_tests/64bit.pnacl.ll
index d667633..54d8ff0 100644
--- a/tests_lit/llvm2ice_tests/64bit.pnacl.ll
+++ b/tests_lit/llvm2ice_tests/64bit.pnacl.ll
@@ -1580,6 +1580,17 @@
; OPTM1: cmp
; OPTM1: cmovne
+; ARM32-LABEL: select64VarVar
+; The initial compare.
+; ARM32: cmp
+; ARM32: cmpeq
+; ARM32: movcc
+; ARM32: movcs
+; The non-folded compare for the select.
+; ARM32: cmp
+; ARM32: movne
+; ARM32: movne
+
define internal i64 @select64VarConst(i64 %a, i64 %b) {
entry:
%cmp = icmp ult i64 %a, %b
@@ -1604,6 +1615,19 @@
; OPTM1: cmp
; OPTM1: cmovne
+; ARM32-LABEL: select64VarConst
+; ARM32: cmp
+; ARM32: cmpeq
+; ARM32: movcc
+; ARM32: movcs
+; ARM32: cmp
+; ARM32: movw
+; ARM32: movt
+; ARM32: movne
+; ARM32: movw
+; ARM32: movt
+; ARM32: movne
+
define internal i64 @select64ConstVar(i64 %a, i64 %b) {
entry:
%cmp = icmp ult i64 %a, %b
@@ -1628,6 +1652,19 @@
; OPTM1: cmp
; OPTM1: cmove
+; ARM32-LABEL: select64ConstVar
+; ARM32: cmp
+; ARM32: cmpeq
+; ARM32: movcc
+; ARM32: movcs
+; ARM32: cmp
+; ARM32: movw
+; ARM32: movt
+; ARM32: movne
+; ARM32: movw
+; ARM32: movt
+; ARM32: movne
+
define internal void @icmpEq64Imm() {
entry:
%cmp = icmp eq i64 123, 234
diff --git a/tests_lit/llvm2ice_tests/select-opt.ll b/tests_lit/llvm2ice_tests/select-opt.ll
index f6d15bf..a34cec6 100644
--- a/tests_lit/llvm2ice_tests/select-opt.ll
+++ b/tests_lit/llvm2ice_tests/select-opt.ll
@@ -3,8 +3,23 @@
; regardless of the optimization level, so there are no special OPTM1
; match lines.
-; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 | FileCheck %s
-; RUN: %p2i -i %s --filetype=obj --disassemble --args -Om1 | FileCheck %s
+; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \
+; RUN: --target x8632 -i %s --args -O2 \
+; RUN: | %if --need=target_X8632 --command FileCheck %s
+; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \
+; RUN: --target x8632 -i %s --args -Om1 \
+; RUN: | %if --need=target_X8632 --command FileCheck %s
+
+; RUN: %if --need=target_ARM32 --need=allow_dump \
+; RUN: --command %p2i --filetype=asm --assemble \
+; RUN: --disassemble --target arm32 -i %s --args -O2 --skip-unimplemented \
+; RUN: | %if --need=target_ARM32 --need=allow_dump \
+; RUN: --command FileCheck --check-prefix ARM32 %s
+; RUN: %if --need=target_ARM32 --need=allow_dump \
+; RUN: --command %p2i --filetype=asm --assemble \
+; RUN: --disassemble --target arm32 -i %s --args -Om1 --skip-unimplemented \
+; RUN: | %if --need=target_ARM32 --need=allow_dump \
+; RUN: --command FileCheck --check-prefix ARM32 %s
define void @testSelect(i32 %a, i32 %b) {
entry:
@@ -32,6 +47,16 @@
; CHECK: cmp
; CHECK: call {{.*}} R_{{.*}} useInt
; CHECK: ret
+; ARM32-LABEL: testSelect
+; ARM32: cmp
+; ARM32: cmp
+; ARM32: bl {{.*}} useInt
+; ARM32: cmp
+; ARM32: cmp
+; ARM32: mov {{.*}}, #20
+; ARM32: movne {{.*}}, #10
+; ARM32: bl {{.*}} useInt
+; ARM32: bx lr
; Check for valid addressing mode in the cmp instruction when the
; operand is an immediate.
@@ -42,6 +67,8 @@
}
; CHECK-LABEL: testSelectImm32
; CHECK-NOT: cmp 0x{{[0-9a-f]+}},
+; ARM32-LABEL: testSelectImm32
+; ARM32-NOT: cmp #{{.*}},
; Check for valid addressing mode in the cmp instruction when the
; operand is an immediate. There is a different x86-32 lowering
@@ -53,3 +80,5 @@
}
; CHECK-LABEL: testSelectImm64
; CHECK-NOT: cmp 0x{{[0-9a-f]+}},
+; ARM32-LABEL: testSelectImm64
+; ARM32-NOT: cmp #{{.*}},