[llvm] e849d99 - [WebAssembly] Use entry block only for initializations in EmSjLj

Heejin Ahn via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 25 15:47:20 PDT 2021


Author: Heejin Ahn
Date: 2021-08-25T15:46:57-07:00
New Revision: e849d99df1822ffe4ceb19771d13d857618009cd

URL: https://github.com/llvm/llvm-project/commit/e849d99df1822ffe4ceb19771d13d857618009cd
DIFF: https://github.com/llvm/llvm-project/commit/e849d99df1822ffe4ceb19771d13d857618009cd.diff

LOG: [WebAssembly] Use entry block only for initializations in EmSjLj

Emscripten SjLj transformation is done in four steps. This will be
mostly the same for the soon-to-be-added Wasm SjLj; the step 1, 3, and 4
will be shared and there will be separate way of doing step 2.
1. Initialize `setjmpTable` and `setjmpTableSize` in the entry BB
2. Handle `setjmp` callsites
3. Handle `longjmp` callsites
4. Cleanup and update SSA

We initialize `setjmpTable` and `setjmpTableSize` in the entry BB. But
if the entry BB contains a `setjmp` call, some `setjmp` handling
transformation will also happen in the entry BB, such as calling
`saveSetjmp`.

This is fine for Emscripten SjLj but not for Wasm SjLj, because in Wasm
SjLj we will add a dispatch BB that contains a `switch` right after the
entry BB, from which we jump to one of post-`setjmp` BBs. And this
dispatch BB should precede all `setjmp` calls.

Emscripten SjLj (current):
```
entry:
  %setjmpTable = ...
  %setjmpTableSize = ...
  ...
  call @saveSetjmp(...)
```

Wasm SjLj (follow-up):
```
entry:
  %setjmpTable = ...
  %setjmpTableSize = ...

setjmp.dispatch:
  ...
  ; Jump to the right post-setjmp BB, if we are returning from a
  ; longjmp. If this is the first setjmp call, go to %entry.split.
  switch i32 %no, label %entry.split [
    i32 1, label %post.setjmp1
    i32 2, label %post.setjmp2
    ...
    i32 N, label %post.setjmpN
  ]

entry.split:
  ...
  call @saveSetjmp(...)
```

So in Wasm SjLj we split the entry BB to make the entry block only for
`setjmpTable` and `setjmpTableSize` initialization and insert a
`setjmp.dispatch` BB. (This part is not in this CL. This will be a
follow-up.) But note that Emscripten SjLj and Wasm SjLj share all
steps except for the step 2. If we only split the entry BB only for Wasm
SjLj, there will be one more `if`-`else` and the code will be more
complicated.

So this CL splits the entry BB in Emscripten SjLj and put only
initialization stuff there as follows:
Emscripten SjLj (this CL):
```
entry:
  %setjmpTable = ...
  %setjmpTableSize = ...
  br %entry.split

entry.split:
  ...
  call @saveSetjmp(...)
```
This is just done to share code with Wasm SjLj. It adds an unnecessary
branch but this will be removed in later optimization passes anyway.

This is in effect NFC, meaning the program behavior will not change, but
existing ll tests files have changed because the entry block was split.
The reason I upload this in a separate CL is to make the Wasm SjLj diff
tidier, because this changes many existing Emscripten SjLj tests, which
can be confusing for the follow-up Wasm SjLj CL.

Reviewed By: tlively

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

Added: 
    

Modified: 
    llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
    llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll
    llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll
    llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll
    llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
index 263c5140f1616..db6aa0caaa477 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -1039,9 +1039,11 @@ bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) {
   // SSAUpdater.AddAvailableValue(...) later.
   BasicBlock *Entry = &F.getEntryBlock();
   DebugLoc FirstDL = getOrCreateDebugLoc(&*Entry->begin(), F.getSubprogram());
+  SplitBlock(Entry, &*Entry->getFirstInsertionPt());
+
   BinaryOperator *SetjmpTableSize =
       BinaryOperator::Create(Instruction::Add, IRB.getInt32(4), IRB.getInt32(0),
-                             "setjmpTableSize", &*Entry->getFirstInsertionPt());
+                             "setjmpTableSize", Entry->getTerminator());
   SetjmpTableSize->setDebugLoc(FirstDL);
   // setjmpTable = (int *) malloc(40);
   Instruction *SetjmpTable = CallInst::CreateMalloc(

diff  --git a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll
index 24c153825b72c..fd0c9445ba8d9 100644
--- a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll
+++ b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll
@@ -21,7 +21,7 @@ entry:
   invoke void @foo()
           to label %try.cont unwind label %lpad
 
-; CHECK:    entry.split:
+; CHECK:    entry.split.split:
 ; CHECK:      %[[CMP0:.*]] = icmp ne i32 %__THREW__.val, 0
 ; CHECK-NEXT: %__threwValue.val = load i32, i32* @__threwValue
 ; CHECK-NEXT: %[[CMP1:.*]] = icmp ne i32 %__threwValue.val, 0
@@ -29,7 +29,7 @@ entry:
 ; CHECK-NEXT: br i1 %[[CMP]], label %if.then1, label %if.else1
 
 ; This is exception checking part. %if.else1 leads here
-; CHECK:    entry.split.split:
+; CHECK:    entry.split.split.split:
 ; CHECK-NEXT: %[[CMP:.*]] = icmp eq i32 %__THREW__.val, 1
 ; CHECK-NEXT: br i1 %[[CMP]], label %lpad, label %try.cont
 

diff  --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll
index 465bd21a624cf..de020c5f26060 100644
--- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll
+++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll
@@ -12,12 +12,7 @@ target triple = "wasm32-unknown-emscripten"
 ; CHECK-LABEL: @malloc_test
 define void @malloc_test() {
 entry:
-; CHECK-LABEL: entry
-  ; All setjmp table preparations have to happen within the entry block. These
-  ; check lines list only some of the instructions for that.
   ; CHECK: call i8* @malloc
-  ; CHECK: call i32* @saveSetjmp
-  ; CHECK: call i32 @getTempRet0
   %retval = alloca i32, align 4
   %jmp = alloca [1 x %struct.__jmp_buf_tag], align 16
   store i32 0, i32* %retval, align 4
@@ -25,8 +20,6 @@ entry:
   %call = call i32 @setjmp(%struct.__jmp_buf_tag* %arraydecay) #0
   call void @foo()
   ret void
-
-; CHECK-LABEL: entry.split
 }
 
 ; This is a dummy dlmalloc implemenation only to make compiler pass, because an

diff  --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll
index 38b60c5bd674f..6e0b711273c8e 100644
--- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll
+++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll
@@ -18,15 +18,17 @@ entry:
 ; CHECK: entry:
   ; CHECK-NEXT: call i8* @malloc(i32 40), !dbg ![[DL0:.*]]
   ; CHECK-NEXT: bitcast {{.*}}, !dbg ![[DL0]]
+
+; CHECK: entry.split:
   ; CHECK: alloca {{.*}}, !dbg ![[DL0]]
   ; CHECK: call i32* @saveSetjmp{{.*}}, !dbg ![[DL1:.*]]
   ; CHECK-NEXT: call i32 @getTempRet0{{.*}}, !dbg ![[DL1]]
   ; CHECK-NEXT: br {{.*}}, !dbg ![[DL2:.*]]
 
-; CHECK: entry.split:
+; CHECK: entry.split.split:
   ; CHECK: call {{.*}} void @__invoke_void{{.*}}, !dbg ![[DL2]]
 
-; CHECK: entry.split.split:
+; CHECK: entry.split.split.split:
   ; CHECK-NEXT: bitcast {{.*}}, !dbg ![[DL3:.*]]
   ; CHECK-NEXT: call void @free{{.*}}, !dbg ![[DL3]]
 

diff  --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
index 7ed2f21e2d71f..fb2686ef1b1f0 100644
--- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
+++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll
@@ -30,14 +30,17 @@ entry:
 ; CHECK-NEXT: %[[SETJMP_TABLE:.*]] = bitcast i8* %[[MALLOCCALL]] to i32*
 ; CHECK-NEXT: store i32 0, i32* %[[SETJMP_TABLE]]
 ; CHECK-NEXT: %[[SETJMP_TABLE_SIZE:.*]] = add i32 4, 0
+; CHECK-NEXT: br label %entry.split
+
+; CHECK: entry.split
 ; CHECK-NEXT: %[[BUF:.*]] = alloca [1 x %struct.__jmp_buf_tag]
 ; CHECK-NEXT: %[[ARRAYDECAY:.*]] = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %[[BUF]], i32 0, i32 0
 ; CHECK-NEXT: %[[SETJMP_TABLE1:.*]] = call i32* @saveSetjmp(%struct.__jmp_buf_tag* %[[ARRAYDECAY]], i32 1, i32* %[[SETJMP_TABLE]], i32 %[[SETJMP_TABLE_SIZE]])
 ; CHECK-NEXT: %[[SETJMP_TABLE_SIZE1:.*]] = call i32 @getTempRet0()
-; CHECK-NEXT: br label %entry.split
+; CHECK-NEXT: br label %entry.split.split
 
-; CHECK: entry.split:
-; CHECK-NEXT: phi i32 [ 0, %entry ], [ %[[LONGJMP_RESULT:.*]], %if.end ]
+; CHECK: entry.split.split:
+; CHECK-NEXT: phi i32 [ 0, %entry.split ], [ %[[LONGJMP_RESULT:.*]], %if.end ]
 ; CHECK-NEXT: %[[ARRAYDECAY1:.*]] = getelementptr inbounds [1 x %struct.__jmp_buf_tag], [1 x %struct.__jmp_buf_tag]* %[[BUF]], i32 0, i32 0
 ; CHECK-NEXT: %[[JMPBUF:.*]] = ptrtoint %struct.__jmp_buf_tag* %[[ARRAYDECAY1]] to [[PTR]]
 ; CHECK-NEXT: store [[PTR]] 0, [[PTR]]* @__THREW__
@@ -50,7 +53,7 @@ entry:
 ; CHECK-NEXT: %[[CMP:.*]] = and i1 %[[CMP0]], %[[CMP1]]
 ; CHECK-NEXT: br i1 %[[CMP]], label %if.then1, label %if.else1
 
-; CHECK: entry.split.split:
+; CHECK: entry.split.split.split:
 ; CHECK-NEXT: unreachable
 
 ; CHECK: if.then1:
@@ -66,8 +69,8 @@ entry:
 ; CHECK: if.end:
 ; CHECK-NEXT: %[[LABEL_PHI:.*]] = phi i32 [ %[[LABEL:.*]], %if.end2 ], [ -1, %if.else1 ]
 ; CHECK-NEXT: %[[LONGJMP_RESULT]] = call i32 @getTempRet0()
-; CHECK-NEXT: switch i32 %[[LABEL_PHI]], label %entry.split.split [
-; CHECK-NEXT:   i32 1, label %entry.split
+; CHECK-NEXT: switch i32 %[[LABEL_PHI]], label %entry.split.split.split [
+; CHECK-NEXT:   i32 1, label %entry.split.split
 ; CHECK-NEXT: ]
 
 ; CHECK: if.then2:
@@ -93,10 +96,10 @@ entry:
 ; CHECK: entry:
 ; CHECK: %[[SETJMP_TABLE:.*]] = call i32* @saveSetjmp(
 
-; CHECK: entry.split:
+; CHECK: entry.split.split:
 ; CHECK: @__invoke_void(void ()* @foo)
 
-; CHECK: entry.split.split:
+; CHECK: entry.split.split.split:
 ; CHECK-NEXT: %[[BUF:.*]] = bitcast i32* %[[SETJMP_TABLE]] to i8*
 ; CHECK-NEXT: tail call void @free(i8* %[[BUF]])
 ; CHECK-NEXT: ret void
@@ -152,9 +155,9 @@ if.end:                                           ; preds = %if.then, %entry
   call void @longjmp(%struct.__jmp_buf_tag* %arraydecay1, i32 5) #1
   unreachable
 ; CHECK: if.end:
-; CHECK: %[[VAR2]] = phi i32 [ %[[VAR1]], %if.then.split ], [ undef, %entry ]
-; CHECK: %[[SETJMP_TABLE_SIZE3]] = phi i32 [ %[[SETJMP_TABLE_SIZE2]], %if.then.split ], [ %[[SETJMP_TABLE_SIZE0]], %entry ]
-; CHECK: %[[SETJMP_TABLE3]] = phi i32* [ %[[SETJMP_TABLE2]], %if.then.split ], [ %[[SETJMP_TABLE0]], %entry ]
+; CHECK: %[[VAR2]] = phi i32 [ %[[VAR1]], %if.then.split ], [ undef, %entry.split ]
+; CHECK: %[[SETJMP_TABLE_SIZE3]] = phi i32 [ %[[SETJMP_TABLE_SIZE2]], %if.then.split ], [ %[[SETJMP_TABLE_SIZE0]], %entry.split ]
+; CHECK: %[[SETJMP_TABLE3]] = phi i32* [ %[[SETJMP_TABLE2]], %if.then.split ], [ %[[SETJMP_TABLE0]], %entry.split ]
 }
 
 ; Test a case when a function only calls other functions that are neither setjmp nor longjmp


        


More information about the llvm-commits mailing list