diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -790,7 +790,8 @@ 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); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1108,9 +1108,8 @@ 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(I)) @@ -2882,6 +2881,9 @@ 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()]; @@ -10058,10 +10060,10 @@ /// 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(TI); SmallPtrSet SuccsHandled; // Check PHI nodes in successors that expect a value to be available from this @@ -10069,6 +10071,21 @@ for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) { const BasicBlock *SuccBB = TI->getSuccessor(succ); if (!isa(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 diff --git a/llvm/test/CodeGen/X86/callbr-asm-phi-nodes.ll b/llvm/test/CodeGen/X86/callbr-asm-phi-nodes.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/callbr-asm-phi-nodes.ll @@ -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 +}