From e4c03abddd29ebd10449dd5991f2d2f20c1cd771 Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Tue, 16 Aug 2016 14:37:46 +0000 Subject: [PATCH] [AArch64][GlobalISel] Select G_MUL. llvm-svn: 278810 --- .../lib/CodeGen/GlobalISel/InstructionSelector.cpp | 4 ++ .../Target/AArch64/AArch64InstructionSelector.cpp | 37 +++++++++++++ .../AArch64/GlobalISel/arm64-instructionselect.mir | 63 ++++++++++++++++++++++ 3 files changed, 104 insertions(+) diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp index d508d1e..9d2630f 100644 --- a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp @@ -39,6 +39,10 @@ bool InstructionSelector::constrainSelectedInstRegOperands( DEBUG(dbgs() << "Converting operand: " << MO << '\n'); assert(MO.isReg() && "Unsupported non-reg operand"); + // Physical registers don't need to be constrained. + if (TRI.isPhysicalRegister(MO.getReg())) + continue; + const TargetRegisterClass *RC = TII.getRegClass(I.getDesc(), OpI, &TRI, MF); assert(RC && "Selected inst should have regclass operand"); diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp index d9469fa..ce274c7 100644 --- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -246,6 +246,43 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const { return constrainSelectedInstRegOperands(I, TII, TRI, RBI); } + case TargetOpcode::G_MUL: { + // Reject the various things we don't support yet. + if (unsupportedBinOp(I, RBI, MRI, TRI)) + return false; + + const unsigned DefReg = I.getOperand(0).getReg(); + const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI); + + if (RB.getID() != AArch64::GPRRegBankID) { + DEBUG(dbgs() << "G_MUL on bank: " << RB << ", expected: GPR\n"); + return false; + } + + unsigned ZeroReg; + unsigned NewOpc; + if (Ty == LLT::scalar(32)) { + NewOpc = AArch64::MADDWrrr; + ZeroReg = AArch64::WZR; + } else if (Ty == LLT::scalar(64)) { + NewOpc = AArch64::MADDXrrr; + ZeroReg = AArch64::XZR; + } else { + DEBUG(dbgs() << "G_MUL has type: " << Ty << ", expected: " + << LLT::scalar(32) << " or " << LLT::scalar(64) << '\n'); + return false; + } + + I.setDesc(TII.get(NewOpc)); + I.removeTypes(); + + I.addOperand(MachineOperand::CreateReg(ZeroReg, /*isDef=*/false)); + + // Now that we selected an opcode, we need to constrain the register + // operands to use appropriate classes. + return constrainSelectedInstRegOperands(I, TII, TRI, RBI); + } + case TargetOpcode::G_OR: case TargetOpcode::G_XOR: case TargetOpcode::G_AND: diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir index fa00874..bb641c9 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir @@ -31,6 +31,9 @@ define void @ashr_s32_gpr() { ret void } define void @ashr_s64_gpr() { ret void } + define void @mul_s32_gpr() { ret void } + define void @mul_s64_gpr() { ret void } + define void @unconditional_br() { ret void } define void @load_s64_gpr(i64* %addr) { ret void } @@ -529,6 +532,66 @@ body: | %2(64) = G_ASHR s64 %0, %1 ... +# Check that we select s32 GPR G_MUL. This is trickier than other binops because +# there is only MADDWrrr, and we have to use the WZR physreg. +# CHECK-LABEL: name: mul_s32_gpr +name: mul_s32_gpr +isSSA: true +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = MADDWrrr %0, %1, %wzr +body: | + bb.0: + liveins: %w0, %w1 + + %0(32) = COPY %w0 + %1(32) = COPY %w1 + %2(32) = G_MUL s32 %0, %1 +... + +--- +# Same as mul_s32_gpr for the s64 type. +# CHECK-LABEL: name: mul_s64_gpr +name: mul_s64_gpr +isSSA: true +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = MADDXrrr %0, %1, %xzr +body: | + bb.0: + liveins: %x0, %x1 + + %0(64) = COPY %x0 + %1(64) = COPY %x1 + %2(64) = G_MUL s64 %0, %1 +... + --- # CHECK-LABEL: name: unconditional_br name: unconditional_br -- 2.7.4