This is an archive of the discontinued LLVM Phabricator instance.

[WebAssembly] Don't analyze branches after CFGStackify
ClosedPublic

Authored by aheejin on Mar 23 2019, 12:57 PM.

Details

Summary

WebAssembly::analyzeBranch now does not analyze anything if the
function is CFG stackified. We were previously doing similar things by
checking if a branch's operand is whether an integer or an MBB, but this
failed to bail out when a BB did not have any terminators.

Consider this case:

bb0:
  try $label0
  call @foo    // unwinds to %ehpad
bb1:
  ...
  br $label0   // jumps to %cont. can be deleted
ehpad:
  catch
  ...
cont:
  end_try

Here br $label0 will be deleted in CFGStackify's
removeUnnecessaryInstrs function, because we jump to the %cont block
even without the branch. But in this case, MachineVerifier fails to
verify this, because ehpad is not a successor of bb1 even if bb1
does not have any terminators. MachineVerifier incorrectly thinks bb1
falls through to the next block.

This pass now consistently rejects all analysis after CFGStackify
whether a BB has terminators or not, also making the MachineVerifier
work. (MachineVerifier does not try to verify relationships between BBs
if analyzeBranch fails, the behavior we want after CFGStackify.)

This also adds a new option -wasm-disable-ehpad-sort for testing. This
option helps create the sorted order we want to test, and without the
fix in this patch, the tests in cfg-stackify-eh.ll fail at
MachineVerifier with -wasm-disable-ehpad-sort.

Diff Detail

Repository
rL LLVM

Event Timeline

aheejin created this revision.Mar 23 2019, 12:57 PM
arsenm added a subscriber: arsenm.Mar 23 2019, 2:01 PM
arsenm added inline comments.
lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
106–107 ↗(On Diff #192013)

I think this isn't what you want to do. analyzeBranch isn't really for turning off transformations. The verifier will stop catching useful cases with this

aheejin marked an inline comment as done.Mar 24 2019, 5:59 AM
aheejin added inline comments.
lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
106–107 ↗(On Diff #192013)

Please note that we were doing this already. (The part of the code I deleted)
CFGStackify is a pass near the end of WebAssembly compilation pipeline, and this pass deletes all MBB operands from branches to replace them with integers, and also deletes some other unnecessary instruction from WebAssembly standpoint, so after that it is not possible to analyze branch anyway. This patch is not introducing a new thing; it is rather filling in a hole, because we rejected analysis only when there were terminators and ignored the case of fall-throughs after CFGStackify.

dschuff added inline comments.Mar 25 2019, 3:30 PM
lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
106–107 ↗(On Diff #192013)

I guess if we actually modeled the wasm control flow structure outside of the CFGStackify pass (e.g. the BeginToEnd mappings etc), then analyzeBranch could use them and it could return the correct successors. But since we don't yet, the control flow really is not analyzable by analyzeBranch and it should return false, right? And as a result any optimization or verification that depends on that can't run.

test/CodeGen/WebAssembly/cfg-stackify-eh.ll
3 ↗(On Diff #192013)

why does this CL now need the ehpad-sort option?

dschuff added inline comments.Mar 25 2019, 3:34 PM
test/CodeGen/WebAssembly/cfg-stackify-eh.ll
3 ↗(On Diff #192013)

nevermind, I re-read the CL description.

aheejin marked an inline comment as done.Mar 25 2019, 4:23 PM
aheejin added inline comments.
lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
106–107 ↗(On Diff #192013)

Not sure what you mean, but this function unintuitively returns false when it is analyzable, and true if not. Please refer to the description of its return values.

dschuff added inline comments.Mar 25 2019, 5:22 PM
lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
106–107 ↗(On Diff #192013)

sorry yes, I meant that it should return true. I'm just saying I think that this behavior is probably consistent with the intention of analyzeBranch. Once it can no longer correctly determine the destination, analyzeBranch should fail.

aheejin marked an inline comment as done.Mar 25 2019, 5:38 PM
aheejin added inline comments.
lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
106–107 ↗(On Diff #192013)

I think that’s what this CL does..?

dschuff accepted this revision.Mar 26 2019, 10:06 AM
dschuff added inline comments.
lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp
106–107 ↗(On Diff #192013)

Yes; my statement was mostly just a reply to @arsenm to try to clarify what we are doing.

This CL looks fine to me; in any case it doesn't change what we are doing already.
WRT the comments, I think @arsenm's point is that if we want to prevent optimizations (as the comment in the code seems to indicate) then this isn't the way to do it because it also prevents verification. But I don't think that is actually what we are doing; in any case AFAIK there aren't any optimization passes that run after CFGStackify that try to reason about branches or the CFG, and we are controlling the pass order explicitly in WebAssemblyPassConfig. So maybe we should just clarify the comment to say something like "WebAssembly has control flow that doesn't have explicit branches or direct fallthrough (e.g. try/catch), which cant' be modeled by analyzeBranch. It is created after CFGStackify"

This revision is now accepted and ready to land.Mar 26 2019, 10:06 AM
aheejin updated this revision to Diff 192302.Mar 26 2019, 11:18 AM
aheejin marked an inline comment as done.
  • Add comment on CFGStackify
This revision was automatically updated to reflect the committed changes.