Skip to content
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

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jmmartinez
Copy link
Contributor

Differential Revision: https://reviews.llvm.org/D159257

@jmmartinez jmmartinez added the clang Clang issues not falling into any other category label Sep 8, 2023
@jmmartinez jmmartinez requested a review from arsenm September 8, 2023 10:04
@jmmartinez jmmartinez self-assigned this Sep 8, 2023
@jmmartinez jmmartinez requested a review from a team as a code owner September 8, 2023 10:04
@llvmbot
Copy link
Member

llvmbot commented Sep 11, 2023

@llvm/pr-subscribers-backend-amdgpu

Changes

Differential Revision: https://reviews.llvm.org/D159257

Full diff: https://github.com/llvm/llvm-project/pull/65737.diff

4 Files Affected:

  • (modified) clang/lib/CodeGen/CGCall.cpp (+20)
  • (modified) clang/lib/CodeGen/CGCall.h (+5)
  • (modified) clang/lib/CodeGen/CodeGenAction.cpp (+3-1)
  • (modified) clang/test/CodeGen/link-builtin-bitcode.c (+1-3)
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 37de2800fd69c02..ace20b0b3745641 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..bca664479fff13d 100644
--- a/clang/lib/CodeGen/CGCall.h
+++ b/clang/lib/CodeGen/CGCall.h
@@ -375,6 +375,11 @@ class ReturnValueSlot {
   bool isExternallyDestructed() const { return IsExternallyDestructed; }
 };
 
+/// If \p F "target-features" are incompatible with the \p TargetOpts features,
+/// it is correct to drop the function. \return true if \p F is dropped
+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..2fcf8c6c4a64dfb 100644
--- a/clang/test/CodeGen/link-builtin-bitcode.c
+++ b/clang/test/CodeGen/link-builtin-bitcode.c
@@ -40,10 +40,8 @@ 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-NOT: @attr_incompatible
 
 // 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" }

@@ -375,6 +375,11 @@ class ReturnValueSlot {
bool isExternallyDestructed() const { return IsExternallyDestructed; }
};

/// If \p F "target-features" are incompatible with the \p TargetOpts features,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment needs more elaboration on what this means and what this is for.

Should think about dropping the incompatible functions pass after this too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the comment but I've realized another problem: since it's dropping the functions in the builtin module, the user's module will still have the declaration.

I've updated the test to show this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AMDGPU clang:codegen clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants