Index: src/IceTargetLoweringARM32.cpp |
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp |
index 3de321e23ea0cf4800d4f418d5b5b4df01ea45e8..ba2b1e6c94542a538314297ef224405c992b6fe0 100644 |
--- a/src/IceTargetLoweringARM32.cpp |
+++ b/src/IceTargetLoweringARM32.cpp |
@@ -124,7 +124,7 @@ namespace { |
const struct TableIcmp32_ { |
CondARM32::Cond Mapping; |
} TableIcmp32[] = { |
-#define X(val, is_signed, swapped64, C_32, C1_64, C2_64) \ |
+#define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V) \ |
{ CondARM32::C_32 } \ |
, |
ICMPARM32_TABLE |
@@ -140,7 +140,7 @@ const struct TableIcmp64_ { |
bool Swapped; |
CondARM32::Cond C1, C2; |
} TableIcmp64[] = { |
-#define X(val, is_signed, swapped64, C_32, C1_64, C2_64) \ |
+#define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V) \ |
{ is_signed, swapped64, CondARM32::C1_64, CondARM32::C2_64 } \ |
, |
ICMPARM32_TABLE |
@@ -163,7 +163,8 @@ CondARM32::Cond getIcmp32Mapping(InstIcmp::ICond Cond) { |
namespace { |
// Define a temporary set of enum values based on low-level table entries. |
enum _icmp_ll_enum { |
-#define X(val, signed, swapped64, C_32, C1_64, C2_64) _icmp_ll_##val, |
+#define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V) \ |
+ _icmp_ll_##val, |
ICMPARM32_TABLE |
#undef X |
_num |
@@ -174,7 +175,7 @@ ICEINSTICMP_TABLE |
#undef X |
// Define a set of constants based on low-level table entries, and ensure the |
// table entry keys are consistent. |
-#define X(val, signed, swapped64, C_32, C1_64, C2_64) \ |
+#define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V) \ |
static_assert( \ |
_icmp_ll_##val == _icmp_hl_##val, \ |
"Inconsistency between ICMPARM32_TABLE and ICEINSTICMP_TABLE: " #val); |
@@ -829,38 +830,6 @@ void TargetARM32::genTargetHelperCallFor(Inst *Instr) { |
} |
llvm::report_fatal_error("Control flow should never have reached here."); |
} |
- case Inst::Icmp: { |
- Variable *Dest = Instr->getDest(); |
- const Type DestTy = Dest->getType(); |
- if (isVectorType(DestTy)) { |
- auto *CmpInstr = llvm::cast<InstIcmp>(Instr); |
- const auto Condition = CmpInstr->getCondition(); |
- scalarizeInstruction( |
- Dest, |
- [this, Condition](Variable *Dest, Variable *Src0, Variable *Src1) { |
- return Context.insert<InstIcmp>(Condition, Dest, Src0, Src1); |
- }, |
- CmpInstr->getSrc(0), CmpInstr->getSrc(1)); |
- CmpInstr->setDeleted(); |
- } |
- return; |
- } |
- case Inst::Fcmp: { |
- Variable *Dest = Instr->getDest(); |
- const Type DestTy = Dest->getType(); |
- if (isVectorType(DestTy)) { |
- auto *CmpInstr = llvm::cast<InstFcmp>(Instr); |
- const auto Condition = CmpInstr->getCondition(); |
- scalarizeInstruction( |
- Dest, |
- [this, Condition](Variable *Dest, Variable *Src0, Variable *Src1) { |
- return Context.insert<InstFcmp>(Condition, Dest, Src0, Src1); |
- }, |
- CmpInstr->getSrc(0), CmpInstr->getSrc(1)); |
- CmpInstr->setDeleted(); |
- } |
- return; |
- } |
} |
} |
@@ -4251,7 +4220,7 @@ namespace { |
// Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering |
// (and naming). |
enum { |
-#define X(val, CC0, CC1) _fcmp_ll_##val, |
+#define X(val, CC0, CC1, CC0_V, CC1_V, INV_V, NEG_V) _fcmp_ll_##val, |
FCMPARM32_TABLE |
#undef X |
_fcmp_ll_NUM |
@@ -4277,7 +4246,7 @@ struct { |
CondARM32::Cond CC0; |
CondARM32::Cond CC1; |
} TableFcmp[] = { |
-#define X(val, CC0, CC1) \ |
+#define X(val, CC0, CC1, CC0_V, CC1_V, INV_V, NEG_V) \ |
{ CondARM32::CC0, CondARM32::CC1 } \ |
, |
FCMPARM32_TABLE |
@@ -4322,8 +4291,80 @@ TargetARM32::CondWhenTrue TargetARM32::lowerFcmpCond(const InstFcmp *Instr) { |
void TargetARM32::lowerFcmp(const InstFcmp *Instr) { |
Variable *Dest = Instr->getDest(); |
- if (isVectorType(Dest->getType())) { |
- UnimplementedLoweringError(this, Instr); |
+ const Type DestTy = Dest->getType(); |
+ |
+ if (isVectorType(DestTy)) { |
+ if (Instr->getCondition() == InstFcmp::False) { |
+ constexpr Type SafeTypeForMovingConstant = IceType_v4i32; |
+ auto *T = makeReg(SafeTypeForMovingConstant); |
+ _mov(T, llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); |
+ _mov(Dest, T); |
+ return; |
+ } |
+ |
+ if (Instr->getCondition() == InstFcmp::True) { |
+ constexpr Type SafeTypeForMovingConstant = IceType_v4i32; |
+ auto *T = makeReg(SafeTypeForMovingConstant); |
+ _mov(T, llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(1))); |
+ _mov(Dest, T); |
+ return; |
+ } |
+ |
+ Variable *T0; |
+ Variable *T1; |
+ bool Negate = false; |
+ auto *Src0 = legalizeToReg(Instr->getSrc(0)); |
+ auto *Src1 = legalizeToReg(Instr->getSrc(1)); |
+ |
+ switch (Instr->getCondition()) { |
+ default: |
+ llvm::report_fatal_error("Unhandled fp comparison."); |
+#define _Vcnone(Tptr, S0, S1) \ |
+ do { \ |
+ *(Tptr) = nullptr; \ |
+ } while (0) |
+#define _Vceq(Tptr, S0, S1) \ |
+ do { \ |
+ *(Tptr) = makeReg(DestTy); \ |
+ _vceq(*(Tptr), S0, S1); \ |
+ } while (0) |
+#define _Vcge(Tptr, S0, S1) \ |
+ do { \ |
+ *(Tptr) = makeReg(DestTy); \ |
+ _vcge(*(Tptr), S0, S1)->setSignType(InstARM32::FS_Signed); \ |
+ } while (0) |
+#define _Vcgt(Tptr, S0, S1) \ |
+ do { \ |
+ *(Tptr) = makeReg(DestTy); \ |
+ _vcgt(*(Tptr), S0, S1)->setSignType(InstARM32::FS_Signed); \ |
+ } while (0) |
+#define X(val, CC0, CC1, CC0_V, CC1_V, INV_V, NEG_V) \ |
+ case InstFcmp::val: { \ |
+ _Vc##CC0_V(&T0, (INV_V) ? Src1 : Src0, (INV_V) ? Src0 : Src1); \ |
+ _Vc##CC1_V(&T1, (INV_V) ? Src0 : Src1, (INV_V) ? Src1 : Src0); \ |
+ Negate = NEG_V; \ |
+ } break; |
+ FCMPARM32_TABLE |
+#undef X |
+#undef _Vcgt |
+#undef _Vcge |
+#undef _Vceq |
+#undef _Vcnone |
+ } |
+ assert(T0 != nullptr); |
+ Variable *T = T0; |
+ if (T1 != nullptr) { |
+ T = makeReg(DestTy); |
+ _vorr(T, T0, T1); |
+ } |
+ |
+ if (Negate) { |
+ auto *TNeg = makeReg(DestTy); |
+ _vmvn(TNeg, T); |
+ T = TNeg; |
+ } |
+ |
+ _mov(Dest, T); |
return; |
} |
@@ -4621,9 +4662,78 @@ TargetARM32::CondWhenTrue TargetARM32::lowerIcmpCond(InstIcmp::ICond Condition, |
void TargetARM32::lowerIcmp(const InstIcmp *Instr) { |
Variable *Dest = Instr->getDest(); |
+ const Type DestTy = Dest->getType(); |
- if (isVectorType(Dest->getType())) { |
- UnimplementedLoweringError(this, Instr); |
+ if (isVectorType(DestTy)) { |
+ auto *T = makeReg(DestTy); |
+ auto *Src0 = legalizeToReg(Instr->getSrc(0)); |
+ auto *Src1 = legalizeToReg(Instr->getSrc(1)); |
+ const Type SrcTy = Src0->getType(); |
+ |
+ bool NeedsShl = false; |
+ Type NewTypeAfterShl; |
+ SizeT ShAmt; |
+ switch (SrcTy) { |
+ default: |
+ break; |
+ case IceType_v16i1: |
+ NeedsShl = true; |
+ NewTypeAfterShl = IceType_v16i8; |
+ ShAmt = 7; |
+ break; |
+ case IceType_v8i1: |
+ NeedsShl = true; |
+ NewTypeAfterShl = IceType_v8i16; |
+ ShAmt = 15; |
+ break; |
+ case IceType_v4i1: |
+ NeedsShl = true; |
+ NewTypeAfterShl = IceType_v4i32; |
+ ShAmt = 31; |
+ break; |
+ } |
+ |
+ if (NeedsShl) { |
+ auto *Imm = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(ShAmt)); |
+ auto *Src0T = makeReg(NewTypeAfterShl); |
+ auto *Src0Shl = makeReg(NewTypeAfterShl); |
+ _mov(Src0T, Src0); |
+ _vshl(Src0Shl, Src0T, Imm); |
+ Src0 = Src0Shl; |
+ |
+ auto *Src1T = makeReg(NewTypeAfterShl); |
+ auto *Src1Shl = makeReg(NewTypeAfterShl); |
+ _mov(Src1T, Src1); |
+ _vshl(Src1Shl, Src1T, Imm); |
+ Src1 = Src1Shl; |
+ } |
+ |
+ switch (Instr->getCondition()) { |
+ default: |
+ llvm::report_fatal_error("Unhandled integer comparison."); |
+#define _Vceq(T, S0, S1, Signed) _vceq(T, S0, S1) |
+#define _Vcge(T, S0, S1, Signed) \ |
+ _vcge(T, S0, S1) \ |
+ ->setSignType(Signed ? InstARM32::FS_Signed : InstARM32::FS_Unsigned) |
+#define _Vcgt(T, S0, S1, Signed) \ |
+ _vcgt(T, S0, S1) \ |
+ ->setSignType(Signed ? InstARM32::FS_Signed : InstARM32::FS_Unsigned) |
+#define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V) \ |
+ case InstIcmp::val: { \ |
+ _Vc##C_V(T, (INV_V) ? Src1 : Src0, (INV_V) ? Src0 : Src1, is_signed); \ |
+ if (NEG_V) { \ |
+ auto *TInv = makeReg(DestTy); \ |
+ _vmvn(TInv, T); \ |
+ T = TInv; \ |
+ } \ |
+ } break; |
+ ICMPARM32_TABLE |
+#undef X |
+#undef _Vcgt |
+#undef _Vcge |
+#undef _Vceq |
+ } |
+ _mov(Dest, T); |
return; |
} |