Index: lib/Target/ARM/ARMCallLowering.h =================================================================== --- /dev/null +++ lib/Target/ARM/ARMCallLowering.h @@ -0,0 +1,37 @@ +//===-- llvm/lib/Target/ARM/ARMCallLowering.h - Call lowering -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file describes how to lower LLVM calls to machine code calls. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_ARM_ARMCALLLOWERING +#define LLVM_LIB_TARGET_ARM_ARMCALLLOWERING + +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/GlobalISel/CallLowering.h" +#include "llvm/CodeGen/ValueTypes.h" + +namespace llvm { + +class ARMTargetLowering; + +class ARMCallLowering : public CallLowering { +public: + ARMCallLowering(const ARMTargetLowering &TLI); + + bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val, + unsigned VReg) const override; + + bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, + ArrayRef VRegs) const override; +}; +} // End of namespace llvm +#endif Index: lib/Target/ARM/ARMCallLowering.cpp =================================================================== --- /dev/null +++ lib/Target/ARM/ARMCallLowering.cpp @@ -0,0 +1,47 @@ +//===-- llvm/lib/Target/ARM/ARMCallLowering.cpp - Call lowering -----------===// +// +// 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 lowering of LLVM calls to machine code calls for +/// GlobalISel. +/// +//===----------------------------------------------------------------------===// + +#include "ARMCallLowering.h" + +#include "ARMBaseInstrInfo.h" +#include "ARMISelLowering.h" + +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" + +using namespace llvm; + +#ifndef LLVM_BUILD_GLOBAL_ISEL +#error "This shouldn't be built without GISel" +#endif + +ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI) + : CallLowering(&TLI) {} + +bool ARMCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, + const Value *Val, unsigned VReg) const { + // We're currently only handling void returns + if (Val != nullptr) + return false; + + AddDefaultPred(MIRBuilder.buildInstr(ARM::BX_RET)); + + return true; +} + +bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, + const Function &F, + ArrayRef VRegs) const { + return F.arg_empty(); +} Index: lib/Target/ARM/ARMInstructionSelector.h =================================================================== --- /dev/null +++ lib/Target/ARM/ARMInstructionSelector.h @@ -0,0 +1,42 @@ +//===- ARMInstructionSelector ------------------------------------*- 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 InstructionSelector class for ARM. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_ARM_ARMINSTRUCTIONSELECTOR_H +#define LLVM_LIB_TARGET_ARM_ARMINSTRUCTIONSELECTOR_H + +#include "llvm/CodeGen/GlobalISel/InstructionSelector.h" + +namespace llvm { +class ARMBaseInstrInfo; +class ARMBaseRegisterInfo; +class ARMBaseTargetMachine; +class ARMRegisterBankInfo; +class ARMSubtarget; + +class ARMInstructionSelector : public InstructionSelector { +public: + ARMInstructionSelector(const ARMBaseTargetMachine &TM, + const ARMSubtarget &STI, + const ARMRegisterBankInfo &RBI); + + virtual bool select(MachineInstr &I) const override; + +private: + const ARMBaseTargetMachine &TM; + const ARMSubtarget &STI; + const ARMBaseInstrInfo &TII; + const ARMBaseRegisterInfo &TRI; + const ARMRegisterBankInfo &RBI; +}; + +} // End llvm namespace. +#endif Index: lib/Target/ARM/ARMInstructionSelector.cpp =================================================================== --- /dev/null +++ lib/Target/ARM/ARMInstructionSelector.cpp @@ -0,0 +1,36 @@ +//===- ARMInstructionSelector.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 InstructionSelector class for ARM. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#include "ARMInstructionSelector.h" +#include "ARMRegisterBankInfo.h" +#include "ARMSubtarget.h" +#include "ARMTargetMachine.h" +#include "llvm/Support/Debug.h" + +#define DEBUG_TYPE "arm-isel" + +using namespace llvm; + +#ifndef LLVM_BUILD_GLOBAL_ISEL +#error "You shouldn't build this" +#endif + +ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM, + const ARMSubtarget &STI, + const ARMRegisterBankInfo &RBI) + : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()), + TRI(*STI.getRegisterInfo()), RBI(RBI) {} + +bool ARMInstructionSelector::select(llvm::MachineInstr &I) const { + return !isPreISelGenericOpcode(I.getOpcode()); +} Index: lib/Target/ARM/ARMLegalizerInfo.h =================================================================== --- /dev/null +++ lib/Target/ARM/ARMLegalizerInfo.h @@ -0,0 +1,29 @@ +//===- ARMLegalizerInfo ------------------------------------------*- 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 ARM. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_ARM_ARMMACHINELEGALIZER_H +#define LLVM_LIB_TARGET_ARM_ARMMACHINELEGALIZER_H + +#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" + +namespace llvm { + +class LLVMContext; + +/// This class provides the information for the target register banks. +class ARMLegalizerInfo : public LegalizerInfo { +public: + ARMLegalizerInfo(); +}; +} // End llvm namespace. +#endif Index: lib/Target/ARM/ARMLegalizerInfo.cpp =================================================================== --- /dev/null +++ lib/Target/ARM/ARMLegalizerInfo.cpp @@ -0,0 +1,28 @@ +//===- ARMLegalizerInfo.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 ARM. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#include "ARMLegalizerInfo.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 + +ARMLegalizerInfo::ARMLegalizerInfo() { + computeTables(); +} Index: lib/Target/ARM/ARMRegisterBankInfo.h =================================================================== --- /dev/null +++ lib/Target/ARM/ARMRegisterBankInfo.h @@ -0,0 +1,29 @@ +//===- ARMRegisterBankInfo ---------------------------------------*- 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 ARM. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_ARM_ARMREGISTERBANKINFO_H +#define LLVM_LIB_TARGET_ARM_ARMREGISTERBANKINFO_H + +#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" + +namespace llvm { + +class TargetRegisterInfo; + +/// This class provides the information for the target register banks. +class ARMRegisterBankInfo final : public RegisterBankInfo { +public: + ARMRegisterBankInfo(const TargetRegisterInfo &TRI); +}; +} // End llvm namespace. +#endif Index: lib/Target/ARM/ARMRegisterBankInfo.cpp =================================================================== --- /dev/null +++ lib/Target/ARM/ARMRegisterBankInfo.cpp @@ -0,0 +1,27 @@ +//===- ARMRegisterBankInfo.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 ARM. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#include "ARMRegisterBankInfo.h" +#include "llvm/CodeGen/GlobalISel/RegisterBank.h" +#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" + +using namespace llvm; + +#ifndef LLVM_BUILD_GLOBAL_ISEL +#error "You shouldn't build this" +#endif + +ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) + : RegisterBankInfo(nullptr, 0) {} Index: lib/Target/ARM/ARMSubtarget.h =================================================================== --- lib/Target/ARM/ARMSubtarget.h +++ lib/Target/ARM/ARMSubtarget.h @@ -25,6 +25,7 @@ #include "Thumb1InstrInfo.h" #include "Thumb2InstrInfo.h" #include "llvm/ADT/Triple.h" +#include "llvm/CodeGen/GlobalISel/GISelAccessor.h" #include "llvm/IR/DataLayout.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetSubtargetInfo.h" @@ -350,6 +351,9 @@ ARMSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, const ARMBaseTargetMachine &TM, bool IsLittle); + /// This object will take onwership of \p GISelAccessor. + void setGISelAccessor(GISelAccessor &GISel) { this->GISel.reset(&GISel); } + /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size /// that still makes it profitable to inline the call. unsigned getMaxInlineSizeThreshold() const { @@ -379,6 +383,11 @@ return &InstrInfo->getRegisterInfo(); } + const CallLowering *getCallLowering() const override; + const InstructionSelector *getInstructionSelector() const override; + const LegalizerInfo *getLegalizerInfo() const override; + const RegisterBankInfo *getRegBankInfo() const override; + private: ARMSelectionDAGInfo TSInfo; // Either Thumb1FrameLowering or ARMFrameLowering. @@ -387,6 +396,11 @@ std::unique_ptr InstrInfo; ARMTargetLowering TLInfo; + /// Gather the accessor points to GlobalISel-related APIs. + /// This is used to avoid ifndefs spreading around while GISel is + /// an optional library. + std::unique_ptr GISel; + void initializeEnvironment(); void initSubtargetFeatures(StringRef CPU, StringRef FS); ARMFrameLowering *initializeFrameLowering(StringRef CPU, StringRef FS); Index: lib/Target/ARM/ARMSubtarget.cpp =================================================================== --- lib/Target/ARM/ARMSubtarget.cpp +++ lib/Target/ARM/ARMSubtarget.cpp @@ -98,7 +98,27 @@ : !isThumb() ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this) : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)), - TLInfo(TM, *this) {} + TLInfo(TM, *this), GISel() {} + +const CallLowering *ARMSubtarget::getCallLowering() const { + assert(GISel && "Access to GlobalISel APIs not set"); + return GISel->getCallLowering(); +} + +const InstructionSelector *ARMSubtarget::getInstructionSelector() const { + assert(GISel && "Access to GlobalISel APIs not set"); + return GISel->getInstructionSelector(); +} + +const LegalizerInfo *ARMSubtarget::getLegalizerInfo() const { + assert(GISel && "Access to GlobalISel APIs not set"); + return GISel->getLegalizerInfo(); +} + +const RegisterBankInfo *ARMSubtarget::getRegBankInfo() const { + assert(GISel && "Access to GlobalISel APIs not set"); + return GISel->getRegBankInfo(); +} bool ARMSubtarget::isXRaySupported() const { // We don't currently suppport Thumb, but Windows requires Thumb. Index: lib/Target/ARM/ARMTargetMachine.cpp =================================================================== --- lib/Target/ARM/ARMTargetMachine.cpp +++ lib/Target/ARM/ARMTargetMachine.cpp @@ -10,11 +10,19 @@ // //===----------------------------------------------------------------------===// +#include "ARMTargetMachine.h" #include "ARM.h" +#include "ARMCallLowering.h" #include "ARMFrameLowering.h" -#include "ARMTargetMachine.h" +#include "ARMInstructionSelector.h" +#include "ARMLegalizerInfo.h" +#include "ARMRegisterBankInfo.h" #include "ARMTargetObjectFile.h" #include "ARMTargetTransformInfo.h" +#include "llvm/CodeGen/GlobalISel/IRTranslator.h" +#include "llvm/CodeGen/GlobalISel/InstructionSelect.h" +#include "llvm/CodeGen/GlobalISel/Legalizer.h" +#include "llvm/CodeGen/GlobalISel/RegBankSelect.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/Function.h" @@ -22,8 +30,8 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Transforms/Scalar.h" using namespace llvm; @@ -57,6 +65,7 @@ RegisterTargetMachine B(getTheThumbBETarget()); PassRegistry &Registry = *PassRegistry::getPassRegistry(); + initializeGlobalISel(Registry); initializeARMLoadStoreOptPass(Registry); initializeARMPreAllocLoadStoreOptPass(Registry); } @@ -231,6 +240,29 @@ ARMBaseTargetMachine::~ARMBaseTargetMachine() {} +#ifdef LLVM_BUILD_GLOBAL_ISEL +namespace { +struct ARMGISelActualAccessor : public GISelAccessor { + std::unique_ptr CallLoweringInfo; + std::unique_ptr InstSelector; + std::unique_ptr Legalizer; + std::unique_ptr RegBankInfo; + const CallLowering *getCallLowering() const override { + return CallLoweringInfo.get(); + } + const InstructionSelector *getInstructionSelector() const override { + return InstSelector.get(); + } + const class LegalizerInfo *getLegalizerInfo() const override { + return Legalizer.get(); + } + const RegisterBankInfo *getRegBankInfo() const override { + return RegBankInfo.get(); + } +}; +} // End anonymous namespace. +#endif + const ARMSubtarget * ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const { Attribute CPUAttr = F.getFnAttribute("target-cpu"); @@ -263,6 +295,24 @@ resetTargetOptions(F); I = llvm::make_unique(TargetTriple, CPU, FS, *this, isLittle); } + +#ifndef LLVM_BUILD_GLOBAL_ISEL + GISelAccessor *GISel = new GISelAccessor(); +#else + ARMGISelActualAccessor *GISel = new ARMGISelActualAccessor(); + GISel->CallLoweringInfo.reset(new ARMCallLowering(*I->getTargetLowering())); + GISel->Legalizer.reset(new ARMLegalizerInfo()); + + auto *RBI = new ARMRegisterBankInfo(*I->getRegisterInfo()); + + // FIXME: At this point, we can't rely on Subtarget having RBI. + // It's awkward to mix passing RBI and the Subtarget; should we pass + // TII/TRI as well? + GISel->InstSelector.reset(new ARMInstructionSelector(*this, *I, *RBI)); + + GISel->RegBankInfo.reset(RBI); +#endif + I->setGISelAccessor(*GISel); return I.get(); } @@ -353,6 +403,12 @@ void addIRPasses() override; bool addPreISel() override; bool addInstSelector() override; +#ifdef LLVM_BUILD_GLOBAL_ISEL + bool addIRTranslator() override; + bool addLegalizeMachineIR() override; + bool addRegBankSelect() override; + bool addGlobalInstructionSelect() override; +#endif void addPreRegAlloc() override; void addPreSched2() override; void addPreEmitPass() override; @@ -413,6 +469,28 @@ return false; } +#ifdef LLVM_BUILD_GLOBAL_ISEL +bool ARMPassConfig::addIRTranslator() { + addPass(new IRTranslator()); + return false; +} + +bool ARMPassConfig::addLegalizeMachineIR() { + addPass(new Legalizer()); + return false; +} + +bool ARMPassConfig::addRegBankSelect() { + addPass(new RegBankSelect()); + return false; +} + +bool ARMPassConfig::addGlobalInstructionSelect() { + addPass(new InstructionSelect()); + return false; +} +#endif + void ARMPassConfig::addPreRegAlloc() { if (getOptLevel() != CodeGenOpt::None) { addPass(createMLxExpansionPass()); Index: lib/Target/ARM/CMakeLists.txt =================================================================== --- lib/Target/ARM/CMakeLists.txt +++ lib/Target/ARM/CMakeLists.txt @@ -13,6 +13,21 @@ tablegen(LLVM ARMGenDisassemblerTables.inc -gen-disassembler) add_public_tablegen_target(ARMCommonTableGen) +# Add GlobalISel files if the user wants to build it. +set(GLOBAL_ISEL_FILES + ARMCallLowering.cpp + ARMInstructionSelector.cpp + ARMLegalizerInfo.cpp + ARMRegisterBankInfo.cpp + ) + +if(LLVM_BUILD_GLOBAL_ISEL) + set(GLOBAL_ISEL_BUILD_FILES ${GLOBAL_ISEL_FILES}) +else() + set(GLOBAL_ISEL_BUILD_FILES "") + set(LLVM_OPTIONAL_SOURCES LLVMGlobalISel ${GLOBAL_ISEL_FILES}) +endif() + add_llvm_target(ARMCodeGen A15SDOptimizer.cpp ARMAsmPrinter.cpp @@ -45,6 +60,7 @@ Thumb2InstrInfo.cpp Thumb2SizeReduction.cpp ARMComputeBlockSize.cpp + ${GLOBAL_ISEL_BUILD_FILES} ) add_subdirectory(TargetInfo) Index: lib/Target/ARM/LLVMBuild.txt =================================================================== --- lib/Target/ARM/LLVMBuild.txt +++ lib/Target/ARM/LLVMBuild.txt @@ -31,5 +31,5 @@ type = Library name = ARMCodeGen parent = ARM -required_libraries = ARMAsmPrinter ARMDesc ARMInfo Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target +required_libraries = ARMAsmPrinter ARMDesc ARMInfo Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target GlobalISel add_to_library_groups = ARM Index: test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll @@ -0,0 +1,9 @@ +; RUN: llc -mtriple arm-unknown -global-isel -stop-after=irtranslator %s -o - | FileCheck %s + +define void @test_void_return() { +; CHECK-LABEL: name: test_void_return +; CHECK: BX_RET 14, _ +entry: + ret void +} + Index: test/CodeGen/ARM/GlobalISel/lit.local.cfg =================================================================== --- /dev/null +++ test/CodeGen/ARM/GlobalISel/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'global-isel' in config.root.available_features: + config.unsupported = True