GlobalISel: support selection of G_ICMP on AArch64.

Patch from Ahmed Bougaca again.

llvm-svn: 284072
This commit is contained in:
Tim Northover 2016-10-12 22:49:04 +00:00
parent 5e3dbf326c
commit 6c02ad5e4f
2 changed files with 117 additions and 0 deletions

View File

@ -274,6 +274,33 @@ static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
return true;
}
static AArch64CC::CondCode changeICMPPredToAArch64CC(CmpInst::Predicate P) {
switch (P) {
default:
llvm_unreachable("Unknown condition code!");
case CmpInst::ICMP_NE:
return AArch64CC::NE;
case CmpInst::ICMP_EQ:
return AArch64CC::EQ;
case CmpInst::ICMP_SGT:
return AArch64CC::GT;
case CmpInst::ICMP_SGE:
return AArch64CC::GE;
case CmpInst::ICMP_SLT:
return AArch64CC::LT;
case CmpInst::ICMP_SLE:
return AArch64CC::LE;
case CmpInst::ICMP_UGT:
return AArch64CC::HI;
case CmpInst::ICMP_UGE:
return AArch64CC::HS;
case CmpInst::ICMP_ULT:
return AArch64CC::LO;
case CmpInst::ICMP_ULE:
return AArch64CC::LS;
}
}
bool AArch64InstructionSelector::select(MachineInstr &I) const {
assert(I.getParent() && "Instruction should be in a basic block!");
assert(I.getParent()->getParent() && "Instruction should be in a function!");
@ -577,6 +604,50 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
case TargetOpcode::G_PTRTOINT:
case TargetOpcode::G_BITCAST:
return selectCopy(I, TII, MRI, TRI, RBI);
case TargetOpcode::G_ICMP: {
if (Ty != LLT::scalar(1)) {
DEBUG(dbgs() << "G_ICMP result has type: " << Ty
<< ", expected: " << LLT::scalar(1) << '\n');
return false;
}
unsigned CmpOpc = 0;
unsigned ZReg = 0;
LLT CmpTy = MRI.getType(I.getOperand(2).getReg());
if (CmpTy == LLT::scalar(32)) {
CmpOpc = AArch64::SUBSWrr;
ZReg = AArch64::WZR;
} else if (CmpTy == LLT::scalar(64) || CmpTy.isPointer()) {
CmpOpc = AArch64::SUBSXrr;
ZReg = AArch64::XZR;
} else {
return false;
}
const AArch64CC::CondCode CC = changeICMPPredToAArch64CC(
(CmpInst::Predicate)I.getOperand(1).getPredicate());
MachineInstr &CmpMI = *BuildMI(MBB, I, I.getDebugLoc(), TII.get(CmpOpc))
.addDef(ZReg)
.addUse(I.getOperand(2).getReg())
.addUse(I.getOperand(3).getReg());
MachineInstr &CSetMI =
*BuildMI(MBB, I, I.getDebugLoc(), TII.get(AArch64::CSINCWr))
.addDef(I.getOperand(0).getReg())
.addUse(AArch64::WZR)
.addUse(AArch64::WZR)
.addImm(CC);
constrainSelectedInstRegOperands(CmpMI, TII, TRI, RBI);
constrainSelectedInstRegOperands(CSetMI, TII, TRI, RBI);
I.eraseFromParent();
return true;
}
}
return false;

View File

@ -99,6 +99,7 @@
define void @bitcast_s64_gpr_fpr() { ret void }
define void @bitcast_s64_fpr_gpr() { ret void }
define void @icmp() { ret void }
...
---
@ -1682,3 +1683,48 @@ body: |
%0(s64) = COPY %d0
%1(s64) = G_BITCAST %0
...
---
# CHECK-LABEL: name: icmp
name: icmp
legalized: true
regBankSelected: true
# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gpr32 }
# CHECK-NEXT: - { id: 1, class: gpr32 }
# CHECK-NEXT: - { id: 2, class: gpr64 }
# CHECK-NEXT: - { id: 3, class: gpr32 }
# CHECK-NEXT: - { id: 4, class: gpr64 }
# CHECK-NEXT: - { id: 5, class: gpr32 }
registers:
- { id: 0, class: gpr }
- { id: 1, class: gpr }
- { id: 2, class: gpr }
- { id: 3, class: gpr }
- { id: 4, class: gpr }
- { id: 5, class: gpr }
# CHECK: body:
# CHECK: %wzr = SUBSWrr %0, %0, implicit-def %nzcv
# CHECK: %1 = CSINCWr %wzr, %wzr, 0, implicit %nzcv
# CHECK: %xzr = SUBSXrr %2, %2, implicit-def %nzcv
# CHECK: %3 = CSINCWr %wzr, %wzr, 2, implicit %nzcv
# CHECK: %xzr = SUBSXrr %4, %4, implicit-def %nzcv
# CHECK: %5 = CSINCWr %wzr, %wzr, 1, implicit %nzcv
body: |
bb.0:
liveins: %w0, %x0
%0(s32) = COPY %w0
%1(s1) = G_ICMP intpred(eq), %0, %0
%2(s64) = COPY %x0
%3(s1) = G_ICMP intpred(uge), %2, %2
%4(p0) = COPY %x0
%5(s1) = G_ICMP intpred(ne), %4, %4
...