2016-08-30 03:07:08 +08:00
|
|
|
//===-- lib/CodeGen/GlobalISel/CallLowering.cpp - Call lowering -----------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2016-08-30 03:07:08 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
|
|
|
/// This file implements some simple delegations needed for call lowering.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-06-27 16:54:17 +08:00
|
|
|
#include "llvm/CodeGen/Analysis.h"
|
2019-09-04 05:42:28 +08:00
|
|
|
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
|
|
|
|
#include "llvm/CodeGen/GlobalISel/Utils.h"
|
2016-12-05 18:40:33 +08:00
|
|
|
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
|
2016-08-30 03:07:08 +08:00
|
|
|
#include "llvm/CodeGen/MachineOperand.h"
|
2016-12-13 18:46:12 +08:00
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2017-11-17 09:07:10 +08:00
|
|
|
#include "llvm/CodeGen/TargetLowering.h"
|
2016-09-21 20:57:45 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
2016-12-05 18:40:33 +08:00
|
|
|
#include "llvm/IR/Instructions.h"
|
[GISel] Pass MD_callees metadata down in call lowering.
Summary:
This will make it possible to improve IPRA by taking into account
register usage in indirect calls.
NFC yet; this is just laying the groundwork to start building
up patches to take advantage of the information for improved register
allocation.
Reviewers: aditya_nandakumar, volkan, qcolombet, arsenm, rovka, aemerson, paquette
Subscribers: sdardis, wdng, javed.absar, hiraditya, jrtc27, atanasyan, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65488
llvm-svn: 367476
2019-08-01 04:34:02 +08:00
|
|
|
#include "llvm/IR/LLVMContext.h"
|
2016-09-21 20:57:45 +08:00
|
|
|
#include "llvm/IR/Module.h"
|
2016-08-30 03:07:08 +08:00
|
|
|
|
2019-04-10 05:22:33 +08:00
|
|
|
#define DEBUG_TYPE "call-lowering"
|
|
|
|
|
2016-08-30 03:07:08 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2018-12-29 10:02:13 +08:00
|
|
|
void CallLowering::anchor() {}
|
|
|
|
|
2019-05-24 16:40:13 +08:00
|
|
|
bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, ImmutableCallSite CS,
|
2019-06-27 17:15:53 +08:00
|
|
|
ArrayRef<Register> ResRegs,
|
2019-06-27 17:18:03 +08:00
|
|
|
ArrayRef<ArrayRef<Register>> ArgRegs,
|
2019-06-24 23:50:29 +08:00
|
|
|
Register SwiftErrorVReg,
|
2019-05-24 16:40:13 +08:00
|
|
|
std::function<unsigned()> GetCalleeReg) const {
|
2019-08-09 16:26:38 +08:00
|
|
|
CallLoweringInfo Info;
|
2017-03-10 08:25:44 +08:00
|
|
|
auto &DL = CS.getParent()->getParent()->getParent()->getDataLayout();
|
2016-09-21 20:57:45 +08:00
|
|
|
|
2016-08-30 03:07:08 +08:00
|
|
|
// 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.
|
2016-09-21 20:57:45 +08:00
|
|
|
unsigned i = 0;
|
2017-03-10 08:25:44 +08:00
|
|
|
unsigned NumFixedArgs = CS.getFunctionType()->getNumParams();
|
|
|
|
for (auto &Arg : CS.args()) {
|
2017-01-18 06:30:10 +08:00
|
|
|
ArgInfo OrigArg{ArgRegs[i], Arg->getType(), ISD::ArgFlagsTy{},
|
|
|
|
i < NumFixedArgs};
|
2017-05-04 02:17:31 +08:00
|
|
|
setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, CS);
|
2019-08-09 16:26:38 +08:00
|
|
|
Info.OrigArgs.push_back(OrigArg);
|
2016-09-21 20:57:45 +08:00
|
|
|
++i;
|
|
|
|
}
|
2016-08-30 03:07:08 +08:00
|
|
|
|
2020-02-11 07:41:53 +08:00
|
|
|
// Try looking through a bitcast from one function type to another.
|
|
|
|
// Commonly happens with calls to objc_msgSend().
|
|
|
|
const Value *CalleeV = CS.getCalledValue()->stripPointerCasts();
|
|
|
|
if (const Function *F = dyn_cast<Function>(CalleeV))
|
2019-08-09 16:26:38 +08:00
|
|
|
Info.Callee = MachineOperand::CreateGA(F, 0);
|
2020-02-11 07:41:53 +08:00
|
|
|
else
|
|
|
|
Info.Callee = MachineOperand::CreateReg(GetCalleeReg(), false);
|
2016-08-30 03:07:08 +08:00
|
|
|
|
2019-08-09 16:26:38 +08:00
|
|
|
Info.OrigRet = ArgInfo{ResRegs, CS.getType(), ISD::ArgFlagsTy{}};
|
|
|
|
if (!Info.OrigRet.Ty->isVoidTy())
|
|
|
|
setArgFlags(Info.OrigRet, AttributeList::ReturnIndex, DL, CS);
|
2016-09-21 20:57:45 +08:00
|
|
|
|
2019-08-09 16:26:38 +08:00
|
|
|
Info.KnownCallees =
|
[GISel] Pass MD_callees metadata down in call lowering.
Summary:
This will make it possible to improve IPRA by taking into account
register usage in indirect calls.
NFC yet; this is just laying the groundwork to start building
up patches to take advantage of the information for improved register
allocation.
Reviewers: aditya_nandakumar, volkan, qcolombet, arsenm, rovka, aemerson, paquette
Subscribers: sdardis, wdng, javed.absar, hiraditya, jrtc27, atanasyan, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D65488
llvm-svn: 367476
2019-08-01 04:34:02 +08:00
|
|
|
CS.getInstruction()->getMetadata(LLVMContext::MD_callees);
|
2019-08-09 16:26:38 +08:00
|
|
|
Info.CallConv = CS.getCallingConv();
|
|
|
|
Info.SwiftErrorVReg = SwiftErrorVReg;
|
2019-08-29 00:19:01 +08:00
|
|
|
Info.IsMustTailCall = CS.isMustTailCall();
|
2019-09-06 04:18:34 +08:00
|
|
|
Info.IsTailCall = CS.isTailCall() &&
|
2019-12-03 08:42:33 +08:00
|
|
|
isInTailCallPosition(CS, MIRBuilder.getMF().getTarget()) &&
|
|
|
|
(MIRBuilder.getMF()
|
|
|
|
.getFunction()
|
|
|
|
.getFnAttribute("disable-tail-calls")
|
|
|
|
.getValueAsString() != "true");
|
2019-09-06 04:18:34 +08:00
|
|
|
Info.IsVarArg = CS.getFunctionType()->isVarArg();
|
2019-08-09 16:26:38 +08:00
|
|
|
return lowerCall(MIRBuilder, Info);
|
2016-08-30 03:07:08 +08:00
|
|
|
}
|
2016-09-21 20:57:45 +08:00
|
|
|
|
|
|
|
template <typename FuncInfoTy>
|
|
|
|
void CallLowering::setArgFlags(CallLowering::ArgInfo &Arg, unsigned OpIdx,
|
|
|
|
const DataLayout &DL,
|
|
|
|
const FuncInfoTy &FuncInfo) const {
|
2019-09-04 05:42:28 +08:00
|
|
|
auto &Flags = Arg.Flags[0];
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
const AttributeList &Attrs = FuncInfo.getAttributes();
|
2016-09-21 20:57:45 +08:00
|
|
|
if (Attrs.hasAttribute(OpIdx, Attribute::ZExt))
|
2019-09-04 05:42:28 +08:00
|
|
|
Flags.setZExt();
|
2016-09-21 20:57:45 +08:00
|
|
|
if (Attrs.hasAttribute(OpIdx, Attribute::SExt))
|
2019-09-04 05:42:28 +08:00
|
|
|
Flags.setSExt();
|
2016-09-21 20:57:45 +08:00
|
|
|
if (Attrs.hasAttribute(OpIdx, Attribute::InReg))
|
2019-09-04 05:42:28 +08:00
|
|
|
Flags.setInReg();
|
2016-09-21 20:57:45 +08:00
|
|
|
if (Attrs.hasAttribute(OpIdx, Attribute::StructRet))
|
2019-09-04 05:42:28 +08:00
|
|
|
Flags.setSRet();
|
2016-09-21 20:57:45 +08:00
|
|
|
if (Attrs.hasAttribute(OpIdx, Attribute::SwiftSelf))
|
2019-09-04 05:42:28 +08:00
|
|
|
Flags.setSwiftSelf();
|
2016-09-21 20:57:45 +08:00
|
|
|
if (Attrs.hasAttribute(OpIdx, Attribute::SwiftError))
|
2019-09-04 05:42:28 +08:00
|
|
|
Flags.setSwiftError();
|
2016-09-21 20:57:45 +08:00
|
|
|
if (Attrs.hasAttribute(OpIdx, Attribute::ByVal))
|
2019-09-04 05:42:28 +08:00
|
|
|
Flags.setByVal();
|
2016-09-21 20:57:45 +08:00
|
|
|
if (Attrs.hasAttribute(OpIdx, Attribute::InAlloca))
|
2019-09-04 05:42:28 +08:00
|
|
|
Flags.setInAlloca();
|
2016-09-21 20:57:45 +08:00
|
|
|
|
2019-09-04 05:42:28 +08:00
|
|
|
if (Flags.isByVal() || Flags.isInAlloca()) {
|
2016-09-21 20:57:45 +08:00
|
|
|
Type *ElementTy = cast<PointerType>(Arg.Ty)->getElementType();
|
2019-05-31 02:48:23 +08:00
|
|
|
|
|
|
|
auto Ty = Attrs.getAttribute(OpIdx, Attribute::ByVal).getValueAsType();
|
2019-09-04 05:42:28 +08:00
|
|
|
Flags.setByValSize(DL.getTypeAllocSize(Ty ? Ty : ElementTy));
|
2019-05-31 02:48:23 +08:00
|
|
|
|
2016-09-21 20:57:45 +08:00
|
|
|
// For ByVal, alignment should be passed from FE. BE will guess if
|
|
|
|
// this info is not there but there are cases it cannot get right.
|
|
|
|
unsigned FrameAlign;
|
2017-05-03 06:07:37 +08:00
|
|
|
if (FuncInfo.getParamAlignment(OpIdx - 2))
|
|
|
|
FrameAlign = FuncInfo.getParamAlignment(OpIdx - 2);
|
2016-09-21 20:57:45 +08:00
|
|
|
else
|
|
|
|
FrameAlign = getTLI()->getByValTypeAlignment(ElementTy, DL);
|
2019-10-21 20:05:33 +08:00
|
|
|
Flags.setByValAlign(Align(FrameAlign));
|
2016-09-21 20:57:45 +08:00
|
|
|
}
|
|
|
|
if (Attrs.hasAttribute(OpIdx, Attribute::Nest))
|
2019-09-04 05:42:28 +08:00
|
|
|
Flags.setNest();
|
2019-10-21 19:01:55 +08:00
|
|
|
Flags.setOrigAlign(Align(DL.getABITypeAlignment(Arg.Ty)));
|
2016-09-21 20:57:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template void
|
|
|
|
CallLowering::setArgFlags<Function>(CallLowering::ArgInfo &Arg, unsigned OpIdx,
|
|
|
|
const DataLayout &DL,
|
|
|
|
const Function &FuncInfo) const;
|
|
|
|
|
|
|
|
template void
|
|
|
|
CallLowering::setArgFlags<CallInst>(CallLowering::ArgInfo &Arg, unsigned OpIdx,
|
|
|
|
const DataLayout &DL,
|
|
|
|
const CallInst &FuncInfo) const;
|
2016-12-05 18:40:33 +08:00
|
|
|
|
2019-06-27 16:54:17 +08:00
|
|
|
Register CallLowering::packRegs(ArrayRef<Register> SrcRegs, Type *PackedTy,
|
|
|
|
MachineIRBuilder &MIRBuilder) const {
|
|
|
|
assert(SrcRegs.size() > 1 && "Nothing to pack");
|
|
|
|
|
|
|
|
const DataLayout &DL = MIRBuilder.getMF().getDataLayout();
|
|
|
|
MachineRegisterInfo *MRI = MIRBuilder.getMRI();
|
|
|
|
|
|
|
|
LLT PackedLLT = getLLTForType(*PackedTy, DL);
|
|
|
|
|
|
|
|
SmallVector<LLT, 8> LLTs;
|
|
|
|
SmallVector<uint64_t, 8> Offsets;
|
|
|
|
computeValueLLTs(DL, *PackedTy, LLTs, &Offsets);
|
|
|
|
assert(LLTs.size() == SrcRegs.size() && "Regs / types mismatch");
|
|
|
|
|
|
|
|
Register Dst = MRI->createGenericVirtualRegister(PackedLLT);
|
|
|
|
MIRBuilder.buildUndef(Dst);
|
|
|
|
for (unsigned i = 0; i < SrcRegs.size(); ++i) {
|
|
|
|
Register NewDst = MRI->createGenericVirtualRegister(PackedLLT);
|
|
|
|
MIRBuilder.buildInsert(NewDst, Dst, SrcRegs[i], Offsets[i]);
|
|
|
|
Dst = NewDst;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CallLowering::unpackRegs(ArrayRef<Register> DstRegs, Register SrcReg,
|
|
|
|
Type *PackedTy,
|
|
|
|
MachineIRBuilder &MIRBuilder) const {
|
|
|
|
assert(DstRegs.size() > 1 && "Nothing to unpack");
|
|
|
|
|
|
|
|
const DataLayout &DL = MIRBuilder.getMF().getDataLayout();
|
|
|
|
|
|
|
|
SmallVector<LLT, 8> LLTs;
|
|
|
|
SmallVector<uint64_t, 8> Offsets;
|
|
|
|
computeValueLLTs(DL, *PackedTy, LLTs, &Offsets);
|
|
|
|
assert(LLTs.size() == DstRegs.size() && "Regs / types mismatch");
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < DstRegs.size(); ++i)
|
|
|
|
MIRBuilder.buildExtract(DstRegs[i], SrcReg, Offsets[i]);
|
|
|
|
}
|
|
|
|
|
2016-12-05 18:40:33 +08:00
|
|
|
bool CallLowering::handleAssignments(MachineIRBuilder &MIRBuilder,
|
2019-09-04 05:42:28 +08:00
|
|
|
SmallVectorImpl<ArgInfo> &Args,
|
2016-12-05 18:40:33 +08:00
|
|
|
ValueHandler &Handler) const {
|
|
|
|
MachineFunction &MF = MIRBuilder.getMF();
|
2017-12-16 06:22:58 +08:00
|
|
|
const Function &F = MF.getFunction();
|
2016-12-05 18:40:33 +08:00
|
|
|
SmallVector<CCValAssign, 16> ArgLocs;
|
|
|
|
CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext());
|
2019-07-17 06:41:34 +08:00
|
|
|
return handleAssignments(CCInfo, ArgLocs, MIRBuilder, Args, Handler);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CallLowering::handleAssignments(CCState &CCInfo,
|
|
|
|
SmallVectorImpl<CCValAssign> &ArgLocs,
|
|
|
|
MachineIRBuilder &MIRBuilder,
|
2019-09-04 05:42:28 +08:00
|
|
|
SmallVectorImpl<ArgInfo> &Args,
|
2019-07-17 06:41:34 +08:00
|
|
|
ValueHandler &Handler) const {
|
|
|
|
MachineFunction &MF = MIRBuilder.getMF();
|
|
|
|
const Function &F = MF.getFunction();
|
|
|
|
const DataLayout &DL = F.getParent()->getDataLayout();
|
2016-12-05 18:40:33 +08:00
|
|
|
|
|
|
|
unsigned NumArgs = Args.size();
|
|
|
|
for (unsigned i = 0; i != NumArgs; ++i) {
|
|
|
|
MVT CurVT = MVT::getVT(Args[i].Ty);
|
2019-09-04 05:42:28 +08:00
|
|
|
if (Handler.assignArg(i, CurVT, CurVT, CCValAssign::Full, Args[i],
|
|
|
|
Args[i].Flags[0], CCInfo)) {
|
|
|
|
if (!CurVT.isValid())
|
2019-06-24 23:50:29 +08:00
|
|
|
return false;
|
2019-09-04 05:42:28 +08:00
|
|
|
MVT NewVT = TLI->getRegisterTypeForCallingConv(
|
2019-04-10 05:22:33 +08:00
|
|
|
F.getContext(), F.getCallingConv(), EVT(CurVT));
|
2019-09-04 05:42:28 +08:00
|
|
|
|
|
|
|
// If we need to split the type over multiple regs, check it's a scenario
|
|
|
|
// we currently support.
|
|
|
|
unsigned NumParts = TLI->getNumRegistersForCallingConv(
|
|
|
|
F.getContext(), F.getCallingConv(), CurVT);
|
|
|
|
if (NumParts > 1) {
|
|
|
|
// For now only handle exact splits.
|
|
|
|
if (NewVT.getSizeInBits() * NumParts != CurVT.getSizeInBits())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-10-12 04:22:57 +08:00
|
|
|
// For incoming arguments (physregs to vregs), we could have values in
|
2019-09-04 05:42:28 +08:00
|
|
|
// physregs (or memlocs) which we want to extract and copy to vregs.
|
|
|
|
// During this, we might have to deal with the LLT being split across
|
|
|
|
// multiple regs, so we have to record this information for later.
|
|
|
|
//
|
|
|
|
// If we have outgoing args, then we have the opposite case. We have a
|
|
|
|
// vreg with an LLT which we want to assign to a physical location, and
|
|
|
|
// we might have to record that the value has to be split later.
|
|
|
|
if (Handler.isIncomingArgumentHandler()) {
|
|
|
|
if (NumParts == 1) {
|
|
|
|
// Try to use the register type if we couldn't assign the VT.
|
|
|
|
if (Handler.assignArg(i, NewVT, NewVT, CCValAssign::Full, Args[i],
|
|
|
|
Args[i].Flags[0], CCInfo))
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
// We're handling an incoming arg which is split over multiple regs.
|
2019-10-12 04:22:57 +08:00
|
|
|
// E.g. passing an s128 on AArch64.
|
2019-09-04 05:42:28 +08:00
|
|
|
ISD::ArgFlagsTy OrigFlags = Args[i].Flags[0];
|
|
|
|
Args[i].OrigRegs.push_back(Args[i].Regs[0]);
|
|
|
|
Args[i].Regs.clear();
|
|
|
|
Args[i].Flags.clear();
|
|
|
|
LLT NewLLT = getLLTForMVT(NewVT);
|
|
|
|
// For each split register, create and assign a vreg that will store
|
|
|
|
// the incoming component of the larger value. These will later be
|
|
|
|
// merged to form the final vreg.
|
|
|
|
for (unsigned Part = 0; Part < NumParts; ++Part) {
|
|
|
|
Register Reg =
|
|
|
|
MIRBuilder.getMRI()->createGenericVirtualRegister(NewLLT);
|
|
|
|
ISD::ArgFlagsTy Flags = OrigFlags;
|
|
|
|
if (Part == 0) {
|
|
|
|
Flags.setSplit();
|
|
|
|
} else {
|
[Alignment][NFC] Deprecate Align::None()
Summary:
This is a follow up on https://reviews.llvm.org/D71473#inline-647262.
There's a caveat here that `Align(1)` relies on the compiler understanding of `Log2_64` implementation to produce good code. One could use `Align()` as a replacement but I believe it is less clear that the alignment is one in that case.
Reviewers: xbolva00, courbet, bollu
Subscribers: arsenm, dylanmckay, sdardis, nemanjai, jvesely, nhaehnle, hiraditya, kbarton, jrtc27, atanasyan, jsji, Jim, kerbowa, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D73099
2020-01-21 22:00:04 +08:00
|
|
|
Flags.setOrigAlign(Align(1));
|
2019-09-04 05:42:28 +08:00
|
|
|
if (Part == NumParts - 1)
|
|
|
|
Flags.setSplitEnd();
|
|
|
|
}
|
|
|
|
Args[i].Regs.push_back(Reg);
|
|
|
|
Args[i].Flags.push_back(Flags);
|
2019-09-12 07:53:23 +08:00
|
|
|
if (Handler.assignArg(i + Part, NewVT, NewVT, CCValAssign::Full,
|
|
|
|
Args[i], Args[i].Flags[Part], CCInfo)) {
|
2019-09-04 05:42:28 +08:00
|
|
|
// Still couldn't assign this smaller part type for some reason.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Handling an outgoing arg that might need to be split.
|
|
|
|
if (NumParts < 2)
|
|
|
|
return false; // Don't know how to deal with this type combination.
|
|
|
|
|
|
|
|
// This type is passed via multiple registers in the calling convention.
|
|
|
|
// We need to extract the individual parts.
|
|
|
|
Register LargeReg = Args[i].Regs[0];
|
|
|
|
LLT SmallTy = LLT::scalar(NewVT.getSizeInBits());
|
|
|
|
auto Unmerge = MIRBuilder.buildUnmerge(SmallTy, LargeReg);
|
|
|
|
assert(Unmerge->getNumOperands() == NumParts + 1);
|
|
|
|
ISD::ArgFlagsTy OrigFlags = Args[i].Flags[0];
|
|
|
|
// We're going to replace the regs and flags with the split ones.
|
|
|
|
Args[i].Regs.clear();
|
|
|
|
Args[i].Flags.clear();
|
|
|
|
for (unsigned PartIdx = 0; PartIdx < NumParts; ++PartIdx) {
|
|
|
|
ISD::ArgFlagsTy Flags = OrigFlags;
|
|
|
|
if (PartIdx == 0) {
|
|
|
|
Flags.setSplit();
|
|
|
|
} else {
|
[Alignment][NFC] Deprecate Align::None()
Summary:
This is a follow up on https://reviews.llvm.org/D71473#inline-647262.
There's a caveat here that `Align(1)` relies on the compiler understanding of `Log2_64` implementation to produce good code. One could use `Align()` as a replacement but I believe it is less clear that the alignment is one in that case.
Reviewers: xbolva00, courbet, bollu
Subscribers: arsenm, dylanmckay, sdardis, nemanjai, jvesely, nhaehnle, hiraditya, kbarton, jrtc27, atanasyan, jsji, Jim, kerbowa, cfe-commits, llvm-commits
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D73099
2020-01-21 22:00:04 +08:00
|
|
|
Flags.setOrigAlign(Align(1));
|
2019-09-04 05:42:28 +08:00
|
|
|
if (PartIdx == NumParts - 1)
|
|
|
|
Flags.setSplitEnd();
|
|
|
|
}
|
|
|
|
Args[i].Regs.push_back(Unmerge.getReg(PartIdx));
|
|
|
|
Args[i].Flags.push_back(Flags);
|
2019-09-12 07:53:23 +08:00
|
|
|
if (Handler.assignArg(i + PartIdx, NewVT, NewVT, CCValAssign::Full,
|
|
|
|
Args[i], Args[i].Flags[PartIdx], CCInfo))
|
2019-09-04 05:42:28 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2019-04-10 05:22:33 +08:00
|
|
|
}
|
2016-12-05 18:40:33 +08:00
|
|
|
}
|
|
|
|
|
2017-02-16 15:53:07 +08:00
|
|
|
for (unsigned i = 0, e = Args.size(), j = 0; i != e; ++i, ++j) {
|
|
|
|
assert(j < ArgLocs.size() && "Skipped too many arg locs");
|
|
|
|
|
|
|
|
CCValAssign &VA = ArgLocs[j];
|
|
|
|
assert(VA.getValNo() == i && "Location doesn't correspond to current arg");
|
|
|
|
|
|
|
|
if (VA.needsCustom()) {
|
|
|
|
j += Handler.assignCustomValue(Args[i], makeArrayRef(ArgLocs).slice(j));
|
|
|
|
continue;
|
|
|
|
}
|
2016-12-05 18:40:33 +08:00
|
|
|
|
2019-06-27 16:50:53 +08:00
|
|
|
// FIXME: Pack registers if we have more than one.
|
2019-07-11 22:18:19 +08:00
|
|
|
Register ArgReg = Args[i].Regs[0];
|
2019-06-27 16:50:53 +08:00
|
|
|
|
2019-09-12 07:53:23 +08:00
|
|
|
MVT OrigVT = MVT::getVT(Args[i].Ty);
|
|
|
|
MVT VAVT = VA.getValVT();
|
2019-04-10 05:22:33 +08:00
|
|
|
if (VA.isRegLoc()) {
|
2019-08-06 07:05:28 +08:00
|
|
|
if (Handler.isIncomingArgumentHandler() && VAVT != OrigVT) {
|
2019-09-04 05:42:28 +08:00
|
|
|
if (VAVT.getSizeInBits() < OrigVT.getSizeInBits()) {
|
|
|
|
// Expected to be multiple regs for a single incoming arg.
|
|
|
|
unsigned NumArgRegs = Args[i].Regs.size();
|
|
|
|
if (NumArgRegs < 2)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
assert((j + (NumArgRegs - 1)) < ArgLocs.size() &&
|
|
|
|
"Too many regs for number of args");
|
|
|
|
for (unsigned Part = 0; Part < NumArgRegs; ++Part) {
|
|
|
|
// There should be Regs.size() ArgLocs per argument.
|
|
|
|
VA = ArgLocs[j + Part];
|
|
|
|
Handler.assignValueToReg(Args[i].Regs[Part], VA.getLocReg(), VA);
|
|
|
|
}
|
|
|
|
j += NumArgRegs - 1;
|
|
|
|
// Merge the split registers into the expected larger result vreg
|
|
|
|
// of the original call.
|
|
|
|
MIRBuilder.buildMerge(Args[i].OrigRegs[0], Args[i].Regs);
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-10 05:22:33 +08:00
|
|
|
const LLT VATy(VAVT);
|
2019-07-11 22:18:19 +08:00
|
|
|
Register NewReg =
|
2019-04-10 05:22:33 +08:00
|
|
|
MIRBuilder.getMRI()->createGenericVirtualRegister(VATy);
|
|
|
|
Handler.assignValueToReg(NewReg, VA.getLocReg(), VA);
|
|
|
|
// If it's a vector type, we either need to truncate the elements
|
|
|
|
// or do an unmerge to get the lower block of elements.
|
|
|
|
if (VATy.isVector() &&
|
|
|
|
VATy.getNumElements() > OrigVT.getVectorNumElements()) {
|
|
|
|
const LLT OrigTy(OrigVT);
|
|
|
|
// Just handle the case where the VA type is 2 * original type.
|
|
|
|
if (VATy.getNumElements() != OrigVT.getVectorNumElements() * 2) {
|
|
|
|
LLVM_DEBUG(dbgs()
|
|
|
|
<< "Incoming promoted vector arg has too many elts");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto Unmerge = MIRBuilder.buildUnmerge({OrigTy, OrigTy}, {NewReg});
|
2019-06-27 16:50:53 +08:00
|
|
|
MIRBuilder.buildCopy(ArgReg, Unmerge.getReg(0));
|
2019-04-10 05:22:33 +08:00
|
|
|
} else {
|
2019-06-27 16:50:53 +08:00
|
|
|
MIRBuilder.buildTrunc(ArgReg, {NewReg}).getReg(0);
|
2019-04-10 05:22:33 +08:00
|
|
|
}
|
2019-09-04 05:42:28 +08:00
|
|
|
} else if (!Handler.isIncomingArgumentHandler()) {
|
|
|
|
assert((j + (Args[i].Regs.size() - 1)) < ArgLocs.size() &&
|
|
|
|
"Too many regs for number of args");
|
|
|
|
// This is an outgoing argument that might have been split.
|
|
|
|
for (unsigned Part = 0; Part < Args[i].Regs.size(); ++Part) {
|
|
|
|
// There should be Regs.size() ArgLocs per argument.
|
|
|
|
VA = ArgLocs[j + Part];
|
|
|
|
Handler.assignValueToReg(Args[i].Regs[Part], VA.getLocReg(), VA);
|
|
|
|
}
|
|
|
|
j += Args[i].Regs.size() - 1;
|
2019-04-10 05:22:33 +08:00
|
|
|
} else {
|
2019-06-27 16:50:53 +08:00
|
|
|
Handler.assignValueToReg(ArgReg, VA.getLocReg(), VA);
|
2019-04-10 05:22:33 +08:00
|
|
|
}
|
|
|
|
} else if (VA.isMemLoc()) {
|
2019-09-12 07:53:23 +08:00
|
|
|
// Don't currently support loading/storing a type that needs to be split
|
|
|
|
// to the stack. Should be easy, just not implemented yet.
|
|
|
|
if (Args[i].Regs.size() > 1) {
|
|
|
|
LLVM_DEBUG(
|
|
|
|
dbgs()
|
|
|
|
<< "Load/store a split arg to/from the stack not implemented yet");
|
|
|
|
return false;
|
|
|
|
}
|
2019-04-10 05:22:33 +08:00
|
|
|
MVT VT = MVT::getVT(Args[i].Ty);
|
|
|
|
unsigned Size = VT == MVT::iPTR ? DL.getPointerSize()
|
|
|
|
: alignTo(VT.getSizeInBits(), 8) / 8;
|
2016-12-05 18:40:33 +08:00
|
|
|
unsigned Offset = VA.getLocMemOffset();
|
|
|
|
MachinePointerInfo MPO;
|
2019-07-11 22:18:19 +08:00
|
|
|
Register StackAddr = Handler.getStackAddress(Size, Offset, MPO);
|
2019-06-27 16:50:53 +08:00
|
|
|
Handler.assignValueToAddress(ArgReg, StackAddr, Size, MPO, VA);
|
2016-12-05 18:40:33 +08:00
|
|
|
} else {
|
|
|
|
// FIXME: Support byvals and other weirdness
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2019-09-11 07:25:12 +08:00
|
|
|
}
|
|
|
|
|
2019-09-13 06:10:36 +08:00
|
|
|
bool CallLowering::analyzeArgInfo(CCState &CCState,
|
2019-09-26 00:45:35 +08:00
|
|
|
SmallVectorImpl<ArgInfo> &Args,
|
|
|
|
CCAssignFn &AssignFnFixed,
|
|
|
|
CCAssignFn &AssignFnVarArg) const {
|
2019-09-11 07:25:12 +08:00
|
|
|
for (unsigned i = 0, e = Args.size(); i < e; ++i) {
|
|
|
|
MVT VT = MVT::getVT(Args[i].Ty);
|
2019-09-26 00:45:35 +08:00
|
|
|
CCAssignFn &Fn = Args[i].IsFixed ? AssignFnFixed : AssignFnVarArg;
|
2019-09-11 07:25:12 +08:00
|
|
|
if (Fn(i, VT, VT, CCValAssign::Full, Args[i].Flags[0], CCState)) {
|
|
|
|
// Bail out on anything we can't handle.
|
|
|
|
LLVM_DEBUG(dbgs() << "Cannot analyze " << EVT(VT).getEVTString()
|
|
|
|
<< " (arg number = " << i << "\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CallLowering::resultsCompatible(CallLoweringInfo &Info,
|
|
|
|
MachineFunction &MF,
|
|
|
|
SmallVectorImpl<ArgInfo> &InArgs,
|
2019-09-26 00:45:35 +08:00
|
|
|
CCAssignFn &CalleeAssignFnFixed,
|
|
|
|
CCAssignFn &CalleeAssignFnVarArg,
|
|
|
|
CCAssignFn &CallerAssignFnFixed,
|
|
|
|
CCAssignFn &CallerAssignFnVarArg) const {
|
2019-09-11 07:25:12 +08:00
|
|
|
const Function &F = MF.getFunction();
|
|
|
|
CallingConv::ID CalleeCC = Info.CallConv;
|
|
|
|
CallingConv::ID CallerCC = F.getCallingConv();
|
|
|
|
|
|
|
|
if (CallerCC == CalleeCC)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
SmallVector<CCValAssign, 16> ArgLocs1;
|
|
|
|
CCState CCInfo1(CalleeCC, false, MF, ArgLocs1, F.getContext());
|
2019-09-26 00:45:35 +08:00
|
|
|
if (!analyzeArgInfo(CCInfo1, InArgs, CalleeAssignFnFixed,
|
|
|
|
CalleeAssignFnVarArg))
|
2019-09-11 07:25:12 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
SmallVector<CCValAssign, 16> ArgLocs2;
|
|
|
|
CCState CCInfo2(CallerCC, false, MF, ArgLocs2, F.getContext());
|
2019-09-26 00:45:35 +08:00
|
|
|
if (!analyzeArgInfo(CCInfo2, InArgs, CallerAssignFnFixed,
|
|
|
|
CalleeAssignFnVarArg))
|
2019-09-11 07:25:12 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// We need the argument locations to match up exactly. If there's more in
|
|
|
|
// one than the other, then we are done.
|
|
|
|
if (ArgLocs1.size() != ArgLocs2.size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Make sure that each location is passed in exactly the same way.
|
|
|
|
for (unsigned i = 0, e = ArgLocs1.size(); i < e; ++i) {
|
|
|
|
const CCValAssign &Loc1 = ArgLocs1[i];
|
|
|
|
const CCValAssign &Loc2 = ArgLocs2[i];
|
|
|
|
|
|
|
|
// We need both of them to be the same. So if one is a register and one
|
|
|
|
// isn't, we're done.
|
|
|
|
if (Loc1.isRegLoc() != Loc2.isRegLoc())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (Loc1.isRegLoc()) {
|
|
|
|
// If they don't have the same register location, we're done.
|
|
|
|
if (Loc1.getLocReg() != Loc2.getLocReg())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// They matched, so we can move to the next ArgLoc.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Loc1 wasn't a RegLoc, so they both must be MemLocs. Check if they match.
|
|
|
|
if (Loc1.getLocMemOffset() != Loc2.getLocMemOffset())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
2016-12-05 18:40:33 +08:00
|
|
|
}
|
2016-12-13 18:46:12 +08:00
|
|
|
|
2019-06-25 00:16:12 +08:00
|
|
|
Register CallLowering::ValueHandler::extendRegister(Register ValReg,
|
2016-12-13 18:46:12 +08:00
|
|
|
CCValAssign &VA) {
|
|
|
|
LLT LocTy{VA.getLocVT()};
|
2019-04-10 05:22:33 +08:00
|
|
|
if (LocTy.getSizeInBits() == MRI.getType(ValReg).getSizeInBits())
|
|
|
|
return ValReg;
|
2016-12-13 18:46:12 +08:00
|
|
|
switch (VA.getLocInfo()) {
|
|
|
|
default: break;
|
|
|
|
case CCValAssign::Full:
|
|
|
|
case CCValAssign::BCvt:
|
|
|
|
// FIXME: bitconverting between vector types may or may not be a
|
|
|
|
// nop in big-endian situations.
|
|
|
|
return ValReg;
|
2017-10-10 04:07:43 +08:00
|
|
|
case CCValAssign::AExt: {
|
|
|
|
auto MIB = MIRBuilder.buildAnyExt(LocTy, ValReg);
|
2020-01-23 19:51:35 +08:00
|
|
|
return MIB.getReg(0);
|
2017-10-10 04:07:43 +08:00
|
|
|
}
|
2016-12-13 18:46:12 +08:00
|
|
|
case CCValAssign::SExt: {
|
2019-07-11 22:18:19 +08:00
|
|
|
Register NewReg = MRI.createGenericVirtualRegister(LocTy);
|
2016-12-13 18:46:12 +08:00
|
|
|
MIRBuilder.buildSExt(NewReg, ValReg);
|
|
|
|
return NewReg;
|
|
|
|
}
|
|
|
|
case CCValAssign::ZExt: {
|
2019-07-11 22:18:19 +08:00
|
|
|
Register NewReg = MRI.createGenericVirtualRegister(LocTy);
|
2016-12-13 18:46:12 +08:00
|
|
|
MIRBuilder.buildZExt(NewReg, ValReg);
|
|
|
|
return NewReg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
llvm_unreachable("unable to extend register");
|
|
|
|
}
|
2018-12-29 10:02:13 +08:00
|
|
|
|
|
|
|
void CallLowering::ValueHandler::anchor() {}
|