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