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 @@ -783,7 +783,8 @@ void processIntegerCallValue(const Instruction &I, SDValue Value, bool IsSigned); - void HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); + void HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB, + bool FirstIter); 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 @@ -1084,9 +1084,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)) @@ -1101,6 +1100,7 @@ CopyToExportRegsIfNeeded(&I); CurInst = nullptr; + ConstantsOut.clear(); } void SelectionDAGBuilder::visitPHI(const PHINode &) { @@ -2839,6 +2839,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()]; @@ -9994,9 +9997,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 FirstIter) { const Instruction *TI = LLVMBB->getTerminator(); + const CallBrInst *CI = dyn_cast(TI); SmallPtrSet SuccsHandled; @@ -10005,6 +10009,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 (FirstIter) { + // 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 @@ -10065,8 +10084,6 @@ } } } - - ConstantsOut.clear(); } /// Add a successor MBB to ParentMBB< creating a new MachineBB for BB if SuccMBB 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 +}