[WebAssembly] Disable register coalescing at -O1
authorHeejin Ahn <aheejin@gmail.com>
Wed, 16 Nov 2022 01:30:07 +0000 (17:30 -0800)
committerHeejin Ahn <aheejin@gmail.com>
Mon, 21 Nov 2022 22:16:04 +0000 (14:16 -0800)
This disables `RegisterCoalescer` pass at -O1, which currently runs for
all levels except for -O0, as a part of common optimization pipeline.

`RegisterCoalescer` pass degrades Wasm debug info quality by a
significant margin. When I use `LiveDebugValue` analysis, disabling this
increases the average PC ranges covered by 15% on Emscripten core
benchmarks (52% -> 66.8%). (Our code is currently not using
`LiveDebugValues` analysis at the moment, and the experiment was done on
a local setting that enabled it. I'm planning to upstream it soon.)

In Emscripten core benchmarks, disabling this at -O1 causes +4.5% in
code size and +1% in the number of locals. The number of globals stays
the same. I believe this tradeoff is acceptable given that -O1 is not
usually used in production builds and is often used for debugging when
the application size is very large.

The plan is to investigate and fix what's causing the degradation in
that pass, but for now disabling it seems like a low-hanging quick fix.

Reviewed By: dschuff

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

llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
llvm/test/CodeGen/WebAssembly/regcoalesce-disable.ll [new file with mode: 0644]

index 9e4a303..2200586 100644 (file)
@@ -323,6 +323,7 @@ public:
   void addIRPasses() override;
   void addISelPrepare() override;
   bool addInstSelector() override;
+  void addOptimizedRegAlloc() override;
   void addPostRegAlloc() override;
   bool addGCPasses() override { return false; }
   void addPreEmitPass() override;
@@ -480,6 +481,19 @@ bool WebAssemblyPassConfig::addInstSelector() {
   return false;
 }
 
+void WebAssemblyPassConfig::addOptimizedRegAlloc() {
+  // Currently RegisterCoalesce degrades wasm debug info quality by a
+  // significant margin. As a quick fix, disable this for -O1, which is often
+  // used for debugging large applications. Disabling this increases code size
+  // of Emscripten core benchmarks by ~5%, which is acceptable for -O1, which is
+  // usually not used for production builds.
+  // TODO Investigate why RegisterCoalesce degrades debug info quality and fix
+  // it properly
+  if (getOptLevel() == CodeGenOpt::Less)
+    disablePass(&RegisterCoalescerID);
+  TargetPassConfig::addOptimizedRegAlloc();
+}
+
 void WebAssemblyPassConfig::addPostRegAlloc() {
   // TODO: The following CodeGen passes don't currently support code containing
   // virtual registers. Consider removing their restrictions and re-enabling
diff --git a/llvm/test/CodeGen/WebAssembly/regcoalesce-disable.ll b/llvm/test/CodeGen/WebAssembly/regcoalesce-disable.ll
new file mode 100644 (file)
index 0000000..82d99d2
--- /dev/null
@@ -0,0 +1,12 @@
+; RUN: llc < %s -O1 --debug-pass=Structure 2>&1 | FileCheck %s --check-prefix=O1
+; RUN: llc < %s -O2 --debug-pass=Structure 2>&1 | FileCheck %s --check-prefix=O2
+
+; Test if RegisterCoalesce pass is disabled in -O1.
+
+; O1-NOT: Simple Register Coalescing
+; O2: Simple Register Coalescing
+target triple = "wasm32-unknown-unknown"
+
+define void @test() {
+  ret void
+}