Reverts llvm/llvm-project#179304 due to https://github.com/llvm/llvm-project/pull/179304#issuecomment-3856100622
195 lines
7.1 KiB
C++
195 lines
7.1 KiB
C++
//===--- NVPTX.cpp - Implement NVPTX target feature support ---------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements NVPTX TargetInfo objects.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "NVPTX.h"
|
|
#include "clang/Basic/Builtins.h"
|
|
#include "clang/Basic/MacroBuilder.h"
|
|
#include "clang/Basic/TargetBuiltins.h"
|
|
#include "llvm/ADT/StringSwitch.h"
|
|
|
|
using namespace clang;
|
|
using namespace clang::targets;
|
|
|
|
static constexpr int NumBuiltins =
|
|
clang::NVPTX::LastTSBuiltin - Builtin::FirstTSBuiltin;
|
|
|
|
#define GET_BUILTIN_STR_TABLE
|
|
#include "clang/Basic/BuiltinsNVPTX.inc"
|
|
#undef GET_BUILTIN_STR_TABLE
|
|
|
|
static constexpr Builtin::Info BuiltinInfos[] = {
|
|
#define GET_BUILTIN_INFOS
|
|
#include "clang/Basic/BuiltinsNVPTX.inc"
|
|
#undef GET_BUILTIN_INFOS
|
|
};
|
|
static_assert(std::size(BuiltinInfos) == NumBuiltins);
|
|
|
|
const char *const NVPTXTargetInfo::GCCRegNames[] = {"r0"};
|
|
|
|
NVPTXTargetInfo::NVPTXTargetInfo(const llvm::Triple &Triple,
|
|
const TargetOptions &Opts,
|
|
unsigned TargetPointerWidth)
|
|
: TargetInfo(Triple) {
|
|
assert((TargetPointerWidth == 32 || TargetPointerWidth == 64) &&
|
|
"NVPTX only supports 32- and 64-bit modes.");
|
|
|
|
PTXVersion = 32;
|
|
for (const StringRef Feature : Opts.FeaturesAsWritten) {
|
|
int PTXV;
|
|
if (!Feature.starts_with("+ptx") ||
|
|
Feature.drop_front(4).getAsInteger(10, PTXV))
|
|
continue;
|
|
PTXVersion = PTXV; // TODO: should it be max(PTXVersion, PTXV)?
|
|
}
|
|
|
|
TLSSupported = false;
|
|
VLASupported = false;
|
|
AddrSpaceMap = &NVPTXAddrSpaceMap;
|
|
UseAddrSpaceMapMangling = true;
|
|
// __bf16 is always available as a load/store only type.
|
|
BFloat16Width = BFloat16Align = 16;
|
|
BFloat16Format = &llvm::APFloat::BFloat();
|
|
|
|
// Define available target features
|
|
// These must be defined in sorted order!
|
|
NoAsmVariants = true;
|
|
GPU = OffloadArch::UNUSED;
|
|
|
|
// PTX supports f16 as a fundamental type.
|
|
HasFastHalfType = true;
|
|
HasFloat16 = true;
|
|
|
|
// TODO: Make shortptr a proper ABI?
|
|
DataLayoutString =
|
|
Triple.computeDataLayout(Opts.NVPTXUseShortPointers ? "shortptr" : "");
|
|
|
|
// If possible, get a TargetInfo for our host triple, so we can match its
|
|
// types.
|
|
llvm::Triple HostTriple(Opts.HostTriple);
|
|
if (!HostTriple.isNVPTX())
|
|
HostTarget = AllocateTarget(llvm::Triple(Opts.HostTriple), Opts);
|
|
|
|
// If no host target, make some guesses about the data layout and return.
|
|
if (!HostTarget) {
|
|
LongWidth = LongAlign = TargetPointerWidth;
|
|
PointerWidth = PointerAlign = TargetPointerWidth;
|
|
switch (TargetPointerWidth) {
|
|
case 32:
|
|
SizeType = TargetInfo::UnsignedInt;
|
|
PtrDiffType = TargetInfo::SignedInt;
|
|
IntPtrType = TargetInfo::SignedInt;
|
|
break;
|
|
case 64:
|
|
SizeType = TargetInfo::UnsignedLong;
|
|
PtrDiffType = TargetInfo::SignedLong;
|
|
IntPtrType = TargetInfo::SignedLong;
|
|
break;
|
|
default:
|
|
llvm_unreachable("TargetPointerWidth must be 32 or 64");
|
|
}
|
|
|
|
MaxAtomicInlineWidth = TargetPointerWidth;
|
|
return;
|
|
}
|
|
|
|
// Copy properties from host target.
|
|
PointerWidth = HostTarget->getPointerWidth(LangAS::Default);
|
|
PointerAlign = HostTarget->getPointerAlign(LangAS::Default);
|
|
BoolWidth = HostTarget->getBoolWidth();
|
|
BoolAlign = HostTarget->getBoolAlign();
|
|
IntWidth = HostTarget->getIntWidth();
|
|
IntAlign = HostTarget->getIntAlign();
|
|
HalfWidth = HostTarget->getHalfWidth();
|
|
HalfAlign = HostTarget->getHalfAlign();
|
|
FloatWidth = HostTarget->getFloatWidth();
|
|
FloatAlign = HostTarget->getFloatAlign();
|
|
DoubleWidth = HostTarget->getDoubleWidth();
|
|
DoubleAlign = HostTarget->getDoubleAlign();
|
|
LongWidth = HostTarget->getLongWidth();
|
|
LongAlign = HostTarget->getLongAlign();
|
|
LongLongWidth = HostTarget->getLongLongWidth();
|
|
LongLongAlign = HostTarget->getLongLongAlign();
|
|
MinGlobalAlign = HostTarget->getMinGlobalAlign(/* TypeSize = */ 0,
|
|
/* HasNonWeakDef = */ true);
|
|
NewAlign = HostTarget->getNewAlign();
|
|
DefaultAlignForAttributeAligned =
|
|
HostTarget->getDefaultAlignForAttributeAligned();
|
|
SizeType = HostTarget->getSizeType();
|
|
IntMaxType = HostTarget->getIntMaxType();
|
|
PtrDiffType = HostTarget->getPtrDiffType(LangAS::Default);
|
|
IntPtrType = HostTarget->getIntPtrType();
|
|
WCharType = HostTarget->getWCharType();
|
|
WIntType = HostTarget->getWIntType();
|
|
Char16Type = HostTarget->getChar16Type();
|
|
Char32Type = HostTarget->getChar32Type();
|
|
Int64Type = HostTarget->getInt64Type();
|
|
SigAtomicType = HostTarget->getSigAtomicType();
|
|
ProcessIDType = HostTarget->getProcessIDType();
|
|
|
|
UseBitFieldTypeAlignment = HostTarget->useBitFieldTypeAlignment();
|
|
UseZeroLengthBitfieldAlignment = HostTarget->useZeroLengthBitfieldAlignment();
|
|
UseExplicitBitFieldAlignment = HostTarget->useExplicitBitFieldAlignment();
|
|
ZeroLengthBitfieldBoundary = HostTarget->getZeroLengthBitfieldBoundary();
|
|
|
|
// This is a bit of a lie, but it controls __GCC_ATOMIC_XXX_LOCK_FREE, and
|
|
// we need those macros to be identical on host and device, because (among
|
|
// other things) they affect which standard library classes are defined, and
|
|
// we need all classes to be defined on both the host and device.
|
|
MaxAtomicInlineWidth = HostTarget->getMaxAtomicInlineWidth();
|
|
|
|
// Properties intentionally not copied from host:
|
|
// - LargeArrayMinWidth, LargeArrayAlign: Not visible across the
|
|
// host/device boundary.
|
|
// - SuitableAlign: Not visible across the host/device boundary, and may
|
|
// correctly be different on host/device, e.g. if host has wider vector
|
|
// types than device.
|
|
// - LongDoubleWidth, LongDoubleAlign: nvptx's long double type is the same
|
|
// as its double type, but that's not necessarily true on the host.
|
|
// TODO: nvcc emits a warning when using long double on device; we should
|
|
// do the same.
|
|
}
|
|
|
|
ArrayRef<const char *> NVPTXTargetInfo::getGCCRegNames() const {
|
|
return llvm::ArrayRef(GCCRegNames);
|
|
}
|
|
|
|
bool NVPTXTargetInfo::hasFeature(StringRef Feature) const {
|
|
return llvm::StringSwitch<bool>(Feature)
|
|
.Cases({"ptx", "nvptx"}, true)
|
|
.Default(false);
|
|
}
|
|
|
|
void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
|
|
MacroBuilder &Builder) const {
|
|
Builder.defineMacro("__PTX__");
|
|
Builder.defineMacro("__NVPTX__");
|
|
|
|
// Skip setting architecture dependent macros if undefined.
|
|
if (!IsNVIDIAOffloadArch(GPU))
|
|
return;
|
|
|
|
if (Opts.CUDAIsDevice || Opts.OpenMPIsTargetDevice || !HostTarget) {
|
|
// Set __CUDA_ARCH__ for the GPU specified.
|
|
unsigned ArchID = CudaArchToID(GPU);
|
|
Builder.defineMacro("__CUDA_ARCH__", llvm::Twine(ArchID));
|
|
|
|
if (IsNVIDIAAcceleratedOffloadArch(GPU))
|
|
Builder.defineMacro(
|
|
"__CUDA_ARCH_FEAT_SM" + llvm::Twine(ArchID / 10) + "_ALL", "1");
|
|
}
|
|
}
|
|
|
|
llvm::SmallVector<Builtin::InfosShard>
|
|
NVPTXTargetInfo::getTargetBuiltins() const {
|
|
return {{&BuiltinStrings, BuiltinInfos}};
|
|
}
|