forked from OSchip/llvm-project
[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
This commit is contained in:
parent
0637099f24
commit
76dbf26599
|
@ -12,6 +12,19 @@ tablegen(LLVM X86GenCallingConv.inc -gen-callingconv)
|
||||||
tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget)
|
tablegen(LLVM X86GenSubtargetInfo.inc -gen-subtarget)
|
||||||
add_public_tablegen_target(X86CommonTableGen)
|
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
|
set(sources
|
||||||
X86AsmPrinter.cpp
|
X86AsmPrinter.cpp
|
||||||
X86CallFrameOptimization.cpp
|
X86CallFrameOptimization.cpp
|
||||||
|
@ -41,6 +54,7 @@ set(sources
|
||||||
X86VZeroUpper.cpp
|
X86VZeroUpper.cpp
|
||||||
X86WinAllocaExpander.cpp
|
X86WinAllocaExpander.cpp
|
||||||
X86WinEHState.cpp
|
X86WinEHState.cpp
|
||||||
|
${GLOBAL_ISEL_BUILD_FILES}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_llvm_target(X86CodeGen ${sources})
|
add_llvm_target(X86CodeGen ${sources})
|
||||||
|
|
|
@ -31,5 +31,5 @@ has_jit = 1
|
||||||
type = Library
|
type = Library
|
||||||
name = X86CodeGen
|
name = X86CodeGen
|
||||||
parent = X86
|
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
|
add_to_library_groups = X86
|
||||||
|
|
|
@ -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<unsigned> VRegs) const {
|
||||||
|
// TODO: handle functions with one or more arguments.
|
||||||
|
return F.arg_empty();
|
||||||
|
}
|
|
@ -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<unsigned> VRegs) const override;
|
||||||
|
};
|
||||||
|
} // End of namespace llvm;
|
||||||
|
#endif
|
|
@ -331,6 +331,26 @@ X86Subtarget::X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS,
|
||||||
setPICStyle(PICStyles::GOT);
|
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 {
|
bool X86Subtarget::enableEarlyIfConversion() const {
|
||||||
return hasCMov() && X86EarlyIfConv;
|
return hasCMov() && X86EarlyIfConv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "X86InstrInfo.h"
|
#include "X86InstrInfo.h"
|
||||||
#include "X86SelectionDAGInfo.h"
|
#include "X86SelectionDAGInfo.h"
|
||||||
#include "llvm/ADT/Triple.h"
|
#include "llvm/ADT/Triple.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/GISelAccessor.h"
|
||||||
#include "llvm/IR/CallingConv.h"
|
#include "llvm/IR/CallingConv.h"
|
||||||
#include "llvm/Target/TargetSubtargetInfo.h"
|
#include "llvm/Target/TargetSubtargetInfo.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -298,6 +299,10 @@ protected:
|
||||||
/// Instruction itineraries for scheduling
|
/// Instruction itineraries for scheduling
|
||||||
InstrItineraryData InstrItins;
|
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<GISelAccessor> GISel;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// Override the stack alignment.
|
/// Override the stack alignment.
|
||||||
|
@ -326,6 +331,9 @@ public:
|
||||||
X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS,
|
X86Subtarget(const Triple &TT, StringRef CPU, StringRef FS,
|
||||||
const X86TargetMachine &TM, unsigned StackAlignOverride);
|
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 {
|
const X86TargetLowering *getTargetLowering() const override {
|
||||||
return &TLInfo;
|
return &TLInfo;
|
||||||
}
|
}
|
||||||
|
@ -353,6 +361,11 @@ public:
|
||||||
/// subtarget options. Definition of function is auto generated by tblgen.
|
/// subtarget options. Definition of function is auto generated by tblgen.
|
||||||
void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
|
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:
|
private:
|
||||||
/// Initialize the full set of dependencies so we can use an initializer
|
/// Initialize the full set of dependencies so we can use an initializer
|
||||||
/// list for X86Subtarget.
|
/// list for X86Subtarget.
|
||||||
|
|
|
@ -13,8 +13,11 @@
|
||||||
|
|
||||||
#include "X86TargetMachine.h"
|
#include "X86TargetMachine.h"
|
||||||
#include "X86.h"
|
#include "X86.h"
|
||||||
|
#include "X86CallLowering.h"
|
||||||
#include "X86TargetObjectFile.h"
|
#include "X86TargetObjectFile.h"
|
||||||
#include "X86TargetTransformInfo.h"
|
#include "X86TargetTransformInfo.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/GISelAccessor.h"
|
||||||
|
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
|
||||||
#include "llvm/CodeGen/Passes.h"
|
#include "llvm/CodeGen/Passes.h"
|
||||||
#include "llvm/CodeGen/TargetPassConfig.h"
|
#include "llvm/CodeGen/TargetPassConfig.h"
|
||||||
#include "llvm/IR/Function.h"
|
#include "llvm/IR/Function.h"
|
||||||
|
@ -39,6 +42,7 @@ extern "C" void LLVMInitializeX86Target() {
|
||||||
RegisterTargetMachine<X86TargetMachine> Y(getTheX86_64Target());
|
RegisterTargetMachine<X86TargetMachine> Y(getTheX86_64Target());
|
||||||
|
|
||||||
PassRegistry &PR = *PassRegistry::getPassRegistry();
|
PassRegistry &PR = *PassRegistry::getPassRegistry();
|
||||||
|
initializeGlobalISel(PR);
|
||||||
initializeWinEHStatePassPass(PR);
|
initializeWinEHStatePassPass(PR);
|
||||||
initializeFixupBWInstPassPass(PR);
|
initializeFixupBWInstPassPass(PR);
|
||||||
}
|
}
|
||||||
|
@ -173,6 +177,29 @@ X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT,
|
||||||
|
|
||||||
X86TargetMachine::~X86TargetMachine() {}
|
X86TargetMachine::~X86TargetMachine() {}
|
||||||
|
|
||||||
|
#ifdef LLVM_BUILD_GLOBAL_ISEL
|
||||||
|
namespace {
|
||||||
|
struct X86GISelActualAccessor : public GISelAccessor {
|
||||||
|
std::unique_ptr<CallLowering> 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 *
|
const X86Subtarget *
|
||||||
X86TargetMachine::getSubtargetImpl(const Function &F) const {
|
X86TargetMachine::getSubtargetImpl(const Function &F) const {
|
||||||
Attribute CPUAttr = F.getFnAttribute("target-cpu");
|
Attribute CPUAttr = F.getFnAttribute("target-cpu");
|
||||||
|
@ -212,6 +239,13 @@ X86TargetMachine::getSubtargetImpl(const Function &F) const {
|
||||||
resetTargetOptions(F);
|
resetTargetOptions(F);
|
||||||
I = llvm::make_unique<X86Subtarget>(TargetTriple, CPU, FS, *this,
|
I = llvm::make_unique<X86Subtarget>(TargetTriple, CPU, FS, *this,
|
||||||
Options.StackAlignmentOverride);
|
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();
|
return I.get();
|
||||||
}
|
}
|
||||||
|
@ -252,7 +286,13 @@ public:
|
||||||
|
|
||||||
void addIRPasses() override;
|
void addIRPasses() override;
|
||||||
bool addInstSelector() 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;
|
bool addPreISel() override;
|
||||||
void addPreRegAlloc() override;
|
void addPreRegAlloc() override;
|
||||||
void addPostRegAlloc() override;
|
void addPostRegAlloc() override;
|
||||||
|
@ -287,6 +327,28 @@ bool X86PassConfig::addInstSelector() {
|
||||||
return false;
|
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() {
|
bool X86PassConfig::addILPOpts() {
|
||||||
addPass(&EarlyIfConverterID);
|
addPass(&EarlyIfConverterID);
|
||||||
if (EnableMachineCombinerPass)
|
if (EnableMachineCombinerPass)
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
if not 'global-isel' in config.root.available_features:
|
||||||
|
config.unsupported = True
|
Loading…
Reference in New Issue