From 76dbf26599388196d5f82a492c8d6004559983f7 Mon Sep 17 00:00:00 2001 From: Zvi Rackover Date: Tue, 15 Nov 2016 06:34:33 +0000 Subject: [PATCH] [X86][GlobalISel] Add minimal call lowering support to the IRTranslator Summary: Add basic functionality to support call lowering for X86. Currently only supports functions which return void and take zero arguments. Inspired by commit 286573. Reviewers: ab, qcolombet, t.p.northover Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D26593 llvm-svn: 286935 --- llvm/lib/Target/X86/CMakeLists.txt | 14 ++++ llvm/lib/Target/X86/LLVMBuild.txt | 2 +- llvm/lib/Target/X86/X86CallLowering.cpp | 46 +++++++++++++ llvm/lib/Target/X86/X86CallLowering.h | 39 +++++++++++ llvm/lib/Target/X86/X86Subtarget.cpp | 20 ++++++ llvm/lib/Target/X86/X86Subtarget.h | 13 ++++ llvm/lib/Target/X86/X86TargetMachine.cpp | 64 ++++++++++++++++++- .../X86/GlobalISel/irtranslator-call.ll | 31 +++++++++ .../test/CodeGen/X86/GlobalISel/lit.local.cfg | 2 + 9 files changed, 229 insertions(+), 2 deletions(-) create mode 100644 llvm/lib/Target/X86/X86CallLowering.cpp create mode 100644 llvm/lib/Target/X86/X86CallLowering.h create mode 100644 llvm/test/CodeGen/X86/GlobalISel/irtranslator-call.ll create mode 100644 llvm/test/CodeGen/X86/GlobalISel/lit.local.cfg diff --git a/llvm/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt index bd2d300e4f32a..ddadeba4923d7 100644 --- a/llvm/lib/Target/X86/CMakeLists.txt +++ b/llvm/lib/Target/X86/CMakeLists.txt @@ -12,6 +12,19 @@ tablegen(LLVM X86GenCallingConv.inc -gen-callingconv) tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget) add_public_tablegen_target(X86CommonTableGen) +# Add GlobalISel files if the build option was enabled. +set(GLOBAL_ISEL_FILES + X86CallLowering.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() + + set(sources X86AsmPrinter.cpp X86CallFrameOptimization.cpp @@ -41,6 +54,7 @@ set(sources X86VZeroUpper.cpp X86WinAllocaExpander.cpp X86WinEHState.cpp + ${GLOBAL_ISEL_BUILD_FILES} ) add_llvm_target(X86CodeGen ${sources}) diff --git a/llvm/lib/Target/X86/LLVMBuild.txt b/llvm/lib/Target/X86/LLVMBuild.txt index 87305e0e5f5ca..2062163afb054 100644 --- a/llvm/lib/Target/X86/LLVMBuild.txt +++ b/llvm/lib/Target/X86/LLVMBuild.txt @@ -31,5 +31,5 @@ has_jit = 1 type = Library name = X86CodeGen parent = X86 -required_libraries = Analysis AsmPrinter CodeGen Core MC SelectionDAG Support Target X86AsmPrinter X86Desc X86Info X86Utils +required_libraries = Analysis AsmPrinter CodeGen Core MC SelectionDAG Support Target X86AsmPrinter X86Desc X86Info X86Utils GlobalISel add_to_library_groups = X86 diff --git a/llvm/lib/Target/X86/X86CallLowering.cpp b/llvm/lib/Target/X86/X86CallLowering.cpp new file mode 100644 index 0000000000000..5ae4962378d34 --- /dev/null +++ b/llvm/lib/Target/X86/X86CallLowering.cpp @@ -0,0 +1,46 @@ +//===-- llvm/lib/Target/X86/X86CallLowering.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 "X86CallLowering.h" +#include "X86ISelLowering.h" +#include "X86InstrInfo.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" + +using namespace llvm; + +#ifndef LLVM_BUILD_GLOBAL_ISEL +#error "This shouldn't be built without GISel" +#endif + +X86CallLowering::X86CallLowering(const X86TargetLowering &TLI) + : CallLowering(&TLI) {} + +bool X86CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, + const Value *Val, unsigned VReg) const { + // TODO: handle functions returning non-void values. + if (Val) + return false; + + MIRBuilder.buildInstr(X86::RET).addImm(0); + + return true; +} + +bool X86CallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, + const Function &F, + ArrayRef VRegs) const { + // TODO: handle functions with one or more arguments. + return F.arg_empty(); +} diff --git a/llvm/lib/Target/X86/X86CallLowering.h b/llvm/lib/Target/X86/X86CallLowering.h new file mode 100644 index 0000000000000..f2672f09d8558 --- /dev/null +++ b/llvm/lib/Target/X86/X86CallLowering.h @@ -0,0 +1,39 @@ +//===-- llvm/lib/Target/X86/X86CallLowering.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_X86_X86CALLLOWERING +#define LLVM_LIB_TARGET_X86_X86CALLLOWERING + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/CodeGen/GlobalISel/CallLowering.h" + +namespace llvm { + +class Function; +class MachineIRBuilder; +class X86TargetLowering; +class Value; + +class X86CallLowering : public CallLowering { +public: + X86CallLowering(const X86TargetLowering &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 diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp index 91fdc5afe8aa6..ee37ea7df1c4c 100644 --- a/llvm/lib/Target/X86/X86Subtarget.cpp +++ b/llvm/lib/Target/X86/X86Subtarget.cpp @@ -331,6 +331,26 @@ X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS, setPICStyle(PICStyles::GOT); } +const CallLowering *X86Subtarget::getCallLowering() const { + assert(GISel && "Access to GlobalISel APIs not set"); + return GISel->getCallLowering(); +} + +const InstructionSelector *X86Subtarget::getInstructionSelector() const { + assert(GISel && "Access to GlobalISel APIs not set"); + return GISel->getInstructionSelector(); +} + +const LegalizerInfo *X86Subtarget::getLegalizerInfo() const { + assert(GISel && "Access to GlobalISel APIs not set"); + return GISel->getLegalizerInfo(); +} + +const RegisterBankInfo *X86Subtarget::getRegBankInfo() const { + assert(GISel && "Access to GlobalISel APIs not set"); + return GISel->getRegBankInfo(); +} + bool X86Subtarget::enableEarlyIfConversion() const { return hasCMov() && X86EarlyIfConv; } diff --git a/llvm/lib/Target/X86/X86Subtarget.h b/llvm/lib/Target/X86/X86Subtarget.h index 434edf63c6ece..f5b0a09236d85 100644 --- a/llvm/lib/Target/X86/X86Subtarget.h +++ b/llvm/lib/Target/X86/X86Subtarget.h @@ -19,6 +19,7 @@ #include "X86InstrInfo.h" #include "X86SelectionDAGInfo.h" #include "llvm/ADT/Triple.h" +#include "llvm/CodeGen/GlobalISel/GISelAccessor.h" #include "llvm/IR/CallingConv.h" #include "llvm/Target/TargetSubtargetInfo.h" #include @@ -298,6 +299,10 @@ class X86Subtarget final : public X86GenSubtargetInfo { /// Instruction itineraries for scheduling InstrItineraryData InstrItins; + /// 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; private: /// Override the stack alignment. @@ -326,6 +331,9 @@ class X86Subtarget final : public X86GenSubtargetInfo { X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS, const X86TargetMachine &TM, unsigned StackAlignOverride); + /// This object will take onwership of \p GISelAccessor. + void setGISelAccessor(GISelAccessor &GISel) { this->GISel.reset(&GISel); } + const X86TargetLowering *getTargetLowering() const override { return &TLInfo; } @@ -353,6 +361,11 @@ class X86Subtarget final : public X86GenSubtargetInfo { /// subtarget options. Definition of function is auto generated by tblgen. void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + /// Methods used by Global ISel + const CallLowering *getCallLowering() const override; + const InstructionSelector *getInstructionSelector() const override; + const LegalizerInfo *getLegalizerInfo() const override; + const RegisterBankInfo *getRegBankInfo() const override; private: /// Initialize the full set of dependencies so we can use an initializer /// list for X86Subtarget. diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp index 773438da6c984..b39870265d0b9 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -13,8 +13,11 @@ #include "X86TargetMachine.h" #include "X86.h" +#include "X86CallLowering.h" #include "X86TargetObjectFile.h" #include "X86TargetTransformInfo.h" +#include "llvm/CodeGen/GlobalISel/GISelAccessor.h" +#include "llvm/CodeGen/GlobalISel/IRTranslator.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/Function.h" @@ -39,6 +42,7 @@ extern "C" void LLVMInitializeX86Target() { RegisterTargetMachine Y(getTheX86_64Target()); PassRegistry &PR = *PassRegistry::getPassRegistry(); + initializeGlobalISel(PR); initializeWinEHStatePassPass(PR); initializeFixupBWInstPassPass(PR); } @@ -173,6 +177,29 @@ X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT, X86TargetMachine::~X86TargetMachine() {} +#ifdef LLVM_BUILD_GLOBAL_ISEL +namespace { +struct X86GISelActualAccessor : public GISelAccessor { + std::unique_ptr CL; + X86GISelActualAccessor(CallLowering* CL): CL(CL) {} + const CallLowering *getCallLowering() const override { + return CL.get(); + } + const InstructionSelector *getInstructionSelector() const override { + //TODO: Implement + return nullptr; + } + const class LegalizerInfo *getLegalizerInfo() const override { + //TODO: Implement + return nullptr; + } + const RegisterBankInfo *getRegBankInfo() const override { + //TODO: Implement + return nullptr; + } +}; +} // End anonymous namespace. +#endif const X86Subtarget * X86TargetMachine::getSubtargetImpl(const Function &F) const { Attribute CPUAttr = F.getFnAttribute("target-cpu"); @@ -212,6 +239,13 @@ X86TargetMachine::getSubtargetImpl(const Function &F) const { resetTargetOptions(F); I = llvm::make_unique(TargetTriple, CPU, FS, *this, Options.StackAlignmentOverride); +#ifndef LLVM_BUILD_GLOBAL_ISEL + GISelAccessor *GISel = new GISelAccessor(); +#else + X86GISelActualAccessor *GISel = new X86GISelActualAccessor( + new X86CallLowering(*I->getTargetLowering())); +#endif + I->setGISelAccessor(*GISel); } return I.get(); } @@ -252,7 +286,13 @@ class X86PassConfig : public TargetPassConfig { void addIRPasses() override; bool addInstSelector() override; - bool addILPOpts() override; +#ifdef LLVM_BUILD_GLOBAL_ISEL + bool addIRTranslator() override; + bool addLegalizeMachineIR() override; + bool addRegBankSelect() override; + bool addGlobalInstructionSelect() override; +#endif +bool addILPOpts() override; bool addPreISel() override; void addPreRegAlloc() override; void addPostRegAlloc() override; @@ -287,6 +327,28 @@ bool X86PassConfig::addInstSelector() { return false; } +#ifdef LLVM_BUILD_GLOBAL_ISEL +bool X86PassConfig::addIRTranslator() { + addPass(new IRTranslator()); + return false; +} + +bool X86PassConfig::addLegalizeMachineIR() { + //TODO: Implement + return false; +} + +bool X86PassConfig::addRegBankSelect() { + //TODO: Implement + return false; +} + +bool X86PassConfig::addGlobalInstructionSelect() { + //TODO: Implement + return false; +} +#endif + bool X86PassConfig::addILPOpts() { addPass(&EarlyIfConverterID); if (EnableMachineCombinerPass) diff --git a/llvm/test/CodeGen/X86/GlobalISel/irtranslator-call.ll b/llvm/test/CodeGen/X86/GlobalISel/irtranslator-call.ll new file mode 100644 index 0000000000000..0332d3e9208c2 --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/irtranslator-call.ll @@ -0,0 +1,31 @@ +; RUN: llc -mtriple i386 -global-isel -stop-after=irtranslator %s -o - | FileCheck %s +; RUN: llc -mtriple x86_64 -global-isel -stop-after=irtranslator %s -o - | FileCheck %s + +define void @test_void_return() { +; CHECK-LABEL: name: test_void_return +; CHECK: alignment: 4 +; CHECK-NEXT: exposesReturnsTwice: false +; CHECK-NEXT: legalized: false +; CHECK-NEXT: regBankSelected: false +; CHECK-NEXT: selected: false +; CHECK-NEXT: tracksRegLiveness: true +; CHECK-NEXT: frameInfo: +; CHECK-NEXT: isFrameAddressTaken: false +; CHECK-NEXT: isReturnAddressTaken: false +; CHECK-NEXT: hasStackMap: false +; CHECK-NEXT: hasPatchPoint: false +; CHECK-NEXT: stackSize: 0 +; CHECK-NEXT: offsetAdjustment: 0 +; CHECK-NEXT: maxAlignment: 0 +; CHECK-NEXT: adjustsStack: false +; CHECK-NEXT: hasCalls: false +; CHECK-NEXT: maxCallFrameSize: 0 +; CHECK-NEXT: hasOpaqueSPAdjustment: false +; CHECK-NEXT: hasVAStart: false +; CHECK-NEXT: hasMustTailInVarArgFunc: false +; CHECK-NEXT: body: +; CHECK-NEXT: bb.0: +; CHECK-NEXT: RET 0 +entry: + ret void +} diff --git a/llvm/test/CodeGen/X86/GlobalISel/lit.local.cfg b/llvm/test/CodeGen/X86/GlobalISel/lit.local.cfg new file mode 100644 index 0000000000000..e99d1bb8446ce --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'global-isel' in config.root.available_features: + config.unsupported = True