[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