]> granicus.if.org Git - llvm/commitdiff
[WebAssembly] Fix SSA rebuilding in SjLj transformation
authorHeejin Ahn <aheejin@gmail.com>
Mon, 26 Aug 2019 21:51:35 +0000 (21:51 +0000)
committerHeejin Ahn <aheejin@gmail.com>
Mon, 26 Aug 2019 21:51:35 +0000 (21:51 +0000)
Summary:
Previously we skipped uses within the same BB as a def when rebuilding
SSA after SjLj transformation. For example, before transformation,
```
for.cond:
  %0 = phi i32 [ %var, %for.inc ] ...
  %var = ...
  br label %for.inc

for.inc:                               ; preds = %for.cond
  call i32 @setjmp(...)
  br %for.cond
```

In this BB, %var should be defined in all paths from %for.inc to make %0
valid. In the input it was true; %for.inc's only predecessor was
%for.cond. But after SjLj transformation, it is possible that %for.inc
has other predecessors that are reachable without reaching %for.cond.
```
entry.split:
  ...
  br i1 %a, label %bb.1, label %for.inc

for.cond:
  %0 = phi i32 [ %var, %for.inc ] ...  ; Not valid!
  %var = ...
  br label %for.inc

for.inc:                               ; preds = %for.cond, %entry.split
  call i32 @setjmp(...)
  ...
  br %for.cond
```

In this case, we can't use %var in the `phi` instruction in %for.cond,
because %var is not defined in all paths through %for.inc (If the
control flow is %entry -> %entry.split -> %for.inc -> %for.cond, %var
has not been defined until we reach the `phi`). But the previous code
excluded users within the same BB, skipping instructions within the same
BB so they are not rewritten properly. User instructions within the same
BB also should be candidates for rewriting if they are _before_ the
original definition.

Fixes PR43097.

Reviewers: dschuff

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

Tags: #llvm

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@369978 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
test/CodeGen/WebAssembly/lower-em-sjlj.ll

index 568382bac15c758d58d1442878fcf9e2985b7cbd..d70e197cbcbe3c4dd945b6d65f7e71802fe7b694 100644 (file)
@@ -636,15 +636,12 @@ void WebAssemblyLowerEmscriptenEHSjLj::rebuildSSA(Function &F) {
   SSAUpdater SSA;
   for (BasicBlock &BB : F) {
     for (Instruction &I : BB) {
+      SSA.Initialize(I.getType(), I.getName());
+      SSA.AddAvailableValue(&BB, &I);
       for (auto UI = I.use_begin(), UE = I.use_end(); UI != UE;) {
         Use &U = *UI;
         ++UI;
-        SSA.Initialize(I.getType(), I.getName());
-        SSA.AddAvailableValue(&BB, &I);
         auto *User = cast<Instruction>(U.getUser());
-        if (User->getParent() == &BB)
-          continue;
-
         if (auto *UserPN = dyn_cast<PHINode>(User))
           if (UserPN->getIncomingBlock(U) == &BB)
             continue;
index 5dfdd440fbce4f6b345be15928f65326c3686a51..540b13bdbd83142ad1e2b4ed90082a5fd37f6112 100644 (file)
@@ -226,6 +226,26 @@ entry:
   unreachable
 }
 
+; Tests if SSA rewrite works when a use and its def are within the same BB.
+define void @ssa_rewite_in_same_bb() {
+entry:
+  call void @foo()
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  ; CHECK: %{{.*}} = phi i32 [ %var[[VARNO:.*]], %for.inc.split ]
+  %0 = phi i32 [ %var, %for.inc ], [ undef, %entry ]
+  %var = add i32 0, 0
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.cond
+  %call5 = call i32 @setjmp(%struct.__jmp_buf_tag* undef) #0
+  br label %for.cond
+
+; CHECK: for.inc.split:
+  ; CHECK: %var[[VARNO]] = phi i32 [ %var, %for.inc ]
+}
+
 declare void @foo()
 ; Function Attrs: returns_twice
 declare i32 @setjmp(%struct.__jmp_buf_tag*) #0