llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-webassembly

Author: Aiden Grossman (boomanaiden154)

<details>
<summary>Changes</summary>

Standard NewPM pass porting.


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


5 Files Affected:

- (modified) llvm/lib/Target/WebAssembly/WebAssembly.h (+16-3) 
- (modified) 
llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp 
(+155-138) 
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp 
(+2-1) 
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def (+2) 
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp (+1-1) 


``````````diff
diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.h 
b/llvm/lib/Target/WebAssembly/WebAssembly.h
index 6f84ff8adb4c0..c4820ce7b330a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssembly.h
+++ b/llvm/lib/Target/WebAssembly/WebAssembly.h
@@ -85,8 +85,20 @@ class WebAssemblyReduceToAnyAllTruePass
 
 FunctionPass *
 createWebAssemblyReduceToAnyAllTrueLegacyPass(WebAssemblyTargetMachine &TM);
-ModulePass *
-createWebAssemblyCoalesceFeaturesAndStripAtomics(WebAssemblyTargetMachine &TM);
+
+class WebAssemblyCoalesceFeaturesAndStripAtomicsPass
+    : public RequiredPassInfoMixin<
+          WebAssemblyCoalesceFeaturesAndStripAtomicsPass> {
+  WebAssemblyTargetMachine &TM;
+
+public:
+  WebAssemblyCoalesceFeaturesAndStripAtomicsPass(WebAssemblyTargetMachine &TM)
+      : TM(TM) {}
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
+};
+
+ModulePass *createWebAssemblyCoalesceFeaturesAndStripAtomicsLegacyPass(
+    WebAssemblyTargetMachine &TM);
 
 // GlobalISel
 InstructionSelector *
@@ -162,7 +174,8 @@ void initializeWebAssemblyRegNumberingPass(PassRegistry &);
 void initializeWebAssemblyRegStackifyPass(PassRegistry &);
 void initializeWebAssemblyReplacePhysRegsPass(PassRegistry &);
 void initializeWebAssemblySetP2AlignOperandsPass(PassRegistry &);
-void initializeWebAssemblyCoalesceFeaturesAndStripAtomicsPass(PassRegistry &);
+void initializeWebAssemblyCoalesceFeaturesAndStripAtomicsLegacyPass(
+    PassRegistry &);
 
 namespace WebAssembly {
 enum TargetIndex {
diff --git 
a/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp
index 89c3842241bf7..a040e531ee020 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp
@@ -8,8 +8,10 @@
 
 #include "WebAssembly.h"
 #include "WebAssemblyTargetMachine.h"
+#include "llvm/IR/Analysis.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
 #include "llvm/Pass.h"
 #include "llvm/Transforms/Scalar/LowerAtomicPass.h"
 
@@ -18,7 +20,8 @@ using namespace llvm;
 #define DEBUG_TYPE "wasm-coalesce-features-and-strip-atomics"
 
 namespace {
-class WebAssemblyCoalesceFeaturesAndStripAtomics final : public ModulePass {
+class WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy 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,
@@ -28,170 +31,184 @@ class WebAssemblyCoalesceFeaturesAndStripAtomics final : 
public ModulePass {
 public:
   static char ID;
 
-  WebAssemblyCoalesceFeaturesAndStripAtomics(WebAssemblyTargetMachine *WasmTM)
+  WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy(
+      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);
-    }
+  bool runOnModule(Module &M) override;
+};
+} // namespace
 
-    if (StrippedAtomics && !StrippedTLS && !CooperativeThreading)
-      stripThreadLocals(M);
-    else if (StrippedTLS && !StrippedAtomics)
-      stripAtomics(M);
+char WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy::ID = 0;
+INITIALIZE_PASS(WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy, DEBUG_TYPE,
+                "Coalesce features and strip atomics", true, false)
 
-    recordFeatures(M, ST, Features, StrippedAtomics || StrippedTLS);
+ModulePass *llvm::createWebAssemblyCoalesceFeaturesAndStripAtomicsLegacyPass(
+    WebAssemblyTargetMachine &TM) {
+  return new WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy(&TM);
+}
 
-    // Conservatively assume we have made some change
-    return true;
+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;
+}
 
-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::pair<FeatureBitset, std::string>
+coalesceFeatures(const Module &M, WebAssemblyTargetMachine *WasmTM) {
+  // 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();
   }
 
-  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;
+  // 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();
   }
 
-  void replaceFeatures(Function &F, const std::string &Features) {
-    F.removeFnAttr("target-features");
-    F.removeFnAttr("target-cpu");
-    F.addFnAttr("target-features", Features);
-  }
+  return {Features, getFeatureString(AnyST, 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;
-          }
+static void replaceFeatures(Function &F, const std::string &Features) {
+  F.removeFnAttr("target-features");
+  F.removeFnAttr("target-cpu");
+  F.addFnAttr("target-features", Features);
+}
+
+static 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;
+done:
+  if (!Stripped)
+    return false;
 
-    LowerAtomicPass Lowerer;
-    FunctionAnalysisManager FAM;
-    for (auto &F : M)
-      Lowerer.run(F, FAM);
+  LowerAtomicPass Lowerer;
+  FunctionAnalysisManager FAM;
+  for (auto &F : M)
+    Lowerer.run(F, FAM);
 
-    return true;
-  }
+  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();
-            }
+static 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);
       }
+
+      Stripped = true;
+      GV.setThreadLocal(false);
     }
-    return Stripped;
   }
+  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);
+static 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);
     }
   }
-};
-} // namespace
+  // 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 WebAssemblyCoalesceFeaturesAndStripAtomics::ID = 0;
-INITIALIZE_PASS(WebAssemblyCoalesceFeaturesAndStripAtomics, DEBUG_TYPE,
-                "Coalesce features and strip atomics", true, false)
+static bool coalesceFeaturesAndStripAtomics(Module &M,
+                                            WebAssemblyTargetMachine *WasmTM) {
+  auto [Features, FeatureStr] = coalesceFeatures(M, WasmTM);
 
-ModulePass *llvm::createWebAssemblyCoalesceFeaturesAndStripAtomics(
-    WebAssemblyTargetMachine &TM) {
-  return new WebAssemblyCoalesceFeaturesAndStripAtomics(&TM);
+  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;
+}
+
+bool WebAssemblyCoalesceFeaturesAndStripAtomicsLegacy::runOnModule(Module &M) {
+  return coalesceFeaturesAndStripAtomics(M, WasmTM);
+}
+
+PreservedAnalyses WebAssemblyCoalesceFeaturesAndStripAtomicsPass::run(
+    Module &M, ModuleAnalysisManager &MAM) {
+  return coalesceFeaturesAndStripAtomics(M, &TM) ? PreservedAnalyses::none()
+                                                 : PreservedAnalyses::all();
 }
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
index 48713ecacba0b..b5384b3e005c7 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
@@ -123,7 +123,8 @@ void WebAssemblyCodeGenPassBuilder::addISelPrepare(
   // loads and stores are promoted to local.gets/local.sets.
   addFunctionPass(WebAssemblyRefTypeMem2LocalPass(), PMW);
   // Lower atomics and TLS if necessary
-  // TODO(boomanaiden154): CoalesceFeaturesAndStripAtomics
+  flushFPMsToMPM(PMW);
+  addModulePass(WebAssemblyCoalesceFeaturesAndStripAtomicsPass(TM), PMW);
 
   // This is a no-op if atomics are not used in the module
   addFunctionPass(AtomicExpandPass(TM), PMW);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def 
b/llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def
index 6767f7a6a6b77..a6da272bf3ba7 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyPassRegistry.def
@@ -15,6 +15,8 @@
 #define MODULE_PASS(NAME, CREATE_PASS)
 #endif
 MODULE_PASS("wasm-add-missing-prototypes", 
WebAssemblyAddMissingPrototypesPass())
+MODULE_PASS("wasm-coalesce-features-and-strip-atomics",
+            WebAssemblyCoalesceFeaturesAndStripAtomicsPass(*this))
 MODULE_PASS("wasm-fix-function-bitcasts", WebAssemblyFixFunctionBitcastsPass())
 MODULE_PASS("wasm-lower-em-ehsjlj", WebAssemblyLowerEmscriptenEHSjLjPass())
 #undef MODULE_PASS
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index d5b51c4233afb..9d382451f5123 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -367,7 +367,7 @@ void WebAssemblyPassConfig::addISelPrepare() {
   // loads and stores are promoted to local.gets/local.sets.
   addPass(createWebAssemblyRefTypeMem2LocalLegacyPass());
   // Lower atomics and TLS if necessary
-  addPass(createWebAssemblyCoalesceFeaturesAndStripAtomics(
+  addPass(createWebAssemblyCoalesceFeaturesAndStripAtomicsLegacyPass(
       getWebAssemblyTargetMachine()));
 
   // This is a no-op if atomics are not used in the module

``````````

</details>


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

Reply via email to