| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| //===-- llvm/CodeGen/GlobalISel/MachineLegalizeHelper.cpp -----------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| /// \file This file implements the MachineLegalizeHelper class to legalize | ||
| /// individual instructions and the LegalizeMachineIR wrapper pass for the | ||
| /// primary legalization. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h" | ||
| #include "llvm/CodeGen/GlobalISel/MachineLegalizer.h" | ||
| #include "llvm/CodeGen/MachineRegisterInfo.h" | ||
| #include "llvm/Support/Debug.h" | ||
| #include "llvm/Support/raw_ostream.h" | ||
| #include "llvm/Target/TargetSubtargetInfo.h" | ||
|
|
||
| #include <sstream> | ||
|
|
||
| #define DEBUG_TYPE "legalize-mir" | ||
|
|
||
| using namespace llvm; | ||
|
|
||
| MachineLegalizeHelper::MachineLegalizeHelper(MachineFunction &MF) | ||
| : MRI(MF.getRegInfo()) { | ||
| MIRBuilder.setMF(MF); | ||
| } | ||
|
|
||
| MachineLegalizeHelper::LegalizeResult MachineLegalizeHelper::legalizeInstr( | ||
| MachineInstr &MI, const MachineLegalizer &Legalizer) { | ||
| auto Action = Legalizer.getAction(MI); | ||
| switch (Action.first) { | ||
| case MachineLegalizer::Legal: | ||
| return AlreadyLegal; | ||
| case MachineLegalizer::NarrowScalar: | ||
| return narrowScalar(MI, Action.second); | ||
| case MachineLegalizer::WidenScalar: | ||
| return widenScalar(MI, Action.second); | ||
| case MachineLegalizer::FewerElements: | ||
| return fewerElementsVector(MI, Action.second); | ||
| default: | ||
| return UnableToLegalize; | ||
| } | ||
| } | ||
|
|
||
| void MachineLegalizeHelper::extractParts(unsigned Reg, LLT Ty, int NumParts, | ||
| SmallVectorImpl<unsigned> &VRegs) { | ||
| unsigned Size = Ty.getSizeInBits(); | ||
| SmallVector<unsigned, 4> Indexes; | ||
| for (int i = 0; i < NumParts; ++i) { | ||
| VRegs.push_back(MRI.createGenericVirtualRegister(Size)); | ||
| Indexes.push_back(i * Size); | ||
| } | ||
| MIRBuilder.buildExtract(Ty, VRegs, Reg, Indexes); | ||
| } | ||
|
|
||
| MachineLegalizeHelper::LegalizeResult | ||
| MachineLegalizeHelper::narrowScalar(MachineInstr &MI, LLT NarrowTy) { | ||
| return UnableToLegalize; | ||
| } | ||
|
|
||
| MachineLegalizeHelper::LegalizeResult | ||
| MachineLegalizeHelper::widenScalar(MachineInstr &MI, LLT WideTy) { | ||
| return UnableToLegalize; | ||
| } | ||
|
|
||
| MachineLegalizeHelper::LegalizeResult | ||
| MachineLegalizeHelper::fewerElementsVector(MachineInstr &MI, LLT NarrowTy) { | ||
| switch (MI.getOpcode()) { | ||
| default: | ||
| return UnableToLegalize; | ||
| case TargetOpcode::G_ADD: { | ||
| 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); | ||
|
|
||
| for (int i = 0; i < NumParts; ++i) { | ||
| unsigned DstReg = MRI.createGenericVirtualRegister(NarrowSize); | ||
| MIRBuilder.buildAdd(NarrowTy, DstReg, Src1Regs[i], Src2Regs[i]); | ||
| DstRegs.push_back(DstReg); | ||
| } | ||
|
|
||
| MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstRegs); | ||
| MI.eraseFromParent(); | ||
| return Legalized; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| //===-- llvm/CodeGen/GlobalISel/MachineLegalizePass.cpp -------------------===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| /// \file This file implements the LegalizeHelper class to legalize individual | ||
| /// instructions and the MachineLegalizePass wrapper pass for the primary | ||
| /// legalization. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "llvm/CodeGen/GlobalISel/MachineLegalizePass.h" | ||
| #include "llvm/CodeGen/MachineRegisterInfo.h" | ||
| #include "llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h" | ||
| #include "llvm/CodeGen/GlobalISel/MachineLegalizer.h" | ||
| #include "llvm/Support/Debug.h" | ||
| #include "llvm/Target/TargetSubtargetInfo.h" | ||
|
|
||
| #define DEBUG_TYPE "legalize-mir" | ||
|
|
||
| using namespace llvm; | ||
|
|
||
| char MachineLegalizePass::ID = 0; | ||
| INITIALIZE_PASS(MachineLegalizePass, DEBUG_TYPE, | ||
| "Legalize the Machine IR a function's Machine IR", false, | ||
| false); | ||
|
|
||
| MachineLegalizePass::MachineLegalizePass() : MachineFunctionPass(ID) { | ||
| initializeMachineLegalizePassPass(*PassRegistry::getPassRegistry()); | ||
| } | ||
|
|
||
| void MachineLegalizePass::init(MachineFunction &MF) { | ||
| } | ||
|
|
||
| bool MachineLegalizePass::runOnMachineFunction(MachineFunction &MF) { | ||
| DEBUG(dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n'); | ||
| init(MF); | ||
| const MachineLegalizer &Legalizer = *MF.getSubtarget().getMachineLegalizer(); | ||
| MachineLegalizeHelper Helper(MF); | ||
|
|
||
| // FIXME: an instruction may need more than one pass before it is legal. For | ||
| // example on most architectures <3 x i3> is doubly-illegal. It would | ||
| // typically proceed along a path like: <3 x i3> -> <3 x i8> -> <8 x i8>. We | ||
| // probably want a worklist of instructions rather than naive iterate until | ||
| // convergence for performance reasons. | ||
| bool Changed = false; | ||
| MachineBasicBlock::iterator NextMI; | ||
| for (auto &MBB : MF) | ||
| for (auto MI = MBB.begin(); MI != MBB.end(); MI = NextMI) { | ||
| // Get the next Instruction before we try to legalize, because there's a | ||
| // good chance MI will be deleted. | ||
| NextMI = std::next(MI); | ||
| auto Res = Helper.legalizeInstr(*MI, Legalizer); | ||
|
|
||
| // Error out if we couldn't legalize this instruction. We may want to fall | ||
| // back to DAG ISel instead in the future. | ||
| if (Res == MachineLegalizeHelper::UnableToLegalize) { | ||
| std::string Msg; | ||
| raw_string_ostream OS(Msg); | ||
| OS << "unable to legalize instruction: "; | ||
| MI->print(OS); | ||
| report_fatal_error(OS.str()); | ||
| } | ||
|
|
||
| Changed |= Res == MachineLegalizeHelper::Legalized; | ||
| } | ||
| return Changed; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| //===- AArch64MachineLegalizer.cpp -------------------------------*- C++ -*-==// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| /// \file | ||
| /// This file implements the targeting of the Machinelegalizer class for | ||
| /// AArch64. | ||
| /// \todo This should be generated by TableGen. | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "AArch64MachineLegalizer.h" | ||
| #include "llvm/CodeGen/ValueTypes.h" | ||
| #include "llvm/IR/Type.h" | ||
| #include "llvm/IR/DerivedTypes.h" | ||
| #include "llvm/Target/TargetOpcodes.h" | ||
|
|
||
| using namespace llvm; | ||
|
|
||
| #ifndef LLVM_BUILD_GLOBAL_ISEL | ||
| #error "You shouldn't build this" | ||
| #endif | ||
|
|
||
| AArch64MachineLegalizer::AArch64MachineLegalizer() { | ||
| setAction(TargetOpcode::G_ADD, LLT::vector(2, 64), Legal); | ||
| computeTables(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| //===- AArch64Machinelegalizer --------------------------------*- C++ -*-==// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
| /// \file | ||
| /// This file declares the targeting of the Machinelegalizer class for | ||
| /// AArch64. | ||
| /// \todo This should be generated by TableGen. | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64MACHINELEGALIZER_H | ||
| #define LLVM_LIB_TARGET_AARCH64_AARCH64MACHINELEGALIZER_H | ||
|
|
||
| #include "llvm/CodeGen/GlobalISel/Machinelegalizer.h" | ||
|
|
||
| namespace llvm { | ||
|
|
||
| class LLVMContext; | ||
|
|
||
| /// This class provides the information for the target register banks. | ||
| class AArch64MachineLegalizer : public MachineLegalizer { | ||
| public: | ||
| AArch64MachineLegalizer(); | ||
| }; | ||
| } // End llvm namespace. | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # RUN: llc -O0 -run-pass=legalize-mir -global-isel %s -o - 2>&1 | FileCheck %s | ||
| # REQUIRES: global-isel | ||
|
|
||
| --- | | ||
| target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" | ||
| target triple = "aarch64-apple-ios" | ||
| define void @test_vector_add() { | ||
| entry: | ||
| ret void | ||
| } | ||
| ... | ||
|
|
||
| --- | ||
| name: test_vector_add | ||
| isSSA: true | ||
| registers: | ||
| - { id: 0, class: _ } | ||
| - { id: 1, class: _ } | ||
| - { id: 2, class: _ } | ||
| body: | | ||
| bb.0.entry: | ||
| liveins: %q0, %q1, %q2, %q3 | ||
| ; CHECK-LABEL: name: test_vector_add | ||
| ; CHECK-DAG: [[LHS_LO:%.*]](128), [[LHS_HI:%.*]](128) = G_EXTRACT <2 x s64> %0, 0, 128 | ||
| ; CHECK-DAG: [[RHS_LO:%.*]](128), [[RHS_HI:%.*]](128) = G_EXTRACT <2 x s64> %1, 0, 128 | ||
| ; CHECK: [[RES_LO:%.*]](128) = G_ADD <2 x s64> [[LHS_LO]], [[RHS_LO]] | ||
| ; CHECK: [[RES_HI:%.*]](128) = G_ADD <2 x s64> [[LHS_HI]], [[RHS_HI]] | ||
| ; CHECK: %2(256) = G_SEQUENCE <4 x s64> [[RES_LO]], [[RES_HI]] | ||
| %0(256) = G_SEQUENCE <4 x s64> %q0, %q1 | ||
| %1(256) = G_SEQUENCE <4 x s64> %q2, %q3 | ||
| %2(256) = G_ADD <4 x s64> %0, %1 | ||
| %q0, %q1 = G_EXTRACT <2 x s64> %2, 0, 128 | ||
| ... |