blob: efa5ac61e7458f6f697d4b0eec32cf41a93a5111 [file] [log] [blame]
Dylan McKaya789f402016-11-16 21:58:04 +00001//===-- AVRExpandPseudoInsts.cpp - Expand pseudo instructions -------------===//
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//
10// This file contains a pass that expands pseudo instructions into target
11// instructions. This pass should be run after register allocation but before
12// the post-regalloc scheduling pass.
13//
14//===----------------------------------------------------------------------===//
15
16#include "AVR.h"
17#include "AVRInstrInfo.h"
18#include "AVRTargetMachine.h"
19#include "MCTargetDesc/AVRMCTargetDesc.h"
20
21#include "llvm/CodeGen/MachineFunctionPass.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
Dylan McKay5c90b8c2016-12-10 10:51:55 +000024#include "llvm/CodeGen/RegisterScavenging.h"
Dylan McKaya789f402016-11-16 21:58:04 +000025#include "llvm/Target/TargetRegisterInfo.h"
26
27using namespace llvm;
28
Dylan McKay8cec7eb2016-12-07 11:08:56 +000029#define AVR_EXPAND_PSEUDO_NAME "AVR pseudo instruction expansion pass"
30
Dylan McKaya789f402016-11-16 21:58:04 +000031namespace {
32
33/// Expands "placeholder" instructions marked as pseudo into
34/// actual AVR instructions.
35class AVRExpandPseudo : public MachineFunctionPass {
36public:
37 static char ID;
38
Dylan McKay8cec7eb2016-12-07 11:08:56 +000039 AVRExpandPseudo() : MachineFunctionPass(ID) {
40 initializeAVRExpandPseudoPass(*PassRegistry::getPassRegistry());
41 }
Dylan McKaya789f402016-11-16 21:58:04 +000042
43 bool runOnMachineFunction(MachineFunction &MF) override;
44
Dylan McKay8cec7eb2016-12-07 11:08:56 +000045 StringRef getPassName() const override { return AVR_EXPAND_PSEUDO_NAME; }
Dylan McKaya789f402016-11-16 21:58:04 +000046
47private:
48 typedef MachineBasicBlock Block;
49 typedef Block::iterator BlockIt;
50
51 const AVRRegisterInfo *TRI;
52 const TargetInstrInfo *TII;
53
54 /// The register to be used for temporary storage.
55 const unsigned SCRATCH_REGISTER = AVR::R0;
56 /// The IO address of the status register.
57 const unsigned SREG_ADDR = 0x3f;
58
59 bool expandMBB(Block &MBB);
60 bool expandMI(Block &MBB, BlockIt MBBI);
61 template <unsigned OP> bool expand(Block &MBB, BlockIt MBBI);
62
63 MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode) {
64 return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode));
65 }
66
67 MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode,
68 unsigned DstReg) {
69 return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode), DstReg);
70 }
71
72 MachineRegisterInfo &getRegInfo(Block &MBB) { return MBB.getParent()->getRegInfo(); }
73
74 bool expandArith(unsigned OpLo, unsigned OpHi, Block &MBB, BlockIt MBBI);
75 bool expandLogic(unsigned Op, Block &MBB, BlockIt MBBI);
76 bool expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI);
Dylan McKay453d0422016-12-30 00:21:56 +000077 bool isLogicImmOpRedundant(unsigned Op, unsigned ImmVal) const;
Dylan McKaya789f402016-11-16 21:58:04 +000078
79 template<typename Func>
80 bool expandAtomic(Block &MBB, BlockIt MBBI, Func f);
81
82 template<typename Func>
83 bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI, Func f);
84
85 bool expandAtomicBinaryOp(unsigned Opcode, Block &MBB, BlockIt MBBI);
86
87 bool expandAtomicArithmeticOp(unsigned MemOpcode,
88 unsigned ArithOpcode,
89 Block &MBB,
90 BlockIt MBBI);
Dylan McKay8f515b12017-04-25 15:09:04 +000091
92 /// Scavenges a free GPR8 register for use.
93 unsigned scavengeGPR8(MachineInstr &MI);
Dylan McKaya789f402016-11-16 21:58:04 +000094};
95
96char AVRExpandPseudo::ID = 0;
97
Dylan McKaya789f402016-11-16 21:58:04 +000098bool AVRExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
99 bool Modified = false;
100
101 BlockIt MBBI = MBB.begin(), E = MBB.end();
102 while (MBBI != E) {
103 BlockIt NMBBI = std::next(MBBI);
104 Modified |= expandMI(MBB, MBBI);
105 MBBI = NMBBI;
106 }
107
108 return Modified;
109}
110
111bool AVRExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
112 bool Modified = false;
113
114 const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
115 TRI = STI.getRegisterInfo();
116 TII = STI.getInstrInfo();
117
Dylan McKay5c90b8c2016-12-10 10:51:55 +0000118 // We need to track liveness in order to use register scavenging.
119 MF.getProperties().set(MachineFunctionProperties::Property::TracksLiveness);
120
Dylan McKaya789f402016-11-16 21:58:04 +0000121 for (Block &MBB : MF) {
122 bool ContinueExpanding = true;
123 unsigned ExpandCount = 0;
124
125 // Continue expanding the block until all pseudos are expanded.
126 do {
127 assert(ExpandCount < 10 && "pseudo expand limit reached");
128
129 bool BlockModified = expandMBB(MBB);
130 Modified |= BlockModified;
131 ExpandCount++;
132
133 ContinueExpanding = BlockModified;
134 } while (ContinueExpanding);
135 }
136
137 return Modified;
138}
139
140bool AVRExpandPseudo::
141expandArith(unsigned OpLo, unsigned OpHi, Block &MBB, BlockIt MBBI) {
142 MachineInstr &MI = *MBBI;
143 unsigned SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
144 unsigned DstReg = MI.getOperand(0).getReg();
145 unsigned SrcReg = MI.getOperand(2).getReg();
146 bool DstIsDead = MI.getOperand(0).isDead();
147 bool DstIsKill = MI.getOperand(1).isKill();
148 bool SrcIsKill = MI.getOperand(2).isKill();
149 bool ImpIsDead = MI.getOperand(3).isDead();
150 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
151 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
152
153 buildMI(MBB, MBBI, OpLo)
154 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
155 .addReg(DstLoReg, getKillRegState(DstIsKill))
156 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
157
158 auto MIBHI = buildMI(MBB, MBBI, OpHi)
159 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
160 .addReg(DstHiReg, getKillRegState(DstIsKill))
161 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
162
163 if (ImpIsDead)
164 MIBHI->getOperand(3).setIsDead();
165
166 // SREG is always implicitly killed
167 MIBHI->getOperand(4).setIsKill();
168
169 MI.eraseFromParent();
170 return true;
171}
172
173bool AVRExpandPseudo::
174expandLogic(unsigned Op, Block &MBB, BlockIt MBBI) {
175 MachineInstr &MI = *MBBI;
176 unsigned SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
177 unsigned DstReg = MI.getOperand(0).getReg();
178 unsigned SrcReg = MI.getOperand(2).getReg();
179 bool DstIsDead = MI.getOperand(0).isDead();
180 bool DstIsKill = MI.getOperand(1).isKill();
181 bool SrcIsKill = MI.getOperand(2).isKill();
182 bool ImpIsDead = MI.getOperand(3).isDead();
183 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
184 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
185
186 auto MIBLO = buildMI(MBB, MBBI, Op)
187 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
188 .addReg(DstLoReg, getKillRegState(DstIsKill))
189 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
190
191 // SREG is always implicitly dead
192 MIBLO->getOperand(3).setIsDead();
193
194 auto MIBHI = buildMI(MBB, MBBI, Op)
195 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
196 .addReg(DstHiReg, getKillRegState(DstIsKill))
197 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
198
199 if (ImpIsDead)
200 MIBHI->getOperand(3).setIsDead();
201
202 MI.eraseFromParent();
203 return true;
204}
205
206bool AVRExpandPseudo::
Dylan McKay453d0422016-12-30 00:21:56 +0000207 isLogicImmOpRedundant(unsigned Op, unsigned ImmVal) const {
208
Dylan McKay97cf8372016-12-31 01:07:14 +0000209 // ANDI Rd, 0xff is redundant.
210 if (Op == AVR::ANDIRdK && ImmVal == 0xff)
211 return true;
212
Dylan McKay453d0422016-12-30 00:21:56 +0000213 // ORI Rd, 0x0 is redundant.
214 if (Op == AVR::ORIRdK && ImmVal == 0x0)
215 return true;
216
217 return false;
218}
219
220bool AVRExpandPseudo::
Dylan McKaya789f402016-11-16 21:58:04 +0000221expandLogicImm(unsigned Op, Block &MBB, BlockIt MBBI) {
222 MachineInstr &MI = *MBBI;
223 unsigned DstLoReg, DstHiReg;
224 unsigned DstReg = MI.getOperand(0).getReg();
225 bool DstIsDead = MI.getOperand(0).isDead();
226 bool SrcIsKill = MI.getOperand(1).isKill();
227 bool ImpIsDead = MI.getOperand(3).isDead();
228 unsigned Imm = MI.getOperand(2).getImm();
229 unsigned Lo8 = Imm & 0xff;
230 unsigned Hi8 = (Imm >> 8) & 0xff;
231 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
232
Dylan McKay453d0422016-12-30 00:21:56 +0000233 if (!isLogicImmOpRedundant(Op, Lo8)) {
234 auto MIBLO = buildMI(MBB, MBBI, Op)
235 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
236 .addReg(DstLoReg, getKillRegState(SrcIsKill))
237 .addImm(Lo8);
Dylan McKaya789f402016-11-16 21:58:04 +0000238
Dylan McKay453d0422016-12-30 00:21:56 +0000239 // SREG is always implicitly dead
240 MIBLO->getOperand(3).setIsDead();
241 }
Dylan McKaya789f402016-11-16 21:58:04 +0000242
Dylan McKay453d0422016-12-30 00:21:56 +0000243 if (!isLogicImmOpRedundant(Op, Hi8)) {
244 auto MIBHI = buildMI(MBB, MBBI, Op)
245 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
246 .addReg(DstHiReg, getKillRegState(SrcIsKill))
247 .addImm(Hi8);
Dylan McKaya789f402016-11-16 21:58:04 +0000248
Dylan McKay453d0422016-12-30 00:21:56 +0000249 if (ImpIsDead)
250 MIBHI->getOperand(3).setIsDead();
251 }
Dylan McKaya789f402016-11-16 21:58:04 +0000252
253 MI.eraseFromParent();
254 return true;
255}
256
257template <>
258bool AVRExpandPseudo::expand<AVR::ADDWRdRr>(Block &MBB, BlockIt MBBI) {
259 return expandArith(AVR::ADDRdRr, AVR::ADCRdRr, MBB, MBBI);
260}
261
262template <>
263bool AVRExpandPseudo::expand<AVR::ADCWRdRr>(Block &MBB, BlockIt MBBI) {
264 return expandArith(AVR::ADCRdRr, AVR::ADCRdRr, MBB, MBBI);
265}
266
267template <>
268bool AVRExpandPseudo::expand<AVR::SUBWRdRr>(Block &MBB, BlockIt MBBI) {
269 return expandArith(AVR::SUBRdRr, AVR::SBCRdRr, MBB, MBBI);
270}
271
272template <>
273bool AVRExpandPseudo::expand<AVR::SUBIWRdK>(Block &MBB, BlockIt MBBI) {
274 MachineInstr &MI = *MBBI;
275 unsigned DstLoReg, DstHiReg;
276 unsigned DstReg = MI.getOperand(0).getReg();
277 bool DstIsDead = MI.getOperand(0).isDead();
278 bool SrcIsKill = MI.getOperand(1).isKill();
279 bool ImpIsDead = MI.getOperand(3).isDead();
280 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
281
282 auto MIBLO = buildMI(MBB, MBBI, AVR::SUBIRdK)
283 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
284 .addReg(DstLoReg, getKillRegState(SrcIsKill));
285
286 auto MIBHI = buildMI(MBB, MBBI, AVR::SBCIRdK)
287 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
288 .addReg(DstHiReg, getKillRegState(SrcIsKill));
289
290 switch (MI.getOperand(2).getType()) {
291 case MachineOperand::MO_GlobalAddress: {
292 const GlobalValue *GV = MI.getOperand(2).getGlobal();
293 int64_t Offs = MI.getOperand(2).getOffset();
294 unsigned TF = MI.getOperand(2).getTargetFlags();
295 MIBLO.addGlobalAddress(GV, Offs, TF | AVRII::MO_NEG | AVRII::MO_LO);
296 MIBHI.addGlobalAddress(GV, Offs, TF | AVRII::MO_NEG | AVRII::MO_HI);
297 break;
298 }
299 case MachineOperand::MO_Immediate: {
300 unsigned Imm = MI.getOperand(2).getImm();
301 MIBLO.addImm(Imm & 0xff);
302 MIBHI.addImm((Imm >> 8) & 0xff);
303 break;
304 }
305 default:
306 llvm_unreachable("Unknown operand type!");
307 }
308
309 if (ImpIsDead)
310 MIBHI->getOperand(3).setIsDead();
311
312 // SREG is always implicitly killed
313 MIBHI->getOperand(4).setIsKill();
314
315 MI.eraseFromParent();
316 return true;
317}
318
319template <>
320bool AVRExpandPseudo::expand<AVR::SBCWRdRr>(Block &MBB, BlockIt MBBI) {
321 return expandArith(AVR::SBCRdRr, AVR::SBCRdRr, MBB, MBBI);
322}
323
324template <>
325bool AVRExpandPseudo::expand<AVR::SBCIWRdK>(Block &MBB, BlockIt MBBI) {
326 MachineInstr &MI = *MBBI;
327 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
328 unsigned DstReg = MI.getOperand(0).getReg();
329 bool DstIsDead = MI.getOperand(0).isDead();
330 bool SrcIsKill = MI.getOperand(1).isKill();
331 bool ImpIsDead = MI.getOperand(3).isDead();
332 unsigned Imm = MI.getOperand(2).getImm();
333 unsigned Lo8 = Imm & 0xff;
334 unsigned Hi8 = (Imm >> 8) & 0xff;
335 OpLo = AVR::SBCIRdK;
336 OpHi = AVR::SBCIRdK;
337 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
338
339 auto MIBLO = buildMI(MBB, MBBI, OpLo)
340 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
341 .addReg(DstLoReg, getKillRegState(SrcIsKill))
342 .addImm(Lo8);
343
344 // SREG is always implicitly killed
345 MIBLO->getOperand(4).setIsKill();
346
347 auto MIBHI = buildMI(MBB, MBBI, OpHi)
348 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
349 .addReg(DstHiReg, getKillRegState(SrcIsKill))
350 .addImm(Hi8);
351
352 if (ImpIsDead)
353 MIBHI->getOperand(3).setIsDead();
354
355 // SREG is always implicitly killed
356 MIBHI->getOperand(4).setIsKill();
357
358 MI.eraseFromParent();
359 return true;
360}
361
362template <>
363bool AVRExpandPseudo::expand<AVR::ANDWRdRr>(Block &MBB, BlockIt MBBI) {
364 return expandLogic(AVR::ANDRdRr, MBB, MBBI);
365}
366
367template <>
368bool AVRExpandPseudo::expand<AVR::ANDIWRdK>(Block &MBB, BlockIt MBBI) {
369 return expandLogicImm(AVR::ANDIRdK, MBB, MBBI);
370}
371
372template <>
373bool AVRExpandPseudo::expand<AVR::ORWRdRr>(Block &MBB, BlockIt MBBI) {
374 return expandLogic(AVR::ORRdRr, MBB, MBBI);
375}
376
377template <>
378bool AVRExpandPseudo::expand<AVR::ORIWRdK>(Block &MBB, BlockIt MBBI) {
379 return expandLogicImm(AVR::ORIRdK, MBB, MBBI);
380}
381
382template <>
383bool AVRExpandPseudo::expand<AVR::EORWRdRr>(Block &MBB, BlockIt MBBI) {
384 return expandLogic(AVR::EORRdRr, MBB, MBBI);
385}
386
387template <>
388bool AVRExpandPseudo::expand<AVR::COMWRd>(Block &MBB, BlockIt MBBI) {
389 MachineInstr &MI = *MBBI;
390 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
391 unsigned DstReg = MI.getOperand(0).getReg();
392 bool DstIsDead = MI.getOperand(0).isDead();
393 bool DstIsKill = MI.getOperand(1).isKill();
394 bool ImpIsDead = MI.getOperand(2).isDead();
395 OpLo = AVR::COMRd;
396 OpHi = AVR::COMRd;
397 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
398
399 auto MIBLO = buildMI(MBB, MBBI, OpLo)
400 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
401 .addReg(DstLoReg, getKillRegState(DstIsKill));
402
403 // SREG is always implicitly dead
404 MIBLO->getOperand(2).setIsDead();
405
406 auto MIBHI = buildMI(MBB, MBBI, OpHi)
407 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
408 .addReg(DstHiReg, getKillRegState(DstIsKill));
409
410 if (ImpIsDead)
411 MIBHI->getOperand(2).setIsDead();
412
413 MI.eraseFromParent();
414 return true;
415}
416
417template <>
418bool AVRExpandPseudo::expand<AVR::CPWRdRr>(Block &MBB, BlockIt MBBI) {
419 MachineInstr &MI = *MBBI;
420 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
421 unsigned DstReg = MI.getOperand(0).getReg();
422 unsigned SrcReg = MI.getOperand(1).getReg();
423 bool DstIsKill = MI.getOperand(0).isKill();
424 bool SrcIsKill = MI.getOperand(1).isKill();
425 bool ImpIsDead = MI.getOperand(2).isDead();
426 OpLo = AVR::CPRdRr;
427 OpHi = AVR::CPCRdRr;
428 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
429 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
430
431 // Low part
432 buildMI(MBB, MBBI, OpLo)
433 .addReg(DstLoReg, getKillRegState(DstIsKill))
434 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
435
436 auto MIBHI = buildMI(MBB, MBBI, OpHi)
437 .addReg(DstHiReg, getKillRegState(DstIsKill))
438 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
439
440 if (ImpIsDead)
441 MIBHI->getOperand(2).setIsDead();
442
443 // SREG is always implicitly killed
444 MIBHI->getOperand(3).setIsKill();
445
446 MI.eraseFromParent();
447 return true;
448}
449
450template <>
451bool AVRExpandPseudo::expand<AVR::CPCWRdRr>(Block &MBB, BlockIt MBBI) {
452 MachineInstr &MI = *MBBI;
453 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg, DstLoReg, DstHiReg;
454 unsigned DstReg = MI.getOperand(0).getReg();
455 unsigned SrcReg = MI.getOperand(1).getReg();
456 bool DstIsKill = MI.getOperand(0).isKill();
457 bool SrcIsKill = MI.getOperand(1).isKill();
458 bool ImpIsDead = MI.getOperand(2).isDead();
459 OpLo = AVR::CPCRdRr;
460 OpHi = AVR::CPCRdRr;
461 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
462 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
463
464 auto MIBLO = buildMI(MBB, MBBI, OpLo)
465 .addReg(DstLoReg, getKillRegState(DstIsKill))
466 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
467
468 // SREG is always implicitly killed
469 MIBLO->getOperand(3).setIsKill();
470
471 auto MIBHI = buildMI(MBB, MBBI, OpHi)
472 .addReg(DstHiReg, getKillRegState(DstIsKill))
473 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
474
475 if (ImpIsDead)
476 MIBHI->getOperand(2).setIsDead();
477
478 // SREG is always implicitly killed
479 MIBHI->getOperand(3).setIsKill();
480
481 MI.eraseFromParent();
482 return true;
483}
484
485template <>
486bool AVRExpandPseudo::expand<AVR::LDIWRdK>(Block &MBB, BlockIt MBBI) {
487 MachineInstr &MI = *MBBI;
488 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
489 unsigned DstReg = MI.getOperand(0).getReg();
490 bool DstIsDead = MI.getOperand(0).isDead();
491 OpLo = AVR::LDIRdK;
492 OpHi = AVR::LDIRdK;
493 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
494
495 auto MIBLO = buildMI(MBB, MBBI, OpLo)
496 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead));
497
498 auto MIBHI = buildMI(MBB, MBBI, OpHi)
499 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead));
500
501 switch (MI.getOperand(1).getType()) {
502 case MachineOperand::MO_GlobalAddress: {
503 const GlobalValue *GV = MI.getOperand(1).getGlobal();
504 int64_t Offs = MI.getOperand(1).getOffset();
505 unsigned TF = MI.getOperand(1).getTargetFlags();
506
507 MIBLO.addGlobalAddress(GV, Offs, TF | AVRII::MO_LO);
508 MIBHI.addGlobalAddress(GV, Offs, TF | AVRII::MO_HI);
509 break;
510 }
511 case MachineOperand::MO_BlockAddress: {
512 const BlockAddress *BA = MI.getOperand(1).getBlockAddress();
513 unsigned TF = MI.getOperand(1).getTargetFlags();
514
Diana Picus116bbab2017-01-13 09:58:52 +0000515 MIBLO.add(MachineOperand::CreateBA(BA, TF | AVRII::MO_LO));
516 MIBHI.add(MachineOperand::CreateBA(BA, TF | AVRII::MO_HI));
Dylan McKaya789f402016-11-16 21:58:04 +0000517 break;
518 }
519 case MachineOperand::MO_Immediate: {
520 unsigned Imm = MI.getOperand(1).getImm();
521
522 MIBLO.addImm(Imm & 0xff);
523 MIBHI.addImm((Imm >> 8) & 0xff);
524 break;
525 }
526 default:
527 llvm_unreachable("Unknown operand type!");
528 }
529
530 MI.eraseFromParent();
531 return true;
532}
533
534template <>
535bool AVRExpandPseudo::expand<AVR::LDSWRdK>(Block &MBB, BlockIt MBBI) {
536 MachineInstr &MI = *MBBI;
537 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
538 unsigned DstReg = MI.getOperand(0).getReg();
539 bool DstIsDead = MI.getOperand(0).isDead();
540 OpLo = AVR::LDSRdK;
541 OpHi = AVR::LDSRdK;
542 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
543
544 auto MIBLO = buildMI(MBB, MBBI, OpLo)
545 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead));
546
547 auto MIBHI = buildMI(MBB, MBBI, OpHi)
548 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead));
549
550 switch (MI.getOperand(1).getType()) {
551 case MachineOperand::MO_GlobalAddress: {
552 const GlobalValue *GV = MI.getOperand(1).getGlobal();
553 int64_t Offs = MI.getOperand(1).getOffset();
554 unsigned TF = MI.getOperand(1).getTargetFlags();
555
556 MIBLO.addGlobalAddress(GV, Offs, TF);
557 MIBHI.addGlobalAddress(GV, Offs + 1, TF);
558 break;
559 }
560 case MachineOperand::MO_Immediate: {
561 unsigned Imm = MI.getOperand(1).getImm();
562
563 MIBLO.addImm(Imm);
564 MIBHI.addImm(Imm + 1);
565 break;
566 }
567 default:
568 llvm_unreachable("Unknown operand type!");
569 }
570
571 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
572 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
573
574 MI.eraseFromParent();
575 return true;
576}
577
578template <>
579bool AVRExpandPseudo::expand<AVR::LDWRdPtr>(Block &MBB, BlockIt MBBI) {
580 MachineInstr &MI = *MBBI;
581 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
582 unsigned DstReg = MI.getOperand(0).getReg();
Dylan McKay8f515b12017-04-25 15:09:04 +0000583 unsigned TmpReg = 0; // 0 for no temporary register
Dylan McKaya789f402016-11-16 21:58:04 +0000584 unsigned SrcReg = MI.getOperand(1).getReg();
Dylan McKaya789f402016-11-16 21:58:04 +0000585 bool SrcIsKill = MI.getOperand(1).isKill();
586 OpLo = AVR::LDRdPtr;
587 OpHi = AVR::LDDRdPtrQ;
588 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
589
Dylan McKay8f515b12017-04-25 15:09:04 +0000590 // Use a temporary register if src and dst registers are the same.
591 if (DstReg == SrcReg)
592 TmpReg = scavengeGPR8(MI);
Dylan McKaya789f402016-11-16 21:58:04 +0000593
Dylan McKay8f515b12017-04-25 15:09:04 +0000594 unsigned CurDstLoReg = (DstReg == SrcReg) ? TmpReg : DstLoReg;
595 unsigned CurDstHiReg = (DstReg == SrcReg) ? TmpReg : DstHiReg;
596
597 // Load low byte.
Dylan McKaya789f402016-11-16 21:58:04 +0000598 auto MIBLO = buildMI(MBB, MBBI, OpLo)
Dylan McKay8f515b12017-04-25 15:09:04 +0000599 .addReg(CurDstLoReg, RegState::Define)
Dylan McKaya789f402016-11-16 21:58:04 +0000600 .addReg(SrcReg);
601
Dylan McKay8f515b12017-04-25 15:09:04 +0000602 // Push low byte onto stack if necessary.
603 if (TmpReg)
604 buildMI(MBB, MBBI, AVR::PUSHRr).addReg(TmpReg);
605
606 // Load high byte.
Dylan McKaya789f402016-11-16 21:58:04 +0000607 auto MIBHI = buildMI(MBB, MBBI, OpHi)
Dylan McKay8f515b12017-04-25 15:09:04 +0000608 .addReg(CurDstHiReg, RegState::Define)
Dylan McKaya789f402016-11-16 21:58:04 +0000609 .addReg(SrcReg, getKillRegState(SrcIsKill))
610 .addImm(1);
611
Dylan McKay8f515b12017-04-25 15:09:04 +0000612 if (TmpReg) {
613 // Move the high byte into the final destination.
614 buildMI(MBB, MBBI, AVR::MOVRdRr).addReg(DstHiReg).addReg(TmpReg);
615
616 // Move the low byte from the scratch space into the final destination.
617 buildMI(MBB, MBBI, AVR::POPRd).addReg(DstLoReg);
618 }
619
Dylan McKaya789f402016-11-16 21:58:04 +0000620 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
621 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
622
623 MI.eraseFromParent();
624 return true;
625}
626
627template <>
628bool AVRExpandPseudo::expand<AVR::LDWRdPtrPi>(Block &MBB, BlockIt MBBI) {
629 MachineInstr &MI = *MBBI;
630 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
631 unsigned DstReg = MI.getOperand(0).getReg();
632 unsigned SrcReg = MI.getOperand(1).getReg();
633 bool DstIsDead = MI.getOperand(0).isDead();
634 bool SrcIsDead = MI.getOperand(1).isKill();
635 OpLo = AVR::LDRdPtrPi;
636 OpHi = AVR::LDRdPtrPi;
637 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
638
639 assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
640
641 auto MIBLO = buildMI(MBB, MBBI, OpLo)
642 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
643 .addReg(SrcReg, RegState::Define)
644 .addReg(SrcReg, RegState::Kill);
645
646 auto MIBHI = buildMI(MBB, MBBI, OpHi)
647 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
648 .addReg(SrcReg, RegState::Define | getDeadRegState(SrcIsDead))
649 .addReg(SrcReg, RegState::Kill);
650
651 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
652 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
653
654 MI.eraseFromParent();
655 return true;
656}
657
658template <>
659bool AVRExpandPseudo::expand<AVR::LDWRdPtrPd>(Block &MBB, BlockIt MBBI) {
660 MachineInstr &MI = *MBBI;
661 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
662 unsigned DstReg = MI.getOperand(0).getReg();
663 unsigned SrcReg = MI.getOperand(1).getReg();
664 bool DstIsDead = MI.getOperand(0).isDead();
665 bool SrcIsDead = MI.getOperand(1).isKill();
666 OpLo = AVR::LDRdPtrPd;
667 OpHi = AVR::LDRdPtrPd;
668 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
669
670 assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
671
672 auto MIBHI = buildMI(MBB, MBBI, OpHi)
673 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
674 .addReg(SrcReg, RegState::Define)
675 .addReg(SrcReg, RegState::Kill);
676
677 auto MIBLO = buildMI(MBB, MBBI, OpLo)
678 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
679 .addReg(SrcReg, RegState::Define | getDeadRegState(SrcIsDead))
680 .addReg(SrcReg, RegState::Kill);
681
682 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
683 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
684
685 MI.eraseFromParent();
686 return true;
687}
688
689template <>
690bool AVRExpandPseudo::expand<AVR::LDDWRdPtrQ>(Block &MBB, BlockIt MBBI) {
691 MachineInstr &MI = *MBBI;
692 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
693 unsigned DstReg = MI.getOperand(0).getReg();
Dylan McKay8f515b12017-04-25 15:09:04 +0000694 unsigned TmpReg = 0; // 0 for no temporary register
Dylan McKaya789f402016-11-16 21:58:04 +0000695 unsigned SrcReg = MI.getOperand(1).getReg();
696 unsigned Imm = MI.getOperand(2).getImm();
Dylan McKaya789f402016-11-16 21:58:04 +0000697 bool SrcIsKill = MI.getOperand(1).isKill();
698 OpLo = AVR::LDDRdPtrQ;
699 OpHi = AVR::LDDRdPtrQ;
700 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
701
Dylan McKayf3685092016-12-10 05:48:48 +0000702 assert(Imm <= 63 && "Offset is out of range");
Dylan McKay8cec7eb2016-12-07 11:08:56 +0000703
Dylan McKay8f515b12017-04-25 15:09:04 +0000704 // Use a temporary register if src and dst registers are the same.
705 if (DstReg == SrcReg)
706 TmpReg = scavengeGPR8(MI);
Dylan McKay8cec7eb2016-12-07 11:08:56 +0000707
Dylan McKay8f515b12017-04-25 15:09:04 +0000708 unsigned CurDstLoReg = (DstReg == SrcReg) ? TmpReg : DstLoReg;
709 unsigned CurDstHiReg = (DstReg == SrcReg) ? TmpReg : DstHiReg;
Dylan McKaya789f402016-11-16 21:58:04 +0000710
Dylan McKay8f515b12017-04-25 15:09:04 +0000711 // Load low byte.
712 auto MIBLO = buildMI(MBB, MBBI, OpLo)
713 .addReg(CurDstLoReg, RegState::Define)
714 .addReg(SrcReg)
715 .addImm(Imm);
Dylan McKaya789f402016-11-16 21:58:04 +0000716
Dylan McKay8f515b12017-04-25 15:09:04 +0000717 // Push low byte onto stack if necessary.
718 if (TmpReg)
719 buildMI(MBB, MBBI, AVR::PUSHRr).addReg(TmpReg);
Dylan McKay8cec7eb2016-12-07 11:08:56 +0000720
Dylan McKay8f515b12017-04-25 15:09:04 +0000721 // Load high byte.
722 auto MIBHI = buildMI(MBB, MBBI, OpHi)
723 .addReg(CurDstHiReg, RegState::Define)
724 .addReg(SrcReg, getKillRegState(SrcIsKill))
725 .addImm(Imm + 1);
Dylan McKaya789f402016-11-16 21:58:04 +0000726
Dylan McKay8f515b12017-04-25 15:09:04 +0000727 if (TmpReg) {
728 // Move the high byte into the final destination.
Dylan McKay5c90b8c2016-12-10 10:51:55 +0000729 buildMI(MBB, MBBI, AVR::MOVRdRr).addReg(DstHiReg).addReg(TmpReg);
Dylan McKay5c90b8c2016-12-10 10:51:55 +0000730
Dylan McKay8f515b12017-04-25 15:09:04 +0000731 // Move the low byte from the scratch space into the final destination.
732 buildMI(MBB, MBBI, AVR::POPRd).addReg(DstLoReg);
Dylan McKay8cec7eb2016-12-07 11:08:56 +0000733 }
734
Dylan McKaya789f402016-11-16 21:58:04 +0000735 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
736 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
737
738 MI.eraseFromParent();
739 return true;
740}
741
Dylan McKaya5d49df2016-12-09 07:49:04 +0000742template <>
743bool AVRExpandPseudo::expand<AVR::LPMWRdZ>(Block &MBB, BlockIt MBBI) {
744 llvm_unreachable("wide LPM is unimplemented");
745}
746
747template <>
748bool AVRExpandPseudo::expand<AVR::LPMWRdZPi>(Block &MBB, BlockIt MBBI) {
749 llvm_unreachable("wide LPMPi is unimplemented");
750}
751
Dylan McKaya789f402016-11-16 21:58:04 +0000752template<typename Func>
753bool AVRExpandPseudo::expandAtomic(Block &MBB, BlockIt MBBI, Func f) {
754 // Remove the pseudo instruction.
755 MachineInstr &MI = *MBBI;
756
757 // Store the SREG.
758 buildMI(MBB, MBBI, AVR::INRdA)
759 .addReg(SCRATCH_REGISTER, RegState::Define)
760 .addImm(SREG_ADDR);
761
762 // Disable exceptions.
763 buildMI(MBB, MBBI, AVR::BCLRs).addImm(7); // CLI
764
765 f(MI);
766
767 // Restore the status reg.
768 buildMI(MBB, MBBI, AVR::OUTARr)
769 .addImm(SREG_ADDR)
770 .addReg(SCRATCH_REGISTER);
771
772 MI.eraseFromParent();
773 return true;
774}
775
776template<typename Func>
777bool AVRExpandPseudo::expandAtomicBinaryOp(unsigned Opcode,
778 Block &MBB,
779 BlockIt MBBI,
780 Func f) {
781 return expandAtomic(MBB, MBBI, [&](MachineInstr &MI) {
782 auto Op1 = MI.getOperand(0);
783 auto Op2 = MI.getOperand(1);
784
Diana Picus116bbab2017-01-13 09:58:52 +0000785 MachineInstr &NewInst =
786 *buildMI(MBB, MBBI, Opcode).add(Op1).add(Op2).getInstr();
Dylan McKaya789f402016-11-16 21:58:04 +0000787 f(NewInst);
788 });
789}
790
791bool AVRExpandPseudo::expandAtomicBinaryOp(unsigned Opcode,
792 Block &MBB,
793 BlockIt MBBI) {
794 return expandAtomicBinaryOp(Opcode, MBB, MBBI, [](MachineInstr &MI) {});
795}
796
797bool AVRExpandPseudo::expandAtomicArithmeticOp(unsigned Width,
798 unsigned ArithOpcode,
799 Block &MBB,
800 BlockIt MBBI) {
801 return expandAtomic(MBB, MBBI, [&](MachineInstr &MI) {
802 auto Op1 = MI.getOperand(0);
803 auto Op2 = MI.getOperand(1);
804
805 unsigned LoadOpcode = (Width == 8) ? AVR::LDRdPtr : AVR::LDWRdPtr;
806 unsigned StoreOpcode = (Width == 8) ? AVR::STPtrRr : AVR::STWPtrRr;
807
808 // Create the load
Diana Picus116bbab2017-01-13 09:58:52 +0000809 buildMI(MBB, MBBI, LoadOpcode).add(Op1).add(Op2);
Dylan McKaya789f402016-11-16 21:58:04 +0000810
811 // Create the arithmetic op
Diana Picus116bbab2017-01-13 09:58:52 +0000812 buildMI(MBB, MBBI, ArithOpcode).add(Op1).add(Op1).add(Op2);
Dylan McKaya789f402016-11-16 21:58:04 +0000813
814 // Create the store
Diana Picus116bbab2017-01-13 09:58:52 +0000815 buildMI(MBB, MBBI, StoreOpcode).add(Op2).add(Op1);
Dylan McKaya789f402016-11-16 21:58:04 +0000816 });
817}
818
Dylan McKay8f515b12017-04-25 15:09:04 +0000819unsigned AVRExpandPseudo::scavengeGPR8(MachineInstr &MI) {
820 MachineBasicBlock &MBB = *MI.getParent();
821 RegScavenger RS;
822
823 RS.enterBasicBlock(MBB);
824 RS.forward(MI);
825
826 BitVector Candidates =
827 TRI->getAllocatableSet
828 (*MBB.getParent(), &AVR::GPR8RegClass);
829
830 // Exclude all the registers being used by the instruction.
831 for (MachineOperand &MO : MI.operands()) {
832 if (MO.isReg() && MO.getReg() != 0 && !MO.isDef() &&
833 !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
834 Candidates.reset(MO.getReg());
835 }
836
837 BitVector Available = RS.getRegsAvailable(&AVR::GPR8RegClass);
838 Available &= Candidates;
839
840 signed Reg = Available.find_first();
841 assert(Reg != -1 && "ran out of registers");
842 return Reg;
843}
844
Dylan McKaya789f402016-11-16 21:58:04 +0000845template<>
846bool AVRExpandPseudo::expand<AVR::AtomicLoad8>(Block &MBB, BlockIt MBBI) {
847 return expandAtomicBinaryOp(AVR::LDRdPtr, MBB, MBBI);
848}
849
850template<>
851bool AVRExpandPseudo::expand<AVR::AtomicLoad16>(Block &MBB, BlockIt MBBI) {
852 return expandAtomicBinaryOp(AVR::LDWRdPtr, MBB, MBBI);
853}
854
855template<>
856bool AVRExpandPseudo::expand<AVR::AtomicStore8>(Block &MBB, BlockIt MBBI) {
857 return expandAtomicBinaryOp(AVR::STPtrRr, MBB, MBBI);
858}
859
860template<>
861bool AVRExpandPseudo::expand<AVR::AtomicStore16>(Block &MBB, BlockIt MBBI) {
862 return expandAtomicBinaryOp(AVR::STWPtrRr, MBB, MBBI);
863}
864
865template<>
866bool AVRExpandPseudo::expand<AVR::AtomicLoadAdd8>(Block &MBB, BlockIt MBBI) {
867 return expandAtomicArithmeticOp(8, AVR::ADDRdRr, MBB, MBBI);
868}
869
870template<>
871bool AVRExpandPseudo::expand<AVR::AtomicLoadAdd16>(Block &MBB, BlockIt MBBI) {
872 return expandAtomicArithmeticOp(16, AVR::ADDWRdRr, MBB, MBBI);
873}
874
875template<>
876bool AVRExpandPseudo::expand<AVR::AtomicLoadSub8>(Block &MBB, BlockIt MBBI) {
877 return expandAtomicArithmeticOp(8, AVR::SUBRdRr, MBB, MBBI);
878}
879
880template<>
881bool AVRExpandPseudo::expand<AVR::AtomicLoadSub16>(Block &MBB, BlockIt MBBI) {
882 return expandAtomicArithmeticOp(16, AVR::SUBWRdRr, MBB, MBBI);
883}
884
885template<>
886bool AVRExpandPseudo::expand<AVR::AtomicLoadAnd8>(Block &MBB, BlockIt MBBI) {
887 return expandAtomicArithmeticOp(8, AVR::ANDRdRr, MBB, MBBI);
888}
889
890template<>
891bool AVRExpandPseudo::expand<AVR::AtomicLoadAnd16>(Block &MBB, BlockIt MBBI) {
892 return expandAtomicArithmeticOp(16, AVR::ANDWRdRr, MBB, MBBI);
893}
894
895template<>
896bool AVRExpandPseudo::expand<AVR::AtomicLoadOr8>(Block &MBB, BlockIt MBBI) {
897 return expandAtomicArithmeticOp(8, AVR::ORRdRr, MBB, MBBI);
898}
899
900template<>
901bool AVRExpandPseudo::expand<AVR::AtomicLoadOr16>(Block &MBB, BlockIt MBBI) {
902 return expandAtomicArithmeticOp(16, AVR::ORWRdRr, MBB, MBBI);
903}
904
905template<>
906bool AVRExpandPseudo::expand<AVR::AtomicLoadXor8>(Block &MBB, BlockIt MBBI) {
907 return expandAtomicArithmeticOp(8, AVR::EORRdRr, MBB, MBBI);
908}
909
910template<>
911bool AVRExpandPseudo::expand<AVR::AtomicLoadXor16>(Block &MBB, BlockIt MBBI) {
912 return expandAtomicArithmeticOp(16, AVR::EORWRdRr, MBB, MBBI);
913}
914
915template<>
916bool AVRExpandPseudo::expand<AVR::AtomicFence>(Block &MBB, BlockIt MBBI) {
917 // On AVR, there is only one core and so atomic fences do nothing.
918 MBBI->eraseFromParent();
919 return true;
920}
921
922template <>
923bool AVRExpandPseudo::expand<AVR::STSWKRr>(Block &MBB, BlockIt MBBI) {
924 MachineInstr &MI = *MBBI;
925 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
926 unsigned SrcReg = MI.getOperand(1).getReg();
927 bool SrcIsKill = MI.getOperand(1).isKill();
928 OpLo = AVR::STSKRr;
929 OpHi = AVR::STSKRr;
930 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
931
932 // Write the high byte first in case this address belongs to a special
933 // I/O address with a special temporary register.
934 auto MIBHI = buildMI(MBB, MBBI, OpHi);
935 auto MIBLO = buildMI(MBB, MBBI, OpLo);
936
937 switch (MI.getOperand(0).getType()) {
938 case MachineOperand::MO_GlobalAddress: {
939 const GlobalValue *GV = MI.getOperand(0).getGlobal();
940 int64_t Offs = MI.getOperand(0).getOffset();
941 unsigned TF = MI.getOperand(0).getTargetFlags();
942
943 MIBLO.addGlobalAddress(GV, Offs, TF);
944 MIBHI.addGlobalAddress(GV, Offs + 1, TF);
945 break;
946 }
947 case MachineOperand::MO_Immediate: {
948 unsigned Imm = MI.getOperand(0).getImm();
949
950 MIBLO.addImm(Imm);
951 MIBHI.addImm(Imm + 1);
952 break;
953 }
954 default:
955 llvm_unreachable("Unknown operand type!");
956 }
957
958 MIBLO.addReg(SrcLoReg, getKillRegState(SrcIsKill));
959 MIBHI.addReg(SrcHiReg, getKillRegState(SrcIsKill));
960
961 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
962 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
963
964 MI.eraseFromParent();
965 return true;
966}
967
968template <>
969bool AVRExpandPseudo::expand<AVR::STWPtrRr>(Block &MBB, BlockIt MBBI) {
970 MachineInstr &MI = *MBBI;
971 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
972 unsigned DstReg = MI.getOperand(0).getReg();
973 unsigned SrcReg = MI.getOperand(1).getReg();
974 bool DstIsKill = MI.getOperand(0).isKill();
975 bool SrcIsKill = MI.getOperand(1).isKill();
976 OpLo = AVR::STPtrRr;
977 OpHi = AVR::STDPtrQRr;
978 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
979
980 //:TODO: need to reverse this order like inw and stsw?
981 auto MIBLO = buildMI(MBB, MBBI, OpLo)
982 .addReg(DstReg)
983 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
984
985 auto MIBHI = buildMI(MBB, MBBI, OpHi)
Dylan McKayff49a052017-04-25 23:58:20 +0000986 .addReg(DstReg)
Dylan McKaya789f402016-11-16 21:58:04 +0000987 .addImm(1)
988 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
989
990 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
991 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
992
993 MI.eraseFromParent();
994 return true;
995}
996
997template <>
998bool AVRExpandPseudo::expand<AVR::STWPtrPiRr>(Block &MBB, BlockIt MBBI) {
999 MachineInstr &MI = *MBBI;
1000 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
1001 unsigned DstReg = MI.getOperand(0).getReg();
1002 unsigned SrcReg = MI.getOperand(2).getReg();
1003 unsigned Imm = MI.getOperand(3).getImm();
1004 bool DstIsDead = MI.getOperand(0).isDead();
1005 bool SrcIsKill = MI.getOperand(2).isKill();
1006 OpLo = AVR::STPtrPiRr;
1007 OpHi = AVR::STPtrPiRr;
1008 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1009
1010 assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
1011
1012 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1013 .addReg(DstReg, RegState::Define)
1014 .addReg(DstReg, RegState::Kill)
1015 .addReg(SrcLoReg, getKillRegState(SrcIsKill))
1016 .addImm(Imm);
1017
1018 auto MIBHI = buildMI(MBB, MBBI, OpHi)
1019 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
1020 .addReg(DstReg, RegState::Kill)
1021 .addReg(SrcHiReg, getKillRegState(SrcIsKill))
1022 .addImm(Imm);
1023
1024 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1025 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1026
1027 MI.eraseFromParent();
1028 return true;
1029}
1030
1031template <>
1032bool AVRExpandPseudo::expand<AVR::STWPtrPdRr>(Block &MBB, BlockIt MBBI) {
1033 MachineInstr &MI = *MBBI;
1034 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
1035 unsigned DstReg = MI.getOperand(0).getReg();
1036 unsigned SrcReg = MI.getOperand(2).getReg();
1037 unsigned Imm = MI.getOperand(3).getImm();
1038 bool DstIsDead = MI.getOperand(0).isDead();
1039 bool SrcIsKill = MI.getOperand(2).isKill();
1040 OpLo = AVR::STPtrPdRr;
1041 OpHi = AVR::STPtrPdRr;
1042 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1043
1044 assert(DstReg != SrcReg && "SrcReg and DstReg cannot be the same");
1045
1046 auto MIBHI = buildMI(MBB, MBBI, OpHi)
1047 .addReg(DstReg, RegState::Define)
1048 .addReg(DstReg, RegState::Kill)
1049 .addReg(SrcHiReg, getKillRegState(SrcIsKill))
1050 .addImm(Imm);
1051
1052 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1053 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
1054 .addReg(DstReg, RegState::Kill)
1055 .addReg(SrcLoReg, getKillRegState(SrcIsKill))
1056 .addImm(Imm);
1057
1058 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1059 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1060
1061 MI.eraseFromParent();
1062 return true;
1063}
1064
1065template <>
1066bool AVRExpandPseudo::expand<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
1067 MachineInstr &MI = *MBBI;
1068 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
1069 unsigned DstReg = MI.getOperand(0).getReg();
1070 unsigned SrcReg = MI.getOperand(2).getReg();
1071 unsigned Imm = MI.getOperand(1).getImm();
1072 bool DstIsKill = MI.getOperand(0).isKill();
1073 bool SrcIsKill = MI.getOperand(2).isKill();
1074 OpLo = AVR::STDPtrQRr;
1075 OpHi = AVR::STDPtrQRr;
1076 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1077
Dylan McKayf3685092016-12-10 05:48:48 +00001078 assert(Imm <= 63 && "Offset is out of range");
Dylan McKaya789f402016-11-16 21:58:04 +00001079
1080 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1081 .addReg(DstReg)
1082 .addImm(Imm)
1083 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
1084
1085 auto MIBHI = buildMI(MBB, MBBI, OpHi)
1086 .addReg(DstReg, getKillRegState(DstIsKill))
1087 .addImm(Imm + 1)
1088 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
1089
1090 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1091 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1092
1093 MI.eraseFromParent();
1094 return true;
1095}
1096
1097template <>
1098bool AVRExpandPseudo::expand<AVR::INWRdA>(Block &MBB, BlockIt MBBI) {
1099 MachineInstr &MI = *MBBI;
1100 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1101 unsigned Imm = MI.getOperand(1).getImm();
1102 unsigned DstReg = MI.getOperand(0).getReg();
1103 bool DstIsDead = MI.getOperand(0).isDead();
1104 OpLo = AVR::INRdA;
1105 OpHi = AVR::INRdA;
1106 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1107
Dylan McKayf3685092016-12-10 05:48:48 +00001108 assert(Imm <= 63 && "Address is out of range");
Dylan McKaya789f402016-11-16 21:58:04 +00001109
1110 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1111 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1112 .addImm(Imm);
1113
1114 auto MIBHI = buildMI(MBB, MBBI, OpHi)
1115 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1116 .addImm(Imm + 1);
1117
1118 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1119 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1120
1121 MI.eraseFromParent();
1122 return true;
1123}
1124
1125template <>
1126bool AVRExpandPseudo::expand<AVR::OUTWARr>(Block &MBB, BlockIt MBBI) {
1127 MachineInstr &MI = *MBBI;
1128 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
1129 unsigned Imm = MI.getOperand(0).getImm();
1130 unsigned SrcReg = MI.getOperand(1).getReg();
1131 bool SrcIsKill = MI.getOperand(1).isKill();
1132 OpLo = AVR::OUTARr;
1133 OpHi = AVR::OUTARr;
1134 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1135
Dylan McKayf3685092016-12-10 05:48:48 +00001136 assert(Imm <= 63 && "Address is out of range");
Dylan McKaya789f402016-11-16 21:58:04 +00001137
1138 // 16 bit I/O writes need the high byte first
1139 auto MIBHI = buildMI(MBB, MBBI, OpHi)
1140 .addImm(Imm + 1)
1141 .addReg(SrcHiReg, getKillRegState(SrcIsKill));
1142
1143 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1144 .addImm(Imm)
1145 .addReg(SrcLoReg, getKillRegState(SrcIsKill));
1146
1147 MIBLO->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1148 MIBHI->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1149
1150 MI.eraseFromParent();
1151 return true;
1152}
1153
1154template <>
1155bool AVRExpandPseudo::expand<AVR::PUSHWRr>(Block &MBB, BlockIt MBBI) {
1156 MachineInstr &MI = *MBBI;
1157 unsigned OpLo, OpHi, SrcLoReg, SrcHiReg;
1158 unsigned SrcReg = MI.getOperand(0).getReg();
1159 bool SrcIsKill = MI.getOperand(0).isKill();
1160 unsigned Flags = MI.getFlags();
1161 OpLo = AVR::PUSHRr;
1162 OpHi = AVR::PUSHRr;
1163 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1164
1165 // Low part
1166 buildMI(MBB, MBBI, OpLo)
1167 .addReg(SrcLoReg, getKillRegState(SrcIsKill))
1168 .setMIFlags(Flags);
1169
1170 // High part
1171 buildMI(MBB, MBBI, OpHi)
1172 .addReg(SrcHiReg, getKillRegState(SrcIsKill))
1173 .setMIFlags(Flags);
1174
1175 MI.eraseFromParent();
1176 return true;
1177}
1178
1179template <>
1180bool AVRExpandPseudo::expand<AVR::POPWRd>(Block &MBB, BlockIt MBBI) {
1181 MachineInstr &MI = *MBBI;
1182 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1183 unsigned DstReg = MI.getOperand(0).getReg();
1184 unsigned Flags = MI.getFlags();
1185 OpLo = AVR::POPRd;
1186 OpHi = AVR::POPRd;
1187 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1188
1189 buildMI(MBB, MBBI, OpHi, DstHiReg).setMIFlags(Flags); // High
1190 buildMI(MBB, MBBI, OpLo, DstLoReg).setMIFlags(Flags); // Low
1191
1192 MI.eraseFromParent();
1193 return true;
1194}
1195
1196template <>
1197bool AVRExpandPseudo::expand<AVR::LSLWRd>(Block &MBB, BlockIt MBBI) {
1198 MachineInstr &MI = *MBBI;
1199 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1200 unsigned DstReg = MI.getOperand(0).getReg();
1201 bool DstIsDead = MI.getOperand(0).isDead();
1202 bool DstIsKill = MI.getOperand(1).isKill();
1203 bool ImpIsDead = MI.getOperand(2).isDead();
1204 OpLo = AVR::LSLRd;
1205 OpHi = AVR::ROLRd;
1206 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1207
1208 // Low part
1209 buildMI(MBB, MBBI, OpLo)
1210 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1211 .addReg(DstLoReg, getKillRegState(DstIsKill));
1212
1213 auto MIBHI = buildMI(MBB, MBBI, OpHi)
1214 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1215 .addReg(DstHiReg, getKillRegState(DstIsKill));
1216
1217 if (ImpIsDead)
1218 MIBHI->getOperand(2).setIsDead();
1219
1220 // SREG is always implicitly killed
1221 MIBHI->getOperand(3).setIsKill();
1222
1223 MI.eraseFromParent();
1224 return true;
1225}
1226
1227template <>
1228bool AVRExpandPseudo::expand<AVR::LSRWRd>(Block &MBB, BlockIt MBBI) {
1229 MachineInstr &MI = *MBBI;
1230 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1231 unsigned DstReg = MI.getOperand(0).getReg();
1232 bool DstIsDead = MI.getOperand(0).isDead();
1233 bool DstIsKill = MI.getOperand(1).isKill();
1234 bool ImpIsDead = MI.getOperand(2).isDead();
1235 OpLo = AVR::RORRd;
1236 OpHi = AVR::LSRRd;
1237 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1238
1239 // High part
1240 buildMI(MBB, MBBI, OpHi)
1241 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1242 .addReg(DstHiReg, getKillRegState(DstIsKill));
1243
1244 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1245 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1246 .addReg(DstLoReg, getKillRegState(DstIsKill));
1247
1248 if (ImpIsDead)
1249 MIBLO->getOperand(2).setIsDead();
1250
1251 // SREG is always implicitly killed
1252 MIBLO->getOperand(3).setIsKill();
1253
1254 MI.eraseFromParent();
1255 return true;
1256}
1257
1258template <>
1259bool AVRExpandPseudo::expand<AVR::RORWRd>(Block &MBB, BlockIt MBBI) {
1260 llvm_unreachable("RORW unimplemented");
1261 return false;
1262}
1263
1264template <>
1265bool AVRExpandPseudo::expand<AVR::ROLWRd>(Block &MBB, BlockIt MBBI) {
1266 llvm_unreachable("ROLW unimplemented");
1267 return false;
1268}
1269
1270template <>
1271bool AVRExpandPseudo::expand<AVR::ASRWRd>(Block &MBB, BlockIt MBBI) {
1272 MachineInstr &MI = *MBBI;
1273 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1274 unsigned DstReg = MI.getOperand(0).getReg();
1275 bool DstIsDead = MI.getOperand(0).isDead();
1276 bool DstIsKill = MI.getOperand(1).isKill();
1277 bool ImpIsDead = MI.getOperand(2).isDead();
1278 OpLo = AVR::RORRd;
1279 OpHi = AVR::ASRRd;
1280 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1281
1282 // High part
1283 buildMI(MBB, MBBI, OpHi)
1284 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1285 .addReg(DstHiReg, getKillRegState(DstIsKill));
1286
1287 auto MIBLO = buildMI(MBB, MBBI, OpLo)
1288 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1289 .addReg(DstLoReg, getKillRegState(DstIsKill));
1290
1291 if (ImpIsDead)
1292 MIBLO->getOperand(2).setIsDead();
1293
1294 // SREG is always implicitly killed
1295 MIBLO->getOperand(3).setIsKill();
1296
1297 MI.eraseFromParent();
1298 return true;
1299}
1300
1301template <> bool AVRExpandPseudo::expand<AVR::SEXT>(Block &MBB, BlockIt MBBI) {
1302 MachineInstr &MI = *MBBI;
1303 unsigned DstLoReg, DstHiReg;
1304 // sext R17:R16, R17
1305 // mov r16, r17
1306 // lsl r17
1307 // sbc r17, r17
1308 // sext R17:R16, R13
1309 // mov r16, r13
1310 // mov r17, r13
1311 // lsl r17
1312 // sbc r17, r17
1313 // sext R17:R16, R16
1314 // mov r17, r16
1315 // lsl r17
1316 // sbc r17, r17
1317 unsigned DstReg = MI.getOperand(0).getReg();
1318 unsigned SrcReg = MI.getOperand(1).getReg();
1319 bool DstIsDead = MI.getOperand(0).isDead();
1320 bool SrcIsKill = MI.getOperand(1).isKill();
1321 bool ImpIsDead = MI.getOperand(2).isDead();
1322 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1323
1324 if (SrcReg != DstLoReg) {
1325 auto MOV = buildMI(MBB, MBBI, AVR::MOVRdRr)
1326 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1327 .addReg(SrcReg);
1328
1329 if (SrcReg == DstHiReg) {
1330 MOV->getOperand(1).setIsKill();
1331 }
1332 }
1333
1334 if (SrcReg != DstHiReg) {
1335 buildMI(MBB, MBBI, AVR::MOVRdRr)
1336 .addReg(DstHiReg, RegState::Define)
1337 .addReg(SrcReg, getKillRegState(SrcIsKill));
1338 }
1339
1340 buildMI(MBB, MBBI, AVR::LSLRd)
1341 .addReg(DstHiReg, RegState::Define)
1342 .addReg(DstHiReg, RegState::Kill);
1343
1344 auto SBC = buildMI(MBB, MBBI, AVR::SBCRdRr)
1345 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1346 .addReg(DstHiReg, RegState::Kill)
1347 .addReg(DstHiReg, RegState::Kill);
1348
1349 if (ImpIsDead)
1350 SBC->getOperand(3).setIsDead();
1351
1352 // SREG is always implicitly killed
1353 SBC->getOperand(4).setIsKill();
1354
1355 MI.eraseFromParent();
1356 return true;
1357}
1358
1359template <> bool AVRExpandPseudo::expand<AVR::ZEXT>(Block &MBB, BlockIt MBBI) {
1360 MachineInstr &MI = *MBBI;
1361 unsigned DstLoReg, DstHiReg;
1362 // zext R25:R24, R20
1363 // mov R24, R20
1364 // eor R25, R25
1365 // zext R25:R24, R24
1366 // eor R25, R25
1367 // zext R25:R24, R25
1368 // mov R24, R25
1369 // eor R25, R25
1370 unsigned DstReg = MI.getOperand(0).getReg();
1371 unsigned SrcReg = MI.getOperand(1).getReg();
1372 bool DstIsDead = MI.getOperand(0).isDead();
1373 bool SrcIsKill = MI.getOperand(1).isKill();
1374 bool ImpIsDead = MI.getOperand(2).isDead();
1375 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1376
1377 if (SrcReg != DstLoReg) {
1378 buildMI(MBB, MBBI, AVR::MOVRdRr)
1379 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1380 .addReg(SrcReg, getKillRegState(SrcIsKill));
1381 }
1382
1383 auto EOR = buildMI(MBB, MBBI, AVR::EORRdRr)
1384 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1385 .addReg(DstHiReg, RegState::Kill)
1386 .addReg(DstHiReg, RegState::Kill);
1387
1388 if (ImpIsDead)
1389 EOR->getOperand(3).setIsDead();
1390
1391 MI.eraseFromParent();
1392 return true;
1393}
1394
1395template <>
1396bool AVRExpandPseudo::expand<AVR::SPREAD>(Block &MBB, BlockIt MBBI) {
1397 MachineInstr &MI = *MBBI;
1398 unsigned OpLo, OpHi, DstLoReg, DstHiReg;
1399 unsigned DstReg = MI.getOperand(0).getReg();
1400 bool DstIsDead = MI.getOperand(0).isDead();
1401 unsigned Flags = MI.getFlags();
1402 OpLo = AVR::INRdA;
1403 OpHi = AVR::INRdA;
1404 TRI->splitReg(DstReg, DstLoReg, DstHiReg);
1405
1406 // Low part
1407 buildMI(MBB, MBBI, OpLo)
1408 .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
1409 .addImm(0x3d)
1410 .setMIFlags(Flags);
1411
1412 // High part
1413 buildMI(MBB, MBBI, OpHi)
1414 .addReg(DstHiReg, RegState::Define | getDeadRegState(DstIsDead))
1415 .addImm(0x3e)
1416 .setMIFlags(Flags);
1417
1418 MI.eraseFromParent();
1419 return true;
1420}
1421
1422template <>
1423bool AVRExpandPseudo::expand<AVR::SPWRITE>(Block &MBB, BlockIt MBBI) {
1424 MachineInstr &MI = *MBBI;
1425 unsigned SrcLoReg, SrcHiReg;
1426 unsigned SrcReg = MI.getOperand(1).getReg();
1427 bool SrcIsKill = MI.getOperand(1).isKill();
1428 unsigned Flags = MI.getFlags();
1429 TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
1430
1431 buildMI(MBB, MBBI, AVR::INRdA)
1432 .addReg(AVR::R0, RegState::Define)
1433 .addImm(SREG_ADDR)
1434 .setMIFlags(Flags);
1435
1436 buildMI(MBB, MBBI, AVR::BCLRs).addImm(0x07).setMIFlags(Flags);
1437
1438 buildMI(MBB, MBBI, AVR::OUTARr)
1439 .addImm(0x3e)
1440 .addReg(SrcHiReg, getKillRegState(SrcIsKill))
1441 .setMIFlags(Flags);
1442
1443 buildMI(MBB, MBBI, AVR::OUTARr)
1444 .addImm(SREG_ADDR)
1445 .addReg(AVR::R0, RegState::Kill)
1446 .setMIFlags(Flags);
1447
1448 buildMI(MBB, MBBI, AVR::OUTARr)
1449 .addImm(0x3d)
1450 .addReg(SrcLoReg, getKillRegState(SrcIsKill))
1451 .setMIFlags(Flags);
1452
1453 MI.eraseFromParent();
1454 return true;
1455}
1456
1457bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
1458 MachineInstr &MI = *MBBI;
1459 int Opcode = MBBI->getOpcode();
1460
1461#define EXPAND(Op) \
1462 case Op: \
1463 return expand<Op>(MBB, MI)
1464
1465 switch (Opcode) {
1466 EXPAND(AVR::ADDWRdRr);
1467 EXPAND(AVR::ADCWRdRr);
1468 EXPAND(AVR::SUBWRdRr);
1469 EXPAND(AVR::SUBIWRdK);
1470 EXPAND(AVR::SBCWRdRr);
1471 EXPAND(AVR::SBCIWRdK);
1472 EXPAND(AVR::ANDWRdRr);
1473 EXPAND(AVR::ANDIWRdK);
1474 EXPAND(AVR::ORWRdRr);
1475 EXPAND(AVR::ORIWRdK);
1476 EXPAND(AVR::EORWRdRr);
1477 EXPAND(AVR::COMWRd);
1478 EXPAND(AVR::CPWRdRr);
1479 EXPAND(AVR::CPCWRdRr);
1480 EXPAND(AVR::LDIWRdK);
1481 EXPAND(AVR::LDSWRdK);
1482 EXPAND(AVR::LDWRdPtr);
1483 EXPAND(AVR::LDWRdPtrPi);
1484 EXPAND(AVR::LDWRdPtrPd);
1485 case AVR::LDDWRdYQ: //:FIXME: remove this once PR13375 gets fixed
1486 EXPAND(AVR::LDDWRdPtrQ);
Dylan McKaya5d49df2016-12-09 07:49:04 +00001487 EXPAND(AVR::LPMWRdZ);
1488 EXPAND(AVR::LPMWRdZPi);
Dylan McKaya789f402016-11-16 21:58:04 +00001489 EXPAND(AVR::AtomicLoad8);
1490 EXPAND(AVR::AtomicLoad16);
1491 EXPAND(AVR::AtomicStore8);
1492 EXPAND(AVR::AtomicStore16);
1493 EXPAND(AVR::AtomicLoadAdd8);
1494 EXPAND(AVR::AtomicLoadAdd16);
1495 EXPAND(AVR::AtomicLoadSub8);
1496 EXPAND(AVR::AtomicLoadSub16);
1497 EXPAND(AVR::AtomicLoadAnd8);
1498 EXPAND(AVR::AtomicLoadAnd16);
1499 EXPAND(AVR::AtomicLoadOr8);
1500 EXPAND(AVR::AtomicLoadOr16);
1501 EXPAND(AVR::AtomicLoadXor8);
1502 EXPAND(AVR::AtomicLoadXor16);
1503 EXPAND(AVR::AtomicFence);
1504 EXPAND(AVR::STSWKRr);
1505 EXPAND(AVR::STWPtrRr);
1506 EXPAND(AVR::STWPtrPiRr);
1507 EXPAND(AVR::STWPtrPdRr);
1508 EXPAND(AVR::STDWPtrQRr);
1509 EXPAND(AVR::INWRdA);
1510 EXPAND(AVR::OUTWARr);
1511 EXPAND(AVR::PUSHWRr);
1512 EXPAND(AVR::POPWRd);
1513 EXPAND(AVR::LSLWRd);
1514 EXPAND(AVR::LSRWRd);
1515 EXPAND(AVR::RORWRd);
1516 EXPAND(AVR::ROLWRd);
1517 EXPAND(AVR::ASRWRd);
1518 EXPAND(AVR::SEXT);
1519 EXPAND(AVR::ZEXT);
1520 EXPAND(AVR::SPREAD);
1521 EXPAND(AVR::SPWRITE);
1522 }
1523#undef EXPAND
1524 return false;
1525}
1526
Dylan McKay017a55b2016-11-16 23:06:14 +00001527} // end of anonymous namespace
1528
Dylan McKay8cec7eb2016-12-07 11:08:56 +00001529INITIALIZE_PASS(AVRExpandPseudo, "avr-expand-pseudo",
1530 AVR_EXPAND_PSEUDO_NAME, false, false)
Dylan McKaya789f402016-11-16 21:58:04 +00001531namespace llvm {
1532
1533FunctionPass *createAVRExpandPseudoPass() { return new AVRExpandPseudo(); }
1534
1535} // end of namespace llvm