[PATCH] D147397: [WebAssembly] Fix selection of global calls

Heejin Ahn via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 1 21:17:28 PDT 2023


aheejin created this revision.
aheejin added reviewers: tlively, RReverser, HerrCai0907.
Herald added subscribers: pmatos, asb, wingo, ecnelises, sunfish, hiraditya, jgravelle-google, sbc100, dschuff.
Herald added a project: All.
aheejin requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

When selecting calls, currently we unconditionally remove `Wrapper`s of
the call target. But we are supposed to do that only when the target is
a function, an external symbol (= library function), or an alias of a
function. Otherwise we end up directly calling globals that are not
functions.

Fixes https://github.com/llvm/llvm-project/issues/60003.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D147397

Files:
  llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
  llvm/test/CodeGen/WebAssembly/call.ll


Index: llvm/test/CodeGen/WebAssembly/call.ll
===================================================================
--- llvm/test/CodeGen/WebAssembly/call.ll
+++ llvm/test/CodeGen/WebAssembly/call.ll
@@ -1,5 +1,5 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=+sign-ext,+simd128 | FileCheck --check-prefixes=CHECK,NO-TAIL %s
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 -mattr=+sign-ext,+simd128 | FileCheck --check-prefixes=CHECK,NO-TAIL %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=+sign-ext,+simd128 | FileCheck --check-prefixes=CHECK,SLOW,NO-TAIL %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 -mattr=+sign-ext,+simd128 | FileCheck --check-prefixes=CHECK,FAST,NO-TAIL %s
 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=+sign-ext,+simd128,+tail-call | FileCheck --check-prefixes=CHECK,SLOW-TAIL %s
 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers -fast-isel -fast-isel-abort=1 -mattr=+sign-ext,+simd128,+tail-call | FileCheck --check-prefixes=CHECK,FAST-TAIL %s
 
@@ -251,6 +251,46 @@
   ret void
 }
 
+; Calling non-functional globals should be lowered to call_indirects.
+; CHECK-LABEL: call_indirect_int:
+; CHECK:      i32.const  $push[[L0:[0-9]+]]=, global_i8
+; CHECK-NEXT: call_indirect  $pop[[L0]]
+; CHECK-NEXT: i32.const  $push[[L1:[0-9]+]]=, global_i32
+; CHECK-NEXT: call_indirect  $pop[[L1]]
+ at global_i8 = global i8 0
+ at global_i32 = global i32 0
+define void @call_indirect_int() {
+  call void @global_i8()
+  call void @global_i32()
+  ret void
+}
+
+; Calling aliases of non-functional globals should be lowered to call_indirects.
+; CHECK-LABEL: call_indirect_int_alias:
+; CHECK:      i32.const  $push[[L0:[0-9]+]]=, global_i8_alias
+; CHECK-NEXT: call_indirect  $pop[[L0]]
+; CHECK-NEXT: i32.const  $push[[L1:[0-9]+]]=, global_i32_alias
+; CHECK-NEXT: call_indirect  $pop[[L1]]
+ at global_i8_alias = alias i8, ptr @global_i8
+ at global_i32_alias = alias i32, ptr @global_i32
+define void @call_indirect_int_alias() {
+  call void @global_i8_alias()
+  call void @global_i32_alias()
+  ret void
+}
+
+; Ideally calling aliases of functions should be lowered to direct calls. We
+; support this in the normal (=slow) isel.
+; CHECK-LABEL: call_func_alias:
+; SLOW:      call  func_alias
+; FAST:      i32.const  $push[[L0:[0-9]+]]=, func_alias
+; FAST-NEXT: call_indirect  $pop[[L0]]
+ at func_alias = alias void (), ptr @call_void_nullary
+define void @call_func_alias() {
+  call void @func_alias()
+  ret void
+}
+
 ; TODO: test the following:
 ;  - More argument combinations.
 ;  - Tail call.
Index: llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
===================================================================
--- llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -249,8 +249,21 @@
     SmallVector<SDValue, 16> Ops;
     for (size_t i = 1; i < Node->getNumOperands(); ++i) {
       SDValue Op = Node->getOperand(i);
-      if (i == 1 && Op->getOpcode() == WebAssemblyISD::Wrapper)
-        Op = Op->getOperand(0);
+      // Remove the wrapper when the call target is a function or an external
+      // symbol (which will be lowered to a library function), or an alias of
+      // it. If the target is not a function/external symbol, not removing the
+      // wrapper will cause it to be loaded with a CONST instruction and be
+      // called with a call_indirect later, which is the correct behavior.
+      if (i == 1 && Op->getOpcode() == WebAssemblyISD::Wrapper) {
+        SDValue NewOp = Op->getOperand(0);
+        if (auto *GlobalOp = dyn_cast<GlobalAddressSDNode>(NewOp.getNode())) {
+          if (isa<Function>(
+                  GlobalOp->getGlobal()->stripPointerCastsAndAliases()))
+            Op = NewOp;
+        } else if (isa<ExternalSymbolSDNode>(NewOp.getNode())) {
+          Op = NewOp;
+        }
+      }
       Ops.push_back(Op);
     }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D147397.510294.patch
Type: text/x-patch
Size: 4241 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230402/7724e3a9/attachment.bin>


More information about the llvm-commits mailing list