This is an archive of the discontinued LLVM Phabricator instance.

Don't tail merge EHPads
ClosedPublic

Authored by aeubanks on May 15 2020, 4:21 PM.

Diff Detail

Event Timeline

aeubanks created this revision.May 15 2020, 4:21 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 15 2020, 4:21 PM
aeubanks retitled this revision from Don't merge EHPads to Don't tail merge EHPads.May 15 2020, 4:23 PM
aeubanks added a reviewer: rnk.

I'm not sure if this is the right thing to do, I'd like some input before continuing with tests.
I ran check-llvm and this only caused one autogenerated test to fail, which is a good sign

Could you explain why you think this is the right thing to do?

At first glance, I don't see any obvious problem with tail merging in this context unless this is illegal due to "region" restrictions (merging code in different unwind handlers). And if the issue is in fact a problem with merging across regions, this fix is clearly insufficient; isEHPad() is only true for the first MBB of an unwind handler.

I'm definitely not confident that this is the right thing to do, but this seems to prevent changing

bb.9:
; predecessors: %bb.8
  successors: %bb.15(0x80000000); %bb.15(100.00%)

  renamable $eax = MOV32r0 implicit-def dead $eflags
  JMP_1 %bb.15

bb.11.__except (landing-pad):
; predecessors: %bb.10
  successors: %bb.15(0x80000000); %bb.15(100.00%)

  renamable $eax = MOV32r0 implicit-def dead $eflags
  JMP_1 %bb.15

to

bb.9:
; predecessors: %bb.8
  successors: %bb.11(0x80000000); %bb.11(100.00%)


bb.11.__except (landing-pad):
; predecessors: %bb.10, %bb.9
  successors: %bb.15(0x80000000); %bb.15(100.00%)

  renamable $eax = MOV32r0 implicit-def dead $eflags
  JMP_1 %bb.15

I think you're not supposed to enter a landing pad through normal control flow, in this case a fallthrough (correct me if I'm wrong).

This causes a later pass (MachineBlockPlacement) to not properly update the terminator for a basic block, since MachineBasicBlock::updateTerminator() ignores landing pad basic block successors in the case where a block has an unconditional fallthrough.

I think it's specifically the tailIsWholeBlock() cases that require more care to handle your example correctly, in BranchFolder::TryTailMergeBlocks. The general transform is fine. -verify-machineinstrs should catch the transform in your example, I think.

Well, there are also potential issues on Windows involving funclets, but it looks like that isn't the problem here.

aeubanks updated this revision to Diff 265527.May 21 2020, 9:46 AM

Don't jump to landing pads in Control Flow Optimizer

What I'm confused about though is this comment in MachineVerifier:

// Block unconditionally branches somewhere.
// If the block has exactly one successor, that happens to be a
// landingpad, accept it as valid control flow.

which originates from fb6eeb74c58a

[MachineVerifier] Accept a MBB with a single landing pad successor.

The MachineVerifier used to check that there was always exactly one
unconditional branch to a non-landingpad (normal) successor.
If that normal successor to an invoke BB is unreachable, it seems
reasonable to only have one successor, the landing pad.
On targets other than AArch64 (and on AArch64 with a different testcase),
the branch folder turns the branch to the landing pad into a fallthrough.
The MachineVerifier, which relies on AnalyzeBranch, is unable to check
the condition, and doesn't complain. However, it does in this specific
testcase, where the branch to the landing pad remained.
Make the MachineVerifier accept it.

I was under the impression that you couldn't jump/fallthrough to landing pads.

There's a few weird edge cases because we don't explicitly mark blocks where the fallthrough is unreachable; I think @jyknight is working on a patch for that. In particular, suppose you have a block that has both an unwind edge and an unreachable fallthrough.

The patch looks right.

Now that you know what the issue is, do you think you could construct an MIR testcase?

aeubanks updated this revision to Diff 265584.May 21 2020, 1:12 PM

Add test
Made sure it fails without this patch
I thought the MIR serialization didn't support landing pads but upon closer look at https://llvm.org/docs/MIRLangRef.html#miscellaneous-attributes it does. I also figured out that you could manually specify successors even if they aren't implicit, else the landing pad BB would get removed.

If we could get rid of the edge cases and add a check to the machine verifier for control flow into landing pads, that could help with potential similar future issues.

efriedma added inline comments.May 21 2020, 1:58 PM
llvm/test/CodeGen/X86/branchfolding-ehpad.mir
18 ↗(On Diff #265584)

Can you check that we still perform tail merging here?

aeubanks updated this revision to Diff 265604.May 21 2020, 2:27 PM

Check that we still do tail merging in a landing pad

This revision is now accepted and ready to land.May 21 2020, 2:57 PM
This revision was automatically updated to reflect the committed changes.