From e69580818fc9e6d03c472bf9b6976f202b476a8b Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Mon, 15 Apr 2019 12:03:54 +0000 Subject: [PATCH] DAG: propagate whether an arg is a pointer for CallingConv decisions. The arm64_32 ABI specifies that pointers (despite being 32-bits) should be zero-extended to 64-bits when passed in registers for efficiency reasons. This means that the SelectionDAG needs to be able to tell the backend that an argument was originally a pointer, which is implmented here. Additionally, some memory intrinsics need to be declared as taking an i8* instead of an iPTR. There should be no CodeGen change yet, but it will be triggered when AArch64 backend support for ILP32 is added. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358398 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/TargetCallingConv.h | 16 +++++++++++--- include/llvm/Target/TargetCallingConv.td | 9 ++++++++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 13 ++++++----- .../SelectionDAG/SelectionDAGBuilder.cpp | 22 +++++++++++++++++++ 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/include/llvm/CodeGen/TargetCallingConv.h b/include/llvm/CodeGen/TargetCallingConv.h index f82c05dc82d..aebeeecbe50 100644 --- a/include/llvm/CodeGen/TargetCallingConv.h +++ b/include/llvm/CodeGen/TargetCallingConv.h @@ -45,9 +45,12 @@ namespace ISD { unsigned IsInConsecutiveRegsLast : 1; unsigned IsInConsecutiveRegs : 1; unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate + unsigned IsPointer : 1; unsigned ByValSize; ///< Byval struct size + unsigned PointerAddrSpace; ///< Address space of pointer argument + public: ArgFlagsTy() : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsNest(0), @@ -55,8 +58,9 @@ namespace ISD { IsSwiftSelf(0), IsSwiftError(0), IsHva(0), IsHvaStart(0), IsSecArgPass(0), ByValAlign(0), OrigAlign(0), IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0), - IsCopyElisionCandidate(0), ByValSize(0) { - static_assert(sizeof(*this) == 2 * sizeof(unsigned), "flags are too big"); + IsCopyElisionCandidate(0), IsPointer(0), ByValSize(0), + PointerAddrSpace(0) { + static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big"); } bool isZExt() const { return IsZExt; } @@ -113,6 +117,9 @@ namespace ISD { bool isCopyElisionCandidate() const { return IsCopyElisionCandidate; } void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; } + bool isPointer() const { return IsPointer; } + void setPointer() { IsPointer = 1; } + unsigned getByValAlign() const { return (1U << ByValAlign) / 2; } void setByValAlign(unsigned A) { ByValAlign = Log2_32(A) + 1; @@ -127,7 +134,10 @@ namespace ISD { unsigned getByValSize() const { return ByValSize; } void setByValSize(unsigned S) { ByValSize = S; } - }; + + unsigned getPointerAddrSpace() const { return PointerAddrSpace; } + void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; } +}; /// InputArg - This struct carries flags and type information about a /// single incoming (formal) argument or incoming (from the perspective diff --git a/include/llvm/Target/TargetCallingConv.td b/include/llvm/Target/TargetCallingConv.td index 11ed4f5b808..1bc03cf8a49 100644 --- a/include/llvm/Target/TargetCallingConv.td +++ b/include/llvm/Target/TargetCallingConv.td @@ -82,6 +82,15 @@ class CCIfVarArg : CCIf<"State.isVarArg()", A> {} /// CCIfNotVarArg - If the current function is not vararg - apply the action class CCIfNotVarArg : CCIf<"!State.isVarArg()", A> {} +/// CCIfPtrAddrSpace - If the top-level parent of the current argument has +/// pointer type in the specified address-space. +class CCIfPtrAddrSpace + : CCIf<"(ArgFlags.isPointer() && ArgFlags.getPointerAddrSpace() == " # AS # ")", A> {} + +/// CCIfPtr - If the top-level parent of the current argument had +/// pointer type in some address-space. +class CCIfPtr : CCIf<"ArgFlags.isPointer()", A> {} + /// CCAssignToReg - This action matches if there is a register in the specified /// list that is still available. If so, it assigns the value to the first /// available register and succeeds. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 43e9b52b0f9..5689a152ca5 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -6093,9 +6093,11 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, // Emit a library call. TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; - Entry.Ty = getDataLayout().getIntPtrType(*getContext()); + Entry.Ty = Type::getInt8PtrTy(*getContext()); Entry.Node = Dst; Args.push_back(Entry); Entry.Node = Src; Args.push_back(Entry); + + Entry.Ty = getDataLayout().getIntPtrType(*getContext()); Entry.Node = Size; Args.push_back(Entry); // FIXME: pass in SDLoc TargetLowering::CallLoweringInfo CLI(*this); @@ -6195,9 +6197,11 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst, // Emit a library call. TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; - Entry.Ty = getDataLayout().getIntPtrType(*getContext()); + Entry.Ty = Type::getInt8PtrTy(*getContext()); Entry.Node = Dst; Args.push_back(Entry); Entry.Node = Src; Args.push_back(Entry); + + Entry.Ty = getDataLayout().getIntPtrType(*getContext()); Entry.Node = Size; Args.push_back(Entry); // FIXME: pass in SDLoc TargetLowering::CallLoweringInfo CLI(*this); @@ -6290,16 +6294,15 @@ SDValue SelectionDAG::getMemset(SDValue Chain, const SDLoc &dl, SDValue Dst, checkAddrSpaceIsValidForLibcall(TLI, DstPtrInfo.getAddrSpace()); // Emit a library call. - Type *IntPtrTy = getDataLayout().getIntPtrType(*getContext()); TargetLowering::ArgListTy Args; TargetLowering::ArgListEntry Entry; - Entry.Node = Dst; Entry.Ty = IntPtrTy; + Entry.Node = Dst; Entry.Ty = Type::getInt8PtrTy(*getContext()); Args.push_back(Entry); Entry.Node = Src; Entry.Ty = Src.getValueType().getTypeForEVT(*getContext()); Args.push_back(Entry); Entry.Node = Size; - Entry.Ty = IntPtrTy; + Entry.Ty = getDataLayout().getIntPtrType(*getContext()); Args.push_back(Entry); // FIXME: pass in SDLoc diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 2bf68ac81c9..4391acd6ea6 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1846,6 +1846,12 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) { if (RetInReg) Flags.setInReg(); + if (I.getOperand(0)->getType()->isPointerTy()) { + Flags.setPointer(); + Flags.setPointerAddrSpace( + cast(I.getOperand(0)->getType())->getAddressSpace()); + } + // Propagate extension type if any if (ExtendKind == ISD::SIGN_EXTEND) Flags.setSExt(); @@ -8834,9 +8840,15 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const { CLI.CallConv, VT); for (unsigned i = 0; i != NumRegs; ++i) { ISD::InputArg MyFlags; + MyFlags.Flags = Flags; MyFlags.VT = RegisterVT; MyFlags.ArgVT = VT; MyFlags.Used = CLI.IsReturnValueUsed; + if (CLI.RetTy->isPointerTy()) { + MyFlags.Flags.setPointer(); + MyFlags.Flags.setPointerAddrSpace( + cast(CLI.RetTy)->getAddressSpace()); + } if (CLI.RetSExt) MyFlags.Flags.setSExt(); if (CLI.RetZExt) @@ -8887,6 +8899,11 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const { // specify the alignment it wants. unsigned OriginalAlignment = getABIAlignmentForCallingConv(ArgTy, DL); + if (Args[i].Ty->isPointerTy()) { + Flags.setPointer(); + Flags.setPointerAddrSpace( + cast(Args[i].Ty)->getAddressSpace()); + } if (Args[i].IsZExt) Flags.setZExt(); if (Args[i].IsSExt) @@ -9375,6 +9392,11 @@ void SelectionDAGISel::LowerArguments(const Function &F) { unsigned OriginalAlignment = TLI->getABIAlignmentForCallingConv(ArgTy, DL); + if (Arg.getType()->isPointerTy()) { + Flags.setPointer(); + Flags.setPointerAddrSpace( + cast(Arg.getType())->getAddressSpace()); + } if (Arg.hasAttribute(Attribute::ZExt)) Flags.setZExt(); if (Arg.hasAttribute(Attribute::SExt)) -- 2.50.1