[llvm] r279842 - GlobalISel: legalize sdiv and srem operations.

Tim Northover via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 26 10:46:13 PDT 2016


Author: tnorthover
Date: Fri Aug 26 12:46:13 2016
New Revision: 279842

URL: http://llvm.org/viewvc/llvm-project?rev=279842&view=rev
Log:
GlobalISel: legalize sdiv and srem operations.

Added:
    llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir
Modified:
    llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
    llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h
    llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizer.h
    llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
    llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp
    llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizer.cpp
    llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp
    llvm/trunk/unittests/CodeGen/GlobalISel/MachineLegalizerTest.cpp

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h?rev=279842&r1=279841&r2=279842&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h Fri Aug 26 12:46:13 2016
@@ -144,6 +144,28 @@ public:
   MachineInstrBuilder buildAdd(LLT Ty, unsigned Res, unsigned Op0,
                                 unsigned Op1);
 
+  /// Build and insert \p Res<def> = G_SUB \p Ty \p Op0, \p Op1
+  ///
+  /// G_SUB sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
+  /// truncated to their width.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+  MachineInstrBuilder buildSub(LLT Ty, unsigned Res, unsigned Op0,
+                               unsigned Op1);
+
+  /// Build and insert \p Res<def> = G_MUL \p Ty \p Op0, \p Op1
+  ///
+  /// G_MUL sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
+  /// truncated to their width.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  ///
+  /// \return a MachineInstrBuilder for the newly created instruction.
+  MachineInstrBuilder buildMul(LLT Ty, unsigned Res, unsigned Op0,
+                               unsigned Op1);
+
   /// Build and insert \p Res<def>, \p CarryOut = G_UADDE \p Tys \p Op0, \p Op1,
   /// \p CarryIn
   ///

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h?rev=279842&r1=279841&r2=279842&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h Fri Aug 26 12:46:13 2016
@@ -70,6 +70,10 @@ public:
   /// precision, ignoring the unused bits).
   LegalizeResult widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy);
 
+  /// Legalize an instruction by splitting it into simpler parts, hopefully
+  /// understood by the target.
+  LegalizeResult lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty);
+
   /// Legalize a vector instruction by splitting into multiple components, each
   /// acting on the same scalar type as the original but with fewer elements.
   LegalizeResult fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizer.h?rev=279842&r1=279841&r2=279842&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizer.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizer.h Fri Aug 26 12:46:13 2016
@@ -87,6 +87,10 @@ public:
     /// the first two results.
     MoreElements,
 
+    /// The operation itself must be expressed in terms of simpler actions on
+    /// this target. E.g. a SREM replaced by an SDIV and subtraction.
+    Lower,
+
     /// The operation should be implemented as a call to some kind of runtime
     /// support library. For example this usually happens on machines that don't
     /// support floating-point operations natively.

Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp?rev=279842&r1=279841&r2=279842&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp Fri Aug 26 12:46:13 2016
@@ -99,6 +99,22 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addUse(Op1);
 }
 
+MachineInstrBuilder MachineIRBuilder::buildSub(LLT Ty, unsigned Res,
+                                                unsigned Op0, unsigned Op1) {
+  return buildInstr(TargetOpcode::G_SUB, Ty)
+      .addDef(Res)
+      .addUse(Op0)
+      .addUse(Op1);
+}
+
+MachineInstrBuilder MachineIRBuilder::buildMul(LLT Ty, unsigned Res,
+                                                unsigned Op0, unsigned Op1) {
+  return buildInstr(TargetOpcode::G_MUL, Ty)
+      .addDef(Res)
+      .addUse(Op0)
+      .addUse(Op1);
+}
+
 MachineInstrBuilder MachineIRBuilder::buildBr(MachineBasicBlock &Dest) {
   return buildInstr(TargetOpcode::G_BR, LLT::unsized()).addMBB(&Dest);
 }

Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp?rev=279842&r1=279841&r2=279842&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp Fri Aug 26 12:46:13 2016
@@ -42,6 +42,8 @@ MachineLegalizeHelper::legalizeInstrStep
     return narrowScalar(MI, std::get<1>(Action), std::get<2>(Action));
   case MachineLegalizer::WidenScalar:
     return widenScalar(MI, std::get<1>(Action), std::get<2>(Action));
+  case MachineLegalizer::Lower:
+    return lower(MI, std::get<1>(Action), std::get<2>(Action));
   case MachineLegalizer::FewerElements:
     return fewerElementsVector(MI, std::get<1>(Action), std::get<2>(Action));
   default:
@@ -267,6 +269,33 @@ MachineLegalizeHelper::widenScalar(Machi
   }
   }
 }
+
+MachineLegalizeHelper::LegalizeResult
+MachineLegalizeHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
+  using namespace TargetOpcode;
+  unsigned Size = Ty.getSizeInBits();
+  MIRBuilder.setInstr(MI);
+
+  switch(MI.getOpcode()) {
+  default:
+    return UnableToLegalize;
+  case TargetOpcode::G_SREM:
+  case TargetOpcode::G_UREM: {
+    unsigned QuotReg = MRI.createGenericVirtualRegister(Size);
+    MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, Ty)
+        .addDef(QuotReg)
+        .addUse(MI.getOperand(1).getReg())
+        .addUse(MI.getOperand(2).getReg());
+
+    unsigned ProdReg = MRI.createGenericVirtualRegister(Size);
+    MIRBuilder.buildMul(Ty, ProdReg, QuotReg, MI.getOperand(2).getReg());
+    MIRBuilder.buildSub(Ty, MI.getOperand(0).getReg(),
+                        MI.getOperand(1).getReg(), ProdReg);
+    MI.eraseFromParent();
+    return Legalized;
+  }
+  }
+}
 
 MachineLegalizeHelper::LegalizeResult
 MachineLegalizeHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,

Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizer.cpp?rev=279842&r1=279841&r2=279842&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizer.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizer.cpp Fri Aug 26 12:46:13 2016
@@ -126,6 +126,7 @@ LLT MachineLegalizer::findLegalType(cons
   default:
     llvm_unreachable("Cannot find legal type");
   case Legal:
+  case Lower:
     return Aspect.Type;
   case NarrowScalar: {
     return findLegalType(Aspect,

Modified: llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp?rev=279842&r1=279841&r2=279842&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp Fri Aug 26 12:46:13 2016
@@ -51,6 +51,10 @@ AArch64MachineLegalizer::AArch64MachineL
       setAction({BinOp, Ty}, WidenScalar);
   }
 
+  for (auto BinOp : { G_SREM, G_UREM })
+    for (auto Ty : { s1, s8, s16, s32, s64 })
+      setAction({BinOp, Ty}, Lower);
+
   for (auto Op : { G_UADDE, G_USUBE, G_SADDO, G_SSUBO, G_SMULO, G_UMULO }) {
     for (auto Ty : { s32, s64 })
       setAction({Op, Ty}, Legal);

Added: llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir?rev=279842&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir (added)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-rem.mir Fri Aug 26 12:46:13 2016
@@ -0,0 +1,52 @@
+# RUN: llc -O0 -run-pass=legalize-mir -global-isel %s -o - 2>&1 | FileCheck %s
+
+--- |
+  target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+  target triple = "aarch64-apple-ios"
+  define void @test_rem() {
+  entry:
+    ret void
+  }
+...
+
+---
+name:            test_rem
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+  - { id: 3, class: _ }
+  - { id: 4, class: _ }
+  - { id: 5, class: _ }
+  - { id: 6, class: _ }
+  - { id: 7, class: _ }
+  - { id: 8, class: _ }
+body: |
+  bb.0.entry:
+    liveins: %x0, %x1, %x2, %x3
+
+    ; CHECK: [[QUOT:%[0-9]+]](64) = G_UDIV s64 %0, %1
+    ; CHECK: [[PROD:%[0-9]+]](64) = G_MUL s64 [[QUOT]], %1
+    ; CHECK: [[RES:%[0-9]+]](64) = G_SUB s64 %0, [[PROD]]
+    %0(64) = COPY %x0
+    %1(64) = COPY %x1
+    %2(64) = G_UREM s64 %0, %1
+
+    ; CHECK: [[QUOT:%[0-9]+]](32) = G_SDIV s32 %3, %4
+    ; CHECK: [[PROD:%[0-9]+]](32) = G_MUL s32 [[QUOT]], %4
+    ; CHECK: [[RES:%[0-9]+]](32) = G_SUB s32 %3, [[PROD]]
+    %3(32) = G_TRUNC { s32, s64 } %0
+    %4(32) = G_TRUNC { s32, s64 } %1
+    %5(32) = G_SREM s32 %3, %4
+
+    ; CHECK: [[LHS32:%[0-9]+]](32) = G_SEXT { s32, s8 } %6
+    ; CHECK: [[RHS32:%[0-9]+]](32) = G_SEXT { s32, s8 } %7
+    ; CHECK: [[QUOT32:%[0-9]+]](32) = G_SDIV s32 [[LHS32]], [[RHS32]]
+    ; CHECK: [[QUOT:%[0-9]+]](8) = G_TRUNC { s8, s32 } [[QUOT32]]
+    ; CHECK: [[PROD:%[0-9]+]](8) = G_MUL s8 [[QUOT]], %7
+    ; CHECK: [[RES:%[0-9]+]](8) = G_SUB s8 %6, [[PROD]]
+    %6(8) = G_TRUNC { s8, s64 } %0
+    %7(8) = G_TRUNC { s8, s64 } %1
+    %8(8) = G_SREM s8 %6, %7
+
+...

Modified: llvm/trunk/unittests/CodeGen/GlobalISel/MachineLegalizerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/CodeGen/GlobalISel/MachineLegalizerTest.cpp?rev=279842&r1=279841&r2=279842&view=diff
==============================================================================
--- llvm/trunk/unittests/CodeGen/GlobalISel/MachineLegalizerTest.cpp (original)
+++ llvm/trunk/unittests/CodeGen/GlobalISel/MachineLegalizerTest.cpp Fri Aug 26 12:46:13 2016
@@ -13,6 +13,7 @@
 
 using namespace llvm;
 using llvm::MachineLegalizer::LegalizeAction::Legal;
+using llvm::MachineLegalizer::LegalizeAction::Lower;
 using llvm::MachineLegalizer::LegalizeAction::NarrowScalar;
 using llvm::MachineLegalizer::LegalizeAction::WidenScalar;
 using llvm::MachineLegalizer::LegalizeAction::FewerElements;
@@ -26,6 +27,7 @@ namespace llvm {
 std::ostream &
 operator<<(std::ostream &OS, const llvm::MachineLegalizer::LegalizeAction Act) {
   switch (Act) {
+  case Lower: OS << "Lower"; break;
   case Legal: OS << "Legal"; break;
   case NarrowScalar: OS << "NarrowScalar"; break;
   case WidenScalar:  OS << "WidenScalar"; break;




More information about the llvm-commits mailing list