Index: llvm/trunk/lib/Target/X86/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Target/X86/CMakeLists.txt +++ llvm/trunk/lib/Target/X86/CMakeLists.txt @@ -10,11 +10,17 @@ tablegen(LLVM X86GenFastISel.inc -gen-fast-isel) tablegen(LLVM X86GenCallingConv.inc -gen-callingconv) tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget) +if(LLVM_BUILD_GLOBAL_ISEL) + tablegen(LLVM X86GenRegisterBank.inc -gen-register-bank) +endif() + add_public_tablegen_target(X86CommonTableGen) # Add GlobalISel files if the build option was enabled. set(GLOBAL_ISEL_FILES X86CallLowering.cpp + X86LegalizerInfo.cpp + X86RegisterBankInfo.cpp ) if(LLVM_BUILD_GLOBAL_ISEL) Index: llvm/trunk/lib/Target/X86/X86.td =================================================================== --- llvm/trunk/lib/Target/X86/X86.td +++ llvm/trunk/lib/Target/X86/X86.td @@ -811,6 +811,7 @@ //===----------------------------------------------------------------------===// include "X86RegisterInfo.td" +include "X86RegisterBanks.td" //===----------------------------------------------------------------------===// // Instruction Descriptions Index: llvm/trunk/lib/Target/X86/X86GenRegisterBankInfo.def =================================================================== --- llvm/trunk/lib/Target/X86/X86GenRegisterBankInfo.def +++ llvm/trunk/lib/Target/X86/X86GenRegisterBankInfo.def @@ -0,0 +1,60 @@ +//===- X86GenRegisterBankInfo.def ----------------------------*- 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 defines all the static objects used by X86RegisterBankInfo. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BUILD_GLOBAL_ISEL +#error "You shouldn't build this" +#endif + +namespace llvm { +RegisterBankInfo::PartialMapping X86GenRegisterBankInfo::PartMappings[]{ + /* StartIdx, Length, RegBank */ + // GPR value + {0, 8, X86::GPRRegBank}, // :0 + {0, 16, X86::GPRRegBank}, // :1 + {0, 32, X86::GPRRegBank}, // :2 + {0, 64, X86::GPRRegBank}, // :3 +}; + +enum PartialMappingIdx { + PMI_None = -1, + PMI_GPR8, + PMI_GPR16, + PMI_GPR32, + PMI_GPR64, +}; + +#define INSTR_3OP(INFO) INFO, INFO, INFO, +#define BREAKDOWN(INDEX, NUM) \ + { &X86GenRegisterBankInfo::PartMappings[INDEX], NUM } +// ValueMappings. +RegisterBankInfo::ValueMapping X86GenRegisterBankInfo::ValMappings[]{ + /* BreakDown, NumBreakDowns */ + // 3-operands instructions (all binary operations should end up with one of + // those mapping). + INSTR_3OP(BREAKDOWN(PMI_GPR8, 1)) // 0: GPR_8 + INSTR_3OP(BREAKDOWN(PMI_GPR16, 1)) // 3: GPR_16 + INSTR_3OP(BREAKDOWN(PMI_GPR32, 1)) // 6: GPR_32 + INSTR_3OP(BREAKDOWN(PMI_GPR64, 1)) // 9: GPR_64 +}; +#undef INSTR_3OP +#undef BREAKDOWN + +enum ValueMappingIdx { + VMI_None = -1, + VMI_3OpsGpr8Idx = 0, + VMI_3OpsGpr16Idx = 3, + VMI_3OpsGpr32Idx = 6, + VMI_3OpsGpr64Idx = 9, +}; + +} // End llvm namespace. Index: llvm/trunk/lib/Target/X86/X86LegalizerInfo.h =================================================================== --- llvm/trunk/lib/Target/X86/X86LegalizerInfo.h +++ llvm/trunk/lib/Target/X86/X86LegalizerInfo.h @@ -0,0 +1,39 @@ +//===- X86LegalizerInfo.h ------------------------------------------*- 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 X86. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_X86_X86MACHINELEGALIZER_H +#define LLVM_LIB_TARGET_X86_X86MACHINELEGALIZER_H + +#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" + +namespace llvm { + +class X86Subtarget; + +/// This class provides the information for the target register banks. +class X86LegalizerInfo : public LegalizerInfo { +private: + /// Keep a reference to the X86Subtarget around so that we can + /// make the right decision when generating code for different targets. + const X86Subtarget &Subtarget; + +public: + X86LegalizerInfo(const X86Subtarget &STI); + +private: + void setLegalizerInfo32bit(); + void setLegalizerInfo64bit(); +}; +} // End llvm namespace. +#endif Index: llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp +++ llvm/trunk/lib/Target/X86/X86LegalizerInfo.cpp @@ -0,0 +1,54 @@ +//===- X86LegalizerInfo.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 X86. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#include "X86LegalizerInfo.h" +#include "X86Subtarget.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Type.h" +#include "llvm/Target/TargetOpcodes.h" + +using namespace llvm; + +#ifndef LLVM_BUILD_GLOBAL_ISEL +#error "You shouldn't build this" +#endif + +X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI) : Subtarget(STI) { + + setLegalizerInfo32bit(); + setLegalizerInfo64bit(); + + computeTables(); +} + +void X86LegalizerInfo::setLegalizerInfo32bit() { + + const LLT s8 = LLT::scalar(8); + const LLT s16 = LLT::scalar(16); + const LLT s32 = LLT::scalar(32); + + for (auto Ty : {s8, s16, s32}) + setAction({TargetOpcode::G_ADD, Ty}, Legal); +} +void + +X86LegalizerInfo::setLegalizerInfo64bit() { + + if (!Subtarget.is64Bit()) + return; + + const LLT s64 = LLT::scalar(64); + + setAction({TargetOpcode::G_ADD, s64}, Legal); +} Index: llvm/trunk/lib/Target/X86/X86RegisterBankInfo.h =================================================================== --- llvm/trunk/lib/Target/X86/X86RegisterBankInfo.h +++ llvm/trunk/lib/Target/X86/X86RegisterBankInfo.h @@ -0,0 +1,54 @@ +//===- X86RegisterBankInfo ---------------------------------------*- 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 RegisterBankInfo class for X86. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_X86_X86REGISTERBANKINFO_H +#define LLVM_LIB_TARGET_X86_X86REGISTERBANKINFO_H + +#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" + +#define GET_REGBANK_DECLARATIONS +#include "X86GenRegisterBank.inc" + +namespace llvm { + +class X86GenRegisterBankInfo : public RegisterBankInfo { +protected: + static RegisterBankInfo::PartialMapping PartMappings[]; + static RegisterBankInfo::ValueMapping ValMappings[]; + +#define GET_TARGET_REGBANK_CLASS +#include "X86GenRegisterBank.inc" +}; + +class TargetRegisterInfo; + +/// This class provides the information for the target register banks. +class X86RegisterBankInfo final : public X86GenRegisterBankInfo { +private: + /// Get an instruction mapping. + /// \return An InstructionMappings with a statically allocated + /// OperandsMapping. + static InstructionMapping getOperandsMapping(const MachineInstr &MI, + bool isFP); + +public: + X86RegisterBankInfo(const TargetRegisterInfo &TRI); + + const RegisterBank & + getRegBankFromRegClass(const TargetRegisterClass &RC) const override; + + InstructionMapping getInstrMapping(const MachineInstr &MI) const override; +}; + +} // End llvm namespace. +#endif Index: llvm/trunk/lib/Target/X86/X86RegisterBankInfo.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86RegisterBankInfo.cpp +++ llvm/trunk/lib/Target/X86/X86RegisterBankInfo.cpp @@ -0,0 +1,121 @@ +//===- X86RegisterBankInfo.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 RegisterBankInfo class for X86. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#include "X86RegisterBankInfo.h" +#include "X86InstrInfo.h" +#include "llvm/CodeGen/GlobalISel/RegisterBank.h" +#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" + +#define GET_TARGET_REGBANK_IMPL +#include "X86GenRegisterBank.inc" + +// This file will be TableGen'ed at some point. +#include "X86GenRegisterBankInfo.def" + +using namespace llvm; + +#ifndef LLVM_BUILD_GLOBAL_ISEL +#error "You shouldn't build this" +#endif + +X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI) + : X86GenRegisterBankInfo() { + + // validate RegBank initialization. + const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID); + (void)RBGPR; + assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization."); + + // The GPR register bank is fully defined by all the registers in + // GR64 + its subclasses. + assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) && + "Subclass not added?"); + assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit"); +} + +const RegisterBank &X86RegisterBankInfo::getRegBankFromRegClass( + const TargetRegisterClass &RC) const { + + if (X86::GR8RegClass.hasSubClassEq(&RC) || + X86::GR16RegClass.hasSubClassEq(&RC) || + X86::GR32RegClass.hasSubClassEq(&RC) || + X86::GR64RegClass.hasSubClassEq(&RC)) + return getRegBank(X86::GPRRegBankID); + + llvm_unreachable("Unsupported register kind yet."); +} + +RegisterBankInfo::InstructionMapping +X86RegisterBankInfo::getOperandsMapping(const MachineInstr &MI, bool isFP) { + const MachineFunction &MF = *MI.getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); + + unsigned NumOperands = MI.getNumOperands(); + LLT Ty = MRI.getType(MI.getOperand(0).getReg()); + + if (NumOperands != 3 || + (Ty != MRI.getType(MI.getOperand(1).getReg())) || + (Ty != MRI.getType(MI.getOperand(2).getReg()))) + llvm_unreachable("Unsupported operand maping yet."); + + ValueMappingIdx ValMapIdx = VMI_None; + if (!isFP) { + switch (Ty.getSizeInBits()) { + case 8: + ValMapIdx = VMI_3OpsGpr8Idx; + break; + case 16: + ValMapIdx = VMI_3OpsGpr16Idx; + break; + case 32: + ValMapIdx = VMI_3OpsGpr32Idx; + break; + case 64: + ValMapIdx = VMI_3OpsGpr64Idx; + break; + default: + llvm_unreachable("Unsupported register size."); + break; + } + } else { + llvm_unreachable("Floating point not supported yet."); + } + + return InstructionMapping{DefaultMappingID, 1, &ValMappings[ValMapIdx], + NumOperands}; +} + +RegisterBankInfo::InstructionMapping +X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { + auto Opc = MI.getOpcode(); + + // Try the default logic for non-generic instructions that are either copies + // or already have some operands assigned to banks. + if (!isPreISelGenericOpcode(Opc)) { + InstructionMapping Mapping = getInstrMappingImpl(MI); + if (Mapping.isValid()) + return Mapping; + } + + switch (Opc) { + case TargetOpcode::G_ADD: + return getOperandsMapping(MI, false); + break; + default: + return InstructionMapping{}; + } + + return InstructionMapping{}; +} Index: llvm/trunk/lib/Target/X86/X86RegisterBanks.td =================================================================== --- llvm/trunk/lib/Target/X86/X86RegisterBanks.td +++ llvm/trunk/lib/Target/X86/X86RegisterBanks.td @@ -0,0 +1,14 @@ +//=- X86RegisterBank.td - Describe the AArch64 Banks -----*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +/// General Purpose Registers: RAX, RCX,... +def GPRRegBank : RegisterBank<"GPR", [GR64]>; Index: llvm/trunk/lib/Target/X86/X86TargetMachine.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86TargetMachine.cpp +++ llvm/trunk/lib/Target/X86/X86TargetMachine.cpp @@ -14,6 +14,8 @@ #include "MCTargetDesc/X86MCTargetDesc.h" #include "X86.h" #include "X86CallLowering.h" +#include "X86LegalizerInfo.h" +#include "X86RegisterBankInfo.h" #include "X86MacroFusion.h" #include "X86Subtarget.h" #include "X86TargetMachine.h" @@ -28,6 +30,8 @@ #include "llvm/CodeGen/GlobalISel/CallLowering.h" #include "llvm/CodeGen/GlobalISel/GISelAccessor.h" #include "llvm/CodeGen/GlobalISel/IRTranslator.h" +#include "llvm/CodeGen/GlobalISel/Legalizer.h" +#include "llvm/CodeGen/GlobalISel/RegBankSelect.h" #include "llvm/CodeGen/MachineScheduler.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" @@ -202,12 +206,12 @@ namespace { struct X86GISelActualAccessor : public GISelAccessor { - std::unique_ptr CL; - - X86GISelActualAccessor(CallLowering* CL): CL(CL) {} + std::unique_ptr CallLoweringInfo; + std::unique_ptr Legalizer; + std::unique_ptr RegBankInfo; const CallLowering *getCallLowering() const override { - return CL.get(); + return CallLoweringInfo.get(); } const InstructionSelector *getInstructionSelector() const override { @@ -216,13 +220,11 @@ } const LegalizerInfo *getLegalizerInfo() const override { - //TODO: Implement - return nullptr; + return Legalizer.get(); } const RegisterBankInfo *getRegBankInfo() const override { - //TODO: Implement - return nullptr; + return RegBankInfo.get(); } }; @@ -271,8 +273,14 @@ #ifndef LLVM_BUILD_GLOBAL_ISEL GISelAccessor *GISel = new GISelAccessor(); #else - X86GISelActualAccessor *GISel = new X86GISelActualAccessor( - new X86CallLowering(*I->getTargetLowering())); + X86GISelActualAccessor *GISel = new X86GISelActualAccessor(); + + GISel->CallLoweringInfo.reset(new X86CallLowering(*I->getTargetLowering())); + GISel->Legalizer.reset(new X86LegalizerInfo(*I)); + + auto *RBI = new X86RegisterBankInfo(*I->getRegisterInfo()); + GISel->RegBankInfo.reset(RBI); + #endif I->setGISelAccessor(*GISel); } @@ -371,12 +379,12 @@ } bool X86PassConfig::addLegalizeMachineIR() { - //TODO: Implement + addPass(new Legalizer()); return false; } bool X86PassConfig::addRegBankSelect() { - //TODO: Implement + addPass(new RegBankSelect()); return false; } Index: llvm/trunk/test/CodeGen/X86/GlobalISel/X86-regbankselect.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/X86-regbankselect.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/X86-regbankselect.mir @@ -0,0 +1,137 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=regbankselect %s -o - | FileCheck %s + +--- | + ; ModuleID = 'tmp.ll' + source_filename = "tmp.ll" + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64--linux-gnu" + + define i8 @test_add_i8(i8 %arg1, i8 %arg2) { + %ret = add i8 %arg1, %arg2 + ret i8 %ret + } + + define i16 @test_add_i16(i16 %arg1, i16 %arg2) { + %ret = add i16 %arg1, %arg2 + ret i16 %ret + } + + define i32 @test_add_i32(i32 %arg1, i32 %arg2) { + %ret = add i32 %arg1, %arg2 + ret i32 %ret + } + + define i64 @test_add_i64(i64 %arg1, i64 %arg2) { + %ret = add i64 %arg1, %arg2 + ret i64 %ret + } + +... +--- +name: test_add_i8 +alignment: 4 +legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +# CHECK-LABEL: name: test_add_i8 +# CHECK: registers: +# CHECK: - { id: 0, class: gpr } +# CHECK: - { id: 1, class: gpr } +# CHECK: - { id: 2, class: gpr } +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.1 (%ir-block.0): + liveins: %edi, %esi + + %0(s8) = COPY %edi + %1(s8) = COPY %esi + %2(s8) = G_ADD %0, %1 + %al = COPY %2(s8) + RET 0, implicit %al + +... +--- +name: test_add_i16 +alignment: 4 +legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +# CHECK-LABEL: name: test_add_i16 +# CHECK: registers: +# CHECK: - { id: 0, class: gpr } +# CHECK: - { id: 1, class: gpr } +# CHECK: - { id: 2, class: gpr } +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.1 (%ir-block.0): + liveins: %edi, %esi + + %0(s16) = COPY %edi + %1(s16) = COPY %esi + %2(s16) = G_ADD %0, %1 + %ax = COPY %2(s16) + RET 0, implicit %ax + +... +--- +name: test_add_i32 +alignment: 4 +legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +# CHECK-LABEL: name: test_add_i32 +# CHECK: registers: +# CHECK: - { id: 0, class: gpr } +# CHECK: - { id: 1, class: gpr } +# CHECK: - { id: 2, class: gpr } +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.1 (%ir-block.0): + liveins: %edi, %esi + + %0(s32) = COPY %edi + %1(s32) = COPY %esi + %2(s32) = G_ADD %0, %1 + %eax = COPY %2(s32) + RET 0, implicit %eax + +... +--- +name: test_add_i64 +alignment: 4 +legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +# CHECK-LABEL: name: test_add_i64 +# CHECK: registers: +# CHECK: - { id: 0, class: gpr } +# CHECK: - { id: 1, class: gpr } +# CHECK: - { id: 2, class: gpr } +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.1 (%ir-block.0): + liveins: %rdi, %rsi + + %0(s64) = COPY %rdi + %1(s64) = COPY %rsi + %2(s64) = G_ADD %0, %1 + %rax = COPY %2(s64) + RET 0, implicit %rax + +... Index: llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-add.mir =================================================================== --- llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-add.mir +++ llvm/trunk/test/CodeGen/X86/GlobalISel/legalize-add.mir @@ -0,0 +1,40 @@ +# RUN: llc -mtriple=x86_64-linux-gnu -global-isel -run-pass=legalizer %s -o - | FileCheck %s + +--- | + ; ModuleID = '' + source_filename = "" + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64--linux-gnu" + + define i32 @test_add_i32(i32 %arg1, i32 %arg2) { + %ret = add i32 %arg1, %arg2 + ret i32 %ret + } + +... +--- +name: test_add_i32 +alignment: 4 +legalized: false +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _ } + - { id: 1, class: _ } + - { id: 2, class: _ } +body: | + bb.1 (%ir-block.0): + liveins: %edi, %esi + ; CHECK-LABEL: name: test_add_i32 + ; CHECK: [[VAL1:%.*]](s32) = COPY %edi + ; CHECK: [[VAL2:%.*]](s32) = COPY %esi + ; CHECK: [[RES:%.*]](s32) = G_ADD [[VAL1:%.*]], [[VAL2:%.*]] + + %0(s32) = COPY %edi + %1(s32) = COPY %esi + %2(s32) = G_ADD %0, %1 + %eax = COPY %2(s32) + RET 0, implicit %eax + +...