llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-webassembly

Author: Aiden Grossman (boomanaiden154)

<details>
<summary>Changes</summary>

Move WebAssemblyCoalesceFeaturesAndStripAtomics to a separate file.
Having a pass implemented directly in the TargetMachine file is a bit
weird.


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


4 Files Affected:

- (modified) llvm/lib/Target/WebAssembly/CMakeLists.txt (+1) 
- (modified) llvm/lib/Target/WebAssembly/WebAssembly.h (+3) 
- (added) 
llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp 
(+195) 
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp (+2-169) 


``````````diff
diff --git a/llvm/lib/Target/WebAssembly/CMakeLists.txt 
b/llvm/lib/Target/WebAssembly/CMakeLists.txt
index 980250198ff24..1a73567f535bb 100644
--- a/llvm/lib/Target/WebAssembly/CMakeLists.txt
+++ b/llvm/lib/Target/WebAssembly/CMakeLists.txt
@@ -36,6 +36,7 @@ add_llvm_target(WebAssemblyCodeGen
   WebAssemblyCFGStackify.cpp
   WebAssemblyCleanCodeAfterTrap.cpp
   WebAssemblyCFGSort.cpp
+  WebAssemblyCoalesceFeaturesAndStripAtomics.cpp
   WebAssemblyCodeGenPassBuilder.cpp
   WebAssemblyDebugFixup.cpp
   WebAssemblyDebugValueManager.cpp
diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.h 
b/llvm/lib/Target/WebAssembly/WebAssembly.h
index 933062c86c8eb..6f84ff8adb4c0 100644
--- a/llvm/lib/Target/WebAssembly/WebAssembly.h
+++ b/llvm/lib/Target/WebAssembly/WebAssembly.h
@@ -85,6 +85,8 @@ class WebAssemblyReduceToAnyAllTruePass
 
 FunctionPass *
 createWebAssemblyReduceToAnyAllTrueLegacyPass(WebAssemblyTargetMachine &TM);
+ModulePass *
+createWebAssemblyCoalesceFeaturesAndStripAtomics(WebAssemblyTargetMachine &TM);
 
 // GlobalISel
 InstructionSelector *
@@ -160,6 +162,7 @@ void initializeWebAssemblyRegNumberingPass(PassRegistry &);
 void initializeWebAssemblyRegStackifyPass(PassRegistry &);
 void initializeWebAssemblyReplacePhysRegsPass(PassRegistry &);
 void initializeWebAssemblySetP2AlignOperandsPass(PassRegistry &);
+void initializeWebAssemblyCoalesceFeaturesAndStripAtomicsPass(PassRegistry &);
 
 namespace WebAssembly {
 enum TargetIndex {
diff --git 
a/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp
new file mode 100644
index 0000000000000..99127117f2615
--- /dev/null
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp
@@ -0,0 +1,195 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "WebAssembly.h"
+#include "WebAssemblyTargetMachine.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/Scalar/LowerAtomicPass.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "wasm-coalesce-features-and-strip-atomics"
+
+namespace {
+class WebAssemblyCoalesceFeaturesAndStripAtomics final : public ModulePass {
+  // Take the union of all features used in the module and use it for each
+  // function individually, since having multiple feature sets in one module
+  // currently does not make sense for WebAssembly. If atomics are not enabled,
+  // also strip atomic operations and thread local storage.
+  WebAssemblyTargetMachine *WasmTM;
+
+public:
+  static char ID;
+
+  WebAssemblyCoalesceFeaturesAndStripAtomics(WebAssemblyTargetMachine *WasmTM)
+      : ModulePass(ID), WasmTM(WasmTM) {}
+
+  bool runOnModule(Module &M) override {
+    auto [Features, FeatureStr] = coalesceFeatures(M);
+
+    WasmTM->setTargetFeatureString(FeatureStr);
+    for (auto &F : M)
+      replaceFeatures(F, FeatureStr);
+
+    bool StrippedAtomics = false;
+    bool StrippedTLS = false;
+
+    // In cooperative threading mode, thread locals are meaningful even without
+    // atomics.
+    const WebAssemblySubtarget *ST = WasmTM->getSubtargetImpl();
+    bool CooperativeThreading = ST->hasCooperativeMultithreading();
+
+    if (!Features[WebAssembly::FeatureAtomics]) {
+      StrippedAtomics = stripAtomics(M);
+      if (!CooperativeThreading)
+        StrippedTLS = stripThreadLocals(M);
+    }
+    if (!Features[WebAssembly::FeatureBulkMemory] && !StrippedTLS) {
+      StrippedTLS = stripThreadLocals(M);
+    }
+
+    if (StrippedAtomics && !StrippedTLS && !CooperativeThreading)
+      stripThreadLocals(M);
+    else if (StrippedTLS && !StrippedAtomics)
+      stripAtomics(M);
+
+    recordFeatures(M, ST, Features, StrippedAtomics || StrippedTLS);
+
+    // Conservatively assume we have made some change
+    return true;
+  }
+
+private:
+  std::pair<FeatureBitset, std::string> coalesceFeatures(const Module &M) {
+    // Union the features of all defined functions. Start with an empty set, so
+    // that if a feature is disabled in every function, we'll compute it as
+    // disabled. If any function lacks a target-features attribute, it'll
+    // default to the target CPU from the `TargetMachine`.
+    FeatureBitset Features;
+    // We need any MCSubtargetInfo to access WebAssemblyFeatureKV.
+    const WebAssemblySubtarget *AnyST = nullptr;
+    for (auto &F : M) {
+      if (F.isDeclaration())
+        continue;
+
+      AnyST = WasmTM->getSubtargetImpl(F);
+      Features |= AnyST->getFeatureBits();
+    }
+
+    // If we have no defined functions, use the target CPU from the
+    // `TargetMachine`.
+    if (!AnyST) {
+      AnyST = WasmTM->getSubtargetImpl(
+          std::string(WasmTM->getTargetCPU()),
+          std::string(WasmTM->getTargetFeatureString()));
+      Features = AnyST->getFeatureBits();
+    }
+
+    return {Features, getFeatureString(AnyST, Features)};
+  }
+
+  static std::string getFeatureString(const WebAssemblySubtarget *ST,
+                                      const FeatureBitset &Features) {
+    std::string Ret;
+    for (const SubtargetFeatureKV &KV : ST->getAllProcessorFeatures()) {
+      if (Features[KV.Value])
+        Ret += (StringRef("+") + KV.key() + ",").str();
+      else
+        Ret += (StringRef("-") + KV.key() + ",").str();
+    }
+    // remove trailing ','
+    Ret.pop_back();
+    return Ret;
+  }
+
+  void replaceFeatures(Function &F, const std::string &Features) {
+    F.removeFnAttr("target-features");
+    F.removeFnAttr("target-cpu");
+    F.addFnAttr("target-features", Features);
+  }
+
+  bool stripAtomics(Module &M) {
+    // Detect whether any atomics will be lowered, since there is no way to 
tell
+    // whether the LowerAtomic pass lowers e.g. stores.
+    bool Stripped = false;
+    for (auto &F : M) {
+      for (auto &B : F) {
+        for (auto &I : B) {
+          if (I.isAtomic()) {
+            Stripped = true;
+            goto done;
+          }
+        }
+      }
+    }
+
+  done:
+    if (!Stripped)
+      return false;
+
+    LowerAtomicPass Lowerer;
+    FunctionAnalysisManager FAM;
+    for (auto &F : M)
+      Lowerer.run(F, FAM);
+
+    return true;
+  }
+
+  bool stripThreadLocals(Module &M) {
+    bool Stripped = false;
+    for (auto &GV : M.globals()) {
+      if (GV.isThreadLocal()) {
+        // replace `@llvm.threadlocal.address.pX(GV)` with `GV`.
+        for (Use &U : make_early_inc_range(GV.uses())) {
+          if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U.getUser())) {
+            if (II->getIntrinsicID() == Intrinsic::threadlocal_address &&
+                II->getArgOperand(0) == &GV) {
+              II->replaceAllUsesWith(&GV);
+              II->eraseFromParent();
+            }
+          }
+        }
+
+        Stripped = true;
+        GV.setThreadLocal(false);
+      }
+    }
+    return Stripped;
+  }
+
+  void recordFeatures(Module &M, const WebAssemblySubtarget *ST,
+                      const FeatureBitset &Features, bool Stripped) {
+    for (const SubtargetFeatureKV &KV : ST->getAllProcessorFeatures()) {
+      if (Features[KV.Value]) {
+        // Mark features as used
+        std::string MDKey = (StringRef("wasm-feature-") + KV.key()).str();
+        M.addModuleFlag(Module::ModFlagBehavior::Error, MDKey,
+                        wasm::WASM_FEATURE_PREFIX_USED);
+      }
+    }
+    // Code compiled without atomics or bulk-memory may have had its atomics or
+    // thread-local data lowered to nonatomic operations or non-thread-local
+    // data. In that case, we mark the pseudo-feature "shared-mem" as 
disallowed
+    // to tell the linker that it would be unsafe to allow this code to be used
+    // in a module with shared memory.
+    if (Stripped) {
+      M.addModuleFlag(Module::ModFlagBehavior::Error, 
"wasm-feature-shared-mem",
+                      wasm::WASM_FEATURE_PREFIX_DISALLOWED);
+    }
+  }
+};
+} // namespace
+
+char WebAssemblyCoalesceFeaturesAndStripAtomics::ID = 0;
+INITIALIZE_PASS(WebAssemblyCoalesceFeaturesAndStripAtomics, DEBUG_TYPE,
+                "Coalesce features and strip atomics", true, false)
+
+ModulePass *llvm::createWebAssemblyCoalesceFeaturesAndStripAtomics(
+    WebAssemblyTargetMachine &TM) {
+  return new WebAssemblyCoalesceFeaturesAndStripAtomics(&TM);
+}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index cdea4298aed20..d5b51c4233afb 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -255,174 +255,6 @@ WebAssemblyTargetMachine::getSubtargetImpl(const Function 
&F) const {
 
 namespace {
 
-class CoalesceFeaturesAndStripAtomics final : public ModulePass {
-  // Take the union of all features used in the module and use it for each
-  // function individually, since having multiple feature sets in one module
-  // currently does not make sense for WebAssembly. If atomics are not enabled,
-  // also strip atomic operations and thread local storage.
-  static char ID;
-  WebAssemblyTargetMachine *WasmTM;
-
-public:
-  CoalesceFeaturesAndStripAtomics(WebAssemblyTargetMachine *WasmTM)
-      : ModulePass(ID), WasmTM(WasmTM) {}
-
-  bool runOnModule(Module &M) override {
-    auto [Features, FeatureStr] = coalesceFeatures(M);
-
-    WasmTM->setTargetFeatureString(FeatureStr);
-    for (auto &F : M)
-      replaceFeatures(F, FeatureStr);
-
-    bool StrippedAtomics = false;
-    bool StrippedTLS = false;
-
-    // In cooperative threading mode, thread locals are meaningful even without
-    // atomics.
-    const WebAssemblySubtarget *ST = WasmTM->getSubtargetImpl();
-    bool CooperativeThreading = ST->hasCooperativeMultithreading();
-
-    if (!Features[WebAssembly::FeatureAtomics]) {
-      StrippedAtomics = stripAtomics(M);
-      if (!CooperativeThreading)
-        StrippedTLS = stripThreadLocals(M);
-    }
-    if (!Features[WebAssembly::FeatureBulkMemory] && !StrippedTLS) {
-      StrippedTLS = stripThreadLocals(M);
-    }
-
-    if (StrippedAtomics && !StrippedTLS && !CooperativeThreading)
-      stripThreadLocals(M);
-    else if (StrippedTLS && !StrippedAtomics)
-      stripAtomics(M);
-
-    recordFeatures(M, ST, Features, StrippedAtomics || StrippedTLS);
-
-    // Conservatively assume we have made some change
-    return true;
-  }
-
-private:
-  std::pair<FeatureBitset, std::string> coalesceFeatures(const Module &M) {
-    // Union the features of all defined functions. Start with an empty set, so
-    // that if a feature is disabled in every function, we'll compute it as
-    // disabled. If any function lacks a target-features attribute, it'll
-    // default to the target CPU from the `TargetMachine`.
-    FeatureBitset Features;
-    // We need any MCSubtargetInfo to access WebAssemblyFeatureKV.
-    const WebAssemblySubtarget *AnyST = nullptr;
-    for (auto &F : M) {
-      if (F.isDeclaration())
-        continue;
-
-      AnyST = WasmTM->getSubtargetImpl(F);
-      Features |= AnyST->getFeatureBits();
-    }
-
-    // If we have no defined functions, use the target CPU from the
-    // `TargetMachine`.
-    if (!AnyST) {
-      AnyST = WasmTM->getSubtargetImpl(
-          std::string(WasmTM->getTargetCPU()),
-          std::string(WasmTM->getTargetFeatureString()));
-      Features = AnyST->getFeatureBits();
-    }
-
-    return {Features, getFeatureString(AnyST, Features)};
-  }
-
-  static std::string getFeatureString(const WebAssemblySubtarget *ST,
-                                      const FeatureBitset &Features) {
-    std::string Ret;
-    for (const SubtargetFeatureKV &KV : ST->getAllProcessorFeatures()) {
-      if (Features[KV.Value])
-        Ret += (StringRef("+") + KV.key() + ",").str();
-      else
-        Ret += (StringRef("-") + KV.key() + ",").str();
-    }
-    // remove trailing ','
-    Ret.pop_back();
-    return Ret;
-  }
-
-  void replaceFeatures(Function &F, const std::string &Features) {
-    F.removeFnAttr("target-features");
-    F.removeFnAttr("target-cpu");
-    F.addFnAttr("target-features", Features);
-  }
-
-  bool stripAtomics(Module &M) {
-    // Detect whether any atomics will be lowered, since there is no way to 
tell
-    // whether the LowerAtomic pass lowers e.g. stores.
-    bool Stripped = false;
-    for (auto &F : M) {
-      for (auto &B : F) {
-        for (auto &I : B) {
-          if (I.isAtomic()) {
-            Stripped = true;
-            goto done;
-          }
-        }
-      }
-    }
-
-  done:
-    if (!Stripped)
-      return false;
-
-    LowerAtomicPass Lowerer;
-    FunctionAnalysisManager FAM;
-    for (auto &F : M)
-      Lowerer.run(F, FAM);
-
-    return true;
-  }
-
-  bool stripThreadLocals(Module &M) {
-    bool Stripped = false;
-    for (auto &GV : M.globals()) {
-      if (GV.isThreadLocal()) {
-        // replace `@llvm.threadlocal.address.pX(GV)` with `GV`.
-        for (Use &U : make_early_inc_range(GV.uses())) {
-          if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U.getUser())) {
-            if (II->getIntrinsicID() == Intrinsic::threadlocal_address &&
-                II->getArgOperand(0) == &GV) {
-              II->replaceAllUsesWith(&GV);
-              II->eraseFromParent();
-            }
-          }
-        }
-
-        Stripped = true;
-        GV.setThreadLocal(false);
-      }
-    }
-    return Stripped;
-  }
-
-  void recordFeatures(Module &M, const WebAssemblySubtarget *ST,
-                      const FeatureBitset &Features, bool Stripped) {
-    for (const SubtargetFeatureKV &KV : ST->getAllProcessorFeatures()) {
-      if (Features[KV.Value]) {
-        // Mark features as used
-        std::string MDKey = (StringRef("wasm-feature-") + KV.key()).str();
-        M.addModuleFlag(Module::ModFlagBehavior::Error, MDKey,
-                        wasm::WASM_FEATURE_PREFIX_USED);
-      }
-    }
-    // Code compiled without atomics or bulk-memory may have had its atomics or
-    // thread-local data lowered to nonatomic operations or non-thread-local
-    // data. In that case, we mark the pseudo-feature "shared-mem" as 
disallowed
-    // to tell the linker that it would be unsafe to allow this code to be used
-    // in a module with shared memory.
-    if (Stripped) {
-      M.addModuleFlag(Module::ModFlagBehavior::Error, 
"wasm-feature-shared-mem",
-                      wasm::WASM_FEATURE_PREFIX_DISALLOWED);
-    }
-  }
-};
-char CoalesceFeaturesAndStripAtomics::ID = 0;
-
 /// WebAssembly Code Generator Pass Configuration Options.
 class WebAssemblyPassConfig final : public TargetPassConfig {
 public:
@@ -535,7 +367,8 @@ void WebAssemblyPassConfig::addISelPrepare() {
   // loads and stores are promoted to local.gets/local.sets.
   addPass(createWebAssemblyRefTypeMem2LocalLegacyPass());
   // Lower atomics and TLS if necessary
-  addPass(new CoalesceFeaturesAndStripAtomics(&getWebAssemblyTargetMachine()));
+  addPass(createWebAssemblyCoalesceFeaturesAndStripAtomics(
+      getWebAssemblyTargetMachine()));
 
   // This is a no-op if atomics are not used in the module
   addPass(createAtomicExpandLegacyPass());

``````````

</details>


https://github.com/llvm/llvm-project/pull/209046
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to