[llvm] r277769 - GlobalISel: implement narrowing for G_ADD.

Tim Northover via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 4 13:54:14 PDT 2016


Author: tnorthover
Date: Thu Aug  4 15:54:13 2016
New Revision: 277769

URL: http://llvm.org/viewvc/llvm-project?rev=277769&view=rev
Log:
GlobalISel: implement narrowing for G_ADD.

Modified:
    llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
    llvm/trunk/include/llvm/Target/GenericOpcodes.td
    llvm/trunk/include/llvm/Target/TargetOpcodes.def
    llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
    llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp
    llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp
    llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir

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=277769&r1=277768&r2=277769&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h Thu Aug  4 15:54:13 2016
@@ -131,6 +131,19 @@ public:
   MachineInstrBuilder buildAdd(LLT Ty, unsigned Res, unsigned Op0,
                                 unsigned Op1);
 
+  /// Build and insert \p Res<def>, \p CarryOut = G_ADDE \p Ty \p Op0, \p Op1,
+  /// \p CarryIn
+  ///
+  /// G_ADDE sets \p Res to \p Op0 + \p Op1 + \p CarryIn (truncated to the bit
+  /// width) and sets \p CarryOut to 1 if the result overflowed in 2s-complement
+  /// arithmetic.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  ///
+  /// \return The newly created instruction.
+  MachineInstrBuilder buildAdde(LLT Ty, unsigned Res, unsigned CarryOut,
+                                unsigned Op0, unsigned Op1, unsigned CarryIn);
+
   /// Build and insert \p Res<def> = G_ANYEXTEND \p Ty \p Op0
   ///
   /// G_ANYEXTEND produces a register of the specified width, with bits 0 to
@@ -163,6 +176,15 @@ public:
   /// \return The newly created instruction.
   MachineInstrBuilder buildBrCond(LLT Ty, unsigned Tst, MachineBasicBlock &BB);
 
+  /// Build and insert \p Res = G_CONSTANT \p Ty \p Val
+  ///
+  /// G_CONSTANT is an integer constant with the specified size and value.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  ///
+  /// \return The newly created instruction.
+  MachineInstrBuilder buildConstant(LLT Ty, unsigned Res, int64_t Val);
+
   /// Build and insert \p Res<def> = COPY Op
   ///
   /// Register-to-register COPY sets \p Res to \p Op.

Modified: llvm/trunk/include/llvm/Target/GenericOpcodes.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/GenericOpcodes.td?rev=277769&r1=277768&r2=277769&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/GenericOpcodes.td (original)
+++ llvm/trunk/include/llvm/Target/GenericOpcodes.td Thu Aug  4 15:54:13 2016
@@ -59,6 +59,12 @@ def G_BITCAST : Instruction {
   let hasSideEffects = 0;
 }
 
+def G_CONSTANT : Instruction {
+  let OutOperandList = (outs unknown:$dst);
+  let InOperandList = (ins unknown:$imm);
+  let hasSideEffects = 0;
+}
+
 //------------------------------------------------------------------------------
 // Binary ops.
 //------------------------------------------------------------------------------
@@ -79,6 +85,14 @@ def G_SUB : Instruction {
   let isCommutable = 0;
 }
 
+// Generic addition consuming and producing a carry flag.
+def G_ADDE : Instruction {
+  let OutOperandList = (outs unknown:$dst, unknown:$carry_out);
+  let InOperandList = (ins unknown:$src1, unknown:$src2, unknown:$carry_in);
+  let hasSideEffects = 0;
+  let isCommutable = 1;
+}
+
 // Generic bitwise and.
 def G_AND : Instruction {
   let OutOperandList = (outs unknown:$dst);
@@ -163,6 +177,7 @@ def G_INTRINSIC_W_SIDE_EFFECTS : Instruc
 //------------------------------------------------------------------------------
 // Branches.
 //------------------------------------------------------------------------------
+
 // Generic unconditional branch.
 def G_BR : Instruction {
   let OutOperandList = (outs);

Modified: llvm/trunk/include/llvm/Target/TargetOpcodes.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetOpcodes.def?rev=277769&r1=277768&r2=277769&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetOpcodes.def (original)
+++ llvm/trunk/include/llvm/Target/TargetOpcodes.def Thu Aug  4 15:54:13 2016
@@ -159,16 +159,20 @@ HANDLE_TARGET_OPCODE(PATCHABLE_RET)
 HANDLE_TARGET_OPCODE(G_ADD)
 HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_START, G_ADD)
 
+/// Generic ADD instruction, consuming the normal operands plus a carry flag,
+/// and similarly producing the result and a carry flag.
+HANDLE_TARGET_OPCODE(G_ADDE)
+
 /// Generic SUB instruction. This is an integer sub.
 HANDLE_TARGET_OPCODE(G_SUB)
 
 /// Generic Bitwise-AND instruction.
 HANDLE_TARGET_OPCODE(G_AND)
 
-/// Generic Bitwise-OR instruction.
+/// Generic bitwise or instruction.
 HANDLE_TARGET_OPCODE(G_OR)
 
-/// Generic Bitwise-OR instruction.
+/// Generic bitwise exclusive-or instruction.
 HANDLE_TARGET_OPCODE(G_XOR)
 
 /// Generic instruction to materialize the address of an alloca or other
@@ -214,6 +218,9 @@ HANDLE_TARGET_OPCODE(G_ANYEXTEND)
 /// Generic truncation.
 HANDLE_TARGET_OPCODE(G_TRUNC)
 
+/// Generic integer constant.
+HANDLE_TARGET_OPCODE(G_CONSTANT)
+
 /// Generic BRANCH instruction. This is an unconditional branch.
 HANDLE_TARGET_OPCODE(G_BR)
 

Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp?rev=277769&r1=277768&r2=277769&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp Thu Aug  4 15:54:13 2016
@@ -95,6 +95,11 @@ MachineInstrBuilder MachineIRBuilder::bu
   return buildInstr(TargetOpcode::COPY).addDef(Res).addUse(Op);
 }
 
+MachineInstrBuilder MachineIRBuilder::buildConstant(LLT Ty, unsigned Res,
+                                                    int64_t Val) {
+  return buildInstr(TargetOpcode::G_CONSTANT, Ty).addDef(Res).addImm(Val);
+}
+
 MachineInstrBuilder MachineIRBuilder::buildBrCond(LLT Ty, unsigned Tst,
                                                   MachineBasicBlock &Dest) {
   return buildInstr(TargetOpcode::G_BRCOND, Ty).addUse(Tst).addMBB(&Dest);
@@ -119,6 +124,18 @@ MachineInstrBuilder MachineIRBuilder::bu
       .addMemOperand(&MMO);
 }
 
+MachineInstrBuilder MachineIRBuilder::buildAdde(LLT Ty, unsigned Res,
+                                                unsigned CarryOut, unsigned Op0,
+                                                unsigned Op1,
+                                                unsigned CarryIn) {
+  return buildInstr(TargetOpcode::G_ADDE, Ty)
+      .addDef(Res)
+      .addDef(CarryOut)
+      .addUse(Op0)
+      .addUse(Op1)
+      .addUse(CarryIn);
+}
+
 MachineInstrBuilder MachineIRBuilder::buildAnyExtend(LLT Ty, unsigned Res,
                                                      unsigned Op) {
   return buildInstr(TargetOpcode::G_ANYEXTEND, Ty).addDef(Res).addUse(Op);

Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp?rev=277769&r1=277768&r2=277769&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp Thu Aug  4 15:54:13 2016
@@ -61,7 +61,38 @@ void MachineLegalizeHelper::extractParts
 
 MachineLegalizeHelper::LegalizeResult
 MachineLegalizeHelper::narrowScalar(MachineInstr &MI, LLT NarrowTy) {
-  return UnableToLegalize;
+  switch (MI.getOpcode()) {
+  default:
+    return UnableToLegalize;
+  case TargetOpcode::G_ADD: {
+    // Expand in terms of carry-setting/consuming G_ADDE instructions.
+    unsigned NarrowSize = NarrowTy.getSizeInBits();
+    int NumParts = MI.getType().getSizeInBits() / NarrowSize;
+
+    MIRBuilder.setInstr(MI);
+
+    SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
+    extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
+    extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
+
+    unsigned CarryIn = MRI.createGenericVirtualRegister(1);
+    MIRBuilder.buildConstant(LLT::scalar(1), CarryIn, 0);
+
+    for (int i = 0; i < NumParts; ++i) {
+      unsigned DstReg = MRI.createGenericVirtualRegister(NarrowSize);
+      unsigned CarryOut = MRI.createGenericVirtualRegister(1);
+
+      MIRBuilder.buildAdde(NarrowTy, DstReg, CarryOut, Src1Regs[i], Src2Regs[i],
+                           CarryIn);
+
+      DstRegs.push_back(DstReg);
+      CarryIn = CarryOut;
+    }
+    MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstRegs);
+    MI.eraseFromParent();
+    return Legalized;
+  }
+  }
 }
 
 MachineLegalizeHelper::LegalizeResult

Modified: llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp?rev=277769&r1=277768&r2=277769&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp Thu Aug  4 15:54:13 2016
@@ -26,20 +26,27 @@ using namespace llvm;
 
 AArch64MachineLegalizer::AArch64MachineLegalizer() {
   using namespace TargetOpcode;
+  const LLT s8 = LLT::scalar(8);
+  const LLT s16 = LLT::scalar(16);
   const LLT s32 = LLT::scalar(32);
   const LLT s64 = LLT::scalar(64);
   const LLT v2s32 = LLT::vector(2, 32);
   const LLT v4s32 = LLT::vector(4, 32);
   const LLT v2s64 = LLT::vector(2, 64);
 
-  for (auto BinOp : {G_ADD, G_SUB, G_AND, G_OR, G_XOR})
+  for (auto BinOp : {G_ADD, G_SUB, G_AND, G_OR, G_XOR}) {
     for (auto Ty : {s32, s64, v2s32, v4s32, v2s64})
       setAction(BinOp, Ty, Legal);
 
+    for (auto Ty : {s8, s16})
+      setAction(BinOp, Ty, WidenScalar);
+  }
+
   for (auto MemOp : {G_LOAD, G_STORE})
     for (auto Ty : {s32, s64})
       setAction(MemOp, Ty, Legal);
 
+
   setAction(G_BR, LLT::unsized(), Legal);
 
   computeTables();

Modified: llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir?rev=277769&r1=277768&r2=277769&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir (original)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir Thu Aug  4 15:54:13 2016
@@ -3,6 +3,10 @@
 --- |
   target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
   target triple = "aarch64-apple-ios"
+  define void @test_scalar_add_big() {
+  entry:
+    ret void
+  }
   define void @test_scalar_add_small() {
   entry:
     ret void
@@ -14,6 +18,30 @@
 ...
 
 ---
+name:            test_scalar_add_big
+isSSA:           true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body: |
+  bb.0.entry:
+    liveins: %x0, %x1, %x2, %x3
+    ; CHECK-LABEL: name: test_scalar_add_big
+    ; CHECK-DAG: [[LHS_LO:%.*]](64), [[LHS_HI:%.*]](64) = G_EXTRACT s64 %0, 0, 64
+    ; CHECK-DAG: [[RHS_LO:%.*]](64), [[RHS_HI:%.*]](64) = G_EXTRACT s64 %1, 0, 64
+    ; CHECK-DAG: [[CARRY0:%.*]](1) = G_CONSTANT s1 0
+    ; CHECK: [[RES_LO:%.*]](64), [[CARRY:%.*]](1) = G_ADDE s64 [[LHS_LO]], [[RHS_LO]], [[CARRY0]]
+    ; CHECK: [[RES_HI:%.*]](64), {{%.*}}(1) = G_ADDE s64 [[LHS_HI]], [[RHS_HI]], [[CARRY]]
+    ; CHECK: %2(128) = G_SEQUENCE s128 [[RES_LO]], [[RES_HI]]
+
+    %0(128) = G_SEQUENCE s128 %x0, %x1
+    %1(128) = G_SEQUENCE s128 %x2, %x3
+    %2(128) = G_ADD s128 %0, %1
+    %x0, %x1 = G_EXTRACT s64 %2, 0, 64
+...
+
+---
 name:            test_scalar_add_small
 isSSA:           true
 registers:




More information about the llvm-commits mailing list