[llvm] r373967 - [WebAssembly] Add memory intrinsics handling to mayThrow()

Heejin Ahn via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 7 14:14:45 PDT 2019


Author: aheejin
Date: Mon Oct  7 14:14:45 2019
New Revision: 373967

URL: http://llvm.org/viewvc/llvm-project?rev=373967&view=rev
Log:
[WebAssembly] Add memory intrinsics handling to mayThrow()

Summary:
Previously, `WebAssembly::mayThrow()` assumed all inputs are global
addresses. But when intrinsics, such as `memcpy`, `memmove`, or `memset`
are lowered to external symbols in instruction selection and later
emitted as library calls. And these functions don't throw.

This patch adds handling to those memory intrinsics to `mayThrow`
function. But while most of libcalls don't throw, we can't guarantee all
of them don't throw, so currently we conservatively return true for all
other external symbols.

I think a better way to solve this problem is to embed 'nounwind' info
in `TargetLowering::CallLoweringInfo`, so that we can access the info
from the backend. This will also enable transferring 'nounwind'
properties of LLVM IR instructions. Currently we don't transfer that
info and we can only access properties of callee functions, if the
callees are within the module. Other targets don't need this info in the
backend because they do all the processing before isel, but it will help
us because that info will reduce code size increase in fixing unwind
destination mismatches in CFGStackify.

But for now we return false for these memory intrinsics and true for all
other libcalls conservatively.

Reviewers: dschuff

Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits

Tags: #llvm

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

Modified:
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
    llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.cpp?rev=373967&r1=373966&r2=373967&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyUtilities.cpp Mon Oct  7 14:14:45 2019
@@ -50,7 +50,21 @@ bool WebAssembly::mayThrow(const Machine
     return false;
 
   const MachineOperand &MO = MI.getOperand(getCalleeOpNo(MI.getOpcode()));
-  assert(MO.isGlobal());
+  assert(MO.isGlobal() || MO.isSymbol());
+
+  if (MO.isSymbol()) {
+    // Some intrinsics are lowered to calls to external symbols, which are then
+    // lowered to calls to library functions. Most of libcalls don't throw, but
+    // we only list some of them here now.
+    // TODO Consider adding 'nounwind' info in TargetLowering::CallLoweringInfo
+    // instead for more accurate info.
+    const char *Name = MO.getSymbolName();
+    if (strcmp(Name, "memcpy") == 0 || strcmp(Name, "memmove") == 0 ||
+        strcmp(Name, "memset") == 0)
+      return false;
+    return true;
+  }
+
   const auto *F = dyn_cast<Function>(MO.getGlobal());
   if (!F)
     return true;

Modified: llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll?rev=373967&r1=373966&r2=373967&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll (original)
+++ llvm/trunk/test/CodeGen/WebAssembly/cfg-stackify-eh.ll Mon Oct  7 14:14:45 2019
@@ -664,11 +664,51 @@ if.end:
   ret void
 }
 
+%class.Object = type { i8 }
+
+; Intrinsics like memcpy, memmove, and memset don't throw and are lowered into
+; calls to external symbols (not global addresses) in instruction selection,
+; which will be eventually lowered to library function calls.
+; Because this test runs with -wasm-disable-ehpad-sort, these library calls in
+; invoke.cont BB fall within try~end_try, but they shouldn't cause crashes or
+; unwinding destination mismatches in CFGStackify.
+
+; NOSORT-LABEL: test10
+; NOSORT: try
+; NOSORT:   call  foo
+; NOSORT:   i32.call {{.*}} memcpy
+; NOSORT:   i32.call {{.*}} memmove
+; NOSORT:   i32.call {{.*}} memset
+; NOSORT:   return
+; NOSORT: catch
+; NOSORT:   rethrow
+; NOSORT: end_try
+define void @test10(i8* %a, i8* %b) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
+entry:
+  %o = alloca %class.Object, align 1
+  invoke void @foo()
+          to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:                                      ; preds = %entry
+  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %b, i32 100, i1 false)
+  call void @llvm.memmove.p0i8.p0i8.i32(i8* %a, i8* %b, i32 100, i1 false)
+  call void @llvm.memset.p0i8.i32(i8* %a, i8 0, i32 100, i1 false)
+  %call = call %class.Object* @_ZN6ObjectD2Ev(%class.Object* %o) #1
+  ret void
+
+ehcleanup:                                        ; preds = %entry
+  %0 = cleanuppad within none []
+  %call2 = call %class.Object* @_ZN6ObjectD2Ev(%class.Object* %o) #1 [ "funclet"(token %0) ]
+  cleanupret from %0 unwind to caller
+}
+
 declare void @foo()
 declare void @bar()
 declare i32 @baz()
 ; Function Attrs: nounwind
 declare void @nothrow(i32) #0
+; Function Attrs: nounwind
+declare %class.Object* @_ZN6ObjectD2Ev(%class.Object* returned) #0
 declare i32 @__gxx_wasm_personality_v0(...)
 declare i8* @llvm.wasm.get.exception(token)
 declare i32 @llvm.wasm.get.ehselector(token)
@@ -678,5 +718,11 @@ declare i8* @__cxa_begin_catch(i8*)
 declare void @__cxa_end_catch()
 declare void @__clang_call_terminate(i8*)
 declare void @_ZSt9terminatev()
+; Function Attrs: nounwind
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i32, i1 immarg) #0
+; Function Attrs: nounwind
+declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1 immarg) #0
+; Function Attrs: nounwind
+declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1 immarg) #0
 
 attributes #0 = { nounwind }




More information about the llvm-commits mailing list