[RFC] Syncing Asm Goto with Outputs with GCC

Summarizing feedback from ⚙ D139565 [IR] add new callbrpad instruction as the new plan:

  1. allow the use of callbr values along ANY edge; direct or indirect. i.e. restore ⚙ D135997 [Dominators] check indirect branches of callbr.
  2. Create a new function pass (as part of TargetPassConfig::addISelPasses so it runs before isel on LLVM IR) that:
    A. for each basic block terminator if it’s a callbr that has outputs that have uses:
    a. splits indirect edges that happen to also be critical edges (if any) (akin to ⚙ D138078 [SelectionDAGISel] split critical indirect edges from callbr w/ outputs, but in a dedicated pass)
    b. inserts a new SSA value produced from either a intrinsic call. This will be used a marker during SelectionDAGBuilder to denote where physreg to virtreg copies need to go. It need not reference the corresponding callbr since we split critical edges in 2.A.a previously, so it’s unambiguous that our corresponding callbr is the terminator of my lone predecessor.
    c. Replaces the uses dominated by the indirect edge to use the newly created value. We might need to insert phis where previously there were none. llvm::SSAUpdater can help with this.
  3. Add a mapping from CallBrInst to either INLINEASM_BR MachineInstr or first defined virtreg (not sure yet), probably in SelectionDAGBuilder’s FunctionLoweringInfo instance member. Create an entry in this mapping when lowering a callbr or inlineasm. Consume this mapping info when visiting the “new value” created from 2.A.b above to insert COPYs as necessary. (May need to handle visiting the use before the def).

Ideas for names for the intrinsic: callbrdef, terminatordef, callbrpad, callbr_landingpad.