This is a prototype of the CFG "stackifier" algorithm for creating structured control flow out of a CFG.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
- add tests for interesting loop-with-split-backedge cases
- rewrite the successor sorting code to be more readable
- misc cleanups
include/llvm/CodeGen/AsmPrinter.h | ||
---|---|---|
239 ↗ | (On Diff #34456) | This should probably be in its own patch once this one is ready to go, just so other folks who care can notice it. |
lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | ||
11 ↗ | (On Diff #34456) | Could you have a bit of a longer description of what that means? |
58 ↗ | (On Diff #34456) | std::vector, or non-zero size. |
67 ↗ | (On Diff #34456) | Can this be Succs(MBB->successors())? |
70 ↗ | (On Diff #34456) | Could you explain the strategy? You leave me hanging! |
87 ↗ | (On Diff #34456) | It's a bit obvious, but it would be nice to have a comment here that says that A and B are now in the same loop depth. It doesn't mean it's the same loop, though! Would it make sense to check that too, and order them based on which of their loop heads is earlier in PO? |
95 ↗ | (On Diff #34456) | Could you also take into account "furthest from backedge" in ordering? It also seems like you want a tie-breaker here, and that can be as arbitrary as the block name? Maybe also something about instructions contained, including "ends with a non-reachable instr". What does this do with unlikely/cold/landingpad? |
104 ↗ | (On Diff #34456) | Expand on why we want that control. |
107 ↗ | (On Diff #34456) | 4 seems pretty conservative for most functions! I'd do 16 as a random guess (though of course data would win here...). |
121 ↗ | (On Diff #34456) | This code is written as a test for itself? ;-) |
A few more high-level comments...
lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | ||
---|---|---|
130 ↗ | (On Diff #34456) | Shouldn't this instead test for isConditionalBranch, not isBranch? Also: conservatively, isInlineAsm? |
lib/Target/WebAssembly/WebAssemblyInstrControl.td | ||
61 ↗ | (On Diff #34456) | Why (select Int64:$a? Isn't the condition just a bool, so Int32 suffices (as for the other types)? |
69 ↗ | (On Diff #34456) | Aggressive multiclass for SELECT? |
lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp | ||
52 ↗ | (On Diff #34456) | Why instructions can these be? |
test/CodeGen/WebAssembly/cfg-stackify.ll | ||
9 ↗ | (On Diff #34456) | Add a test with:
|
test/CodeGen/WebAssembly/switch.ll | ||
6 ↗ | (On Diff #34456) | TODO on testing computed goto. |
lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | ||
---|---|---|
58 ↗ | (On Diff #34456) | std::vector doesn't support Succs(MBB->successors()) below ;-). |
87 ↗ | (On Diff #34456) | Ah, this was just a thinko on my part. This code should just check the actual loop, not the loop depth. |
95 ↗ | (On Diff #34456) | I'm just trying to do something simple that does reasonable things in most cases right now. There will be plenty of time for tweaking this function. Unlikely/cold are handled by MachineBlockPlacementID, and this pass attempts to respect that by preserving the original order of the blocks when it can. However, note that MachineBlockPlacementID is currently disabled; see the comments for details. landingpad gets lowered away before we get here. |
121 ↗ | (On Diff #34456) | Ok, it's not hard to rewrite this code to avoid a goto for the benefit of people who make remarks like this, so I've now done that. |
130 ↗ | (On Diff #34456) | It needs to accept isBranch too because moving the block could mean that the branch should turn into a fallthrough. LLVM doesn't support 'asm goto' so we can't get isInlineAsm here. I added a check and a report_fatal_error to catch cases like this in case they do get added though. |
lib/Target/WebAssembly/WebAssemblyInstrControl.td | ||
69 ↗ | (On Diff #34456) | SELECT isn't really part of this patch, so I dropped it for now. |
lib/Target/WebAssembly/WebAssemblyInstrInfo.cpp | ||
52 ↗ | (On Diff #34456) | switches, for example. |
test/CodeGen/WebAssembly/cfg-stackify.ll | ||
9 ↗ | (On Diff #34456) |
We have these already.
Patches welcome. ;-)
There are no asm terminators in LLVM, so it's not possible get this right now. And, I added checking code which should catch this case in case LLVM ever adds them in the future.
The TODO is to set our ExceptionHandling type to something other than ExceptionHandling::None so that landingpad doesn't get stripped out entirely before it gets to this pass.
They deal with multiple terminators at the MachineBasicBlock level, which isn't exposed or testable from an LLVM IR unittest. |
You should mark comments that are addressed as "done"!
lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | ||
---|---|---|
58 ↗ | (On Diff #34456) | Non-zero size then? Most blocks won't have more than 8 successors, and that's cheap to put on the stack compared to heap allocating! |
95 ↗ | (On Diff #34456) | Could you add TODOs for the things that make sense to try out? You still want a final tie breaker though: as it stands the code breaks std::stable_sort's contract by having A < B and B < A both false! |
lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | ||
---|---|---|
59 ↗ | (On Diff #34714) | (Notice how this comment is no longer displayed anywhere near the code that it's about.) It's inside another vector, so making it zero size is nice because it means move constructing is trivial. However, it's not really that important since neither one of us has profiled this ;-). |
96 ↗ | (On Diff #34714) | Ok, I added a TODO. stable_sort just wants a strict weak ordering. When A < B and B < A are both false, then stable_sort treats them as equal and orders them according to their original order. |
108 ↗ | (On Diff #34714) | When data arrives, we can update these accordingly. |
test/CodeGen/WebAssembly/cfg-stackify.ll | ||
10 ↗ | (On Diff #34714) | FYI, I have added several more tests now. |
test/CodeGen/WebAssembly/switch.ll | ||
7 ↗ | (On Diff #34714) | That would go in a new file, rather than switch.ll. |
I think this is pretty good now. I like the approach as it reuses some LLVM infrastructure, and is overall simpler than the relooper. I'd like us to revisit and compare what we're missing from the relooper, but at this point in time we want to move things forward so I think this is a good start, and we'll do more comparative science later.
lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | ||
---|---|---|
59 ↗ | (On Diff #34714) | Much appreciated :-) |
lib/Target/WebAssembly/WebAssemblyInstrControl.td | ||
41 ↗ | (On Diff #34757) | Shouldn't we support switch 64 on either architecture? |
- Allow SWITCH_I64 in wasm32 mode and vice versa, and add a TODO comment to actually make use of this.
lib/Target/WebAssembly/WebAssemblyInstrControl.td | ||
---|---|---|
41 ↗ | (On Diff #34770) | Good point. LLVM's jump table lowering forces the index to be pointer-sized, but we don't need that restriction. I fixed this, added a test, and added a TODO comment. |
One small comment, then lgtm. As we discussed offline, I'll unhook D12744 and commit it, since we'll probably want a hybrid approach for a while (or at least compare approaches).
lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | ||
---|---|---|
161 ↗ | (On Diff #34770) | Shouldn't the above be in a separate patch, since you removed select handling? |