xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/PHIEliminationUtils.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===-- PHIEliminationUtils.cpp - Helper functions for PHI elimination ----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "PHIEliminationUtils.h"
100b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
110b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
120b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
130b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
140b57cec5SDimitry Andric using namespace llvm;
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric // findCopyInsertPoint - Find a safe place in MBB to insert a copy from SrcReg
170b57cec5SDimitry Andric // when following the CFG edge to SuccMBB. This needs to be after any def of
180b57cec5SDimitry Andric // SrcReg, but before any subsequent point where control flow might jump out of
190b57cec5SDimitry Andric // the basic block.
200b57cec5SDimitry Andric MachineBasicBlock::iterator
210b57cec5SDimitry Andric llvm::findPHICopyInsertPoint(MachineBasicBlock* MBB, MachineBasicBlock* SuccMBB,
220b57cec5SDimitry Andric                              unsigned SrcReg) {
230b57cec5SDimitry Andric   // Handle the trivial case trivially.
240b57cec5SDimitry Andric   if (MBB->empty())
250b57cec5SDimitry Andric     return MBB->begin();
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric   // Usually, we just want to insert the copy before the first terminator
280b57cec5SDimitry Andric   // instruction. However, for the edge going to a landing pad, we must insert
29*5ffd83dbSDimitry Andric   // the copy before the call/invoke instruction. Similarly for an INLINEASM_BR
30*5ffd83dbSDimitry Andric   // going to an indirect target.
31*5ffd83dbSDimitry Andric   if (!SuccMBB->isEHPad() && !SuccMBB->isInlineAsmBrIndirectTarget())
320b57cec5SDimitry Andric     return MBB->getFirstTerminator();
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric   // Discover any defs/uses in this basic block.
350b57cec5SDimitry Andric   SmallPtrSet<MachineInstr*, 8> DefUsesInMBB;
360b57cec5SDimitry Andric   MachineRegisterInfo& MRI = MBB->getParent()->getRegInfo();
370b57cec5SDimitry Andric   for (MachineInstr &RI : MRI.reg_instructions(SrcReg)) {
380b57cec5SDimitry Andric     if (RI.getParent() == MBB)
390b57cec5SDimitry Andric       DefUsesInMBB.insert(&RI);
400b57cec5SDimitry Andric   }
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   MachineBasicBlock::iterator InsertPoint;
430b57cec5SDimitry Andric   if (DefUsesInMBB.empty()) {
440b57cec5SDimitry Andric     // No defs.  Insert the copy at the start of the basic block.
450b57cec5SDimitry Andric     InsertPoint = MBB->begin();
460b57cec5SDimitry Andric   } else if (DefUsesInMBB.size() == 1) {
470b57cec5SDimitry Andric     // Insert the copy immediately after the def/use.
480b57cec5SDimitry Andric     InsertPoint = *DefUsesInMBB.begin();
490b57cec5SDimitry Andric     ++InsertPoint;
500b57cec5SDimitry Andric   } else {
510b57cec5SDimitry Andric     // Insert the copy immediately after the last def/use.
520b57cec5SDimitry Andric     InsertPoint = MBB->end();
530b57cec5SDimitry Andric     while (!DefUsesInMBB.count(&*--InsertPoint)) {}
540b57cec5SDimitry Andric     ++InsertPoint;
550b57cec5SDimitry Andric   }
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   // Make sure the copy goes after any phi nodes but before
580b57cec5SDimitry Andric   // any debug nodes.
590b57cec5SDimitry Andric   return MBB->SkipPHIsAndLabels(InsertPoint);
600b57cec5SDimitry Andric }
61