unsigned STORE8;
unsigned LOAD8;
+ unsigned CMPrr;
+ unsigned MOVi;
+ unsigned MOVCCi;
+
OpcodeCache(const ARMSubtarget &STI);
} const Opcodes;
STORE_OPCODE(STORE8, STRBi12);
STORE_OPCODE(LOAD8, LDRBi12);
+
+ STORE_OPCODE(CMPrr, CMPrr);
+ STORE_OPCODE(MOVi, MOVi);
+ STORE_OPCODE(MOVCCi, MOVCCi);
#undef MAP_OPCODE
}
}
struct ARMInstructionSelector::CmpConstants {
- CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned OpRegBank,
- unsigned OpSize)
+ CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned SelectOpcode,
+ unsigned OpRegBank, unsigned OpSize)
: ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
- OperandRegBankID(OpRegBank), OperandSize(OpSize) {}
+ SelectResultOpcode(SelectOpcode), OperandRegBankID(OpRegBank),
+ OperandSize(OpSize) {}
// The opcode used for performing the comparison.
const unsigned ComparisonOpcode;
// ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
const unsigned ReadFlagsOpcode;
+ // The opcode used for materializing the result of the comparison.
+ const unsigned SelectResultOpcode;
+
// The assumed register bank ID for the operands.
const unsigned OperandRegBankID;
void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
unsigned Constant) const {
- (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(ARM::MOVi))
+ (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Opcodes.MOVi))
.addDef(DestReg)
.addImm(Constant)
.add(predOps(ARMCC::AL))
}
// Select either 1 or the previous result based on the value of the flags.
- auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(ARM::MOVCCi))
+ auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
+ TII.get(Helper.SelectResultOpcode))
.addDef(ResReg)
.addUse(PrevRes)
.addImm(1)
case G_SELECT:
return selectSelect(MIB, MRI);
case G_ICMP: {
- CmpConstants Helper(ARM::CMPrr, ARM::INSTRUCTION_LIST_END,
- ARM::GPRRegBankID, 32);
+ CmpConstants Helper(Opcodes.CMPrr, ARM::INSTRUCTION_LIST_END,
+ Opcodes.MOVCCi, ARM::GPRRegBankID, 32);
return selectCmp(Helper, MIB, MRI);
}
case G_FCMP: {
}
CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
- ARM::FPRRegBankID, Size);
+ Opcodes.MOVCCi, ARM::FPRRegBankID, Size);
return selectCmp(Helper, MIB, MRI);
}
case G_LSHR:
--- /dev/null
+# RUN: llc -O0 -mtriple thumb-- -mattr=+v6t2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
+--- |
+ define void @test_icmp_eq_s32() { ret void }
+ define void @test_icmp_ne_s32() { ret void }
+ define void @test_icmp_ugt_s32() { ret void }
+ define void @test_icmp_uge_s32() { ret void }
+ define void @test_icmp_ult_s32() { ret void }
+ define void @test_icmp_ule_s32() { ret void }
+ define void @test_icmp_sgt_s32() { ret void }
+ define void @test_icmp_sge_s32() { ret void }
+ define void @test_icmp_slt_s32() { ret void }
+ define void @test_icmp_sle_s32() { ret void }
+...
+---
+name: test_icmp_eq_s32
+legalized: true
+regBankSelected: true
+selected: false
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+ - { id: 3, class: gprb }
+body: |
+ bb.0:
+ liveins: $r0, $r1
+
+ ; CHECK-LABEL: name: test_icmp_eq_s32
+ ; CHECK: [[COPY:%[0-9]+]]:gprnopc = COPY $r0
+ ; CHECK: [[COPY1:%[0-9]+]]:rgpr = COPY $r1
+ ; CHECK: [[MOVi:%[0-9]+]]:rgpr = t2MOVi 0, 14, $noreg, $noreg
+ ; CHECK: t2CMPrr [[COPY]], [[COPY1]], 14, $noreg, implicit-def $cpsr
+ ; CHECK: [[MOVCCi:%[0-9]+]]:rgpr = t2MOVCCi [[MOVi]], 1, 0, $cpsr
+ ; CHECK: [[ANDri:%[0-9]+]]:rgpr = t2ANDri [[MOVCCi]], 1, 14, $noreg, $noreg
+ ; CHECK: $r0 = COPY [[ANDri]]
+ ; CHECK: BX_RET 14, $noreg, implicit $r0
+ %0(s32) = COPY $r0
+ %1(s32) = COPY $r1
+ %2(s1) = G_ICMP intpred(eq), %0(s32), %1
+ %3(s32) = G_ZEXT %2(s1)
+ $r0 = COPY %3(s32)
+ BX_RET 14, $noreg, implicit $r0
+...
+---
+name: test_icmp_ne_s32
+legalized: true
+regBankSelected: true
+selected: false
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+ - { id: 3, class: gprb }
+body: |
+ bb.0:
+ liveins: $r0, $r1
+
+ ; CHECK-LABEL: name: test_icmp_ne_s32
+ ; CHECK: [[COPY:%[0-9]+]]:gprnopc = COPY $r0
+ ; CHECK: [[COPY1:%[0-9]+]]:rgpr = COPY $r1
+ ; CHECK: [[MOVi:%[0-9]+]]:rgpr = t2MOVi 0, 14, $noreg, $noreg
+ ; CHECK: t2CMPrr [[COPY]], [[COPY1]], 14, $noreg, implicit-def $cpsr
+ ; CHECK: [[MOVCCi:%[0-9]+]]:rgpr = t2MOVCCi [[MOVi]], 1, 1, $cpsr
+ ; CHECK: [[ANDri:%[0-9]+]]:rgpr = t2ANDri [[MOVCCi]], 1, 14, $noreg, $noreg
+ ; CHECK: $r0 = COPY [[ANDri]]
+ ; CHECK: BX_RET 14, $noreg, implicit $r0
+ %0(s32) = COPY $r0
+ %1(s32) = COPY $r1
+ %2(s1) = G_ICMP intpred(ne), %0(s32), %1
+ %3(s32) = G_ZEXT %2(s1)
+ $r0 = COPY %3(s32)
+ BX_RET 14, $noreg, implicit $r0
+...
+---
+name: test_icmp_ugt_s32
+legalized: true
+regBankSelected: true
+selected: false
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+ - { id: 3, class: gprb }
+body: |
+ bb.0:
+ liveins: $r0, $r1
+
+ ; CHECK-LABEL: name: test_icmp_ugt_s32
+ ; CHECK: [[COPY:%[0-9]+]]:gprnopc = COPY $r0
+ ; CHECK: [[COPY1:%[0-9]+]]:rgpr = COPY $r1
+ ; CHECK: [[MOVi:%[0-9]+]]:rgpr = t2MOVi 0, 14, $noreg, $noreg
+ ; CHECK: t2CMPrr [[COPY]], [[COPY1]], 14, $noreg, implicit-def $cpsr
+ ; CHECK: [[MOVCCi:%[0-9]+]]:rgpr = t2MOVCCi [[MOVi]], 1, 8, $cpsr
+ ; CHECK: [[ANDri:%[0-9]+]]:rgpr = t2ANDri [[MOVCCi]], 1, 14, $noreg, $noreg
+ ; CHECK: $r0 = COPY [[ANDri]]
+ ; CHECK: BX_RET 14, $noreg, implicit $r0
+ %0(s32) = COPY $r0
+ %1(s32) = COPY $r1
+ %2(s1) = G_ICMP intpred(ugt), %0(s32), %1
+ %3(s32) = G_ZEXT %2(s1)
+ $r0 = COPY %3(s32)
+ BX_RET 14, $noreg, implicit $r0
+...
+---
+name: test_icmp_uge_s32
+legalized: true
+regBankSelected: true
+selected: false
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+ - { id: 3, class: gprb }
+body: |
+ bb.0:
+ liveins: $r0, $r1
+
+ ; CHECK-LABEL: name: test_icmp_uge_s32
+ ; CHECK: [[COPY:%[0-9]+]]:gprnopc = COPY $r0
+ ; CHECK: [[COPY1:%[0-9]+]]:rgpr = COPY $r1
+ ; CHECK: [[MOVi:%[0-9]+]]:rgpr = t2MOVi 0, 14, $noreg, $noreg
+ ; CHECK: t2CMPrr [[COPY]], [[COPY1]], 14, $noreg, implicit-def $cpsr
+ ; CHECK: [[MOVCCi:%[0-9]+]]:rgpr = t2MOVCCi [[MOVi]], 1, 2, $cpsr
+ ; CHECK: [[ANDri:%[0-9]+]]:rgpr = t2ANDri [[MOVCCi]], 1, 14, $noreg, $noreg
+ ; CHECK: $r0 = COPY [[ANDri]]
+ ; CHECK: BX_RET 14, $noreg, implicit $r0
+ %0(s32) = COPY $r0
+ %1(s32) = COPY $r1
+ %2(s1) = G_ICMP intpred(uge), %0(s32), %1
+ %3(s32) = G_ZEXT %2(s1)
+ $r0 = COPY %3(s32)
+ BX_RET 14, $noreg, implicit $r0
+...
+---
+name: test_icmp_ult_s32
+legalized: true
+regBankSelected: true
+selected: false
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+ - { id: 3, class: gprb }
+body: |
+ bb.0:
+ liveins: $r0, $r1
+
+ ; CHECK-LABEL: name: test_icmp_ult_s32
+ ; CHECK: [[COPY:%[0-9]+]]:gprnopc = COPY $r0
+ ; CHECK: [[COPY1:%[0-9]+]]:rgpr = COPY $r1
+ ; CHECK: [[MOVi:%[0-9]+]]:rgpr = t2MOVi 0, 14, $noreg, $noreg
+ ; CHECK: t2CMPrr [[COPY]], [[COPY1]], 14, $noreg, implicit-def $cpsr
+ ; CHECK: [[MOVCCi:%[0-9]+]]:rgpr = t2MOVCCi [[MOVi]], 1, 3, $cpsr
+ ; CHECK: [[ANDri:%[0-9]+]]:rgpr = t2ANDri [[MOVCCi]], 1, 14, $noreg, $noreg
+ ; CHECK: $r0 = COPY [[ANDri]]
+ ; CHECK: BX_RET 14, $noreg, implicit $r0
+ %0(s32) = COPY $r0
+ %1(s32) = COPY $r1
+ %2(s1) = G_ICMP intpred(ult), %0(s32), %1
+ %3(s32) = G_ZEXT %2(s1)
+ $r0 = COPY %3(s32)
+ BX_RET 14, $noreg, implicit $r0
+...
+---
+name: test_icmp_ule_s32
+legalized: true
+regBankSelected: true
+selected: false
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+ - { id: 3, class: gprb }
+body: |
+ bb.0:
+ liveins: $r0, $r1
+
+ ; CHECK-LABEL: name: test_icmp_ule_s32
+ ; CHECK: [[COPY:%[0-9]+]]:gprnopc = COPY $r0
+ ; CHECK: [[COPY1:%[0-9]+]]:rgpr = COPY $r1
+ ; CHECK: [[MOVi:%[0-9]+]]:rgpr = t2MOVi 0, 14, $noreg, $noreg
+ ; CHECK: t2CMPrr [[COPY]], [[COPY1]], 14, $noreg, implicit-def $cpsr
+ ; CHECK: [[MOVCCi:%[0-9]+]]:rgpr = t2MOVCCi [[MOVi]], 1, 9, $cpsr
+ ; CHECK: [[ANDri:%[0-9]+]]:rgpr = t2ANDri [[MOVCCi]], 1, 14, $noreg, $noreg
+ ; CHECK: $r0 = COPY [[ANDri]]
+ ; CHECK: BX_RET 14, $noreg, implicit $r0
+ %0(s32) = COPY $r0
+ %1(s32) = COPY $r1
+ %2(s1) = G_ICMP intpred(ule), %0(s32), %1
+ %3(s32) = G_ZEXT %2(s1)
+ $r0 = COPY %3(s32)
+ BX_RET 14, $noreg, implicit $r0
+...
+---
+name: test_icmp_sgt_s32
+legalized: true
+regBankSelected: true
+selected: false
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+ - { id: 3, class: gprb }
+body: |
+ bb.0:
+ liveins: $r0, $r1
+
+ ; CHECK-LABEL: name: test_icmp_sgt_s32
+ ; CHECK: [[COPY:%[0-9]+]]:gprnopc = COPY $r0
+ ; CHECK: [[COPY1:%[0-9]+]]:rgpr = COPY $r1
+ ; CHECK: [[MOVi:%[0-9]+]]:rgpr = t2MOVi 0, 14, $noreg, $noreg
+ ; CHECK: t2CMPrr [[COPY]], [[COPY1]], 14, $noreg, implicit-def $cpsr
+ ; CHECK: [[MOVCCi:%[0-9]+]]:rgpr = t2MOVCCi [[MOVi]], 1, 12, $cpsr
+ ; CHECK: [[ANDri:%[0-9]+]]:rgpr = t2ANDri [[MOVCCi]], 1, 14, $noreg, $noreg
+ ; CHECK: $r0 = COPY [[ANDri]]
+ ; CHECK: BX_RET 14, $noreg, implicit $r0
+ %0(s32) = COPY $r0
+ %1(s32) = COPY $r1
+ %2(s1) = G_ICMP intpred(sgt), %0(s32), %1
+ %3(s32) = G_ZEXT %2(s1)
+ $r0 = COPY %3(s32)
+ BX_RET 14, $noreg, implicit $r0
+...
+---
+name: test_icmp_sge_s32
+legalized: true
+regBankSelected: true
+selected: false
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+ - { id: 3, class: gprb }
+body: |
+ bb.0:
+ liveins: $r0, $r1
+
+ ; CHECK-LABEL: name: test_icmp_sge_s32
+ ; CHECK: [[COPY:%[0-9]+]]:gprnopc = COPY $r0
+ ; CHECK: [[COPY1:%[0-9]+]]:rgpr = COPY $r1
+ ; CHECK: [[MOVi:%[0-9]+]]:rgpr = t2MOVi 0, 14, $noreg, $noreg
+ ; CHECK: t2CMPrr [[COPY]], [[COPY1]], 14, $noreg, implicit-def $cpsr
+ ; CHECK: [[MOVCCi:%[0-9]+]]:rgpr = t2MOVCCi [[MOVi]], 1, 10, $cpsr
+ ; CHECK: [[ANDri:%[0-9]+]]:rgpr = t2ANDri [[MOVCCi]], 1, 14, $noreg, $noreg
+ ; CHECK: $r0 = COPY [[ANDri]]
+ ; CHECK: BX_RET 14, $noreg, implicit $r0
+ %0(s32) = COPY $r0
+ %1(s32) = COPY $r1
+ %2(s1) = G_ICMP intpred(sge), %0(s32), %1
+ %3(s32) = G_ZEXT %2(s1)
+ $r0 = COPY %3(s32)
+ BX_RET 14, $noreg, implicit $r0
+...
+---
+name: test_icmp_slt_s32
+legalized: true
+regBankSelected: true
+selected: false
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+ - { id: 3, class: gprb }
+body: |
+ bb.0:
+ liveins: $r0, $r1
+
+ ; CHECK-LABEL: name: test_icmp_slt_s32
+ ; CHECK: [[COPY:%[0-9]+]]:gprnopc = COPY $r0
+ ; CHECK: [[COPY1:%[0-9]+]]:rgpr = COPY $r1
+ ; CHECK: [[MOVi:%[0-9]+]]:rgpr = t2MOVi 0, 14, $noreg, $noreg
+ ; CHECK: t2CMPrr [[COPY]], [[COPY1]], 14, $noreg, implicit-def $cpsr
+ ; CHECK: [[MOVCCi:%[0-9]+]]:rgpr = t2MOVCCi [[MOVi]], 1, 11, $cpsr
+ ; CHECK: [[ANDri:%[0-9]+]]:rgpr = t2ANDri [[MOVCCi]], 1, 14, $noreg, $noreg
+ ; CHECK: $r0 = COPY [[ANDri]]
+ ; CHECK: BX_RET 14, $noreg, implicit $r0
+ %0(s32) = COPY $r0
+ %1(s32) = COPY $r1
+ %2(s1) = G_ICMP intpred(slt), %0(s32), %1
+ %3(s32) = G_ZEXT %2(s1)
+ $r0 = COPY %3(s32)
+ BX_RET 14, $noreg, implicit $r0
+...
+---
+name: test_icmp_sle_s32
+legalized: true
+regBankSelected: true
+selected: false
+registers:
+ - { id: 0, class: gprb }
+ - { id: 1, class: gprb }
+ - { id: 2, class: gprb }
+ - { id: 3, class: gprb }
+body: |
+ bb.0:
+ liveins: $r0, $r1
+
+ ; CHECK-LABEL: name: test_icmp_sle_s32
+ ; CHECK: [[COPY:%[0-9]+]]:gprnopc = COPY $r0
+ ; CHECK: [[COPY1:%[0-9]+]]:rgpr = COPY $r1
+ ; CHECK: [[MOVi:%[0-9]+]]:rgpr = t2MOVi 0, 14, $noreg, $noreg
+ ; CHECK: t2CMPrr [[COPY]], [[COPY1]], 14, $noreg, implicit-def $cpsr
+ ; CHECK: [[MOVCCi:%[0-9]+]]:rgpr = t2MOVCCi [[MOVi]], 1, 13, $cpsr
+ ; CHECK: [[ANDri:%[0-9]+]]:rgpr = t2ANDri [[MOVCCi]], 1, 14, $noreg, $noreg
+ ; CHECK: $r0 = COPY [[ANDri]]
+ ; CHECK: BX_RET 14, $noreg, implicit $r0
+ %0(s32) = COPY $r0
+ %1(s32) = COPY $r1
+ %2(s1) = G_ICMP intpred(sle), %0(s32), %1
+ %3(s32) = G_ZEXT %2(s1)
+ $r0 = COPY %3(s32)
+ BX_RET 14, $noreg, implicit $r0
+...