From: Tim Northover Date: Wed, 12 Oct 2016 22:49:04 +0000 (+0000) Subject: GlobalISel: support selection of G_ICMP on AArch64. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7bd256df7fe167dd8c814e9f6cb904731c330ea9;p=llvm GlobalISel: support selection of G_ICMP on AArch64. Patch from Ahmed Bougaca again. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284072 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/AArch64/AArch64InstructionSelector.cpp b/lib/Target/AArch64/AArch64InstructionSelector.cpp index 5be437d610b..63f59cfd003 100644 --- a/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -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; diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir b/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir index 57a52bf3107..6aeb84a406a 100644 --- a/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir +++ b/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir @@ -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 +...