From 7b111890d1f90dcb0e629b07720db1a7ae6f32bf Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Tue, 8 Nov 2016 00:45:29 +0000 Subject: [PATCH] GlobalISel: support selecting G_SELECT on AArch64. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286185 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../AArch64/AArch64InstructionSelector.cpp | 40 +++++++++++++++++ .../GlobalISel/arm64-instructionselect.mir | 44 +++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/lib/Target/AArch64/AArch64InstructionSelector.cpp b/lib/Target/AArch64/AArch64InstructionSelector.cpp index 7f2ce779a0cb3..80ea8d6d61d40 100644 --- a/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -18,6 +18,7 @@ #include "AArch64RegisterInfo.h" #include "AArch64Subtarget.h" #include "AArch64TargetMachine.h" +#include "MCTargetDesc/AArch64AddressingModes.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" @@ -952,6 +953,45 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const { case TargetOpcode::G_BITCAST: return selectCopy(I, TII, MRI, TRI, RBI); + case TargetOpcode::G_SELECT: { + if (MRI.getType(I.getOperand(1).getReg()) != LLT::scalar(1)) { + DEBUG(dbgs() << "G_SELECT cond has type: " << Ty + << ", expected: " << LLT::scalar(1) << '\n'); + return false; + } + + const unsigned CondReg = I.getOperand(1).getReg(); + const unsigned TReg = I.getOperand(2).getReg(); + const unsigned FReg = I.getOperand(3).getReg(); + + unsigned CSelOpc = 0; + + if (Ty == LLT::scalar(32)) { + CSelOpc = AArch64::CSELWr; + } else if (Ty == LLT::scalar(64)) { + CSelOpc = AArch64::CSELXr; + } else { + return false; + } + + MachineInstr &TstMI = + *BuildMI(MBB, I, I.getDebugLoc(), TII.get(AArch64::ANDSWri)) + .addDef(AArch64::WZR) + .addUse(CondReg) + .addImm(AArch64_AM::encodeLogicalImmediate(1, 32)); + + MachineInstr &CSelMI = *BuildMI(MBB, I, I.getDebugLoc(), TII.get(CSelOpc)) + .addDef(I.getOperand(0).getReg()) + .addUse(TReg) + .addUse(FReg) + .addImm(AArch64CC::NE); + + constrainSelectedInstRegOperands(TstMI, TII, TRI, RBI); + constrainSelectedInstRegOperands(CSelMI, TII, TRI, RBI); + + I.eraseFromParent(); + return true; + } case TargetOpcode::G_ICMP: { if (Ty != LLT::scalar(1)) { DEBUG(dbgs() << "G_ICMP result has type: " << Ty diff --git a/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir b/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir index 7d0ec021239c8..e9c165b892be6 100644 --- a/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir +++ b/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir @@ -150,6 +150,7 @@ define void @phi() { ret void } + define void @select() { ret void } ... --- @@ -2874,3 +2875,46 @@ body: | %s0 = COPY %2 RET_ReallyLR implicit %s0 ... + +--- +# CHECK-LABEL: name: select +name: select +legalized: true +regBankSelected: true +tracksRegLiveness: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +# CHECK-NEXT: - { id: 3, class: gpr32 } +# CHECK-NEXT: - { id: 4, class: gpr64 } +# CHECK-NEXT: - { id: 5, class: gpr64 } +# CHECK-NEXT: - { id: 6, class: gpr64 } +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 } + - { id: 6, class: gpr } + +# CHECK: body: +# CHECK: %wzr = ANDSWri %0, 0, implicit-def %nzcv +# CHECK: %3 = CSELWr %1, %2, 1, implicit %nzcv +# CHECK: %wzr = ANDSWri %0, 0, implicit-def %nzcv +# CHECK: %6 = CSELXr %4, %5, 1, implicit %nzcv +body: | + bb.0: + liveins: %w0, %w1, %w2 + %0(s1) = COPY %w0 + + %1(s32) = COPY %w1 + %2(s32) = COPY %w2 + %3(s32) = G_SELECT %0, %1, %2 + + %4(s64) = COPY %x0 + %5(s64) = COPY %x1 + %6(s64) = G_SELECT %0, %4, %5 +...