]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- HexagonExpandPredSpillCode.cpp - Expand Predicate Spill Code ------===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is distributed under the University of Illinois Open Source | |
6 | // License. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // The Hexagon processor has no instructions that load or store predicate | |
10 | // registers directly. So, when these registers must be spilled a general | |
11 | // purpose register must be found and the value copied to/from it from/to | |
12 | // the predicate register. This code currently does not use the register | |
13 | // scavenger mechanism available in the allocator. There are two registers | |
14 | // reserved to allow spilling/restoring predicate registers. One is used to | |
15 | // hold the predicate value. The other is used when stack frame offsets are | |
16 | // too large. | |
17 | // | |
18 | //===----------------------------------------------------------------------===// | |
19 | ||
970d7e83 | 20 | #include "Hexagon.h" |
223e47cc | 21 | #include "HexagonMachineFunctionInfo.h" |
970d7e83 LB |
22 | #include "HexagonSubtarget.h" |
23 | #include "HexagonTargetMachine.h" | |
223e47cc LB |
24 | #include "llvm/ADT/Statistic.h" |
25 | #include "llvm/CodeGen/LatencyPriorityQueue.h" | |
26 | #include "llvm/CodeGen/MachineDominators.h" | |
27 | #include "llvm/CodeGen/MachineFunctionPass.h" | |
28 | #include "llvm/CodeGen/MachineInstrBuilder.h" | |
29 | #include "llvm/CodeGen/MachineLoopInfo.h" | |
30 | #include "llvm/CodeGen/MachineRegisterInfo.h" | |
31 | #include "llvm/CodeGen/Passes.h" | |
32 | #include "llvm/CodeGen/ScheduleHazardRecognizer.h" | |
33 | #include "llvm/CodeGen/SchedulerRegistry.h" | |
223e47cc LB |
34 | #include "llvm/Support/Compiler.h" |
35 | #include "llvm/Support/Debug.h" | |
36 | #include "llvm/Support/MathExtras.h" | |
970d7e83 LB |
37 | #include "llvm/Target/TargetInstrInfo.h" |
38 | #include "llvm/Target/TargetMachine.h" | |
39 | #include "llvm/Target/TargetRegisterInfo.h" | |
223e47cc LB |
40 | |
41 | using namespace llvm; | |
42 | ||
43 | ||
1a4d82fc JJ |
44 | namespace llvm { |
45 | void initializeHexagonExpandPredSpillCodePass(PassRegistry&); | |
46 | } | |
47 | ||
48 | ||
223e47cc LB |
49 | namespace { |
50 | ||
51 | class HexagonExpandPredSpillCode : public MachineFunctionPass { | |
1a4d82fc | 52 | const HexagonTargetMachine& QTM; |
223e47cc LB |
53 | const HexagonSubtarget &QST; |
54 | ||
55 | public: | |
56 | static char ID; | |
1a4d82fc JJ |
57 | HexagonExpandPredSpillCode(const HexagonTargetMachine& TM) : |
58 | MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) { | |
59 | PassRegistry &Registry = *PassRegistry::getPassRegistry(); | |
60 | initializeHexagonExpandPredSpillCodePass(Registry); | |
61 | } | |
223e47cc | 62 | |
1a4d82fc | 63 | const char *getPassName() const override { |
223e47cc LB |
64 | return "Hexagon Expand Predicate Spill Code"; |
65 | } | |
1a4d82fc | 66 | bool runOnMachineFunction(MachineFunction &Fn) override; |
223e47cc LB |
67 | }; |
68 | ||
69 | ||
70 | char HexagonExpandPredSpillCode::ID = 0; | |
71 | ||
72 | ||
73 | bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) { | |
74 | ||
1a4d82fc | 75 | const HexagonInstrInfo *TII = QTM.getSubtargetImpl()->getInstrInfo(); |
223e47cc LB |
76 | |
77 | // Loop over all of the basic blocks. | |
78 | for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); | |
79 | MBBb != MBBe; ++MBBb) { | |
80 | MachineBasicBlock* MBB = MBBb; | |
81 | // Traverse the basic block. | |
82 | for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); | |
83 | ++MII) { | |
84 | MachineInstr *MI = MII; | |
85 | int Opc = MI->getOpcode(); | |
86 | if (Opc == Hexagon::STriw_pred) { | |
87 | // STriw_pred [R30], ofst, SrcReg; | |
88 | unsigned FP = MI->getOperand(0).getReg(); | |
1a4d82fc JJ |
89 | assert( |
90 | FP == | |
91 | QTM.getSubtargetImpl()->getRegisterInfo()->getFrameRegister() && | |
92 | "Not a Frame Pointer, Nor a Spill Slot"); | |
223e47cc LB |
93 | assert(MI->getOperand(1).isImm() && "Not an offset"); |
94 | int Offset = MI->getOperand(1).getImm(); | |
95 | int SrcReg = MI->getOperand(2).getReg(); | |
96 | assert(Hexagon::PredRegsRegClass.contains(SrcReg) && | |
97 | "Not a predicate register"); | |
85aaf69f | 98 | if (!TII->isValidOffset(Hexagon::S2_storeri_io, Offset)) { |
223e47cc LB |
99 | if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { |
100 | BuildMI(*MBB, MII, MI->getDebugLoc(), | |
101 | TII->get(Hexagon::CONST32_Int_Real), | |
102 | HEXAGON_RESERVED_REG_1).addImm(Offset); | |
85aaf69f | 103 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add), |
223e47cc LB |
104 | HEXAGON_RESERVED_REG_1) |
105 | .addReg(FP).addReg(HEXAGON_RESERVED_REG_1); | |
85aaf69f | 106 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), |
223e47cc LB |
107 | HEXAGON_RESERVED_REG_2).addReg(SrcReg); |
108 | BuildMI(*MBB, MII, MI->getDebugLoc(), | |
85aaf69f | 109 | TII->get(Hexagon::S2_storeri_io)) |
223e47cc LB |
110 | .addReg(HEXAGON_RESERVED_REG_1) |
111 | .addImm(0).addReg(HEXAGON_RESERVED_REG_2); | |
112 | } else { | |
113 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), | |
114 | HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); | |
85aaf69f | 115 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), |
223e47cc LB |
116 | HEXAGON_RESERVED_REG_2).addReg(SrcReg); |
117 | BuildMI(*MBB, MII, MI->getDebugLoc(), | |
85aaf69f | 118 | TII->get(Hexagon::S2_storeri_io)) |
223e47cc LB |
119 | .addReg(HEXAGON_RESERVED_REG_1) |
120 | .addImm(0) | |
121 | .addReg(HEXAGON_RESERVED_REG_2); | |
122 | } | |
123 | } else { | |
85aaf69f | 124 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), |
223e47cc LB |
125 | HEXAGON_RESERVED_REG_2).addReg(SrcReg); |
126 | BuildMI(*MBB, MII, MI->getDebugLoc(), | |
85aaf69f | 127 | TII->get(Hexagon::S2_storeri_io)). |
223e47cc LB |
128 | addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2); |
129 | } | |
130 | MII = MBB->erase(MI); | |
131 | --MII; | |
132 | } else if (Opc == Hexagon::LDriw_pred) { | |
133 | // DstReg = LDriw_pred [R30], ofst. | |
134 | int DstReg = MI->getOperand(0).getReg(); | |
135 | assert(Hexagon::PredRegsRegClass.contains(DstReg) && | |
136 | "Not a predicate register"); | |
137 | unsigned FP = MI->getOperand(1).getReg(); | |
1a4d82fc JJ |
138 | assert( |
139 | FP == | |
140 | QTM.getSubtargetImpl()->getRegisterInfo()->getFrameRegister() && | |
141 | "Not a Frame Pointer, Nor a Spill Slot"); | |
223e47cc LB |
142 | assert(MI->getOperand(2).isImm() && "Not an offset"); |
143 | int Offset = MI->getOperand(2).getImm(); | |
85aaf69f | 144 | if (!TII->isValidOffset(Hexagon::L2_loadri_io, Offset)) { |
223e47cc LB |
145 | if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { |
146 | BuildMI(*MBB, MII, MI->getDebugLoc(), | |
147 | TII->get(Hexagon::CONST32_Int_Real), | |
148 | HEXAGON_RESERVED_REG_1).addImm(Offset); | |
85aaf69f | 149 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add), |
223e47cc LB |
150 | HEXAGON_RESERVED_REG_1) |
151 | .addReg(FP) | |
152 | .addReg(HEXAGON_RESERVED_REG_1); | |
85aaf69f | 153 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), |
223e47cc LB |
154 | HEXAGON_RESERVED_REG_2) |
155 | .addReg(HEXAGON_RESERVED_REG_1) | |
156 | .addImm(0); | |
85aaf69f | 157 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), |
223e47cc LB |
158 | DstReg).addReg(HEXAGON_RESERVED_REG_2); |
159 | } else { | |
160 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), | |
161 | HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); | |
85aaf69f | 162 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), |
223e47cc LB |
163 | HEXAGON_RESERVED_REG_2) |
164 | .addReg(HEXAGON_RESERVED_REG_1) | |
165 | .addImm(0); | |
85aaf69f | 166 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), |
223e47cc LB |
167 | DstReg).addReg(HEXAGON_RESERVED_REG_2); |
168 | } | |
169 | } else { | |
85aaf69f | 170 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), |
223e47cc | 171 | HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset); |
85aaf69f | 172 | BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), |
223e47cc LB |
173 | DstReg).addReg(HEXAGON_RESERVED_REG_2); |
174 | } | |
175 | MII = MBB->erase(MI); | |
176 | --MII; | |
177 | } | |
178 | } | |
179 | } | |
180 | ||
181 | return true; | |
182 | } | |
183 | ||
184 | } | |
185 | ||
186 | //===----------------------------------------------------------------------===// | |
187 | // Public Constructor Functions | |
188 | //===----------------------------------------------------------------------===// | |
189 | ||
1a4d82fc JJ |
190 | static void initializePassOnce(PassRegistry &Registry) { |
191 | const char *Name = "Hexagon Expand Predicate Spill Code"; | |
192 | PassInfo *PI = new PassInfo(Name, "hexagon-spill-pred", | |
193 | &HexagonExpandPredSpillCode::ID, | |
194 | nullptr, false, false); | |
195 | Registry.registerPass(*PI, true); | |
196 | } | |
197 | ||
198 | void llvm::initializeHexagonExpandPredSpillCodePass(PassRegistry &Registry) { | |
199 | CALL_ONCE_INITIALIZATION(initializePassOnce) | |
200 | } | |
201 | ||
202 | FunctionPass* | |
203 | llvm::createHexagonExpandPredSpillCode(const HexagonTargetMachine &TM) { | |
223e47cc LB |
204 | return new HexagonExpandPredSpillCode(TM); |
205 | } |