[AArch64][GlobalISel] Select G_MUL.
authorAhmed Bougacha <ahmed.bougacha@gmail.com>
Tue, 16 Aug 2016 14:37:46 +0000 (14:37 +0000)
committerAhmed Bougacha <ahmed.bougacha@gmail.com>
Tue, 16 Aug 2016 14:37:46 +0000 (14:37 +0000)
llvm-svn: 278810

llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir

index d508d1e..9d2630f 100644 (file)
@@ -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");
 
index d9469fa..ce274c7 100644 (file)
@@ -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:
index fa00874..bb641c9 100644 (file)
@@ -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