1//===-- PHIEliminationUtils.cpp - Helper functions for PHI elimination ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "PHIEliminationUtils.h"
10#include "llvm/ADT/SmallPtrSet.h"
11#include "llvm/CodeGen/MachineFunction.h"
12#include "llvm/CodeGen/MachineRegisterInfo.h"
13
14using namespace llvm;
15
16// Returns true if MBB contains an INLINEASM_BR instruction that may
17// branch to SuccMBB, requiring specialized copy placement.
18static bool hasInlineAsmBrToSuccessor(MachineBasicBlock *MBB,
19 MachineBasicBlock *SuccMBB) {
20 if (!SuccMBB->isInlineAsmBrIndirectTarget())
21 return false;
22
23 for (const MachineInstr &MI : reverse(C&: *MBB))
24 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
25 return true;
26 return false;
27}
28
29// findCopyInsertPoint - Find a safe place in MBB to insert a copy from SrcReg
30// when following the CFG edge to SuccMBB. This needs to be after any def of
31// SrcReg, but before any subsequent point where control flow might jump out of
32// the basic block.
33MachineBasicBlock::iterator
34llvm::findPHICopyInsertPoint(MachineBasicBlock* MBB, MachineBasicBlock* SuccMBB,
35 Register SrcReg) {
36 // Handle the trivial case trivially.
37 if (MBB->empty())
38 return MBB->begin();
39
40 // Usually, we just want to insert the copy before the first terminator
41 // instruction. However, for the edge going to a landing pad, we must insert
42 // the copy before the call/invoke instruction. Similarly for an INLINEASM_BR
43 // going to an indirect target. This is similar to SplitKit.cpp's
44 // computeLastInsertPoint, and similarly assumes that there cannot be multiple
45 // instructions that are Calls with EHPad successors or INLINEASM_BR in a
46 // block.
47 // Note that, if the successor basic block happens to be an indirect target,
48 // and the current block, which may be the successor itself, does not contain
49 // any INLINEASM_BR, we may not need any specialized handling.
50 bool EHPadSuccessor = SuccMBB->isEHPad();
51 if (!EHPadSuccessor && !hasInlineAsmBrToSuccessor(MBB, SuccMBB))
52 return MBB->getFirstTerminator();
53
54 // Discover any defs in this basic block.
55 SmallPtrSet<MachineInstr *, 8> DefsInMBB;
56 MachineRegisterInfo& MRI = MBB->getParent()->getRegInfo();
57 for (MachineInstr &RI : MRI.def_instructions(Reg: SrcReg))
58 if (RI.getParent() == MBB)
59 DefsInMBB.insert(Ptr: &RI);
60
61 MachineBasicBlock::iterator InsertPoint = MBB->begin();
62 // Insert the copy at the _latest_ point of:
63 // 1. Immediately AFTER the last def
64 // 2. Immediately BEFORE a call/inlineasm_br.
65 for (auto I = MBB->rbegin(), E = MBB->rend(); I != E; ++I) {
66 if (DefsInMBB.contains(Ptr: &*I)) {
67 InsertPoint = std::next(x: I.getReverse());
68 break;
69 }
70 if ((EHPadSuccessor && I->isCall()) ||
71 I->getOpcode() == TargetOpcode::INLINEASM_BR) {
72 InsertPoint = I.getReverse();
73 break;
74 }
75 }
76
77 // Make sure the copy goes after any phi nodes but before
78 // any debug nodes.
79 return MBB->SkipPHIsAndLabels(I: InsertPoint);
80}
81