1//===- AArch64PostCoalescerPass.cpp - AArch64 Post Coalescer pass ---------===//
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
10#include "AArch64.h"
11#include "AArch64MachineFunctionInfo.h"
12#include "llvm/CodeGen/LiveIntervals.h"
13#include "llvm/CodeGen/MachineFunctionPass.h"
14#include "llvm/CodeGen/MachineRegisterInfo.h"
15#include "llvm/CodeGen/Passes.h"
16#include "llvm/InitializePasses.h"
17
18using namespace llvm;
19
20#define DEBUG_TYPE "aarch64-post-coalescer"
21
22namespace {
23
24bool runAArch64PostCoalescer(MachineFunction &MF, LiveIntervals &LIS) {
25 AArch64FunctionInfo *FuncInfo = MF.getInfo<AArch64FunctionInfo>();
26 if (!FuncInfo->hasStreamingModeChanges())
27 return false;
28
29 MachineRegisterInfo &MRI = MF.getRegInfo();
30 bool Changed = false;
31
32 for (MachineBasicBlock &MBB : MF) {
33 for (MachineInstr &MI : make_early_inc_range(Range&: MBB)) {
34 switch (MI.getOpcode()) {
35 default:
36 break;
37 case AArch64::COALESCER_BARRIER_FPR16:
38 case AArch64::COALESCER_BARRIER_FPR32:
39 case AArch64::COALESCER_BARRIER_FPR64:
40 case AArch64::COALESCER_BARRIER_FPR128: {
41 Register Src = MI.getOperand(i: 1).getReg();
42 Register Dst = MI.getOperand(i: 0).getReg();
43 if (Src != Dst)
44 MRI.replaceRegWith(FromReg: Dst, ToReg: Src);
45
46 if (MI.getOperand(i: 1).isUndef())
47 for (MachineOperand &MO : MRI.use_operands(Reg: Dst))
48 MO.setIsUndef();
49
50 // MI must be erased from the basic block before recalculating the live
51 // interval.
52 LIS.RemoveMachineInstrFromMaps(MI);
53 MI.eraseFromParent();
54
55 LIS.removeInterval(Reg: Src);
56 LIS.createAndComputeVirtRegInterval(Reg: Src);
57
58 Changed = true;
59 break;
60 }
61 }
62 }
63 }
64
65 return Changed;
66}
67
68struct AArch64PostCoalescerLegacy : public MachineFunctionPass {
69 static char ID;
70
71 AArch64PostCoalescerLegacy() : MachineFunctionPass(ID) {}
72
73 bool runOnMachineFunction(MachineFunction &MF) override;
74
75 StringRef getPassName() const override {
76 return "AArch64 Post Coalescer pass";
77 }
78
79 void getAnalysisUsage(AnalysisUsage &AU) const override {
80 AU.setPreservesCFG();
81 AU.addRequired<LiveIntervalsWrapperPass>();
82 AU.addPreserved<LiveIntervalsWrapperPass>();
83 AU.addPreserved<SlotIndexesWrapperPass>();
84 MachineFunctionPass::getAnalysisUsage(AU);
85 }
86};
87
88char AArch64PostCoalescerLegacy::ID = 0;
89
90} // end anonymous namespace
91
92INITIALIZE_PASS_BEGIN(AArch64PostCoalescerLegacy, "aarch64-post-coalescer",
93 "AArch64 Post Coalescer Pass", false, false)
94INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass)
95INITIALIZE_PASS_END(AArch64PostCoalescerLegacy, "aarch64-post-coalescer",
96 "AArch64 Post Coalescer Pass", false, false)
97
98bool AArch64PostCoalescerLegacy::runOnMachineFunction(MachineFunction &MF) {
99 if (skipFunction(F: MF.getFunction()))
100 return false;
101
102 auto &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
103 return runAArch64PostCoalescer(MF, LIS);
104}
105
106PreservedAnalyses
107AArch64PostCoalescerPass::run(MachineFunction &MF,
108 MachineFunctionAnalysisManager &MFAM) {
109 auto &LIS = MFAM.getResult<LiveIntervalsAnalysis>(IR&: MF);
110 const bool Changed = runAArch64PostCoalescer(MF, LIS);
111 if (!Changed)
112 return PreservedAnalyses::all();
113 PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
114 PA.preserveSet<CFGAnalyses>();
115 PA.preserve<LiveIntervalsAnalysis>();
116 PA.preserve<SlotIndexesAnalysis>();
117 return PA;
118}
119
120FunctionPass *llvm::createAArch64PostCoalescerPass() {
121 return new AArch64PostCoalescerLegacy();
122}
123