From: Tim Northover Date: Mon, 29 Aug 2016 19:07:08 +0000 (+0000) Subject: GlobalISel: rework CallLowering so that it can be used for libcalls too. X-Git-Tag: llvmorg-4.0.0-rc1~11243 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fe5f89ba144f03fa10e93307988d787309d3a744;p=platform%2Fupstream%2Fllvm.git GlobalISel: rework CallLowering so that it can be used for libcalls too. There should be no functional change here, I'm just making the implementation of "frem" (to libcall) legalization easier for a followup. llvm-svn: 279987 --- diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h index df010fd..c293ad2 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CallLowering.h @@ -16,11 +16,13 @@ #define LLVM_CODEGEN_GLOBALISEL_CALLLOWERING_H #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/Function.h" namespace llvm { // Forward declarations. class MachineIRBuilder; +class MachineOperand; class TargetLowering; class Value; @@ -70,22 +72,47 @@ class CallLowering { /// This hook must be implemented to lower the given call instruction, /// including argument and return value marshalling. /// - /// \p CalleeReg is a virtual-register containing the destination if - /// `CI.getCalledFunction()` returns null (i.e. if the call is indirect); - /// otherwise it is 0. + /// \p Callee is the destination of the call. It should be either a register, + /// globaladdress, or externalsymbol. /// - /// \p ResReg is a register where the call's return value should be stored (or - /// 0 if there is no return value). + /// \p ResTys is a list of the individual result types this function call will + /// produce. The types are used to assign physical registers to each slot. + /// + /// \p ResRegs is a list of the virtual registers that we expect to be defined + /// by this call, one per entry in \p ResTys. + /// + /// \p ArgTys is a list of the types each member of \p ArgRegs has; used by + /// the target to decide which register/stack slot should be allocated. /// /// \p ArgRegs is a list of virtual registers containing each argument that /// needs to be passed. /// /// \return true if the lowering succeeded, false otherwise. - virtual bool lowerCall(MachineIRBuilder &MIRBuilder, const CallInst &CI, - unsigned CalleeReg, unsigned ResReg, + virtual bool lowerCall(MachineIRBuilder &MIRBuilder, MachineOperand &Callee, + ArrayRef ResTys, ArrayRef ResRegs, + ArrayRef ArgTys, ArrayRef ArgRegs) const { return false; } + + /// This hook must be implemented to lower the given call instruction, + /// including argument and return value marshalling. + /// + /// \p ResReg is a register where the call's return value should be stored (or + /// 0 if there is no return value). + /// + /// \p ArgRegs is a list of virtual registers containing each argument that + /// needs to be passed. + /// + /// \p GetCalleeReg is a callback to materialize a register for the callee if + /// the target determines it cannot jump to the destination based purely on \p + /// CI. This might be because \p CI is indirect, or because of the limited + /// range of an immediate jump. + /// + /// \return true if the lowering succeeded, false otherwise. + virtual bool lowerCall(MachineIRBuilder &MIRBuilder, const CallInst &CI, + unsigned ResReg, ArrayRef ArgRegs, + std::function GetCalleeReg) const; }; } // End namespace llvm. diff --git a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt index bad5c03..87b4708 100644 --- a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt +++ b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt @@ -1,5 +1,6 @@ # List of all GlobalISel files. set(GLOBAL_ISEL_FILES + CallLowering.cpp IRTranslator.cpp InstructionSelect.cpp InstructionSelector.cpp diff --git a/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp new file mode 100644 index 0000000..9d1c1e7 --- /dev/null +++ b/llvm/lib/CodeGen/GlobalISel/CallLowering.cpp @@ -0,0 +1,40 @@ +//===-- lib/CodeGen/GlobalISel/CallLowering.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 some simple delegations needed for call lowering. +/// +//===----------------------------------------------------------------------===// + + +#include "llvm/CodeGen/GlobalISel/CallLowering.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/Instructions.h" + +using namespace llvm; + +bool CallLowering::lowerCall( + MachineIRBuilder &MIRBuilder, const CallInst &CI, unsigned ResReg, + ArrayRef ArgRegs, std::function GetCalleeReg) const { + // First step is to marshall all the function's parameters into the correct + // physregs and memory locations. Gather the sequence of argument types that + // we'll pass to the assigner function. + SmallVector ArgTys; + for (auto &Arg : CI.arg_operands()) + ArgTys.push_back(MVT::getVT(Arg->getType())); + + MachineOperand Callee = MachineOperand::CreateImm(0); + if (Function *F = CI.getCalledFunction()) + Callee = MachineOperand::CreateGA(F, 0); + else + Callee = MachineOperand::CreateReg(GetCalleeReg(), false); + + return lowerCall(MIRBuilder, Callee, MVT::getVT(CI.getType()), + ResReg ? ResReg : ArrayRef(), ArgTys, ArgRegs); +} diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 64316a1..a27d539 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -347,9 +347,9 @@ bool IRTranslator::translateCall(const User &U) { for (auto &Arg: CI.arg_operands()) Args.push_back(getOrCreateVReg(*Arg)); - return CLI->lowerCall(MIRBuilder, CI, - F ? 0 : getOrCreateVReg(*CI.getCalledValue()), Res, - Args); + return CLI->lowerCall(MIRBuilder, CI, Res, Args, [&]() { + return getOrCreateVReg(*CI.getCalledValue()); + }); } Intrinsic::ID ID = F->getIntrinsicID(); diff --git a/llvm/lib/Target/AArch64/AArch64CallLowering.cpp b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp index 4f2add2..6fa2975 100644 --- a/llvm/lib/Target/AArch64/AArch64CallLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64CallLowering.cpp @@ -131,19 +131,14 @@ bool AArch64CallLowering::lowerFormalArguments( } bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, - const CallInst &CI, unsigned CalleeReg, - unsigned ResReg, + MachineOperand &Callee, + ArrayRef ResTys, + ArrayRef ResRegs, + ArrayRef ArgTys, ArrayRef ArgRegs) const { MachineFunction &MF = MIRBuilder.getMF(); const Function &F = *MF.getFunction(); - // First step is to marshall all the function's parameters into the correct - // physregs and memory locations. Gather the sequence of argument types that - // we'll pass to the assigner function. - SmallVector ArgTys; - for (auto &Arg : CI.arg_operands()) - ArgTys.push_back(MVT::getVT(Arg->getType())); - // Find out which ABI gets to decide where things go. const AArch64TargetLowering &TLI = *getTLI(); CCAssignFn *CallAssignFn = @@ -160,12 +155,8 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, }); // Now we can build the actual call instruction. - MachineInstrBuilder MIB; - if (CalleeReg) - MIB = MIRBuilder.buildInstr(AArch64::BLR).addUse(CalleeReg); - else - MIB = MIRBuilder.buildInstr(AArch64::BL) - .addGlobalAddress(CI.getCalledFunction()); + auto MIB = MIRBuilder.buildInstr(Callee.isReg() ? AArch64::BLR : AArch64::BL); + MIB.addOperand(Callee); // Tell the call which registers are clobbered. auto TRI = MF.getSubtarget().getRegisterInfo(); @@ -178,9 +169,9 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, // symmetry with the arugments, the physical register must be an // implicit-define of the call instruction. CCAssignFn *RetAssignFn = TLI.CCAssignFnForReturn(F.getCallingConv()); - if (!CI.getType()->isVoidTy()) + if (!ResRegs.empty()) handleAssignments( - MIRBuilder, RetAssignFn, MVT::getVT(CI.getType()), ResReg, + MIRBuilder, RetAssignFn, ResTys, ResRegs, [&](MachineIRBuilder &MIRBuilder, unsigned ValReg, unsigned PhysReg) { MIRBuilder.buildCopy(ValReg, PhysReg); MIB.addDef(PhysReg, RegState::Implicit); diff --git a/llvm/lib/Target/AArch64/AArch64CallLowering.h b/llvm/lib/Target/AArch64/AArch64CallLowering.h index e5cf8de..1fe929d 100644 --- a/llvm/lib/Target/AArch64/AArch64CallLowering.h +++ b/llvm/lib/Target/AArch64/AArch64CallLowering.h @@ -34,8 +34,9 @@ class AArch64CallLowering: public CallLowering { const Function::ArgumentListType &Args, ArrayRef VRegs) const override; - bool lowerCall(MachineIRBuilder &MIRBuilder, const CallInst &CI, - unsigned CalleeReg, unsigned ResReg, + bool lowerCall(MachineIRBuilder &MIRBuilder, MachineOperand &Callee, + ArrayRef ResTys, ArrayRef ResRegs, + ArrayRef ArgTys, ArrayRef ArgRegs) const override; private: