LLVM 22.0.0git
MipsSEFrameLowering.cpp
Go to the documentation of this file.
1//===- MipsSEFrameLowering.cpp - Mips32/64 Frame Information --------------===//
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 the Mips32/64 implementation of TargetFrameLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MipsSEFrameLowering.h"
15#include "MipsMachineFunction.h"
16#include "MipsRegisterInfo.h"
17#include "MipsSEInstrInfo.h"
18#include "MipsSubtarget.h"
19#include "llvm/ADT/BitVector.h"
20#include "llvm/ADT/StringRef.h"
35#include "llvm/IR/DebugLoc.h"
36#include "llvm/IR/Function.h"
40#include <cassert>
41#include <cstdint>
42#include <utility>
43#include <vector>
44
45using namespace llvm;
46
47static std::pair<unsigned, unsigned> getMFHiLoOpc(unsigned Src) {
48 if (Mips::ACC64RegClass.contains(Src))
49 return std::make_pair((unsigned)Mips::PseudoMFHI,
50 (unsigned)Mips::PseudoMFLO);
51
52 if (Mips::ACC64DSPRegClass.contains(Src))
53 return std::make_pair((unsigned)Mips::MFHI_DSP, (unsigned)Mips::MFLO_DSP);
54
55 if (Mips::ACC128RegClass.contains(Src))
56 return std::make_pair((unsigned)Mips::PseudoMFHI64,
57 (unsigned)Mips::PseudoMFLO64);
58
59 return std::make_pair(0, 0);
60}
61
62namespace {
63
64/// Helper class to expand pseudos.
65class ExpandPseudo {
66public:
67 ExpandPseudo(MachineFunction &MF);
68 bool expand();
69
70private:
71 using Iter = MachineBasicBlock::iterator;
72
73 bool expandInstr(MachineBasicBlock &MBB, Iter I);
74 void expandLoadCCond(MachineBasicBlock &MBB, Iter I);
75 void expandStoreCCond(MachineBasicBlock &MBB, Iter I);
76 void expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize);
77 void expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc,
78 unsigned MFLoOpc, unsigned RegSize);
79 bool expandCopy(MachineBasicBlock &MBB, Iter I);
80 bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc,
81 unsigned MFLoOpc);
82 bool expandBuildPairF64(MachineBasicBlock &MBB,
83 MachineBasicBlock::iterator I, bool FP64) const;
84 bool expandExtractElementF64(MachineBasicBlock &MBB,
85 MachineBasicBlock::iterator I, bool FP64) const;
86
89 const MipsSubtarget &Subtarget;
90 const MipsSEInstrInfo &TII;
92};
93
94} // end anonymous namespace
95
96ExpandPseudo::ExpandPseudo(MachineFunction &MF_)
97 : MF(MF_), MRI(MF.getRegInfo()),
98 Subtarget(MF.getSubtarget<MipsSubtarget>()),
99 TII(*static_cast<const MipsSEInstrInfo *>(Subtarget.getInstrInfo())),
100 RegInfo(*Subtarget.getRegisterInfo()) {}
101
102bool ExpandPseudo::expand() {
103 bool Expanded = false;
104
105 for (auto &MBB : MF) {
106 for (Iter I = MBB.begin(), End = MBB.end(); I != End;)
107 Expanded |= expandInstr(MBB, I++);
108 }
109
110 return Expanded;
111}
112
113bool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) {
114 switch(I->getOpcode()) {
115 case Mips::LOAD_CCOND_DSP:
116 expandLoadCCond(MBB, I);
117 break;
118 case Mips::STORE_CCOND_DSP:
119 expandStoreCCond(MBB, I);
120 break;
121 case Mips::LOAD_ACC64:
122 case Mips::LOAD_ACC64DSP:
123 expandLoadACC(MBB, I, 4);
124 break;
125 case Mips::LOAD_ACC128:
126 expandLoadACC(MBB, I, 8);
127 break;
128 case Mips::STORE_ACC64:
129 expandStoreACC(MBB, I, Mips::PseudoMFHI, Mips::PseudoMFLO, 4);
130 break;
131 case Mips::STORE_ACC64DSP:
132 expandStoreACC(MBB, I, Mips::MFHI_DSP, Mips::MFLO_DSP, 4);
133 break;
134 case Mips::STORE_ACC128:
135 expandStoreACC(MBB, I, Mips::PseudoMFHI64, Mips::PseudoMFLO64, 8);
136 break;
137 case Mips::BuildPairF64:
138 if (expandBuildPairF64(MBB, I, false))
139 MBB.erase(I);
140 return false;
141 case Mips::BuildPairF64_64:
142 if (expandBuildPairF64(MBB, I, true))
143 MBB.erase(I);
144 return false;
145 case Mips::ExtractElementF64:
146 if (expandExtractElementF64(MBB, I, false))
147 MBB.erase(I);
148 return false;
149 case Mips::ExtractElementF64_64:
150 if (expandExtractElementF64(MBB, I, true))
151 MBB.erase(I);
152 return false;
153 case TargetOpcode::COPY:
154 if (!expandCopy(MBB, I))
155 return false;
156 break;
157 default:
158 return false;
159 }
160
161 MBB.erase(I);
162 return true;
163}
164
165void ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) {
166 // load $vr, FI
167 // copy ccond, $vr
168
169 assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
170
171 const TargetRegisterClass *RC = RegInfo.intRegClass(4);
172 Register VR = MRI.createVirtualRegister(RC);
173 Register Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
174
175 TII.loadRegFromStack(MBB, I, VR, FI, RC, &RegInfo, 0);
176 BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), Dst)
178}
179
180void ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) {
181 // copy $vr, ccond
182 // store $vr, FI
183
184 assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
185
186 const TargetRegisterClass *RC = RegInfo.intRegClass(4);
187 Register VR = MRI.createVirtualRegister(RC);
188 Register Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
189
190 BuildMI(MBB, I, I->getDebugLoc(), TII.get(TargetOpcode::COPY), VR)
191 .addReg(Src, getKillRegState(I->getOperand(0).isKill()));
192 TII.storeRegToStack(MBB, I, VR, true, FI, RC, &RegInfo, 0);
193}
194
195void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I,
196 unsigned RegSize) {
197 // load $vr0, FI
198 // copy lo, $vr0
199 // load $vr1, FI + 4
200 // copy hi, $vr1
201
202 assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
203
204 const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
205 Register VR0 = MRI.createVirtualRegister(RC);
206 Register VR1 = MRI.createVirtualRegister(RC);
207 Register Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
208 Register Lo = RegInfo.getSubReg(Dst, Mips::sub_lo);
209 Register Hi = RegInfo.getSubReg(Dst, Mips::sub_hi);
210 DebugLoc DL = I->getDebugLoc();
211 const MCInstrDesc &Desc = TII.get(TargetOpcode::COPY);
212
213 TII.loadRegFromStack(MBB, I, VR0, FI, RC, &RegInfo, 0);
215 TII.loadRegFromStack(MBB, I, VR1, FI, RC, &RegInfo, RegSize);
217}
218
219void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I,
220 unsigned MFHiOpc, unsigned MFLoOpc,
221 unsigned RegSize) {
222 // mflo $vr0, src
223 // store $vr0, FI
224 // mfhi $vr1, src
225 // store $vr1, FI + 4
226
227 assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
228
229 const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
230 Register VR0 = MRI.createVirtualRegister(RC);
231 Register VR1 = MRI.createVirtualRegister(RC);
232 Register Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
233 unsigned SrcKill = getKillRegState(I->getOperand(0).isKill());
234 DebugLoc DL = I->getDebugLoc();
235
236 BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src);
237 TII.storeRegToStack(MBB, I, VR0, true, FI, RC, &RegInfo, 0);
238 BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill);
239 TII.storeRegToStack(MBB, I, VR1, true, FI, RC, &RegInfo, RegSize);
240}
241
242bool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) {
243 Register Src = I->getOperand(1).getReg();
244 std::pair<unsigned, unsigned> Opcodes = getMFHiLoOpc(Src);
245
246 if (!Opcodes.first)
247 return false;
248
249 return expandCopyACC(MBB, I, Opcodes.first, Opcodes.second);
250}
251
252bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I,
253 unsigned MFHiOpc, unsigned MFLoOpc) {
254 // mflo $vr0, src
255 // copy dst_lo, $vr0
256 // mfhi $vr1, src
257 // copy dst_hi, $vr1
258
259 unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg();
260 const TargetRegisterClass *DstRC = RegInfo.getMinimalPhysRegClass(Dst);
261 unsigned VRegSize = RegInfo.getRegSizeInBits(*DstRC) / 16;
262 const TargetRegisterClass *RC = RegInfo.intRegClass(VRegSize);
263 Register VR0 = MRI.createVirtualRegister(RC);
264 Register VR1 = MRI.createVirtualRegister(RC);
265 unsigned SrcKill = getKillRegState(I->getOperand(1).isKill());
266 Register DstLo = RegInfo.getSubReg(Dst, Mips::sub_lo);
267 Register DstHi = RegInfo.getSubReg(Dst, Mips::sub_hi);
268 DebugLoc DL = I->getDebugLoc();
269
270 BuildMI(MBB, I, DL, TII.get(MFLoOpc), VR0).addReg(Src);
271 BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstLo)
272 .addReg(VR0, RegState::Kill);
273 BuildMI(MBB, I, DL, TII.get(MFHiOpc), VR1).addReg(Src, SrcKill);
274 BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstHi)
275 .addReg(VR1, RegState::Kill);
276 return true;
277}
278
279/// This method expands the same instruction that MipsSEInstrInfo::
280/// expandBuildPairF64 does, for the case when ABI is fpxx and mthc1 is not
281/// available and the case where the ABI is FP64A. It is implemented here
282/// because frame indexes are eliminated before MipsSEInstrInfo::
283/// expandBuildPairF64 is called.
284bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB,
286 bool FP64) const {
287 // For fpxx and when mthc1 is not available, use:
288 // spill + reload via ldc1
289 //
290 // The case where dmtc1 is available doesn't need to be handled here
291 // because it never creates a BuildPairF64 node.
292 //
293 // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence
294 // for odd-numbered double precision values (because the lower 32-bits is
295 // transferred with mtc1 which is redirected to the upper half of the even
296 // register). Unfortunately, we have to make this decision before register
297 // allocation so for now we use a spill/reload sequence for all
298 // double-precision values in regardless of being an odd/even register.
299 //
300 // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as
301 // implicit operand, so other passes (like ShrinkWrapping) are aware that
302 // stack is used.
303 if (I->getNumOperands() == 4 && I->getOperand(3).isReg()
304 && I->getOperand(3).getReg() == Mips::SP) {
305 Register DstReg = I->getOperand(0).getReg();
306 Register LoReg = I->getOperand(1).getReg();
307 Register HiReg = I->getOperand(2).getReg();
308
309 // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are
310 // the cases where mthc1 is not available). 64-bit architectures and
311 // MIPS32r2 or later can use FGR64 though.
312 assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() ||
313 !Subtarget.isFP64bit());
314
315 const TargetRegisterClass *RC = &Mips::GPR32RegClass;
316 const TargetRegisterClass *RC2 =
317 FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
318
319 // We re-use the same spill slot each time so that the stack frame doesn't
320 // grow too much in functions with a large number of moves.
321 int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(MF, RC2);
322 if (!Subtarget.isLittle())
323 std::swap(LoReg, HiReg);
324 TII.storeRegToStack(MBB, I, LoReg, I->getOperand(1).isKill(), FI, RC,
325 &RegInfo, 0);
326 TII.storeRegToStack(MBB, I, HiReg, I->getOperand(2).isKill(), FI, RC,
327 &RegInfo, 4);
328 TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &RegInfo, 0);
329 return true;
330 }
331
332 return false;
333}
334
335/// This method expands the same instruction that MipsSEInstrInfo::
336/// expandExtractElementF64 does, for the case when ABI is fpxx and mfhc1 is not
337/// available and the case where the ABI is FP64A. It is implemented here
338/// because frame indexes are eliminated before MipsSEInstrInfo::
339/// expandExtractElementF64 is called.
340bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB,
342 bool FP64) const {
343 const MachineOperand &Op1 = I->getOperand(1);
344 const MachineOperand &Op2 = I->getOperand(2);
345
346 if ((Op1.isReg() && Op1.isUndef()) || (Op2.isReg() && Op2.isUndef())) {
347 Register DstReg = I->getOperand(0).getReg();
348 BuildMI(MBB, I, I->getDebugLoc(), TII.get(Mips::IMPLICIT_DEF), DstReg);
349 return true;
350 }
351
352 // For fpxx and when mfhc1 is not available, use:
353 // spill + reload via ldc1
354 //
355 // The case where dmfc1 is available doesn't need to be handled here
356 // because it never creates a ExtractElementF64 node.
357 //
358 // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence
359 // for odd-numbered double precision values (because the lower 32-bits is
360 // transferred with mfc1 which is redirected to the upper half of the even
361 // register). Unfortunately, we have to make this decision before register
362 // allocation so for now we use a spill/reload sequence for all
363 // double-precision values in regardless of being an odd/even register.
364 //
365 // For the cases that should be covered here MipsSEISelDAGToDAG adds $sp as
366 // implicit operand, so other passes (like ShrinkWrapping) are aware that
367 // stack is used.
368 if (I->getNumOperands() == 4 && I->getOperand(3).isReg()
369 && I->getOperand(3).getReg() == Mips::SP) {
370 Register DstReg = I->getOperand(0).getReg();
371 Register SrcReg = Op1.getReg();
372 unsigned N = Op2.getImm();
373 int64_t Offset = 4 * (Subtarget.isLittle() ? N : (1 - N));
374
375 // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are
376 // the cases where mfhc1 is not available). 64-bit architectures and
377 // MIPS32r2 or later can use FGR64 though.
378 assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() ||
379 !Subtarget.isFP64bit());
380
381 const TargetRegisterClass *RC =
382 FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass;
383 const TargetRegisterClass *RC2 = &Mips::GPR32RegClass;
384
385 // We re-use the same spill slot each time so that the stack frame doesn't
386 // grow too much in functions with a large number of moves.
387 int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(MF, RC);
388 TII.storeRegToStack(MBB, I, SrcReg, Op1.isKill(), FI, RC, &RegInfo, 0);
389 TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &RegInfo, Offset);
390 return true;
391 }
392
393 return false;
394}
395
397 : MipsFrameLowering(STI, STI.getStackAlignment()) {}
398
400 MachineBasicBlock &MBB) const {
401 MachineFrameInfo &MFI = MF.getFrameInfo();
403
404 const MipsSEInstrInfo &TII =
405 *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo());
406 const MipsRegisterInfo &RegInfo = *STI.getRegisterInfo();
407
409 DebugLoc dl;
410 MipsABIInfo ABI = STI.getABI();
411 unsigned SP = ABI.GetStackPtr();
412 unsigned FP = ABI.GetFramePtr();
413 unsigned ZERO = ABI.GetNullPtr();
414 unsigned MOVE = ABI.GetGPRMoveOp();
415 unsigned ADDiu = ABI.GetPtrAddiuOp();
416 unsigned AND = ABI.IsN64() ? Mips::AND64 : Mips::AND;
417
418 const TargetRegisterClass *RC = ABI.ArePtrs64bit() ?
419 &Mips::GPR64RegClass : &Mips::GPR32RegClass;
420
421 // First, compute final stack size.
422 uint64_t StackSize = MFI.getStackSize();
423
424 // No need to allocate space on the stack.
425 if (StackSize == 0 && !MFI.adjustsStack()) return;
426
428
429 // Adjust stack.
430 TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
431 CFIBuilder.buildDefCFAOffset(StackSize);
432
433 if (MF.getFunction().hasFnAttribute("interrupt"))
434 emitInterruptPrologueStub(MF, MBB);
435
436 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
437
438 // Find the instruction past the last instruction that saves a callee-saved
439 // register to the stack.
440 std::advance(MBBI, CSI.size());
441 CFIBuilder.setInsertPoint(MBBI);
442
443 if (!CSI.empty()) {
444 // Iterate over list of callee-saved registers and emit .cfi_offset
445 // directives.
446 for (const CalleeSavedInfo &I : CSI) {
447 int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
448 MCRegister Reg = I.getReg();
449
450 // If Reg is a double precision register, emit two cfa_offsets,
451 // one for each of the paired single precision registers.
452 if (Mips::AFGR64RegClass.contains(Reg)) {
453 MCRegister Reg0 = RegInfo.getSubReg(Reg, Mips::sub_lo);
454 MCRegister Reg1 = RegInfo.getSubReg(Reg, Mips::sub_hi);
455
456 if (!STI.isLittle())
457 std::swap(Reg0, Reg1);
458
459 CFIBuilder.buildOffset(Reg0, Offset);
460 CFIBuilder.buildOffset(Reg1, Offset + 4);
461 } else if (Mips::FGR64RegClass.contains(Reg)) {
462 MCRegister Reg0 = Reg;
463 MCRegister Reg1 = Reg + 1;
464
465 if (!STI.isLittle())
466 std::swap(Reg0, Reg1);
467
468 CFIBuilder.buildOffset(Reg0, Offset);
469 CFIBuilder.buildOffset(Reg1, Offset + 4);
470 } else {
471 // Reg is either in GPR32 or FGR32.
472 CFIBuilder.buildOffset(Reg, Offset);
473 }
474 }
475 }
476
477 if (MipsFI->callsEhReturn()) {
478 // Insert instructions that spill eh data registers.
479 for (int I = 0; I < 4; ++I) {
480 if (!MBB.isLiveIn(ABI.GetEhDataReg(I)))
481 MBB.addLiveIn(ABI.GetEhDataReg(I));
482 TII.storeRegToStackSlot(MBB, MBBI, ABI.GetEhDataReg(I), false,
483 MipsFI->getEhDataRegFI(I), RC, &RegInfo,
484 Register());
485 }
486
487 // Emit .cfi_offset directives for eh data registers.
488 for (int I = 0; I < 4; ++I) {
489 int64_t Offset = MFI.getObjectOffset(MipsFI->getEhDataRegFI(I));
490 CFIBuilder.buildOffset(ABI.GetEhDataReg(I), Offset);
491 }
492 }
493
494 // if framepointer enabled, set it to point to the stack pointer.
495 if (hasFP(MF)) {
496 // Insert instruction "move $fp, $sp" at this location.
497 BuildMI(MBB, MBBI, dl, TII.get(MOVE), FP).addReg(SP).addReg(ZERO)
499
500 CFIBuilder.buildDefCFARegister(FP);
501
502 if (RegInfo.hasStackRealignment(MF)) {
503 // addiu $Reg, $zero, -MaxAlignment
504 // andi $sp, $sp, $Reg
506 assert((Log2(MFI.getMaxAlign()) < 16) &&
507 "Function's alignment size requirement is not supported.");
508 int64_t MaxAlign = -(int64_t)MFI.getMaxAlign().value();
509
510 BuildMI(MBB, MBBI, dl, TII.get(ADDiu), VR).addReg(ZERO).addImm(MaxAlign);
511 BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR);
512
513 if (hasBP(MF)) {
514 // move $s7, $sp
515 unsigned BP = STI.isABI_N64() ? Mips::S7_64 : Mips::S7;
516 BuildMI(MBB, MBBI, dl, TII.get(MOVE), BP)
517 .addReg(SP)
518 .addReg(ZERO);
519 }
520 }
521 }
522}
523
524void MipsSEFrameLowering::emitInterruptPrologueStub(
528 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
529
530 // Report an error the target doesn't support Mips32r2 or later.
531 // The epilogue relies on the use of the "ehb" to clear execution
532 // hazards. Pre R2 Mips relies on an implementation defined number
533 // of "ssnop"s to clear the execution hazard. Support for ssnop hazard
534 // clearing is not provided so reject that configuration.
535 if (!STI.hasMips32r2())
537 "\"interrupt\" attribute is not supported on pre-MIPS32R2 or "
538 "MIPS16 targets.");
539
540 // The GP register contains the "user" value, so we cannot perform
541 // any gp relative loads until we restore the "kernel" or "system" gp
542 // value. Until support is written we shall only accept the static
543 // relocation model.
545 report_fatal_error("\"interrupt\" attribute is only supported for the "
546 "static relocation model on MIPS at the present time.");
547
548 if (!STI.isABI_O32() || STI.hasMips64())
549 report_fatal_error("\"interrupt\" attribute is only supported for the "
550 "O32 ABI on MIPS32R2+ at the present time.");
551
552 // Perform ISR handling like GCC
553 StringRef IntKind =
554 MF.getFunction().getFnAttribute("interrupt").getValueAsString();
555 const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass;
556
557 // EIC interrupt handling needs to read the Cause register to disable
558 // interrupts.
559 if (IntKind == "eic") {
560 // Coprocessor registers are always live per se.
561 MBB.addLiveIn(Mips::COP013);
562 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K0)
563 .addReg(Mips::COP013)
564 .addImm(0)
566
567 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::EXT), Mips::K0)
568 .addReg(Mips::K0)
569 .addImm(10)
570 .addImm(6)
572 }
573
574 // Fetch and spill EPC
575 MBB.addLiveIn(Mips::COP014);
576 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K1)
577 .addReg(Mips::COP014)
578 .addImm(0)
580
581 STI.getInstrInfo()->storeRegToStack(MBB, MBBI, Mips::K1, false,
582 MipsFI->getISRRegFI(0), PtrRC,
583 STI.getRegisterInfo(), 0);
584
585 // Fetch and Spill Status
586 MBB.addLiveIn(Mips::COP012);
587 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MFC0), Mips::K1)
588 .addReg(Mips::COP012)
589 .addImm(0)
591
592 STI.getInstrInfo()->storeRegToStack(MBB, MBBI, Mips::K1, false,
593 MipsFI->getISRRegFI(1), PtrRC,
594 STI.getRegisterInfo(), 0);
595
596 // Build the configuration for disabling lower priority interrupts. Non EIC
597 // interrupts need to be masked off with zero, EIC from the Cause register.
598 unsigned InsPosition = 8;
599 unsigned InsSize = 0;
600 unsigned SrcReg = Mips::ZERO;
601
602 // If the interrupt we're tied to is the EIC, switch the source for the
603 // masking off interrupts to the cause register.
604 if (IntKind == "eic") {
605 SrcReg = Mips::K0;
606 InsPosition = 10;
607 InsSize = 6;
608 } else
609 InsSize = StringSwitch<unsigned>(IntKind)
610 .Case("sw0", 1)
611 .Case("sw1", 2)
612 .Case("hw0", 3)
613 .Case("hw1", 4)
614 .Case("hw2", 5)
615 .Case("hw3", 6)
616 .Case("hw4", 7)
617 .Case("hw5", 8)
618 .Default(0);
619 assert(InsSize != 0 && "Unknown interrupt type!");
620
621 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1)
622 .addReg(SrcReg)
623 .addImm(InsPosition)
624 .addImm(InsSize)
625 .addReg(Mips::K1)
627
628 // Mask off KSU, ERL, EXL
629 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1)
630 .addReg(Mips::ZERO)
631 .addImm(1)
632 .addImm(4)
633 .addReg(Mips::K1)
635
636 // Disable the FPU as we are not spilling those register sets.
637 if (!STI.useSoftFloat())
638 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::INS), Mips::K1)
639 .addReg(Mips::ZERO)
640 .addImm(29)
641 .addImm(1)
642 .addReg(Mips::K1)
644
645 // Set the new status
646 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP012)
647 .addReg(Mips::K1)
648 .addImm(0)
650}
651
653 MachineBasicBlock &MBB) const {
655 MachineFrameInfo &MFI = MF.getFrameInfo();
657
658 const MipsSEInstrInfo &TII =
659 *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo());
660 const MipsRegisterInfo &RegInfo = *STI.getRegisterInfo();
661
662 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
663 MipsABIInfo ABI = STI.getABI();
664 unsigned SP = ABI.GetStackPtr();
665 unsigned FP = ABI.GetFramePtr();
666 unsigned ZERO = ABI.GetNullPtr();
667 unsigned MOVE = ABI.GetGPRMoveOp();
668
669 // if framepointer enabled, restore the stack pointer.
670 if (hasFP(MF)) {
671 // Find the first instruction that restores a callee-saved register.
673
674 for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i)
675 --I;
676
677 // Insert instruction "move $sp, $fp" at this location.
678 BuildMI(MBB, I, DL, TII.get(MOVE), SP).addReg(FP).addReg(ZERO);
679 }
680
681 if (MipsFI->callsEhReturn()) {
682 const TargetRegisterClass *RC =
683 ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
684
685 // Find first instruction that restores a callee-saved register.
687 for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i)
688 --I;
689
690 // Insert instructions that restore eh data registers.
691 for (int J = 0; J < 4; ++J) {
692 TII.loadRegFromStackSlot(MBB, I, ABI.GetEhDataReg(J),
693 MipsFI->getEhDataRegFI(J), RC, &RegInfo,
694 Register());
695 }
696 }
697
698 if (MF.getFunction().hasFnAttribute("interrupt"))
699 emitInterruptEpilogueStub(MF, MBB);
700
701 // Get the number of bytes from FrameInfo
702 uint64_t StackSize = MFI.getStackSize();
703
704 if (!StackSize)
705 return;
706
707 // Adjust stack.
708 TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
709}
710
711void MipsSEFrameLowering::emitInterruptEpilogueStub(
715 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
716
717 // Perform ISR handling like GCC
718 const TargetRegisterClass *PtrRC = &Mips::GPR32RegClass;
719
720 // Disable Interrupts.
721 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::DI), Mips::ZERO);
722 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::EHB));
723
724 // Restore EPC
726 MipsFI->getISRRegFI(0), PtrRC,
728 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP014)
729 .addReg(Mips::K1)
730 .addImm(0);
731
732 // Restore Status
734 MipsFI->getISRRegFI(1), PtrRC,
736 BuildMI(MBB, MBBI, DL, STI.getInstrInfo()->get(Mips::MTC0), Mips::COP012)
737 .addReg(Mips::K1)
738 .addImm(0);
739}
740
743 Register &FrameReg) const {
744 const MachineFrameInfo &MFI = MF.getFrameInfo();
745 MipsABIInfo ABI = STI.getABI();
746
747 if (MFI.isFixedObjectIndex(FI))
748 FrameReg = hasFP(MF) ? ABI.GetFramePtr() : ABI.GetStackPtr();
749 else
750 FrameReg = hasBP(MF) ? ABI.GetBasePtr() : ABI.GetStackPtr();
751
752 return StackOffset::getFixed(MFI.getObjectOffset(FI) + MFI.getStackSize() -
754 MFI.getOffsetAdjustment());
755}
756
762
763 for (const CalleeSavedInfo &I : CSI) {
764 // Add the callee-saved register as live-in. Do not add if the register is
765 // RA and return address is taken, because it has already been added in
766 // method MipsTargetLowering::lowerRETURNADDR.
767 // It's killed at the spill, unless the register is RA and return address
768 // is taken.
769 MCRegister Reg = I.getReg();
770 bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64)
772 if (!IsRAAndRetAddrIsTaken)
773 MBB.addLiveIn(Reg);
774
775 // ISRs require HI/LO to be spilled into kernel registers to be then
776 // spilled to the stack frame.
777 bool IsLOHI = (Reg == Mips::LO0 || Reg == Mips::LO0_64 ||
778 Reg == Mips::HI0 || Reg == Mips::HI0_64);
779 const Function &Func = MBB.getParent()->getFunction();
780 if (IsLOHI && Func.hasFnAttribute("interrupt")) {
781 DebugLoc DL = MI->getDebugLoc();
782
783 unsigned Op = 0;
784 if (!STI.getABI().ArePtrs64bit()) {
785 Op = (Reg == Mips::HI0) ? Mips::MFHI : Mips::MFLO;
786 Reg = Mips::K0;
787 } else {
788 Op = (Reg == Mips::HI0) ? Mips::MFHI64 : Mips::MFLO64;
789 Reg = Mips::K0_64;
790 }
791 BuildMI(MBB, MI, DL, TII.get(Op), Mips::K0)
793 }
794
795 // Insert the spill to the stack frame.
796 bool IsKill = !IsRAAndRetAddrIsTaken;
797 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
798 TII.storeRegToStackSlot(MBB, MI, Reg, IsKill, I.getFrameIdx(), RC, TRI,
799 Register());
800 }
801
802 return true;
803}
804
805bool
807 const MachineFrameInfo &MFI = MF.getFrameInfo();
808 // Reserve call frame if the size of the maximum call frame fits into 16-bit
809 // immediate field and there are no variable sized objects on the stack.
810 // Make sure the second register scavenger spill slot can be accessed with one
811 // instruction.
812 return isInt<16>(MFI.getMaxCallFrameSize() + getStackAlignment()) &&
813 !MFI.hasVarSizedObjects();
814}
815
816/// Mark \p Reg and all registers aliasing it in the bitset.
817static void setAliasRegs(MachineFunction &MF, BitVector &SavedRegs,
818 unsigned Reg) {
820 for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
821 SavedRegs.set(*AI);
822}
823
825 BitVector &SavedRegs,
826 RegScavenger *RS) const {
830 MipsABIInfo ABI = STI.getABI();
831 unsigned RA = ABI.IsN64() ? Mips::RA_64 : Mips::RA;
832 unsigned FP = ABI.GetFramePtr();
833 unsigned BP = ABI.IsN64() ? Mips::S7_64 : Mips::S7;
834
835 // Mark $ra and $fp as used if function has dedicated frame pointer.
836 if (hasFP(MF)) {
837 setAliasRegs(MF, SavedRegs, RA);
838 setAliasRegs(MF, SavedRegs, FP);
839 }
840 // Mark $s7 as used if function has dedicated base pointer.
841 if (hasBP(MF))
842 setAliasRegs(MF, SavedRegs, BP);
843
844 // Create spill slots for eh data registers if function calls eh_return.
845 if (MipsFI->callsEhReturn())
846 MipsFI->createEhDataRegsFI(MF);
847
848 // Create spill slots for Coprocessor 0 registers if function is an ISR.
849 if (MipsFI->isISR())
850 MipsFI->createISRRegFI(MF);
851
852 // Expand pseudo instructions which load, store or copy accumulators.
853 // Add an emergency spill slot if a pseudo was expanded.
854 if (ExpandPseudo(MF).expand()) {
855 // The spill slot should be half the size of the accumulator. If target have
856 // general-purpose registers 64 bits wide, it should be 64-bit, otherwise
857 // it should be 32-bit.
858 const TargetRegisterClass &RC = STI.isGP64bit() ?
859 Mips::GPR64RegClass : Mips::GPR32RegClass;
860 int FI = MF.getFrameInfo().CreateSpillStackObject(TRI->getSpillSize(RC),
861 TRI->getSpillAlign(RC));
863 }
864
865 // Set scavenging frame index if necessary.
866 uint64_t MaxSPOffset = estimateStackSize(MF);
867
868 // MSA has a minimum offset of 10 bits signed. If there is a variable
869 // sized object on the stack, the estimation cannot account for it.
870 if (isIntN(STI.hasMSA() ? 10 : 16, MaxSPOffset) &&
872 return;
873
874 const TargetRegisterClass &RC =
875 ABI.ArePtrs64bit() ? Mips::GPR64RegClass : Mips::GPR32RegClass;
876 int FI = MF.getFrameInfo().CreateSpillStackObject(TRI->getSpillSize(RC),
877 TRI->getSpillAlign(RC));
879}
880
881const MipsFrameLowering *
883 return new MipsSEFrameLowering(ST);
884}
unsigned const MachineRegisterInfo * MRI
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
This file implements the BitVector class.
@ ZERO
Special weight used for cases with exact zero probability.
bool End
Definition: ELF_riscv.cpp:480
static Expected< BitVector > expand(StringRef S, StringRef Original)
Definition: GlobPattern.cpp:21
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
Register const TargetRegisterInfo * TRI
static std::pair< unsigned, unsigned > getMFHiLoOpc(unsigned Src)
static void setAliasRegs(MachineFunction &MF, BitVector &SavedRegs, unsigned Reg)
Mark Reg and all registers aliasing it in the bitset.
This file declares the machine register scavenger class.
SI optimize exec mask operations pre RA
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:480
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
support::ulittle16_t & Lo
Definition: aarch32.cpp:205
support::ulittle16_t & Hi
Definition: aarch32.cpp:204
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:400
BitVector & set()
Definition: BitVector.h:351
Helper class for creating CFI instructions and inserting them into MIR.
void buildDefCFAOffset(int64_t Offset, MCSymbol *Label=nullptr) const
void buildDefCFARegister(MCRegister Reg) const
void buildOffset(MCRegister Reg, int64_t Offset) const
void setInsertPoint(MachineBasicBlock::iterator IP)
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
This class represents an Operation in the Expression.
A debug info location.
Definition: DebugLoc.h:124
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition: Function.cpp:762
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:727
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
Store the specified register of the given register class to the specified stack frame index.
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
Load the specified register of the given register class from the specified stack frame index.
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:199
MCRegAliasIterator enumerates all registers aliasing Reg.
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool adjustsStack() const
Return true if this function adjusts the stack – e.g., when calling another function.
bool isReturnAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
int64_t getOffsetAdjustment() const
Return the correction for frame offsets.
LLVM_ABI int CreateSpillStackObject(uint64_t Size, Align Alignment)
Create a new statically sized stack object that represents a spill slot, returning a nonnegative iden...
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool ArePtrs64bit() const
Definition: MipsABIInfo.h:73
bool hasBP(const MachineFunction &MF) const
uint64_t estimateStackSize(const MachineFunction &MF) const
const MipsSubtarget & STI
MipsFunctionInfo - This class is derived from MachineFunction private Mips target-specific informatio...
int getEhDataRegFI(unsigned Reg) const
int getISRRegFI(Register Reg) const
void createEhDataRegsFI(MachineFunction &MF)
void createISRRegFI(MachineFunction &MF)
virtual void storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, int64_t Offset, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const =0
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
MipsSEFrameLowering(const MipsSubtarget &STI)
StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const override
getFrameIndexReference - This method should return the base register and offset used to reference a f...
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
bool isLittle() const
bool useSoftFloat() const
const MipsInstrInfo * getInstrInfo() const override
bool isABI_N64() const
bool hasMips64() const
const MipsRegisterInfo * getRegisterInfo() const override
bool isGP64bit() const
bool hasMips32r2() const
bool hasMSA() const
bool isABI_O32() const
Reloc::Model getRelocationModel() const
const MipsABIInfo & getABI() const
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
StackOffset holds a fixed and a scalable offset in bytes.
Definition: TypeSize.h:34
int64_t getFixed() const
Returns the fixed component of the stack.
Definition: TypeSize.h:50
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:68
R Default(T Value)
Definition: StringSwitch.h:177
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS=nullptr) const
This method determines which of the registers reported by TargetRegisterInfo::getCalleeSavedRegs() sh...
int getOffsetOfLocalArea() const
getOffsetOfLocalArea - This method returns the offset of the local area from the stack pointer on ent...
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
@ Kill
The last use of a register.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1702
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
const MipsFrameLowering * createMipsSEFrameLowering(const MipsSubtarget &ST)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
unsigned getKillRegState(bool B)
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:257
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition: Alignment.h:208
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:858
#define N
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
Description of the encoding of one expression Op.