[CodeGen] Postprocess PHI nodes for callbr

When processing PHI nodes after a callbr, we need to make sure that the
PHI nodes on the default branch are resolved after the callbr
(inserted after INLINEASM_BR). The PHI node values on the indirect
branches are processed before the INLINEASM_BR.

Differential Revision: https://reviews.llvm.org/D86260
This commit is contained in:
Bill Wendling 2020-08-19 19:51:20 -07:00
parent 30514f0afa
commit 7f4c940bd0
3 changed files with 53 additions and 7 deletions

View File

@ -1084,9 +1084,8 @@ SDValue SelectionDAGBuilder::getControlRoot() {
void SelectionDAGBuilder::visit(const Instruction &I) {
// Set up outgoing PHI node register values before emitting the terminator.
if (I.isTerminator()) {
HandlePHINodesInSuccessorBlocks(I.getParent());
}
if (I.isTerminator())
HandlePHINodesInSuccessorBlocks(I.getParent(), true);
// Increase the SDNodeOrder if dealing with a non-debug instruction.
if (!isa<DbgInfoIntrinsic>(I))
@ -2839,6 +2838,9 @@ void SelectionDAGBuilder::visitCallBr(const CallBrInst &I) {
visitInlineAsm(I);
CopyToExportRegsIfNeeded(&I);
// Set up outgoing PHI node register values before emitting the branch.
HandlePHINodesInSuccessorBlocks(I.getParent(), false);
// Retrieve successors.
MachineBasicBlock *Return = FuncInfo.MBBMap[I.getDefaultDest()];
@ -9990,10 +9992,10 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
/// directly add them, because expansion might result in multiple MBB's for one
/// BB. As such, the start of the BB might correspond to a different MBB than
/// the end.
void
SelectionDAGBuilder::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
void SelectionDAGBuilder::HandlePHINodesInSuccessorBlocks(
const BasicBlock *LLVMBB, bool Preprocess) {
const Instruction *TI = LLVMBB->getTerminator();
const CallBrInst *CI = dyn_cast<CallBrInst>(TI);
SmallPtrSet<MachineBasicBlock *, 4> SuccsHandled;
// Check PHI nodes in successors that expect a value to be available from this
@ -10001,6 +10003,21 @@ SelectionDAGBuilder::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) {
const BasicBlock *SuccBB = TI->getSuccessor(succ);
if (!isa<PHINode>(SuccBB->begin())) continue;
if (CI) {
if (Preprocess) {
// Don't push PHI node values back before an INLINEASM_BR instruction on
// the default branch.
if (SuccBB == CI->getDefaultDest())
continue;
} else {
// Don't push PHI node values back after an INLINEASM_BR instruction on
// the indirect branch.
if (SuccBB != CI->getDefaultDest())
continue;
}
}
MachineBasicBlock *SuccMBB = FuncInfo.MBBMap[SuccBB];
// If this terminator has multiple identical successors (common for

View File

@ -783,7 +783,8 @@ private:
void processIntegerCallValue(const Instruction &I,
SDValue Value, bool IsSigned);
void HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB);
void HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB,
bool Preprocess);
void emitInlineAsmError(const CallBase &Call, const Twine &Message);

View File

@ -0,0 +1,28 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=i686-- -verify-machineinstrs < %s | FileCheck %s
@var = global i32 0, align 4
define i32 @test1() {
; CHECK-LABEL: test1:
; CHECK: # %bb.0:
; CHECK-NEXT: #APP
; CHECK-NEXT: jmp .Ltmp0
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: # %bb.2:
; CHECK-NEXT: retl
; CHECK-NEXT: .Ltmp0: # Block address taken
; CHECK-NEXT: .LBB0_1:
; CHECK-NEXT: movl $1, %eax
; CHECK-NEXT: retl
callbr void asm sideeffect "jmp ${1:l}", "*m,X,~{dirflag},~{fpsr},~{flags}"(i32* nonnull @var, i8* blockaddress(@test1, %1))
to label %2 [label %1]
1: ; preds = %0
br label %2
2: ; preds = %0, %1
%3 = phi i32 [ 1, %1 ], [ 0, %0 ]
ret i32 %3
}