Skip to content

[SYCL][NativeCPU] Build libclc target-independently. #17408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Apr 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/lib/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ add_clang_library(clangBasic
Targets/MSP430.cpp
Targets/Mips.cpp
Targets/NVPTX.cpp
Targets/NativeCPU.cpp
Targets/OSTargets.cpp
Targets/PNaCl.cpp
Targets/PPC.cpp
Expand Down
35 changes: 0 additions & 35 deletions clang/lib/Basic/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -546,41 +546,6 @@ void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {

if (Opts.FakeAddressSpaceMap)
AddrSpaceMap = &FakeAddrSpaceMap;

if ((Opts.SYCLIsDevice || Opts.OpenCL) && Opts.SYCLIsNativeCPU) {
// For SYCL Native CPU we use the NVPTXAddrSpaceMap because
// we need builtins to be mangled with AS information.
// This is also enabled in OpenCL mode so that mangling
// matches when building libclc.

static const unsigned SYCLNativeCPUASMap[] = {
0, // Default
1, // opencl_global
3, // opencl_local
4, // opencl_constant
0, // opencl_private
0, // opencl_generic
1, // opencl_global_device
1, // opencl_global_host
1, // cuda_device
4, // cuda_constant
3, // cuda_shared
1, // sycl_global
1, // sycl_global_device
1, // sycl_global_host
3, // sycl_local
0, // sycl_private
0, // ptr32_sptr
0, // ptr32_uptr
0, // ptr64
0, // hlsl_groupshared
0, // hlsl_constant
20, // wasm_funcref
};

AddrSpaceMap = &SYCLNativeCPUASMap;
UseAddrSpaceMapMangling = true;
}
}

bool TargetInfo::initFeatureMap(
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Basic/Targets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "Targets/MSP430.h"
#include "Targets/Mips.h"
#include "Targets/NVPTX.h"
#include "Targets/NativeCPU.h"
#include "Targets/OSTargets.h"
#include "Targets/PNaCl.h"
#include "Targets/PPC.h"
Expand Down Expand Up @@ -117,6 +118,13 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
default:
return nullptr;

case llvm::Triple::UnknownArch:
// native_cpu is only known to Clang, not to LLVM.
if (Triple.str() == "native_cpu")
return std::make_unique<NativeCPUTargetInfo>(Triple, Opts);

return nullptr;

case llvm::Triple::arc:
return std::make_unique<ARCTargetInfo>(Triple, Opts);

Expand Down
109 changes: 109 additions & 0 deletions clang/lib/Basic/Targets/NativeCPU.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//===--- NativeCPU.cpp - Implement NativeCPU 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 NativeCPU TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#include "NativeCPU.h"
#include <llvm/TargetParser/Host.h>

using namespace clang;
using namespace clang::targets;

static const LangASMap NativeCPUASMap = {
0, // Default
1, // opencl_global
3, // opencl_local
4, // opencl_constant
0, // opencl_private
0, // opencl_generic
1, // opencl_global_device
1, // opencl_global_host
1, // cuda_device
4, // cuda_constant
3, // cuda_shared
1, // sycl_global
1, // sycl_global_device
1, // sycl_global_host
3, // sycl_local
0, // sycl_private
0, // ptr32_sptr
0, // ptr32_uptr
0, // ptr64
0, // hlsl_groupshared
0, // hlsl_constant
20, // wasm_funcref
};

NativeCPUTargetInfo::NativeCPUTargetInfo(const llvm::Triple &,
const TargetOptions &Opts)
: TargetInfo(llvm::Triple()) {
AddrSpaceMap = &NativeCPUASMap;
UseAddrSpaceMapMangling = true;
HasLegalHalfType = true;
HasFloat16 = true;
resetDataLayout("e");

llvm::Triple HostTriple([&] {
// Take the default target triple if no other host triple is specified so
// that system headers work.
if (Opts.HostTriple.empty())
return llvm::sys::getDefaultTargetTriple();

return Opts.HostTriple;
}());
if (HostTriple.getArch() != llvm::Triple::UnknownArch) {
HostTarget = AllocateTarget(HostTriple, Opts);

// Copy properties from host target.
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();
PointerWidth = HostTarget->getPointerWidth(LangAS::Default);
PointerAlign = HostTarget->getPointerAlign(LangAS::Default);
MinGlobalAlign = HostTarget->getMinGlobalAlign(/*TypeSize=*/0,
/*HasNonWeakDef=*/true);
NewAlign = HostTarget->getNewAlign();
DefaultAlignForAttributeAligned =
HostTarget->getDefaultAlignForAttributeAligned();
SizeType = HostTarget->getSizeType();
PtrDiffType = HostTarget->getPtrDiffType(LangAS::Default);
IntMaxType = HostTarget->getIntMaxType();
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();
}
}
72 changes: 72 additions & 0 deletions clang/lib/Basic/Targets/NativeCPU.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//===--- NativeCPU.h - Declare NativeCPU target feature support -*- C++ -*-===//
//
// 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 declares NativeCPU TargetInfo objects.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_NATIVECPU_H
#define LLVM_CLANG_LIB_BASIC_TARGETS_NATIVECPU_H

#include "Targets.h"

namespace clang {
namespace targets {

class LLVM_LIBRARY_VISIBILITY NativeCPUTargetInfo final : public TargetInfo {
std::unique_ptr<TargetInfo> HostTarget;

public:
NativeCPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts);

void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override {
DefineStd(Builder, "NativeCPU", Opts);
}

SmallVector<Builtin::InfosShard> getTargetBuiltins() const override {
return {};
}

BuiltinVaListKind getBuiltinVaListKind() const override {
if (HostTarget)
return HostTarget->getBuiltinVaListKind();

return TargetInfo::VoidPtrBuiltinVaList;
}

bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &info) const override {
return true;
}

std::string_view getClobbers() const override { return ""; }

void setSupportedOpenCLOpts() override { supportAllOpenCLOpts(); }

CallingConvCheckResult checkCallingConvention(CallingConv CC) const override {
if (HostTarget)
return HostTarget->checkCallingConvention(CC);

return TargetInfo::checkCallingConvention(CC);
}

protected:
ArrayRef<const char *> getGCCRegNames() const override { return {}; }

ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override {
return {};
}

bool hasBitIntType() const override { return true; }
};

} // namespace targets
} // namespace clang

#endif // LLVM_CLANG_LIB_BASIC_TARGETS_NATIVECPU_H
4 changes: 3 additions & 1 deletion clang/lib/Driver/Compilation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "clang/Driver/Compilation.h"
#include "ToolChains/SYCL.h"
#include "clang/Basic/LLVM.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Driver.h"
Expand Down Expand Up @@ -127,7 +128,8 @@ Compilation::getArgsForToolChain(const ToolChain *TC, StringRef BoundArch,
if (DeviceOffloadKind == Action::OFK_OpenMP ||
DeviceOffloadKind == Action::OFK_SYCL) {
const ToolChain *HostTC = getSingleOffloadToolChain<Action::OFK_Host>();
bool SameTripleAsHost = (TC->getTriple() == HostTC->getTriple());
bool SameTripleAsHost = (TC->getTriple() == HostTC->getTriple()) ||
isSYCLNativeCPU(TC->getTriple());
OffloadArgs = TC->TranslateOffloadTargetArgs(
*TranslatedArgs, SameTripleAsHost, AllocatedArgs, DeviceOffloadKind);
}
Expand Down
34 changes: 9 additions & 25 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,10 @@ static bool isValidSYCLTriple(llvm::Triple T) {
!T.hasEnvironment())
return true;

// 'native_cpu' is valid for Native CPU.
if (isSYCLNativeCPU(T))
return true;

// Check for invalid SYCL device triple values.
// Non-SPIR/SPIRV arch.
if (!T.isSPIROrSPIRV())
Expand Down Expand Up @@ -1392,12 +1396,6 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
}
Arch = Device->data();
UserTargetName = "amdgcn-amd-amdhsa";
} else if (Val == "native_cpu") {
const ToolChain *HostTC =
C.getSingleOffloadToolChain<Action::OFK_Host>();
llvm::Triple HostTriple = HostTC->getTriple();
SYCLTriples.insert(HostTriple.normalize());
continue;
}

llvm::Triple DeviceTriple(getSYCLDeviceTriple(UserTargetName));
Expand Down Expand Up @@ -5667,9 +5665,7 @@ class OffloadingActionBuilder final {
auto IsAMDGCN = TargetTriple.isAMDGCN();
auto IsSPIR = TargetTriple.isSPIROrSPIRV();
bool IsSpirvAOT = TargetTriple.isSPIRAOT();
const bool IsSYCLNativeCPU =
TC->getAuxTriple() &&
driver::isSYCLNativeCPU(TargetTriple, *TC->getAuxTriple());
bool IsSYCLNativeCPU = isSYCLNativeCPU(TargetTriple);
for (const auto &Input : ListIndex) {
if (TargetTriple.getSubArch() == llvm::Triple::SPIRSubArch_fpga &&
types::isFPGA(Input->getType())) {
Expand Down Expand Up @@ -6733,12 +6729,6 @@ class OffloadingActionBuilder final {
C.getDriver().getSYCLDeviceTriple("amdgcn-amd-amdhsa"),
ValidDevice->data());
UserTargetName = "amdgcn-amd-amdhsa";
} else if (Val == "native_cpu") {
const ToolChain *HostTC =
C.getSingleOffloadToolChain<Action::OFK_Host>();
llvm::Triple TT = HostTC->getTriple();
SYCLTripleList.push_back(TT);
continue;
}

llvm::Triple TT(
Expand Down Expand Up @@ -7277,10 +7267,6 @@ class OffloadingActionBuilder final {
/// Offload deps output is then forwarded to active device action builders so
/// they can add it to the device linker inputs.
void addDeviceLinkDependenciesFromHost(ActionList &LinkerInputs) {
if (isSYCLNativeCPU(C.getArgs())) {
// SYCL Native CPU doesn't need deps from clang-offload-deps.
return;
}
// Link image for reading dependencies from it.
auto *LA = C.MakeAction<LinkJobAction>(LinkerInputs,
types::TY_Host_Dependencies_Image);
Expand Down Expand Up @@ -9684,9 +9670,7 @@ InputInfoList Driver::BuildJobsForActionNoCache(
Action::OffloadKind DependentOffloadKind;
if (UI.DependentOffloadKind == Action::OFK_SYCL &&
TargetDeviceOffloadKind == Action::OFK_None &&
!(isSYCLNativeCPU(Args) &&
isSYCLNativeCPU(C.getDefaultToolChain().getTriple(),
TC->getTriple()) &&
!(isSYCLNativeCPU(C.getDefaultToolChain().getTriple()) &&
UA->getDependentActionsInfo().size() > 1))
DependentOffloadKind = Action::OFK_Host;
else
Expand Down Expand Up @@ -10581,9 +10565,9 @@ const ToolChain &Driver::getOffloadToolChain(
*HostTC, Args, Kind);
break;
default:
if (Kind == Action::OFK_SYCL && isSYCLNativeCPU(Args))
TC = std::make_unique<toolchains::SYCLToolChain>(*this, Target,
*HostTC, Args);
if (Kind == Action::OFK_SYCL && isSYCLNativeCPU(Target))
TC = std::make_unique<toolchains::SYCLToolChain>(*this, Target, *HostTC,
Args);
break;
}
}
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Driver/OffloadBundler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ bool OffloadTargetInfo::isOffloadKindCompatible(
}

bool OffloadTargetInfo::isTripleValid() const {
return !Triple.str().empty() && Triple.getArch() != Triple::UnknownArch;
return !Triple.str().empty() && (Triple.getArch() != Triple::UnknownArch ||
Triple.str() == "native_cpu---");
}

bool OffloadTargetInfo::operator==(const OffloadTargetInfo &Target) const {
Expand Down
Loading