[clang] [Clang] Drop functions with incompatible target-features when using mlink-builtin-bitcode (PR #65737)

Juan Manuel Martinez CaamaƱo via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 13 06:51:40 PDT 2023


https://github.com/jmmartinez updated https://github.com/llvm/llvm-project/pull/65737:

>From 112dd3c57c28b467463ef39dfbc33560b652b1c1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20MARTINEZ=20CAAMA=C3=91O?= <juamarti at amd.com>
Date: Fri, 8 Sep 2023 11:25:44 +0200
Subject: [PATCH] [Clang] Drop functions with incompatible target-features when
 using mlink-builtin-bitcode

---
 clang/lib/CodeGen/CGCall.cpp              | 20 ++++++++++++++++++++
 clang/lib/CodeGen/CGCall.h                | 12 ++++++++++++
 clang/lib/CodeGen/CodeGenAction.cpp       |  4 +++-
 clang/test/CodeGen/link-builtin-bitcode.c |  8 +++-----
 4 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index e15a4634b1d041b..8ef8b2fbb2c619a 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2112,6 +2112,26 @@ void CodeGen::mergeDefaultFunctionDefinitionAttributes(
   F.addFnAttrs(FuncAttrs);
 }
 
+bool CodeGen::dropFunctionWithIncompatibleAttributes(
+    llvm::Function &F, const TargetOptions &TargetOpts) {
+  auto FFeatures = F.getFnAttribute("target-features");
+  if (!FFeatures.isValid())
+    return false;
+
+  const auto &TFeatures = TargetOpts.FeatureMap;
+  for (StringRef Feature : llvm::split(FFeatures.getValueAsString(), ',')) {
+    bool EnabledForFunc = Feature[0] == '+';
+    StringRef Name = Feature.substr(1);
+    auto TEntry = TFeatures.find(Name);
+    if (TEntry != TFeatures.end() && TEntry->second != EnabledForFunc) {
+      F.replaceAllUsesWith(llvm::ConstantPointerNull::get(F.getType()));
+      F.eraseFromParent();
+      return true;
+    }
+  }
+  return false;
+}
+
 void CodeGenModule::getTrivialDefaultFunctionAttributes(
     StringRef Name, bool HasOptnone, bool AttrOnCallSite,
     llvm::AttrBuilder &FuncAttrs) {
diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h
index aee86a3242fd3f4..ba57c0333655f4b 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -375,6 +375,18 @@ class ReturnValueSlot {
   bool isExternallyDestructed() const { return IsExternallyDestructed; }
 };
 
+/// If a "target-feature" from \p F is enabled/disabled but the opposite value
+/// is set in \p TargetOpts features, then discard \p \F. This function is
+/// applied over incoming function when linking builtins with
+/// -mlink-builtin-bitcode
+///
+/// This is used when linking CUDA's libdevice or AMD's device_libs, where
+/// precompiled bitcode is linked into the user's module.
+/// Some of the functions being linked may use some features available only on
+/// some GPUs
+bool dropFunctionWithIncompatibleAttributes(llvm::Function &F,
+                                            const TargetOptions &TargetOpts);
+
 /// Adds attributes to \p F according to our \p CodeGenOpts and \p LangOpts, as
 /// though we had emitted it ourselves. We remove any attributes on F that
 /// conflict with the attributes we add here.
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index a3b72381d73fc54..6f8e545a3a50816 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -267,11 +267,13 @@ namespace clang {
       for (auto &LM : LinkModules) {
         assert(LM.Module && "LinkModule does not actually have a module");
         if (LM.PropagateAttrs)
-          for (Function &F : *LM.Module) {
+          for (Function &F : llvm::make_early_inc_range(*LM.Module)) {
             // Skip intrinsics. Keep consistent with how intrinsics are created
             // in LLVM IR.
             if (F.isIntrinsic())
               continue;
+            if (CodeGen::dropFunctionWithIncompatibleAttributes(F, TargetOpts))
+              continue;
             CodeGen::mergeDefaultFunctionDefinitionAttributes(
                 F, CodeGenOpts, LangOpts, TargetOpts, LM.Internalize);
           }
diff --git a/clang/test/CodeGen/link-builtin-bitcode.c b/clang/test/CodeGen/link-builtin-bitcode.c
index fe60a9746f1c85f..48eef5b19a06a77 100644
--- a/clang/test/CodeGen/link-builtin-bitcode.c
+++ b/clang/test/CodeGen/link-builtin-bitcode.c
@@ -30,7 +30,9 @@ int bar() { return no_attr() + attr_in_target() + attr_not_in_target() + attr_in
 
 // CHECK-LABEL: define dso_local i32 @bar
 // CHECK-SAME: () #[[ATTR_BAR:[0-9]+]] {
-//
+
+// CHECK: declare i32 @attr_incompatible
+
 // CHECK-LABEL: define internal i32 @no_attr
 // CHECK-SAME: () #[[ATTR_COMPATIBLE:[0-9]+]] {
 
@@ -40,10 +42,6 @@ int bar() { return no_attr() + attr_in_target() + attr_not_in_target() + attr_in
 // CHECK-LABEL: define internal i32 @attr_not_in_target
 // CHECK-SAME: () #[[ATTR_EXTEND:[0-9]+]] {
 
-// CHECK-LABEL: @attr_incompatible
-// CHECK-SAME: () #[[ATTR_INCOMPATIBLE:[0-9]+]] {
-
 // CHECK: attributes #[[ATTR_BAR]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="gfx90a" "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" }
 // CHECK: attributes #[[ATTR_COMPATIBLE]] = { convergent noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="gfx90a" "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gws,+image-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" }
 // CHECK: attributes #[[ATTR_EXTEND]] = { convergent noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="gfx90a" "target-features"="+extended-image-insts,+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+gfx8-insts,+gfx9-insts,+gfx90a-insts,+gws,+image-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" }
-// CHECK: attributes #[[ATTR_INCOMPATIBLE]] = { convergent noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="gfx90a" "target-features"="-gfx9-insts,+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot1-insts,+dot10-insts,+dot2-insts,+dot3-insts,+dot4-insts,+dot5-insts,+dot6-insts,+dot7-insts,+dpp,+gfx8-insts,+gfx90a-insts,+gws,+image-insts,+mai-insts,+s-memrealtime,+s-memtime-inst,+wavefrontsize64" }



More information about the cfe-commits mailing list