1 //===- ARCBranchFinalize.cpp - ARC conditional branches ---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This pass takes existing conditional branches and expands them into longer
10 // range conditional branches.
11 //===----------------------------------------------------------------------===//
13 #define DEBUG_TYPE "arc-branch-finalize"
15 #include "ARCInstrInfo.h"
16 #include "ARCTargetMachine.h"
17 #include "MCTargetDesc/ARCInfo.h"
18 #include "llvm/CodeGen/MachineFunctionPass.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/CodeGen/Passes.h"
22 #include "llvm/CodeGen/TargetInstrInfo.h"
23 #include "llvm/Support/Debug.h"
30 void initializeARCBranchFinalizePass(PassRegistry
&Registry
);
31 FunctionPass
*createARCBranchFinalizePass();
33 } // end namespace llvm
37 class ARCBranchFinalize
: public MachineFunctionPass
{
41 ARCBranchFinalize() : MachineFunctionPass(ID
) {
42 initializeARCBranchFinalizePass(*PassRegistry::getPassRegistry());
45 StringRef
getPassName() const override
{
46 return "ARC Branch Finalization Pass";
49 bool runOnMachineFunction(MachineFunction
&MF
) override
;
50 void replaceWithBRcc(MachineInstr
*MI
) const;
51 void replaceWithCmpBcc(MachineInstr
*MI
) const;
54 const ARCInstrInfo
*TII
{nullptr};
57 char ARCBranchFinalize::ID
= 0;
59 } // end anonymous namespace
61 INITIALIZE_PASS_BEGIN(ARCBranchFinalize
, "arc-branch-finalize",
62 "ARC finalize branches", false, false)
63 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree
)
64 INITIALIZE_PASS_END(ARCBranchFinalize
, "arc-branch-finalize",
65 "ARC finalize branches", false, false)
67 // BRcc has 6 supported condition codes, which differ from the 16
68 // condition codes supported in the predicated instructions:
75 static unsigned getCCForBRcc(unsigned CC
) {
94 static bool isBRccPseudo(MachineInstr
*MI
) {
95 return !(MI
->getOpcode() != ARC::BRcc_rr_p
&&
96 MI
->getOpcode() != ARC::BRcc_ru6_p
);
99 static unsigned getBRccForPseudo(MachineInstr
*MI
) {
100 assert(isBRccPseudo(MI
) && "Can't get BRcc for wrong instruction.");
101 if (MI
->getOpcode() == ARC::BRcc_rr_p
)
103 return ARC::BRcc_ru6
;
106 static unsigned getCmpForPseudo(MachineInstr
*MI
) {
107 assert(isBRccPseudo(MI
) && "Can't get BRcc for wrong instruction.");
108 if (MI
->getOpcode() == ARC::BRcc_rr_p
)
113 void ARCBranchFinalize::replaceWithBRcc(MachineInstr
*MI
) const {
114 LLVM_DEBUG(dbgs() << "Replacing pseudo branch with BRcc\n");
115 unsigned CC
= getCCForBRcc(MI
->getOperand(3).getImm());
117 BuildMI(*MI
->getParent(), MI
, MI
->getDebugLoc(),
118 TII
->get(getBRccForPseudo(MI
)))
119 .addMBB(MI
->getOperand(0).getMBB())
120 .addReg(MI
->getOperand(1).getReg())
121 .add(MI
->getOperand(2))
122 .addImm(getCCForBRcc(MI
->getOperand(3).getImm()));
123 MI
->eraseFromParent();
125 replaceWithCmpBcc(MI
);
129 void ARCBranchFinalize::replaceWithCmpBcc(MachineInstr
*MI
) const {
130 LLVM_DEBUG(dbgs() << "Branch: " << *MI
<< "\n");
131 LLVM_DEBUG(dbgs() << "Replacing pseudo branch with Cmp + Bcc\n");
132 BuildMI(*MI
->getParent(), MI
, MI
->getDebugLoc(),
133 TII
->get(getCmpForPseudo(MI
)))
134 .addReg(MI
->getOperand(1).getReg())
135 .add(MI
->getOperand(2));
136 BuildMI(*MI
->getParent(), MI
, MI
->getDebugLoc(), TII
->get(ARC::Bcc
))
137 .addMBB(MI
->getOperand(0).getMBB())
138 .addImm(MI
->getOperand(3).getImm());
139 MI
->eraseFromParent();
142 bool ARCBranchFinalize::runOnMachineFunction(MachineFunction
&MF
) {
143 LLVM_DEBUG(dbgs() << "Running ARC Branch Finalize on " << MF
.getName()
145 std::vector
<MachineInstr
*> Branches
;
146 bool Changed
= false;
147 unsigned MaxSize
= 0;
148 TII
= MF
.getSubtarget
<ARCSubtarget
>().getInstrInfo();
149 std::map
<MachineBasicBlock
*, unsigned> BlockToPCMap
;
150 std::vector
<std::pair
<MachineInstr
*, unsigned>> BranchToPCList
;
153 for (auto &MBB
: MF
) {
154 BlockToPCMap
.insert(std::make_pair(&MBB
, PC
));
155 for (auto &MI
: MBB
) {
156 unsigned Size
= TII
->getInstSizeInBytes(MI
);
157 if (Size
> 8 || Size
== 0) {
158 LLVM_DEBUG(dbgs() << "Unknown (or size 0) size for: " << MI
<< "\n");
163 Branches
.push_back(&MI
);
164 BranchToPCList
.emplace_back(&MI
, PC
);
169 for (auto P
: BranchToPCList
) {
170 if (isBRccPseudo(P
.first
))
171 isInt
<9>(MaxSize
) ? replaceWithBRcc(P
.first
) : replaceWithCmpBcc(P
.first
);
174 LLVM_DEBUG(dbgs() << "Estimated function size for " << MF
.getName() << ": "
180 FunctionPass
*llvm::createARCBranchFinalizePass() {
181 return new ARCBranchFinalize();