Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Standalone View
clang/lib/CodeGen/TargetInfo.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show All 27 Lines | |||||
#include "llvm/ADT/StringSwitch.h" | #include "llvm/ADT/StringSwitch.h" | ||||
#include "llvm/ADT/Twine.h" | #include "llvm/ADT/Twine.h" | ||||
#include "llvm/IR/DataLayout.h" | #include "llvm/IR/DataLayout.h" | ||||
#include "llvm/IR/IntrinsicsNVPTX.h" | #include "llvm/IR/IntrinsicsNVPTX.h" | ||||
#include "llvm/IR/IntrinsicsS390.h" | #include "llvm/IR/IntrinsicsS390.h" | ||||
#include "llvm/IR/Type.h" | #include "llvm/IR/Type.h" | ||||
#include "llvm/Support/MathExtras.h" | #include "llvm/Support/MathExtras.h" | ||||
#include "llvm/Support/raw_ostream.h" | #include "llvm/Support/raw_ostream.h" | ||||
#include "llvm/TargetParser/RISCVTargetParser.h" | |||||
#include "llvm/TargetParser/Triple.h" | #include "llvm/TargetParser/Triple.h" | ||||
#include <algorithm> | #include <algorithm> | ||||
using namespace clang; | using namespace clang; | ||||
using namespace CodeGen; | using namespace CodeGen; | ||||
// Helper for coercing an aggregate argument or return value into an integer | // Helper for coercing an aggregate argument or return value into an integer | ||||
// array of the same size (including padding) and alignment. This alternate | // array of the same size (including padding) and alignment. This alternate | ||||
▲ Show 20 Lines • Show All 11,056 Lines • ▼ Show 20 Lines | public: | ||||
bool detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty, | bool detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty, | ||||
CharUnits &Field1Off, llvm::Type *&Field2Ty, | CharUnits &Field1Off, llvm::Type *&Field2Ty, | ||||
CharUnits &Field2Off, int &NeededArgGPRs, | CharUnits &Field2Off, int &NeededArgGPRs, | ||||
int &NeededArgFPRs) const; | int &NeededArgFPRs) const; | ||||
ABIArgInfo coerceAndExpandFPCCEligibleStruct(llvm::Type *Field1Ty, | ABIArgInfo coerceAndExpandFPCCEligibleStruct(llvm::Type *Field1Ty, | ||||
CharUnits Field1Off, | CharUnits Field1Off, | ||||
llvm::Type *Field2Ty, | llvm::Type *Field2Ty, | ||||
CharUnits Field2Off) const; | CharUnits Field2Off) const; | ||||
ABIArgInfo coerceVLSVector(QualType Ty) const; | |||||
}; | }; | ||||
} // end anonymous namespace | } // end anonymous namespace | ||||
void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const { | void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const { | ||||
QualType RetTy = FI.getReturnType(); | QualType RetTy = FI.getReturnType(); | ||||
if (!getCXXABI().classifyReturnType(FI)) | if (!getCXXABI().classifyReturnType(FI)) | ||||
FI.getReturnInfo() = classifyReturnType(RetTy); | FI.getReturnInfo() = classifyReturnType(RetTy); | ||||
▲ Show 20 Lines • Show All 227 Lines • ▼ Show 20 Lines | ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct( | ||||
auto CoerceToType = | auto CoerceToType = | ||||
llvm::StructType::get(getVMContext(), CoerceElts, IsPacked); | llvm::StructType::get(getVMContext(), CoerceElts, IsPacked); | ||||
auto UnpaddedCoerceToType = | auto UnpaddedCoerceToType = | ||||
llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked); | llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked); | ||||
return ABIArgInfo::getCoerceAndExpand(CoerceToType, UnpaddedCoerceToType); | return ABIArgInfo::getCoerceAndExpand(CoerceToType, UnpaddedCoerceToType); | ||||
} | } | ||||
// Fixed-length RVV vectors are represented as scalable vectors in function | |||||
// args/return and must be coerced from fixed vectors. | |||||
ABIArgInfo RISCVABIInfo::coerceVLSVector(QualType Ty) const { | |||||
assert(Ty->isVectorType() && "expected vector type!"); | |||||
const auto *VT = Ty->castAs<VectorType>(); | |||||
assert(VT->getVectorKind() == VectorType::RVVFixedLengthDataVector && | |||||
"Unexpected vector kind"); | |||||
assert(VT->getElementType()->isBuiltinType() && "expected builtin type!"); | |||||
const auto *BT = VT->getElementType()->castAs<BuiltinType>(); | |||||
unsigned EltSize = getContext().getTypeSize(BT); | |||||
llvm::ScalableVectorType *ResType = | |||||
erichkeane: I wonder if at least the inner type can be picked up ConvertType instead. There doesn't seem… | |||||
The last argument is 64 / sizeof(element). I should replace the 64 with RISCV::RVVBitsPerBlock. craig.topper: The last argument is 64 / sizeof(element). I should replace the 64 with RISCV::RVVBitsPerBlock. | |||||
Not Done ReplyInline ActionsIn that case, I'd suggest putting the 'math' in here. It would be much less difficult to read the tea leaves. erichkeane: In that case, I'd suggest putting the 'math' in here. It would be much less difficult to read… | |||||
llvm::ScalableVectorType::get(CGT.ConvertType(VT->getElementType()), | |||||
Not Done ReplyInline ActionsHaving the switch still is awkward, since it only exists for an unreachable. I wonder if splitting off this type checking to a separate function and asserting on it is more valuable? AND could be used elsewhere if we use this pattern again? I'll leave that up to the CodeGen code owners to require however. erichkeane: Having the switch still is awkward, since it only exists for an unreachable. I wonder if… | |||||
llvm::RISCV::RVVBitsPerBlock / EltSize); | |||||
I need to fix this SVE usage here. craig.topper: I need to fix this SVE usage here. | |||||
return ABIArgInfo::getDirect(ResType); | |||||
} | |||||
ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, | ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, | ||||
int &ArgGPRsLeft, | int &ArgGPRsLeft, | ||||
int &ArgFPRsLeft) const { | int &ArgFPRsLeft) const { | ||||
assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); | assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); | ||||
Ty = useFirstFieldIfTransparentUnion(Ty); | Ty = useFirstFieldIfTransparentUnion(Ty); | ||||
// Structures with either a non-trivial destructor or a non-trivial | // Structures with either a non-trivial destructor or a non-trivial | ||||
// copy constructor are always passed indirectly. | // copy constructor are always passed indirectly. | ||||
if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { | if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { | ||||
if (ArgGPRsLeft) | if (ArgGPRsLeft) | ||||
ArgGPRsLeft -= 1; | ArgGPRsLeft -= 1; | ||||
return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == | return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == | ||||
CGCXXABI::RAA_DirectInMemory); | CGCXXABI::RAA_DirectInMemory); | ||||
} | } | ||||
// Ignore empty structs/unions. | // Ignore empty structs/unions. | ||||
Not Done ReplyInline ActionsWhere is 'XLen' from here? erichkeane: Where is 'XLen' from here? | |||||
It's a member of RISCVABIInfo. It's 64 for riscv64 triple and 32 for riscv32 triple. craig.topper: It's a member of RISCVABIInfo. It's 64 for riscv64 triple and 32 for riscv32 triple. | |||||
Not Done ReplyInline ActionsWell, the name is awful :) I'd probably suggest a re-name and hiding it behind a function call (since that way it can be done on the triple, rather than an initialized variable perhaps?), but I'm not really in charge of this target info. erichkeane: Well, the name is awful :) I'd probably suggest a re-name and hiding it behind a function call… | |||||
Not Done ReplyInline ActionsIt's not for anyone in the RISC-V space, since it is defined by the architecture and used pervasively (and means the X register LENgth, i.e. how many bits in the x0-x31 GPRs). Using anything else in a RISC-V ABI context would be worse from a RISC-V perspective. In a random LLVM checkout I have I see 1118 instances of /xlen/i in llvm/lib/Target/RISCV alone. jrtc27: It's not for anyone in the RISC-V space, since it is defined by the architecture and used… | |||||
It's the term in the RISC-V spec for the size of our integer registers. Anyone working on RISC-V should be familiar with it. craig.topper: It's the term in the RISC-V spec for the size of our integer registers. Anyone working on RISC… | |||||
Not Done ReplyInline ActionsBased on Jessica's post, perhaps it is not an issue. Just was jarring to see something as impenetrable. I'd perhaps suggest something like XRegisterLen to make it clear what 'X' is, but just a suggestion for the next folks who are finding their way into contributing patches, despite perhaps not yet being RISCV experts. erichkeane: Based on Jessica's post, perhaps it is not an issue. Just was jarring to see something as… | |||||
I rewrote it using ConvertType and getTypeSize. craig.topper: I rewrote it using ConvertType and getTypeSize. | |||||
if (isEmptyRecord(getContext(), Ty, true)) | if (isEmptyRecord(getContext(), Ty, true)) | ||||
return ABIArgInfo::getIgnore(); | return ABIArgInfo::getIgnore(); | ||||
uint64_t Size = getContext().getTypeSize(Ty); | uint64_t Size = getContext().getTypeSize(Ty); | ||||
// Pass floating point values via FPRs if possible. | // Pass floating point values via FPRs if possible. | ||||
if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() && | if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() && | ||||
FLen >= Size && ArgFPRsLeft) { | FLen >= Size && ArgFPRsLeft) { | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | if (const auto *EIT = Ty->getAs<BitIntType>()) { | ||||
(!getContext().getTargetInfo().hasInt128Type() && | (!getContext().getTargetInfo().hasInt128Type() && | ||||
EIT->getNumBits() > 64)) | EIT->getNumBits() > 64)) | ||||
return getNaturalAlignIndirect(Ty, /*ByVal=*/false); | return getNaturalAlignIndirect(Ty, /*ByVal=*/false); | ||||
} | } | ||||
return ABIArgInfo::getDirect(); | return ABIArgInfo::getDirect(); | ||||
} | } | ||||
if (const VectorType *VT = Ty->getAs<VectorType>()) | |||||
if (VT->getVectorKind() == VectorType::RVVFixedLengthDataVector) | |||||
return coerceVLSVector(Ty); | |||||
// Aggregates which are <= 2*XLen will be passed in registers if possible, | // Aggregates which are <= 2*XLen will be passed in registers if possible, | ||||
// so coerce to integers. | // so coerce to integers. | ||||
if (Size <= 2 * XLen) { | if (Size <= 2 * XLen) { | ||||
unsigned Alignment = getContext().getTypeAlign(Ty); | unsigned Alignment = getContext().getTypeAlign(Ty); | ||||
// Use a single XLen int if possible, 2*XLen if 2*XLen alignment is | // Use a single XLen int if possible, 2*XLen if 2*XLen alignment is | ||||
// required, and a 2-element XLen array if only XLen alignment is required. | // required, and a 2-element XLen array if only XLen alignment is required. | ||||
if (Size <= XLen) { | if (Size <= XLen) { | ||||
▲ Show 20 Lines • Show All 1,176 Lines • Show Last 20 Lines |
I wonder if at least the inner type can be picked up ConvertType instead. There doesn't seem to be obvious rhyme/reason to the last argument to ScalableVectorType, so it might not solve that.
However, it'll solve the long problem.