1 | //===-- MipsExpandPseudoInsts.cpp - Expand pseudo instructions ------------===// |
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 | // This file contains a pass that expands pseudo instructions into target |
10 | // instructions to allow proper scheduling, if-conversion, and other late |
11 | // optimizations. This pass should be run after register allocation but before |
12 | // the post-regalloc scheduling pass. |
13 | // |
14 | // This is currently only used for expanding atomic pseudos after register |
15 | // allocation. We do this to avoid the fast register allocator introducing |
16 | // spills between ll and sc. These stores cause some MIPS implementations to |
17 | // abort the atomic RMW sequence. |
18 | // |
19 | //===----------------------------------------------------------------------===// |
20 | |
21 | #include "Mips.h" |
22 | #include "MipsInstrInfo.h" |
23 | #include "MipsSubtarget.h" |
24 | #include "llvm/CodeGen/LivePhysRegs.h" |
25 | #include "llvm/CodeGen/MachineFunctionPass.h" |
26 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
27 | |
28 | using namespace llvm; |
29 | |
30 | #define DEBUG_TYPE "mips-pseudo" |
31 | |
32 | namespace { |
33 | class MipsExpandPseudo : public MachineFunctionPass { |
34 | public: |
35 | static char ID; |
36 | MipsExpandPseudo() : MachineFunctionPass(ID) {} |
37 | |
38 | const MipsInstrInfo *TII; |
39 | const MipsSubtarget *STI; |
40 | |
41 | bool runOnMachineFunction(MachineFunction &Fn) override; |
42 | |
43 | MachineFunctionProperties getRequiredProperties() const override { |
44 | return MachineFunctionProperties().setNoVRegs(); |
45 | } |
46 | |
47 | StringRef getPassName() const override { |
48 | return "Mips pseudo instruction expansion pass" ; |
49 | } |
50 | |
51 | private: |
52 | bool expandAtomicCmpSwap(MachineBasicBlock &MBB, |
53 | MachineBasicBlock::iterator MBBI, |
54 | MachineBasicBlock::iterator &NextMBBI); |
55 | bool expandAtomicCmpSwapSubword(MachineBasicBlock &MBB, |
56 | MachineBasicBlock::iterator MBBI, |
57 | MachineBasicBlock::iterator &NextMBBI); |
58 | |
59 | bool expandAtomicBinOp(MachineBasicBlock &BB, |
60 | MachineBasicBlock::iterator I, |
61 | MachineBasicBlock::iterator &NMBBI, unsigned Size); |
62 | bool expandAtomicBinOpSubword(MachineBasicBlock &BB, |
63 | MachineBasicBlock::iterator I, |
64 | MachineBasicBlock::iterator &NMBBI); |
65 | |
66 | bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, |
67 | MachineBasicBlock::iterator &NMBB); |
68 | bool expandMBB(MachineBasicBlock &MBB); |
69 | }; |
70 | char MipsExpandPseudo::ID = 0; |
71 | } |
72 | |
73 | bool MipsExpandPseudo::expandAtomicCmpSwapSubword( |
74 | MachineBasicBlock &BB, MachineBasicBlock::iterator I, |
75 | MachineBasicBlock::iterator &NMBBI) { |
76 | |
77 | MachineFunction *MF = BB.getParent(); |
78 | |
79 | const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); |
80 | DebugLoc DL = I->getDebugLoc(); |
81 | unsigned LL, SC; |
82 | |
83 | unsigned ZERO = Mips::ZERO; |
84 | unsigned BNE = Mips::BNE; |
85 | unsigned BEQ = Mips::BEQ; |
86 | unsigned SEOp = |
87 | I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I8_POSTRA ? Mips::SEB : Mips::SEH; |
88 | |
89 | if (STI->inMicroMipsMode()) { |
90 | LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; |
91 | SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; |
92 | BNE = STI->hasMips32r6() ? Mips::BNEC_MMR6 : Mips::BNE_MM; |
93 | BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; |
94 | } else { |
95 | LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) |
96 | : (ArePtrs64bit ? Mips::LL64 : Mips::LL); |
97 | SC = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) |
98 | : (ArePtrs64bit ? Mips::SC64 : Mips::SC); |
99 | } |
100 | |
101 | Register Dest = I->getOperand(i: 0).getReg(); |
102 | Register Ptr = I->getOperand(i: 1).getReg(); |
103 | Register Mask = I->getOperand(i: 2).getReg(); |
104 | Register ShiftCmpVal = I->getOperand(i: 3).getReg(); |
105 | Register Mask2 = I->getOperand(i: 4).getReg(); |
106 | Register ShiftNewVal = I->getOperand(i: 5).getReg(); |
107 | Register ShiftAmnt = I->getOperand(i: 6).getReg(); |
108 | Register Scratch = I->getOperand(i: 7).getReg(); |
109 | Register Scratch2 = I->getOperand(i: 8).getReg(); |
110 | |
111 | // insert new blocks after the current block |
112 | const BasicBlock *LLVM_BB = BB.getBasicBlock(); |
113 | MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
114 | MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
115 | MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
116 | MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
117 | MachineFunction::iterator It = ++BB.getIterator(); |
118 | MF->insert(MBBI: It, MBB: loop1MBB); |
119 | MF->insert(MBBI: It, MBB: loop2MBB); |
120 | MF->insert(MBBI: It, MBB: sinkMBB); |
121 | MF->insert(MBBI: It, MBB: exitMBB); |
122 | |
123 | // Transfer the remainder of BB and its successor edges to exitMBB. |
124 | exitMBB->splice(Where: exitMBB->begin(), Other: &BB, |
125 | From: std::next(x: MachineBasicBlock::iterator(I)), To: BB.end()); |
126 | exitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &BB); |
127 | |
128 | // thisMBB: |
129 | // ... |
130 | // fallthrough --> loop1MBB |
131 | BB.addSuccessor(Succ: loop1MBB, Prob: BranchProbability::getOne()); |
132 | loop1MBB->addSuccessor(Succ: sinkMBB); |
133 | loop1MBB->addSuccessor(Succ: loop2MBB); |
134 | loop1MBB->normalizeSuccProbs(); |
135 | loop2MBB->addSuccessor(Succ: loop1MBB); |
136 | loop2MBB->addSuccessor(Succ: sinkMBB); |
137 | loop2MBB->normalizeSuccProbs(); |
138 | sinkMBB->addSuccessor(Succ: exitMBB, Prob: BranchProbability::getOne()); |
139 | |
140 | // loop1MBB: |
141 | // ll dest, 0(ptr) |
142 | // and Mask', dest, Mask |
143 | // bne Mask', ShiftCmpVal, exitMBB |
144 | BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: LL), DestReg: Scratch).addReg(RegNo: Ptr).addImm(Val: 0); |
145 | BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: Scratch2) |
146 | .addReg(RegNo: Scratch) |
147 | .addReg(RegNo: Mask); |
148 | BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: BNE)) |
149 | .addReg(RegNo: Scratch2).addReg(RegNo: ShiftCmpVal).addMBB(MBB: sinkMBB); |
150 | |
151 | // loop2MBB: |
152 | // and dest, dest, mask2 |
153 | // or dest, dest, ShiftNewVal |
154 | // sc dest, dest, 0(ptr) |
155 | // beq dest, $0, loop1MBB |
156 | BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: Scratch) |
157 | .addReg(RegNo: Scratch, flags: RegState::Kill) |
158 | .addReg(RegNo: Mask2); |
159 | BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: Mips::OR), DestReg: Scratch) |
160 | .addReg(RegNo: Scratch, flags: RegState::Kill) |
161 | .addReg(RegNo: ShiftNewVal); |
162 | BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: Scratch) |
163 | .addReg(RegNo: Scratch, flags: RegState::Kill) |
164 | .addReg(RegNo: Ptr) |
165 | .addImm(Val: 0); |
166 | BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: BEQ)) |
167 | .addReg(RegNo: Scratch, flags: RegState::Kill) |
168 | .addReg(RegNo: ZERO) |
169 | .addMBB(MBB: loop1MBB); |
170 | |
171 | // sinkMBB: |
172 | // srl srlres, Mask', shiftamt |
173 | // sign_extend dest,srlres |
174 | BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRLV), DestReg: Dest) |
175 | .addReg(RegNo: Scratch2) |
176 | .addReg(RegNo: ShiftAmnt); |
177 | if (STI->hasMips32r2()) { |
178 | BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: SEOp), DestReg: Dest).addReg(RegNo: Dest); |
179 | } else { |
180 | const unsigned ShiftImm = |
181 | I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I16_POSTRA ? 16 : 24; |
182 | BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SLL), DestReg: Dest) |
183 | .addReg(RegNo: Dest, flags: RegState::Kill) |
184 | .addImm(Val: ShiftImm); |
185 | BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRA), DestReg: Dest) |
186 | .addReg(RegNo: Dest, flags: RegState::Kill) |
187 | .addImm(Val: ShiftImm); |
188 | } |
189 | |
190 | LivePhysRegs LiveRegs; |
191 | computeAndAddLiveIns(LiveRegs, MBB&: *loop1MBB); |
192 | computeAndAddLiveIns(LiveRegs, MBB&: *loop2MBB); |
193 | computeAndAddLiveIns(LiveRegs, MBB&: *sinkMBB); |
194 | computeAndAddLiveIns(LiveRegs, MBB&: *exitMBB); |
195 | |
196 | NMBBI = BB.end(); |
197 | I->eraseFromParent(); |
198 | return true; |
199 | } |
200 | |
201 | bool MipsExpandPseudo::expandAtomicCmpSwap(MachineBasicBlock &BB, |
202 | MachineBasicBlock::iterator I, |
203 | MachineBasicBlock::iterator &NMBBI) { |
204 | |
205 | const unsigned Size = |
206 | I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I32_POSTRA ? 4 : 8; |
207 | MachineFunction *MF = BB.getParent(); |
208 | |
209 | const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); |
210 | DebugLoc DL = I->getDebugLoc(); |
211 | |
212 | unsigned LL, SC, ZERO, BNE, BEQ, MOVE; |
213 | |
214 | if (Size == 4) { |
215 | if (STI->inMicroMipsMode()) { |
216 | LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; |
217 | SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; |
218 | BNE = STI->hasMips32r6() ? Mips::BNEC_MMR6 : Mips::BNE_MM; |
219 | BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; |
220 | } else { |
221 | LL = STI->hasMips32r6() |
222 | ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) |
223 | : (ArePtrs64bit ? Mips::LL64 : Mips::LL); |
224 | SC = STI->hasMips32r6() |
225 | ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) |
226 | : (ArePtrs64bit ? Mips::SC64 : Mips::SC); |
227 | BNE = Mips::BNE; |
228 | BEQ = Mips::BEQ; |
229 | } |
230 | |
231 | ZERO = Mips::ZERO; |
232 | MOVE = Mips::OR; |
233 | } else { |
234 | LL = STI->hasMips64r6() ? Mips::LLD_R6 : Mips::LLD; |
235 | SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD; |
236 | ZERO = Mips::ZERO_64; |
237 | BNE = Mips::BNE64; |
238 | BEQ = Mips::BEQ64; |
239 | MOVE = Mips::OR64; |
240 | } |
241 | |
242 | Register Dest = I->getOperand(i: 0).getReg(); |
243 | Register Ptr = I->getOperand(i: 1).getReg(); |
244 | Register OldVal = I->getOperand(i: 2).getReg(); |
245 | Register NewVal = I->getOperand(i: 3).getReg(); |
246 | Register Scratch = I->getOperand(i: 4).getReg(); |
247 | |
248 | // insert new blocks after the current block |
249 | const BasicBlock *LLVM_BB = BB.getBasicBlock(); |
250 | MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
251 | MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
252 | MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
253 | MachineFunction::iterator It = ++BB.getIterator(); |
254 | MF->insert(MBBI: It, MBB: loop1MBB); |
255 | MF->insert(MBBI: It, MBB: loop2MBB); |
256 | MF->insert(MBBI: It, MBB: exitMBB); |
257 | |
258 | // Transfer the remainder of BB and its successor edges to exitMBB. |
259 | exitMBB->splice(Where: exitMBB->begin(), Other: &BB, |
260 | From: std::next(x: MachineBasicBlock::iterator(I)), To: BB.end()); |
261 | exitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &BB); |
262 | |
263 | // thisMBB: |
264 | // ... |
265 | // fallthrough --> loop1MBB |
266 | BB.addSuccessor(Succ: loop1MBB, Prob: BranchProbability::getOne()); |
267 | loop1MBB->addSuccessor(Succ: exitMBB); |
268 | loop1MBB->addSuccessor(Succ: loop2MBB); |
269 | loop1MBB->normalizeSuccProbs(); |
270 | loop2MBB->addSuccessor(Succ: loop1MBB); |
271 | loop2MBB->addSuccessor(Succ: exitMBB); |
272 | loop2MBB->normalizeSuccProbs(); |
273 | |
274 | // loop1MBB: |
275 | // ll dest, 0(ptr) |
276 | // bne dest, oldval, exitMBB |
277 | BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: LL), DestReg: Dest).addReg(RegNo: Ptr).addImm(Val: 0); |
278 | BuildMI(BB: loop1MBB, MIMD: DL, MCID: TII->get(Opcode: BNE)) |
279 | .addReg(RegNo: Dest, flags: RegState::Kill).addReg(RegNo: OldVal).addMBB(MBB: exitMBB); |
280 | |
281 | // loop2MBB: |
282 | // move scratch, NewVal |
283 | // sc Scratch, Scratch, 0(ptr) |
284 | // beq Scratch, $0, loop1MBB |
285 | BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: MOVE), DestReg: Scratch).addReg(RegNo: NewVal).addReg(RegNo: ZERO); |
286 | BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: Scratch) |
287 | .addReg(RegNo: Scratch).addReg(RegNo: Ptr).addImm(Val: 0); |
288 | BuildMI(BB: loop2MBB, MIMD: DL, MCID: TII->get(Opcode: BEQ)) |
289 | .addReg(RegNo: Scratch, flags: RegState::Kill).addReg(RegNo: ZERO).addMBB(MBB: loop1MBB); |
290 | |
291 | LivePhysRegs LiveRegs; |
292 | computeAndAddLiveIns(LiveRegs, MBB&: *loop1MBB); |
293 | computeAndAddLiveIns(LiveRegs, MBB&: *loop2MBB); |
294 | computeAndAddLiveIns(LiveRegs, MBB&: *exitMBB); |
295 | |
296 | NMBBI = BB.end(); |
297 | I->eraseFromParent(); |
298 | return true; |
299 | } |
300 | |
301 | bool MipsExpandPseudo::expandAtomicBinOpSubword( |
302 | MachineBasicBlock &BB, MachineBasicBlock::iterator I, |
303 | MachineBasicBlock::iterator &NMBBI) { |
304 | |
305 | MachineFunction *MF = BB.getParent(); |
306 | |
307 | const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); |
308 | DebugLoc DL = I->getDebugLoc(); |
309 | |
310 | unsigned LL, SC, SLT, SLTu, OR, MOVN, MOVZ, SELNEZ, SELEQZ; |
311 | unsigned BEQ = Mips::BEQ; |
312 | unsigned SEOp = Mips::SEH; |
313 | |
314 | if (STI->inMicroMipsMode()) { |
315 | LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; |
316 | SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; |
317 | BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; |
318 | SLT = Mips::SLT_MM; |
319 | SLTu = Mips::SLTu_MM; |
320 | OR = STI->hasMips32r6() ? Mips::OR_MMR6 : Mips::OR_MM; |
321 | MOVN = Mips::MOVN_I_MM; |
322 | MOVZ = Mips::MOVZ_I_MM; |
323 | SELNEZ = STI->hasMips32r6() ? Mips::SELNEZ_MMR6 : Mips::SELNEZ; |
324 | SELEQZ = STI->hasMips32r6() ? Mips::SELEQZ_MMR6 : Mips::SELEQZ; |
325 | } else { |
326 | LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) |
327 | : (ArePtrs64bit ? Mips::LL64 : Mips::LL); |
328 | SC = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) |
329 | : (ArePtrs64bit ? Mips::SC64 : Mips::SC); |
330 | SLT = Mips::SLT; |
331 | SLTu = Mips::SLTu; |
332 | OR = Mips::OR; |
333 | MOVN = Mips::MOVN_I_I; |
334 | MOVZ = Mips::MOVZ_I_I; |
335 | SELNEZ = Mips::SELNEZ; |
336 | SELEQZ = Mips::SELEQZ; |
337 | } |
338 | |
339 | bool IsSwap = false; |
340 | bool IsNand = false; |
341 | bool IsMin = false; |
342 | bool IsMax = false; |
343 | bool IsUnsigned = false; |
344 | bool DestOK = false; |
345 | |
346 | unsigned Opcode = 0; |
347 | switch (I->getOpcode()) { |
348 | case Mips::ATOMIC_LOAD_NAND_I8_POSTRA: |
349 | SEOp = Mips::SEB; |
350 | [[fallthrough]]; |
351 | case Mips::ATOMIC_LOAD_NAND_I16_POSTRA: |
352 | IsNand = true; |
353 | break; |
354 | case Mips::ATOMIC_SWAP_I8_POSTRA: |
355 | SEOp = Mips::SEB; |
356 | [[fallthrough]]; |
357 | case Mips::ATOMIC_SWAP_I16_POSTRA: |
358 | IsSwap = true; |
359 | break; |
360 | case Mips::ATOMIC_LOAD_ADD_I8_POSTRA: |
361 | SEOp = Mips::SEB; |
362 | [[fallthrough]]; |
363 | case Mips::ATOMIC_LOAD_ADD_I16_POSTRA: |
364 | Opcode = Mips::ADDu; |
365 | break; |
366 | case Mips::ATOMIC_LOAD_SUB_I8_POSTRA: |
367 | SEOp = Mips::SEB; |
368 | [[fallthrough]]; |
369 | case Mips::ATOMIC_LOAD_SUB_I16_POSTRA: |
370 | Opcode = Mips::SUBu; |
371 | break; |
372 | case Mips::ATOMIC_LOAD_AND_I8_POSTRA: |
373 | SEOp = Mips::SEB; |
374 | [[fallthrough]]; |
375 | case Mips::ATOMIC_LOAD_AND_I16_POSTRA: |
376 | Opcode = Mips::AND; |
377 | break; |
378 | case Mips::ATOMIC_LOAD_OR_I8_POSTRA: |
379 | SEOp = Mips::SEB; |
380 | [[fallthrough]]; |
381 | case Mips::ATOMIC_LOAD_OR_I16_POSTRA: |
382 | Opcode = Mips::OR; |
383 | break; |
384 | case Mips::ATOMIC_LOAD_XOR_I8_POSTRA: |
385 | SEOp = Mips::SEB; |
386 | [[fallthrough]]; |
387 | case Mips::ATOMIC_LOAD_XOR_I16_POSTRA: |
388 | Opcode = Mips::XOR; |
389 | break; |
390 | case Mips::ATOMIC_LOAD_UMIN_I8_POSTRA: |
391 | SEOp = Mips::SEB; |
392 | IsUnsigned = true; |
393 | IsMin = true; |
394 | break; |
395 | case Mips::ATOMIC_LOAD_UMIN_I16_POSTRA: |
396 | IsUnsigned = true; |
397 | IsMin = true; |
398 | break; |
399 | case Mips::ATOMIC_LOAD_MIN_I8_POSTRA: |
400 | SEOp = Mips::SEB; |
401 | IsMin = true; |
402 | break; |
403 | case Mips::ATOMIC_LOAD_MIN_I16_POSTRA: |
404 | IsMin = true; |
405 | break; |
406 | case Mips::ATOMIC_LOAD_UMAX_I8_POSTRA: |
407 | SEOp = Mips::SEB; |
408 | IsUnsigned = true; |
409 | IsMax = true; |
410 | break; |
411 | case Mips::ATOMIC_LOAD_UMAX_I16_POSTRA: |
412 | IsUnsigned = true; |
413 | IsMax = true; |
414 | break; |
415 | case Mips::ATOMIC_LOAD_MAX_I8_POSTRA: |
416 | SEOp = Mips::SEB; |
417 | IsMax = true; |
418 | break; |
419 | case Mips::ATOMIC_LOAD_MAX_I16_POSTRA: |
420 | IsMax = true; |
421 | break; |
422 | default: |
423 | llvm_unreachable("Unknown subword atomic pseudo for expansion!" ); |
424 | } |
425 | |
426 | Register Dest = I->getOperand(i: 0).getReg(); |
427 | Register Ptr = I->getOperand(i: 1).getReg(); |
428 | Register Incr = I->getOperand(i: 2).getReg(); |
429 | Register Mask = I->getOperand(i: 3).getReg(); |
430 | Register Mask2 = I->getOperand(i: 4).getReg(); |
431 | Register ShiftAmnt = I->getOperand(i: 5).getReg(); |
432 | Register OldVal = I->getOperand(i: 6).getReg(); |
433 | Register BinOpRes = I->getOperand(i: 7).getReg(); |
434 | Register StoreVal = I->getOperand(i: 8).getReg(); |
435 | |
436 | const BasicBlock *LLVM_BB = BB.getBasicBlock(); |
437 | MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
438 | MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
439 | MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
440 | MachineFunction::iterator It = ++BB.getIterator(); |
441 | MF->insert(MBBI: It, MBB: loopMBB); |
442 | MF->insert(MBBI: It, MBB: sinkMBB); |
443 | MF->insert(MBBI: It, MBB: exitMBB); |
444 | |
445 | exitMBB->splice(Where: exitMBB->begin(), Other: &BB, From: std::next(x: I), To: BB.end()); |
446 | exitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &BB); |
447 | |
448 | BB.addSuccessor(Succ: loopMBB, Prob: BranchProbability::getOne()); |
449 | loopMBB->addSuccessor(Succ: sinkMBB); |
450 | loopMBB->addSuccessor(Succ: loopMBB); |
451 | loopMBB->normalizeSuccProbs(); |
452 | |
453 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: LL), DestReg: OldVal).addReg(RegNo: Ptr).addImm(Val: 0); |
454 | if (IsNand) { |
455 | // and andres, oldval, incr2 |
456 | // nor binopres, $0, andres |
457 | // and newval, binopres, mask |
458 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes) |
459 | .addReg(RegNo: OldVal) |
460 | .addReg(RegNo: Incr); |
461 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::NOR), DestReg: BinOpRes) |
462 | .addReg(RegNo: Mips::ZERO) |
463 | .addReg(RegNo: BinOpRes); |
464 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes) |
465 | .addReg(RegNo: BinOpRes) |
466 | .addReg(RegNo: Mask); |
467 | } else if (IsMin || IsMax) { |
468 | |
469 | assert(I->getNumOperands() == 10 && |
470 | "Atomics min|max|umin|umax use an additional register" ); |
471 | Register Scratch4 = I->getOperand(i: 9).getReg(); |
472 | |
473 | unsigned SLTScratch4 = IsUnsigned ? SLTu : SLT; |
474 | unsigned SELIncr = IsMax ? SELNEZ : SELEQZ; |
475 | unsigned SELOldVal = IsMax ? SELEQZ : SELNEZ; |
476 | unsigned MOVIncr = IsMax ? MOVN : MOVZ; |
477 | |
478 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRAV), DestReg: StoreVal) |
479 | .addReg(RegNo: OldVal) |
480 | .addReg(RegNo: ShiftAmnt); |
481 | if (IsUnsigned) { |
482 | const unsigned OpMask = SEOp == Mips::SEH ? 0xffff : 0xff; |
483 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::ANDi), DestReg: StoreVal) |
484 | .addReg(RegNo: StoreVal) |
485 | .addImm(Val: OpMask); |
486 | } else if (STI->hasMips32r2()) { |
487 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SEOp), DestReg: StoreVal).addReg(RegNo: StoreVal); |
488 | } else { |
489 | const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24; |
490 | const unsigned SROp = IsUnsigned ? Mips::SRL : Mips::SRA; |
491 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SLL), DestReg: StoreVal) |
492 | .addReg(RegNo: StoreVal, flags: RegState::Kill) |
493 | .addImm(Val: ShiftImm); |
494 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SROp), DestReg: StoreVal) |
495 | .addReg(RegNo: StoreVal, flags: RegState::Kill) |
496 | .addImm(Val: ShiftImm); |
497 | } |
498 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::OR), DestReg: Dest) |
499 | .addReg(RegNo: Mips::ZERO) |
500 | .addReg(RegNo: StoreVal); |
501 | DestOK = true; |
502 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SLLV), DestReg: StoreVal) |
503 | .addReg(RegNo: StoreVal) |
504 | .addReg(RegNo: ShiftAmnt); |
505 | |
506 | // unsigned: sltu Scratch4, StoreVal, Incr |
507 | // signed: slt Scratch4, StoreVal, Incr |
508 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SLTScratch4), DestReg: Scratch4) |
509 | .addReg(RegNo: StoreVal) |
510 | .addReg(RegNo: Incr); |
511 | |
512 | if (STI->hasMips64r6() || STI->hasMips32r6()) { |
513 | // max: seleqz BinOpRes, OldVal, Scratch4 |
514 | // selnez Scratch4, Incr, Scratch4 |
515 | // or BinOpRes, BinOpRes, Scratch4 |
516 | // min: selnqz BinOpRes, OldVal, Scratch4 |
517 | // seleqz Scratch4, Incr, Scratch4 |
518 | // or BinOpRes, BinOpRes, Scratch4 |
519 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELOldVal), DestReg: BinOpRes) |
520 | .addReg(RegNo: StoreVal) |
521 | .addReg(RegNo: Scratch4); |
522 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELIncr), DestReg: Scratch4) |
523 | .addReg(RegNo: Incr) |
524 | .addReg(RegNo: Scratch4); |
525 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: BinOpRes) |
526 | .addReg(RegNo: BinOpRes) |
527 | .addReg(RegNo: Scratch4); |
528 | } else { |
529 | // max: move BinOpRes, StoreVal |
530 | // movn BinOpRes, Incr, Scratch4, BinOpRes |
531 | // min: move BinOpRes, StoreVal |
532 | // movz BinOpRes, Incr, Scratch4, BinOpRes |
533 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: BinOpRes) |
534 | .addReg(RegNo: StoreVal) |
535 | .addReg(RegNo: Mips::ZERO); |
536 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: MOVIncr), DestReg: BinOpRes) |
537 | .addReg(RegNo: Incr) |
538 | .addReg(RegNo: Scratch4) |
539 | .addReg(RegNo: BinOpRes); |
540 | } |
541 | |
542 | // and BinOpRes, BinOpRes, Mask |
543 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes) |
544 | .addReg(RegNo: BinOpRes) |
545 | .addReg(RegNo: Mask); |
546 | |
547 | } else if (!IsSwap) { |
548 | // <binop> binopres, oldval, incr2 |
549 | // and newval, binopres, mask |
550 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode), DestReg: BinOpRes) |
551 | .addReg(RegNo: OldVal) |
552 | .addReg(RegNo: Incr); |
553 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes) |
554 | .addReg(RegNo: BinOpRes) |
555 | .addReg(RegNo: Mask); |
556 | } else { // atomic.swap |
557 | // and newval, incr2, mask |
558 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: BinOpRes) |
559 | .addReg(RegNo: Incr) |
560 | .addReg(RegNo: Mask); |
561 | } |
562 | |
563 | // and StoreVal, OlddVal, Mask2 |
564 | // or StoreVal, StoreVal, BinOpRes |
565 | // StoreVal<tied1> = sc StoreVal, 0(Ptr) |
566 | // beq StoreVal, zero, loopMBB |
567 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: StoreVal) |
568 | .addReg(RegNo: OldVal).addReg(RegNo: Mask2); |
569 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::OR), DestReg: StoreVal) |
570 | .addReg(RegNo: StoreVal).addReg(RegNo: BinOpRes); |
571 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: StoreVal) |
572 | .addReg(RegNo: StoreVal).addReg(RegNo: Ptr).addImm(Val: 0); |
573 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: BEQ)) |
574 | .addReg(RegNo: StoreVal).addReg(RegNo: Mips::ZERO).addMBB(MBB: loopMBB); |
575 | |
576 | // sinkMBB: |
577 | // and maskedoldval1,oldval,mask |
578 | // srl srlres,maskedoldval1,shiftamt |
579 | // sign_extend dest,srlres |
580 | |
581 | if (!DestOK) { |
582 | sinkMBB->addSuccessor(Succ: exitMBB, Prob: BranchProbability::getOne()); |
583 | BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::AND), DestReg: Dest).addReg(RegNo: OldVal).addReg(RegNo: Mask); |
584 | BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRLV), DestReg: Dest) |
585 | .addReg(RegNo: Dest) |
586 | .addReg(RegNo: ShiftAmnt); |
587 | |
588 | if (STI->hasMips32r2()) { |
589 | BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: SEOp), DestReg: Dest).addReg(RegNo: Dest); |
590 | } else { |
591 | const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24; |
592 | BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SLL), DestReg: Dest) |
593 | .addReg(RegNo: Dest, flags: RegState::Kill) |
594 | .addImm(Val: ShiftImm); |
595 | BuildMI(BB: sinkMBB, MIMD: DL, MCID: TII->get(Opcode: Mips::SRA), DestReg: Dest) |
596 | .addReg(RegNo: Dest, flags: RegState::Kill) |
597 | .addImm(Val: ShiftImm); |
598 | } |
599 | } |
600 | |
601 | LivePhysRegs LiveRegs; |
602 | computeAndAddLiveIns(LiveRegs, MBB&: *loopMBB); |
603 | computeAndAddLiveIns(LiveRegs, MBB&: *sinkMBB); |
604 | computeAndAddLiveIns(LiveRegs, MBB&: *exitMBB); |
605 | |
606 | NMBBI = BB.end(); |
607 | I->eraseFromParent(); |
608 | |
609 | return true; |
610 | } |
611 | |
612 | bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, |
613 | MachineBasicBlock::iterator I, |
614 | MachineBasicBlock::iterator &NMBBI, |
615 | unsigned Size) { |
616 | MachineFunction *MF = BB.getParent(); |
617 | |
618 | const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); |
619 | DebugLoc DL = I->getDebugLoc(); |
620 | |
621 | unsigned LL, SC, ZERO, BEQ, SLT, SLTu, OR, MOVN, MOVZ, SELNEZ, SELEQZ; |
622 | |
623 | if (Size == 4) { |
624 | if (STI->inMicroMipsMode()) { |
625 | LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; |
626 | SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; |
627 | BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; |
628 | SLT = Mips::SLT_MM; |
629 | SLTu = Mips::SLTu_MM; |
630 | OR = STI->hasMips32r6() ? Mips::OR_MMR6 : Mips::OR_MM; |
631 | MOVN = Mips::MOVN_I_MM; |
632 | MOVZ = Mips::MOVZ_I_MM; |
633 | SELNEZ = STI->hasMips32r6() ? Mips::SELNEZ_MMR6 : Mips::SELNEZ; |
634 | SELEQZ = STI->hasMips32r6() ? Mips::SELEQZ_MMR6 : Mips::SELEQZ; |
635 | } else { |
636 | LL = STI->hasMips32r6() |
637 | ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) |
638 | : (ArePtrs64bit ? Mips::LL64 : Mips::LL); |
639 | SC = STI->hasMips32r6() |
640 | ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) |
641 | : (ArePtrs64bit ? Mips::SC64 : Mips::SC); |
642 | BEQ = Mips::BEQ; |
643 | SLT = Mips::SLT; |
644 | SLTu = Mips::SLTu; |
645 | OR = Mips::OR; |
646 | MOVN = Mips::MOVN_I_I; |
647 | MOVZ = Mips::MOVZ_I_I; |
648 | SELNEZ = Mips::SELNEZ; |
649 | SELEQZ = Mips::SELEQZ; |
650 | } |
651 | |
652 | ZERO = Mips::ZERO; |
653 | } else { |
654 | LL = STI->hasMips64r6() ? Mips::LLD_R6 : Mips::LLD; |
655 | SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD; |
656 | ZERO = Mips::ZERO_64; |
657 | BEQ = Mips::BEQ64; |
658 | SLT = Mips::SLT64; |
659 | SLTu = Mips::SLTu64; |
660 | OR = Mips::OR64; |
661 | MOVN = Mips::MOVN_I64_I64; |
662 | MOVZ = Mips::MOVZ_I64_I64; |
663 | SELNEZ = Mips::SELNEZ64; |
664 | SELEQZ = Mips::SELEQZ64; |
665 | } |
666 | |
667 | Register OldVal = I->getOperand(i: 0).getReg(); |
668 | Register Ptr = I->getOperand(i: 1).getReg(); |
669 | Register Incr = I->getOperand(i: 2).getReg(); |
670 | Register Scratch = I->getOperand(i: 3).getReg(); |
671 | |
672 | unsigned Opcode = 0; |
673 | unsigned AND = 0; |
674 | unsigned NOR = 0; |
675 | |
676 | bool IsOr = false; |
677 | bool IsNand = false; |
678 | bool IsMin = false; |
679 | bool IsMax = false; |
680 | bool IsUnsigned = false; |
681 | |
682 | switch (I->getOpcode()) { |
683 | case Mips::ATOMIC_LOAD_ADD_I32_POSTRA: |
684 | Opcode = Mips::ADDu; |
685 | break; |
686 | case Mips::ATOMIC_LOAD_SUB_I32_POSTRA: |
687 | Opcode = Mips::SUBu; |
688 | break; |
689 | case Mips::ATOMIC_LOAD_AND_I32_POSTRA: |
690 | Opcode = Mips::AND; |
691 | break; |
692 | case Mips::ATOMIC_LOAD_OR_I32_POSTRA: |
693 | Opcode = Mips::OR; |
694 | break; |
695 | case Mips::ATOMIC_LOAD_XOR_I32_POSTRA: |
696 | Opcode = Mips::XOR; |
697 | break; |
698 | case Mips::ATOMIC_LOAD_NAND_I32_POSTRA: |
699 | IsNand = true; |
700 | AND = Mips::AND; |
701 | NOR = Mips::NOR; |
702 | break; |
703 | case Mips::ATOMIC_SWAP_I32_POSTRA: |
704 | IsOr = true; |
705 | break; |
706 | case Mips::ATOMIC_LOAD_ADD_I64_POSTRA: |
707 | Opcode = Mips::DADDu; |
708 | break; |
709 | case Mips::ATOMIC_LOAD_SUB_I64_POSTRA: |
710 | Opcode = Mips::DSUBu; |
711 | break; |
712 | case Mips::ATOMIC_LOAD_AND_I64_POSTRA: |
713 | Opcode = Mips::AND64; |
714 | break; |
715 | case Mips::ATOMIC_LOAD_OR_I64_POSTRA: |
716 | Opcode = Mips::OR64; |
717 | break; |
718 | case Mips::ATOMIC_LOAD_XOR_I64_POSTRA: |
719 | Opcode = Mips::XOR64; |
720 | break; |
721 | case Mips::ATOMIC_LOAD_NAND_I64_POSTRA: |
722 | IsNand = true; |
723 | AND = Mips::AND64; |
724 | NOR = Mips::NOR64; |
725 | break; |
726 | case Mips::ATOMIC_SWAP_I64_POSTRA: |
727 | IsOr = true; |
728 | break; |
729 | case Mips::ATOMIC_LOAD_UMIN_I32_POSTRA: |
730 | case Mips::ATOMIC_LOAD_UMIN_I64_POSTRA: |
731 | IsUnsigned = true; |
732 | [[fallthrough]]; |
733 | case Mips::ATOMIC_LOAD_MIN_I32_POSTRA: |
734 | case Mips::ATOMIC_LOAD_MIN_I64_POSTRA: |
735 | IsMin = true; |
736 | break; |
737 | case Mips::ATOMIC_LOAD_UMAX_I32_POSTRA: |
738 | case Mips::ATOMIC_LOAD_UMAX_I64_POSTRA: |
739 | IsUnsigned = true; |
740 | [[fallthrough]]; |
741 | case Mips::ATOMIC_LOAD_MAX_I32_POSTRA: |
742 | case Mips::ATOMIC_LOAD_MAX_I64_POSTRA: |
743 | IsMax = true; |
744 | break; |
745 | default: |
746 | llvm_unreachable("Unknown pseudo atomic!" ); |
747 | } |
748 | |
749 | const BasicBlock *LLVM_BB = BB.getBasicBlock(); |
750 | MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
751 | MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(BB: LLVM_BB); |
752 | MachineFunction::iterator It = ++BB.getIterator(); |
753 | MF->insert(MBBI: It, MBB: loopMBB); |
754 | MF->insert(MBBI: It, MBB: exitMBB); |
755 | |
756 | exitMBB->splice(Where: exitMBB->begin(), Other: &BB, From: std::next(x: I), To: BB.end()); |
757 | exitMBB->transferSuccessorsAndUpdatePHIs(FromMBB: &BB); |
758 | |
759 | BB.addSuccessor(Succ: loopMBB, Prob: BranchProbability::getOne()); |
760 | loopMBB->addSuccessor(Succ: exitMBB); |
761 | loopMBB->addSuccessor(Succ: loopMBB); |
762 | loopMBB->normalizeSuccProbs(); |
763 | |
764 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: LL), DestReg: OldVal).addReg(RegNo: Ptr).addImm(Val: 0); |
765 | assert((OldVal != Ptr) && "Clobbered the wrong ptr reg!" ); |
766 | assert((OldVal != Incr) && "Clobbered the wrong reg!" ); |
767 | if (IsMin || IsMax) { |
768 | |
769 | assert(I->getNumOperands() == 5 && |
770 | "Atomics min|max|umin|umax use an additional register" ); |
771 | MCRegister Scratch2 = I->getOperand(i: 4).getReg().asMCReg(); |
772 | |
773 | // On Mips64 result of slt is GPR32. |
774 | MCRegister Scratch2_32 = |
775 | (Size == 8) ? STI->getRegisterInfo()->getSubReg(Reg: Scratch2, Idx: Mips::sub_32) |
776 | : Scratch2; |
777 | |
778 | unsigned SLTScratch2 = IsUnsigned ? SLTu : SLT; |
779 | unsigned SELIncr = IsMax ? SELNEZ : SELEQZ; |
780 | unsigned SELOldVal = IsMax ? SELEQZ : SELNEZ; |
781 | unsigned MOVIncr = IsMax ? MOVN : MOVZ; |
782 | |
783 | // unsigned: sltu Scratch2, oldVal, Incr |
784 | // signed: slt Scratch2, oldVal, Incr |
785 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SLTScratch2), DestReg: Scratch2_32) |
786 | .addReg(RegNo: OldVal) |
787 | .addReg(RegNo: Incr); |
788 | |
789 | if (STI->hasMips64r6() || STI->hasMips32r6()) { |
790 | // max: seleqz Scratch, OldVal, Scratch2 |
791 | // selnez Scratch2, Incr, Scratch2 |
792 | // or Scratch, Scratch, Scratch2 |
793 | // min: selnez Scratch, OldVal, Scratch2 |
794 | // seleqz Scratch2, Incr, Scratch2 |
795 | // or Scratch, Scratch, Scratch2 |
796 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELOldVal), DestReg: Scratch) |
797 | .addReg(RegNo: OldVal) |
798 | .addReg(RegNo: Scratch2); |
799 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SELIncr), DestReg: Scratch2) |
800 | .addReg(RegNo: Incr) |
801 | .addReg(RegNo: Scratch2); |
802 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch) |
803 | .addReg(RegNo: Scratch) |
804 | .addReg(RegNo: Scratch2); |
805 | } else { |
806 | // max: move Scratch, OldVal |
807 | // movn Scratch, Incr, Scratch2, Scratch |
808 | // min: move Scratch, OldVal |
809 | // movz Scratch, Incr, Scratch2, Scratch |
810 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch) |
811 | .addReg(RegNo: OldVal) |
812 | .addReg(RegNo: ZERO); |
813 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: MOVIncr), DestReg: Scratch) |
814 | .addReg(RegNo: Incr) |
815 | .addReg(RegNo: Scratch2) |
816 | .addReg(RegNo: Scratch); |
817 | } |
818 | |
819 | } else if (Opcode) { |
820 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode), DestReg: Scratch).addReg(RegNo: OldVal).addReg(RegNo: Incr); |
821 | } else if (IsNand) { |
822 | assert(AND && NOR && |
823 | "Unknown nand instruction for atomic pseudo expansion" ); |
824 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: AND), DestReg: Scratch).addReg(RegNo: OldVal).addReg(RegNo: Incr); |
825 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: NOR), DestReg: Scratch).addReg(RegNo: ZERO).addReg(RegNo: Scratch); |
826 | } else { |
827 | assert(IsOr && OR && "Unknown instruction for atomic pseudo expansion!" ); |
828 | (void)IsOr; |
829 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: OR), DestReg: Scratch).addReg(RegNo: Incr).addReg(RegNo: ZERO); |
830 | } |
831 | |
832 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: SC), DestReg: Scratch) |
833 | .addReg(RegNo: Scratch) |
834 | .addReg(RegNo: Ptr) |
835 | .addImm(Val: 0); |
836 | BuildMI(BB: loopMBB, MIMD: DL, MCID: TII->get(Opcode: BEQ)) |
837 | .addReg(RegNo: Scratch) |
838 | .addReg(RegNo: ZERO) |
839 | .addMBB(MBB: loopMBB); |
840 | |
841 | NMBBI = BB.end(); |
842 | I->eraseFromParent(); |
843 | |
844 | LivePhysRegs LiveRegs; |
845 | computeAndAddLiveIns(LiveRegs, MBB&: *loopMBB); |
846 | computeAndAddLiveIns(LiveRegs, MBB&: *exitMBB); |
847 | |
848 | return true; |
849 | } |
850 | |
851 | bool MipsExpandPseudo::expandMI(MachineBasicBlock &MBB, |
852 | MachineBasicBlock::iterator MBBI, |
853 | MachineBasicBlock::iterator &NMBB) { |
854 | |
855 | bool Modified = false; |
856 | |
857 | switch (MBBI->getOpcode()) { |
858 | case Mips::ATOMIC_CMP_SWAP_I32_POSTRA: |
859 | case Mips::ATOMIC_CMP_SWAP_I64_POSTRA: |
860 | return expandAtomicCmpSwap(BB&: MBB, I: MBBI, NMBBI&: NMBB); |
861 | case Mips::ATOMIC_CMP_SWAP_I8_POSTRA: |
862 | case Mips::ATOMIC_CMP_SWAP_I16_POSTRA: |
863 | return expandAtomicCmpSwapSubword(BB&: MBB, I: MBBI, NMBBI&: NMBB); |
864 | case Mips::ATOMIC_SWAP_I8_POSTRA: |
865 | case Mips::ATOMIC_SWAP_I16_POSTRA: |
866 | case Mips::ATOMIC_LOAD_NAND_I8_POSTRA: |
867 | case Mips::ATOMIC_LOAD_NAND_I16_POSTRA: |
868 | case Mips::ATOMIC_LOAD_ADD_I8_POSTRA: |
869 | case Mips::ATOMIC_LOAD_ADD_I16_POSTRA: |
870 | case Mips::ATOMIC_LOAD_SUB_I8_POSTRA: |
871 | case Mips::ATOMIC_LOAD_SUB_I16_POSTRA: |
872 | case Mips::ATOMIC_LOAD_AND_I8_POSTRA: |
873 | case Mips::ATOMIC_LOAD_AND_I16_POSTRA: |
874 | case Mips::ATOMIC_LOAD_OR_I8_POSTRA: |
875 | case Mips::ATOMIC_LOAD_OR_I16_POSTRA: |
876 | case Mips::ATOMIC_LOAD_XOR_I8_POSTRA: |
877 | case Mips::ATOMIC_LOAD_XOR_I16_POSTRA: |
878 | case Mips::ATOMIC_LOAD_MIN_I8_POSTRA: |
879 | case Mips::ATOMIC_LOAD_MIN_I16_POSTRA: |
880 | case Mips::ATOMIC_LOAD_MAX_I8_POSTRA: |
881 | case Mips::ATOMIC_LOAD_MAX_I16_POSTRA: |
882 | case Mips::ATOMIC_LOAD_UMIN_I8_POSTRA: |
883 | case Mips::ATOMIC_LOAD_UMIN_I16_POSTRA: |
884 | case Mips::ATOMIC_LOAD_UMAX_I8_POSTRA: |
885 | case Mips::ATOMIC_LOAD_UMAX_I16_POSTRA: |
886 | return expandAtomicBinOpSubword(BB&: MBB, I: MBBI, NMBBI&: NMBB); |
887 | case Mips::ATOMIC_LOAD_ADD_I32_POSTRA: |
888 | case Mips::ATOMIC_LOAD_SUB_I32_POSTRA: |
889 | case Mips::ATOMIC_LOAD_AND_I32_POSTRA: |
890 | case Mips::ATOMIC_LOAD_OR_I32_POSTRA: |
891 | case Mips::ATOMIC_LOAD_XOR_I32_POSTRA: |
892 | case Mips::ATOMIC_LOAD_NAND_I32_POSTRA: |
893 | case Mips::ATOMIC_SWAP_I32_POSTRA: |
894 | case Mips::ATOMIC_LOAD_MIN_I32_POSTRA: |
895 | case Mips::ATOMIC_LOAD_MAX_I32_POSTRA: |
896 | case Mips::ATOMIC_LOAD_UMIN_I32_POSTRA: |
897 | case Mips::ATOMIC_LOAD_UMAX_I32_POSTRA: |
898 | return expandAtomicBinOp(BB&: MBB, I: MBBI, NMBBI&: NMBB, Size: 4); |
899 | case Mips::ATOMIC_LOAD_ADD_I64_POSTRA: |
900 | case Mips::ATOMIC_LOAD_SUB_I64_POSTRA: |
901 | case Mips::ATOMIC_LOAD_AND_I64_POSTRA: |
902 | case Mips::ATOMIC_LOAD_OR_I64_POSTRA: |
903 | case Mips::ATOMIC_LOAD_XOR_I64_POSTRA: |
904 | case Mips::ATOMIC_LOAD_NAND_I64_POSTRA: |
905 | case Mips::ATOMIC_SWAP_I64_POSTRA: |
906 | case Mips::ATOMIC_LOAD_MIN_I64_POSTRA: |
907 | case Mips::ATOMIC_LOAD_MAX_I64_POSTRA: |
908 | case Mips::ATOMIC_LOAD_UMIN_I64_POSTRA: |
909 | case Mips::ATOMIC_LOAD_UMAX_I64_POSTRA: |
910 | return expandAtomicBinOp(BB&: MBB, I: MBBI, NMBBI&: NMBB, Size: 8); |
911 | default: |
912 | return Modified; |
913 | } |
914 | } |
915 | |
916 | bool MipsExpandPseudo::expandMBB(MachineBasicBlock &MBB) { |
917 | bool Modified = false; |
918 | |
919 | MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); |
920 | while (MBBI != E) { |
921 | MachineBasicBlock::iterator NMBBI = std::next(x: MBBI); |
922 | Modified |= expandMI(MBB, MBBI, NMBB&: NMBBI); |
923 | MBBI = NMBBI; |
924 | } |
925 | |
926 | return Modified; |
927 | } |
928 | |
929 | bool MipsExpandPseudo::runOnMachineFunction(MachineFunction &MF) { |
930 | STI = &MF.getSubtarget<MipsSubtarget>(); |
931 | TII = STI->getInstrInfo(); |
932 | |
933 | bool Modified = false; |
934 | for (MachineBasicBlock &MBB : MF) |
935 | Modified |= expandMBB(MBB); |
936 | |
937 | if (Modified) |
938 | MF.RenumberBlocks(); |
939 | |
940 | return Modified; |
941 | } |
942 | |
943 | /// createMipsExpandPseudoPass - returns an instance of the pseudo instruction |
944 | /// expansion pass. |
945 | FunctionPass *llvm::createMipsExpandPseudoPass() { |
946 | return new MipsExpandPseudo(); |
947 | } |
948 | |