1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00

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
This commit is contained in:
Tim Northover 2016-08-29 19:07:08 +00:00
parent 2e0aaa6df5
commit 05f74b5dbe
6 changed files with 89 additions and 29 deletions

View File

@ -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,9 +72,31 @@ 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 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, MachineOperand &Callee,
ArrayRef<MVT> ResTys, ArrayRef<unsigned> ResRegs,
ArrayRef<MVT> ArgTys,
ArrayRef<unsigned> 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).
@ -80,12 +104,15 @@ class CallLowering {
/// \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 CalleeReg, unsigned ResReg,
ArrayRef<unsigned> ArgRegs) const {
return false;
}
unsigned ResReg, ArrayRef<unsigned> ArgRegs,
std::function<unsigned()> GetCalleeReg) const;
};
} // End namespace llvm.

View File

@ -1,5 +1,6 @@
# List of all GlobalISel files.
set(GLOBAL_ISEL_FILES
CallLowering.cpp
IRTranslator.cpp
InstructionSelect.cpp
InstructionSelector.cpp

View File

@ -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<unsigned> ArgRegs, std::function<unsigned()> 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<MVT, 8> 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<unsigned>(), ArgTys, ArgRegs);
}

View File

@ -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();

View File

@ -131,19 +131,14 @@ bool AArch64CallLowering::lowerFormalArguments(
}
bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
const CallInst &CI, unsigned CalleeReg,
unsigned ResReg,
MachineOperand &Callee,
ArrayRef<MVT> ResTys,
ArrayRef<unsigned> ResRegs,
ArrayRef<MVT> ArgTys,
ArrayRef<unsigned> 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<MVT, 8> 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<AArch64TargetLowering>();
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);

View File

@ -34,8 +34,9 @@ class AArch64CallLowering: public CallLowering {
const Function::ArgumentListType &Args,
ArrayRef<unsigned> VRegs) const override;
bool lowerCall(MachineIRBuilder &MIRBuilder, const CallInst &CI,
unsigned CalleeReg, unsigned ResReg,
bool lowerCall(MachineIRBuilder &MIRBuilder, MachineOperand &Callee,
ArrayRef<MVT> ResTys, ArrayRef<unsigned> ResRegs,
ArrayRef<MVT> ArgTys,
ArrayRef<unsigned> ArgRegs) const override;
private: