LLVM 24.0.0git
MachineIRBuilder.cpp
Go to the documentation of this file.
1//===-- llvm/CodeGen/GlobalISel/MachineIRBuilder.cpp - MIBuilder--*- C++ -*-==//
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/// \file
9/// This file implements the MachineIRBuidler class.
10//===----------------------------------------------------------------------===//
22
23using namespace llvm;
24
26 State.MF = &MF;
27 State.MBB = nullptr;
28 State.MRI = &MF.getRegInfo();
29 State.TII = MF.getSubtarget().getInstrInfo();
30 State.DL = DebugLoc();
31 State.PCSections = nullptr;
32 State.MMRA = nullptr;
33 State.II = MachineBasicBlock::iterator();
34 State.Observer = nullptr;
35}
36
37//------------------------------------------------------------------------------
38// Build instruction variants.
39//------------------------------------------------------------------------------
40
47
53
56 const MDNode *Expr) {
57 assert(isa<DILocalVariable>(Variable) && "not a variable");
58 assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
59 assert(
60 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
61 "Expected inlined-at fields to agree");
62 return insertInstr(BuildMI(getMF(), getDL(),
63 getTII().get(TargetOpcode::DBG_VALUE),
64 /*IsIndirect*/ false, Reg, Variable, Expr));
65}
66
69 const MDNode *Expr) {
70 assert(isa<DILocalVariable>(Variable) && "not a variable");
71 assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
72 assert(
73 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
74 "Expected inlined-at fields to agree");
75 return insertInstr(BuildMI(getMF(), getDL(),
76 getTII().get(TargetOpcode::DBG_VALUE),
77 /*IsIndirect*/ true, Reg, Variable, Expr));
78}
79
81 const MDNode *Variable,
82 const MDNode *Expr) {
83 assert(isa<DILocalVariable>(Variable) && "not a variable");
84 assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
85 assert(
86 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
87 "Expected inlined-at fields to agree");
88 return insertInstr(
89 BuildMI(getMF(), getDL(), getTII().get(TargetOpcode::DBG_VALUE))
90 .addFrameIndex(FI)
91 .addImm(0)
92 .addMetadata(Variable)
93 .addMetadata(Expr));
94}
95
97 const MDNode *Variable,
98 const MDNode *Expr) {
99 assert(isa<DILocalVariable>(Variable) && "not a variable");
100 assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
101 assert(
102 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
103 "Expected inlined-at fields to agree");
104 auto MIB = BuildMI(getMF(), getDL(), getTII().get(TargetOpcode::DBG_VALUE));
105
106 auto *NumericConstant = [&] () -> const Constant* {
107 if (const auto *CE = dyn_cast<ConstantExpr>(&C))
108 if (CE->getOpcode() == Instruction::IntToPtr)
109 return CE->getOperand(0);
110 return &C;
111 }();
112
113 bool IsIndirect = true;
114 int64_t GlobalOffset;
115 if (auto *CI = dyn_cast<ConstantInt>(NumericConstant)) {
116 if (CI->getBitWidth() > 64)
117 MIB.addCImm(CI);
118 else if (CI->getBitWidth() == 1)
119 MIB.addImm(CI->getZExtValue());
120 else
121 MIB.addImm(CI->getSExtValue());
122 } else if (auto *CFP = dyn_cast<ConstantFP>(NumericConstant)) {
123 MIB.addFPImm(CFP);
124 } else if (isa<ConstantPointerNull>(NumericConstant)) {
125 MIB.addImm(0);
126 } else if (const GlobalValue *GV = getDescribableGlobalAddress(
127 NumericConstant, GlobalOffset, getMF())) {
128 // The address of a global is a direct link-time constant. A displacement
129 // from it rides along in the expression rather than in the operand.
130 MIB.addGlobalAddress(GV);
131 if (GlobalOffset) {
133 DIExpression::appendOffset(Ops, GlobalOffset);
135 /*StackValue=*/false);
136 }
137 IsIndirect = false;
138 } else {
139 // Insert $noreg if we didn't find a usable constant and had to drop it.
140 MIB.addReg(Register());
141 }
142
143 // DBG_VALUE spells an indirect location with a zero immediate offset operand
144 // and a direct one with $noreg. isIndirectDebugValue() ignores the offset for
145 // a non-register location operand, but isDebugOffsetImm() does not, and
146 // several consumers ask that instead.
147 if (IsIndirect)
148 MIB.addImm(0);
149 else
150 MIB.addReg(Register());
151 MIB.addMetadata(Variable).addMetadata(Expr);
152 return insertInstr(MIB);
153}
154
156 assert(isa<DILabel>(Label) && "not a label");
157 assert(cast<DILabel>(Label)->isValidLocationForIntrinsic(State.DL) &&
158 "Expected inlined-at fields to agree");
159 auto MIB = insertInstr(
160 BuildMI(getMF(), getDL(), getTII().get(TargetOpcode::DBG_LABEL)));
161
162 return MIB.addMetadata(Label);
163}
164
166 const SrcOp &Size,
167 Align Alignment) {
168 assert(Res.getLLTTy(*getMRI()).isPointer() && "expected ptr dst type");
169 auto MIB = buildInstr(TargetOpcode::G_DYN_STACKALLOC);
170 Res.addDefToMIB(*getMRI(), MIB);
171 Size.addSrcToMIB(MIB);
172 MIB.addImm(Alignment.value());
173 return MIB;
174}
175
177 int Idx) {
178 assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
179 auto MIB = buildInstr(TargetOpcode::G_FRAME_INDEX);
180 Res.addDefToMIB(*getMRI(), MIB);
181 MIB.addFrameIndex(Idx);
182 return MIB;
183}
184
186 const GlobalValue *GV) {
187 assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
189 GV->getType()->getAddressSpace() &&
190 "address space mismatch");
191
192 auto MIB = buildInstr(TargetOpcode::G_GLOBAL_VALUE);
193 Res.addDefToMIB(*getMRI(), MIB);
194 MIB.addGlobalAddress(GV);
195 return MIB;
196}
197
199 unsigned Idx) {
200 assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
201 auto MIB = buildInstr(TargetOpcode::G_CONSTANT_POOL);
202 Res.addDefToMIB(*getMRI(), MIB);
203 MIB.addConstantPoolIndex(Idx);
204 return MIB;
205}
206
208 unsigned JTI) {
209 return buildInstr(TargetOpcode::G_JUMP_TABLE, {PtrTy}, {})
210 .addJumpTableIndex(JTI);
211}
212
213void MachineIRBuilder::validateUnaryOp(const LLT Res, const LLT Op0) {
214 assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
215 assert((Res == Op0) && "type mismatch");
216}
217
219 const LLT Op1) {
220 assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
221 assert((Res == Op0 && Res == Op1) && "type mismatch");
222}
223
224void MachineIRBuilder::validateShiftOp(const LLT Res, const LLT Op0,
225 const LLT Op1) {
226 assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
227 assert((Res == Op0) && "type mismatch");
228}
229
232 const SrcOp &Op1, std::optional<unsigned> Flags) {
233 assert(Res.getLLTTy(*getMRI()).isPointerOrPointerVector() &&
234 Res.getLLTTy(*getMRI()) == Op0.getLLTTy(*getMRI()) && "type mismatch");
235 assert(Op1.getLLTTy(*getMRI()).getScalarType().isScalar() && "invalid offset type");
236
237 return buildInstr(TargetOpcode::G_PTR_ADD, {Res}, {Op0, Op1}, Flags);
238}
239
247
248std::optional<MachineInstrBuilder>
250 const LLT ValueTy, uint64_t Value,
251 std::optional<unsigned> Flags) {
252 assert(Res == 0 && "Res is a result argument");
253 assert(ValueTy.isScalar() && "invalid offset type");
254
255 if (Value == 0) {
256 Res = Op0;
257 return std::nullopt;
258 }
259
261 auto Cst = buildConstant(ValueTy, Value);
262 return buildPtrAdd(Res, Op0, Cst.getReg(0), Flags);
263}
264
265std::optional<MachineInstrBuilder> MachineIRBuilder::materializeObjectPtrOffset(
266 Register &Res, Register Op0, const LLT ValueTy, uint64_t Value) {
267 return materializePtrAdd(Res, Op0, ValueTy, Value,
270}
271
273 const SrcOp &Op0,
274 uint32_t NumBits) {
275 LLT PtrTy = Res.getLLTTy(*getMRI());
276 LLT MaskTy = LLT::integer(PtrTy.getSizeInBits());
277 Register MaskReg = getMRI()->createGenericVirtualRegister(MaskTy);
279 return buildPtrMask(Res, Op0, MaskReg);
280}
281
284 const SrcOp &Op0) {
285 LLT ResTy = Res.getLLTTy(*getMRI());
286 LLT Op0Ty = Op0.getLLTTy(*getMRI());
287
288 assert(ResTy.isVector() && "Res non vector type");
289
291 if (Op0Ty.isVector()) {
292 assert((ResTy.getElementType() == Op0Ty.getElementType()) &&
293 "Different vector element types");
294 assert((ResTy.getNumElements() > Op0Ty.getNumElements()) &&
295 "Op0 has more elements");
296 auto Unmerge = buildUnmerge(Op0Ty.getElementType(), Op0);
297
298 for (auto Op : Unmerge.getInstr()->defs())
299 Regs.push_back(Op.getReg());
300 } else {
301 assert((ResTy.getSizeInBits() > Op0Ty.getSizeInBits()) &&
302 "Op0 has more size");
303 Regs.push_back(Op0.getReg());
304 }
306 buildUndef(Op0Ty.isVector() ? Op0Ty.getElementType() : Op0Ty).getReg(0);
307 unsigned NumberOfPadElts = ResTy.getNumElements() - Regs.size();
308 for (unsigned i = 0; i < NumberOfPadElts; ++i)
309 Regs.push_back(Undef);
310 return buildMergeLikeInstr(Res, Regs);
311}
312
315 const SrcOp &Op0) {
316 LLT ResTy = Res.getLLTTy(*getMRI());
317 LLT Op0Ty = Op0.getLLTTy(*getMRI());
318
319 assert(Op0Ty.isVector() && "Non vector type");
320 assert(((ResTy.isScalar() && (ResTy == Op0Ty.getElementType())) ||
321 (ResTy.isVector() &&
322 (ResTy.getElementType() == Op0Ty.getElementType()))) &&
323 "Different vector element types");
324 assert(
325 (ResTy.isScalar() || (ResTy.getNumElements() < Op0Ty.getNumElements())) &&
326 "Op0 has fewer elements");
327
328 auto Unmerge = buildUnmerge(Op0Ty.getElementType(), Op0);
329 if (ResTy.isScalar())
330 return buildCopy(Res, Unmerge.getReg(0));
332 for (unsigned i = 0; i < ResTy.getNumElements(); ++i)
333 Regs.push_back(Unmerge.getReg(i));
334 return buildMergeLikeInstr(Res, Regs);
335}
336
338 return buildInstr(TargetOpcode::G_BR).addMBB(&Dest);
339}
340
342 assert(getMRI()->getType(Tgt).isPointer() && "invalid branch destination");
343 return buildInstr(TargetOpcode::G_BRINDIRECT).addUse(Tgt);
344}
345
347 unsigned JTI,
348 Register IndexReg) {
349 assert(getMRI()->getType(TablePtr).isPointer() &&
350 "Table reg must be a pointer");
351 return buildInstr(TargetOpcode::G_BRJT)
352 .addUse(TablePtr)
354 .addUse(IndexReg);
355}
356
358 const SrcOp &Op) {
359 return buildInstr(TargetOpcode::COPY, Res, Op);
360}
361
363 const ConstantInt &Val) {
364 assert(!isa<VectorType>(Val.getType()) && "Unexpected vector constant!");
365 LLT Ty = Res.getLLTTy(*getMRI());
366 LLT EltTy = Ty.getScalarType();
367 assert(EltTy.getScalarSizeInBits() == Val.getBitWidth() &&
368 "creating constant with the wrong size");
369
370 assert(!Ty.isScalableVector() &&
371 "unexpected scalable vector in buildConstant");
372
373 if (Ty.isFixedVector()) {
374 auto Const = buildInstr(TargetOpcode::G_CONSTANT)
375 .addDef(getMRI()->createGenericVirtualRegister(EltTy))
376 .addCImm(&Val);
377 return buildSplatBuildVector(Res, Const);
378 }
379
380 auto Const = buildInstr(TargetOpcode::G_CONSTANT);
381 Const->setDebugLoc(DebugLoc());
382 Res.addDefToMIB(*getMRI(), Const);
383 Const.addCImm(&Val);
384 return Const;
385}
386
388 int64_t Val) {
391 // TODO: Avoid implicit trunc?
392 // See https://github.com/llvm/llvm-project/issues/112510.
393 ConstantInt *CI = ConstantInt::getSigned(IntN, Val, /*implicitTrunc=*/true);
394 return buildConstant(Res, *CI);
395}
396
398 const ConstantFP &Val) {
399 assert(!isa<VectorType>(Val.getType()) && "Unexpected vector constant!");
400 LLT Ty = Res.getLLTTy(*getMRI());
401 LLT EltTy = Ty.getScalarType();
402
404 == EltTy.getSizeInBits() &&
405 "creating fconstant with the wrong size");
406
407 assert(!Ty.isPointer() && "invalid operand type");
408
409 assert(!Ty.isScalableVector() &&
410 "unexpected scalable vector in buildFConstant");
411
412 if (Ty.isFixedVector()) {
413 auto Const = buildInstr(TargetOpcode::G_FCONSTANT)
414 .addDef(getMRI()->createGenericVirtualRegister(EltTy))
415 .addFPImm(&Val);
416
417 return buildSplatBuildVector(Res, Const);
418 }
419
420 auto Const = buildInstr(TargetOpcode::G_FCONSTANT);
421 Const->setDebugLoc(DebugLoc());
422 Res.addDefToMIB(*getMRI(), Const);
423 Const.addFPImm(&Val);
424 return Const;
425}
426
428 const APInt &Val) {
429 ConstantInt *CI = ConstantInt::get(getMF().getFunction().getContext(), Val);
430 return buildConstant(Res, *CI);
431}
432
434 double Val) {
435 LLT DstTy = Res.getLLTTy(*getMRI());
436 auto &Ctx = getMF().getFunction().getContext();
437 APFloat APF(Val);
438 bool Ignored;
441 return buildFConstant(Res, *ConstantFP::get(Ctx, APF));
442}
443
445 const APFloat &Val) {
446 auto &Ctx = getMF().getFunction().getContext();
447 auto *CFP = ConstantFP::get(Ctx, Val);
448 return buildFConstant(Res, *CFP);
449}
450
453 const ConstantPtrAuth *CPA,
454 Register Addr, Register AddrDisc) {
455 auto MIB = buildInstr(TargetOpcode::G_PTRAUTH_GLOBAL_VALUE);
456 Res.addDefToMIB(*getMRI(), MIB);
457 MIB.addUse(Addr);
458 MIB.addImm(CPA->getKey()->getZExtValue());
459 MIB.addUse(AddrDisc);
460 MIB.addImm(CPA->getDiscriminator()->getZExtValue());
461 return MIB;
462}
463
465 MachineBasicBlock &Dest) {
466 assert(Tst.getLLTTy(*getMRI()).isScalar() && "invalid operand type");
467
468 auto MIB = buildInstr(TargetOpcode::G_BRCOND);
469 Tst.addSrcToMIB(MIB);
470 MIB.addMBB(&Dest);
471 return MIB;
472}
473
476 MachinePointerInfo PtrInfo, Align Alignment,
478 const AAMDNodes &AAInfo) {
479 MMOFlags |= MachineMemOperand::MOLoad;
480 assert((MMOFlags & MachineMemOperand::MOStore) == 0);
481
482 LLT Ty = Dst.getLLTTy(*getMRI());
483 MachineMemOperand *MMO =
484 getMF().getMachineMemOperand(PtrInfo, MMOFlags, Ty, Alignment, AAInfo);
485 return buildLoad(Dst, Addr, *MMO);
486}
487
489 const DstOp &Res,
490 const SrcOp &Addr,
491 MachineMemOperand &MMO) {
492 assert(Res.getLLTTy(*getMRI()).isValid() && "invalid operand type");
493 assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
494
495 auto MIB = buildInstr(Opcode);
496 Res.addDefToMIB(*getMRI(), MIB);
497 Addr.addSrcToMIB(MIB);
498 MIB.addMemOperand(&MMO);
499 return MIB;
500}
501
503 const DstOp &Dst, const SrcOp &BasePtr,
504 MachineMemOperand &BaseMMO, int64_t Offset) {
505 LLT LoadTy = Dst.getLLTTy(*getMRI());
506 MachineMemOperand *OffsetMMO =
507 getMF().getMachineMemOperand(&BaseMMO, Offset, LoadTy);
508
509 if (Offset == 0) // This may be a size or type changing load.
510 return buildLoad(Dst, BasePtr, *OffsetMMO);
511
512 LLT PtrTy = BasePtr.getLLTTy(*getMRI());
513 LLT OffsetTy = LLT::scalar(PtrTy.getSizeInBits());
514 auto ConstOffset = buildConstant(OffsetTy, Offset);
515 auto Ptr = buildPtrAdd(PtrTy, BasePtr, ConstOffset);
516 return buildLoad(Dst, Ptr, *OffsetMMO);
517}
518
520 const SrcOp &Addr,
521 MachineMemOperand &MMO) {
522 assert(Val.getLLTTy(*getMRI()).isValid() && "invalid operand type");
523 assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
524
525 auto MIB = buildInstr(TargetOpcode::G_STORE);
526 Val.addSrcToMIB(MIB);
527 Addr.addSrcToMIB(MIB);
528 MIB.addMemOperand(&MMO);
529 return MIB;
530}
531
533 const SrcOp &Val,
534 const SrcOp &Addr,
535 MachineMemOperand &MMO) {
536 assert(Val.getLLTTy(*getMRI()).isValid() && "invalid operand type");
537 assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
538
539 auto MIB = buildInstr(Opcode);
540 Val.addSrcToMIB(MIB);
541 Addr.addSrcToMIB(MIB);
542 MIB.addMemOperand(&MMO);
543 return MIB;
544}
545
548 MachinePointerInfo PtrInfo, Align Alignment,
550 const AAMDNodes &AAInfo) {
551 MMOFlags |= MachineMemOperand::MOStore;
552 assert((MMOFlags & MachineMemOperand::MOLoad) == 0);
553
554 LLT Ty = Val.getLLTTy(*getMRI());
555 MachineMemOperand *MMO =
556 getMF().getMachineMemOperand(PtrInfo, MMOFlags, Ty, Alignment, AAInfo);
557 return buildStore(Val, Addr, *MMO);
558}
559
561 const SrcOp &Op) {
562 return buildInstr(TargetOpcode::G_ANYEXT, Res, Op);
563}
564
566 const SrcOp &Op) {
567 return buildInstr(TargetOpcode::G_SEXT, Res, Op);
568}
569
571 const SrcOp &Op,
572 std::optional<unsigned> Flags) {
573 return buildInstr(TargetOpcode::G_ZEXT, Res, Op, Flags);
574}
575
576unsigned MachineIRBuilder::getBoolExtOp(bool IsVec, bool IsFP) const {
577 const auto *TLI = getMF().getSubtarget().getTargetLowering();
578 switch (TLI->getBooleanContents(IsVec, IsFP)) {
580 return TargetOpcode::G_SEXT;
582 return TargetOpcode::G_ZEXT;
583 default:
584 return TargetOpcode::G_ANYEXT;
585 }
586}
587
589 const SrcOp &Op,
590 bool IsFP) {
591 unsigned ExtOp = getBoolExtOp(getMRI()->getType(Op.getReg()).isVector(), IsFP);
592 return buildInstr(ExtOp, Res, Op);
593}
594
596 const SrcOp &Op,
597 bool IsVector,
598 bool IsFP) {
599 const auto *TLI = getMF().getSubtarget().getTargetLowering();
600 switch (TLI->getBooleanContents(IsVector, IsFP)) {
602 return buildSExtInReg(Res, Op, 1);
604 return buildZExtInReg(Res, Op, 1);
606 return buildCopy(Res, Op);
607 }
608
609 llvm_unreachable("unexpected BooleanContent");
610}
611
613 const DstOp &Res,
614 const SrcOp &Op) {
615 assert((TargetOpcode::G_ANYEXT == ExtOpc || TargetOpcode::G_ZEXT == ExtOpc ||
616 TargetOpcode::G_SEXT == ExtOpc) &&
617 "Expecting Extending Opc");
618 assert(Res.getLLTTy(*getMRI()).isScalar() ||
619 Res.getLLTTy(*getMRI()).isVector());
620 assert(Res.getLLTTy(*getMRI()).isScalar() ==
621 Op.getLLTTy(*getMRI()).isScalar());
622
623 unsigned Opcode = TargetOpcode::COPY;
624 if (Res.getLLTTy(*getMRI()).getSizeInBits() >
625 Op.getLLTTy(*getMRI()).getSizeInBits())
626 Opcode = ExtOpc;
627 else if (Res.getLLTTy(*getMRI()).getSizeInBits() <
628 Op.getLLTTy(*getMRI()).getSizeInBits())
629 Opcode = TargetOpcode::G_TRUNC;
630 else
631 assert(Res.getLLTTy(*getMRI()).getSizeInBits() ==
632 Op.getLLTTy(*getMRI()).getSizeInBits());
633
634 return buildInstr(Opcode, Res, Op);
635}
636
638 const SrcOp &Op) {
639 return buildExtOrTrunc(TargetOpcode::G_SEXT, Res, Op);
640}
641
643 const SrcOp &Op) {
644 return buildExtOrTrunc(TargetOpcode::G_ZEXT, Res, Op);
645}
646
648 const SrcOp &Op) {
649 return buildExtOrTrunc(TargetOpcode::G_ANYEXT, Res, Op);
650}
651
653 const SrcOp &Op,
654 int64_t ImmOp) {
655 LLT ResTy = Res.getLLTTy(*getMRI());
656 auto Mask = buildConstant(
657 ResTy, APInt::getLowBitsSet(ResTy.getScalarSizeInBits(), ImmOp));
658 return buildAnd(Res, Op, Mask);
659}
660
662 const SrcOp &Src) {
663 LLT SrcTy = Src.getLLTTy(*getMRI());
664 LLT DstTy = Dst.getLLTTy(*getMRI());
665 if (SrcTy == DstTy)
666 return buildCopy(Dst, Src);
667
668 unsigned Opcode;
669 if (SrcTy.isPointerOrPointerVector())
670 Opcode = TargetOpcode::G_PTRTOINT;
671 else if (DstTy.isPointerOrPointerVector())
672 Opcode = TargetOpcode::G_INTTOPTR;
673 else {
674 assert(!SrcTy.isPointerOrPointerVector() &&
675 !DstTy.isPointerOrPointerVector() && "no G_ADDRCAST yet");
676 Opcode = TargetOpcode::G_BITCAST;
677 }
678
679 return buildInstr(Opcode, Dst, Src);
680}
681
683 const SrcOp &Src,
684 uint64_t Index) {
685 LLT SrcTy = Src.getLLTTy(*getMRI());
686 LLT DstTy = Dst.getLLTTy(*getMRI());
687
688#ifndef NDEBUG
689 assert(SrcTy.isValid() && "invalid operand type");
690 assert(DstTy.isValid() && "invalid operand type");
691 assert(Index + DstTy.getSizeInBits() <= SrcTy.getSizeInBits() &&
692 "extracting off end of register");
693#endif
694
695 if (DstTy.getSizeInBits() == SrcTy.getSizeInBits()) {
696 assert(Index == 0 && "insertion past the end of a register");
697 return buildCast(Dst, Src);
698 }
699
700 auto Extract = buildInstr(TargetOpcode::G_EXTRACT);
701 Dst.addDefToMIB(*getMRI(), Extract);
702 Src.addSrcToMIB(Extract);
703 Extract.addImm(Index);
704 return Extract;
705}
706
708 return buildInstr(TargetOpcode::G_IMPLICIT_DEF, {Res}, {});
709}
710
713 // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
714 // we need some temporary storage for the DstOp objects. Here we use a
715 // sufficiently large SmallVector to not go through the heap.
717 assert(TmpVec.size() > 1);
718 return buildInstr(TargetOpcode::G_MERGE_VALUES, Res, TmpVec);
719}
720
724 // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
725 // we need some temporary storage for the DstOp objects. Here we use a
726 // sufficiently large SmallVector to not go through the heap.
728 assert(TmpVec.size() > 1);
729 return buildInstr(getOpcodeForMerge(Res, TmpVec), Res, TmpVec);
730}
731
734 std::initializer_list<SrcOp> Ops) {
735 assert(Ops.size() > 1);
736 return buildInstr(getOpcodeForMerge(Res, Ops), Res, Ops);
737}
738
739unsigned MachineIRBuilder::getOpcodeForMerge(const DstOp &DstOp,
740 ArrayRef<SrcOp> SrcOps) const {
741 if (DstOp.getLLTTy(*getMRI()).isVector()) {
742 if (SrcOps[0].getLLTTy(*getMRI()).isVector())
743 return TargetOpcode::G_CONCAT_VECTORS;
744 return TargetOpcode::G_BUILD_VECTOR;
745 }
746
747 return TargetOpcode::G_MERGE_VALUES;
748}
749
751 const SrcOp &Op) {
752 // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<DstOp>,
753 // we need some temporary storage for the DstOp objects. Here we use a
754 // sufficiently large SmallVector to not go through the heap.
755 SmallVector<DstOp, 8> TmpVec(Res);
756 assert(TmpVec.size() > 1);
757 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
758}
759
761 const SrcOp &Op) {
762 unsigned NumReg = Op.getLLTTy(*getMRI()).getSizeInBits() / Res.getSizeInBits();
763 SmallVector<DstOp, 8> TmpVec(NumReg, Res);
764 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
765}
766
769 const SrcOp &Op) {
770 LLT OpTy = Op.getLLTTy(*getMRI());
771 unsigned NumRegs = OpTy.getSizeInBits() / Attrs.Ty.getSizeInBits();
772 SmallVector<DstOp, 8> TmpVec(NumRegs, Attrs);
773 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
774}
775
777 const SrcOp &Op) {
778 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<DstOp>,
779 // we need some temporary storage for the DstOp objects. Here we use a
780 // sufficiently large SmallVector to not go through the heap.
781 SmallVector<DstOp, 8> TmpVec(Res);
782 assert(TmpVec.size() > 1);
783 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
784}
785
788 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
789 // we need some temporary storage for the DstOp objects. Here we use a
790 // sufficiently large SmallVector to not go through the heap.
792 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
793}
794
798 SmallVector<SrcOp> TmpVec;
799 TmpVec.reserve(Ops.size());
800 LLT EltTy = Res.getLLTTy(*getMRI()).getElementType();
801 for (const auto &Op : Ops)
802 TmpVec.push_back(buildConstant(EltTy, Op));
803 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
804}
805
809 SmallVector<SrcOp> TmpVec;
810 TmpVec.reserve(Ops.size());
811 LLT EltTy = Res.getLLTTy(*getMRI()).getElementType();
812 for (const auto &Op : Ops)
813 TmpVec.push_back(buildFConstant(EltTy, Op));
814 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
815}
816
818 const SrcOp &Src) {
819 SmallVector<SrcOp, 8> TmpVec(Res.getLLTTy(*getMRI()).getNumElements(), Src);
820 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
821}
822
826 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
827 // we need some temporary storage for the DstOp objects. Here we use a
828 // sufficiently large SmallVector to not go through the heap.
830 if (TmpVec[0].getLLTTy(*getMRI()).getSizeInBits() ==
831 Res.getLLTTy(*getMRI()).getElementType().getSizeInBits())
832 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
833 return buildInstr(TargetOpcode::G_BUILD_VECTOR_TRUNC, Res, TmpVec);
834}
835
837 const SrcOp &Src) {
838 LLT DstTy = Res.getLLTTy(*getMRI());
839 assert(Src.getLLTTy(*getMRI()) == DstTy.getElementType() &&
840 "Expected Src to match Dst elt ty");
841 auto UndefVec = buildUndef(DstTy);
842 auto Zero = buildConstant(LLT::integer(64), 0);
843 auto InsElt = buildInsertVectorElement(DstTy, UndefVec, Src, Zero);
844 SmallVector<int, 16> ZeroMask(DstTy.getNumElements());
845 return buildShuffleVector(DstTy, InsElt, UndefVec, ZeroMask);
846}
847
849 const SrcOp &Src) {
850 assert(Src.getLLTTy(*getMRI()) == Res.getLLTTy(*getMRI()).getElementType() &&
851 "Expected Src to match Dst elt ty");
852 return buildInstr(TargetOpcode::G_SPLAT_VECTOR, Res, Src);
853}
854
856 const SrcOp &Src1,
857 const SrcOp &Src2,
858 ArrayRef<int> Mask) {
859 LLT DstTy = Res.getLLTTy(*getMRI());
860 LLT Src1Ty = Src1.getLLTTy(*getMRI());
861 LLT Src2Ty = Src2.getLLTTy(*getMRI());
862 const LLT DstElemTy = DstTy.getScalarType();
863 const LLT ElemTy1 = Src1Ty.getScalarType();
864 const LLT ElemTy2 = Src2Ty.getScalarType();
865 assert(DstElemTy == ElemTy1 && DstElemTy == ElemTy2);
866 assert(Mask.size() > 1 && "Scalar G_SHUFFLE_VECTOR are not supported");
867 (void)DstElemTy;
868 (void)ElemTy1;
869 (void)ElemTy2;
870 ArrayRef<int> MaskAlloc = getMF().allocateShuffleMask(Mask);
871 return buildInstr(TargetOpcode::G_SHUFFLE_VECTOR, {Res}, {Src1, Src2})
872 .addShuffleMask(MaskAlloc);
873}
874
877 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
878 // we need some temporary storage for the DstOp objects. Here we use a
879 // sufficiently large SmallVector to not go through the heap.
881 return buildInstr(TargetOpcode::G_CONCAT_VECTORS, Res, TmpVec);
882}
883
885 const SrcOp &Src,
886 const SrcOp &Op,
887 unsigned Index) {
888 assert(Index + Op.getLLTTy(*getMRI()).getSizeInBits() <=
889 Res.getLLTTy(*getMRI()).getSizeInBits() &&
890 "insertion past the end of a register");
891
892 if (Res.getLLTTy(*getMRI()).getSizeInBits() ==
893 Op.getLLTTy(*getMRI()).getSizeInBits()) {
894 return buildCast(Res, Op);
895 }
896
897 return buildInstr(TargetOpcode::G_INSERT, Res, {Src, Op, uint64_t(Index)});
898}
899
901 unsigned Step) {
902 unsigned Bitwidth = Res.getLLTTy(*getMRI()).getElementType().getSizeInBits();
903 ConstantInt *CI = ConstantInt::get(getMF().getFunction().getContext(),
904 APInt(Bitwidth, Step));
905 auto StepVector = buildInstr(TargetOpcode::G_STEP_VECTOR);
906 StepVector->setDebugLoc(DebugLoc());
907 Res.addDefToMIB(*getMRI(), StepVector);
908 StepVector.addCImm(CI);
909 return StepVector;
910}
911
913 unsigned MinElts) {
914
917 ConstantInt *CI = ConstantInt::get(IntN, MinElts);
918 return buildVScale(Res, *CI);
919}
920
922 const ConstantInt &MinElts) {
923 auto VScale = buildInstr(TargetOpcode::G_VSCALE);
924 VScale->setDebugLoc(DebugLoc());
925 Res.addDefToMIB(*getMRI(), VScale);
926 VScale.addCImm(&MinElts);
927 return VScale;
928}
929
931 const APInt &MinElts) {
932 ConstantInt *CI =
933 ConstantInt::get(getMF().getFunction().getContext(), MinElts);
934 return buildVScale(Res, *CI);
935}
936
937static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) {
938 if (HasSideEffects && IsConvergent)
939 return TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS;
940 if (HasSideEffects)
941 return TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS;
942 if (IsConvergent)
943 return TargetOpcode::G_INTRINSIC_CONVERGENT;
944 return TargetOpcode::G_INTRINSIC;
945}
946
949 ArrayRef<Register> ResultRegs,
950 bool HasSideEffects, bool isConvergent) {
951 auto MIB = buildInstr(getIntrinsicOpcode(HasSideEffects, isConvergent));
952 for (Register ResultReg : ResultRegs)
953 MIB.addDef(ResultReg);
954 MIB.addIntrinsicID(ID);
955 return MIB;
956}
957
960 ArrayRef<Register> ResultRegs) {
962 bool HasSideEffects = !Attrs.getMemoryEffects().doesNotAccessMemory();
963 bool isConvergent = Attrs.hasAttribute(Attribute::Convergent);
964 return buildIntrinsic(ID, ResultRegs, HasSideEffects, isConvergent);
969 bool HasSideEffects,
970 bool isConvergent) {
971 auto MIB = buildInstr(getIntrinsicOpcode(HasSideEffects, isConvergent));
972 for (DstOp Result : Results)
973 Result.addDefToMIB(*getMRI(), MIB);
974 MIB.addIntrinsicID(ID);
975 return MIB;
976}
977
981 bool HasSideEffects = !Attrs.getMemoryEffects().doesNotAccessMemory();
982 bool isConvergent = Attrs.hasAttribute(Attribute::Convergent);
983 return buildIntrinsic(ID, Results, HasSideEffects, isConvergent);
984}
985
988 std::optional<unsigned> Flags) {
989 return buildInstr(TargetOpcode::G_TRUNC, Res, Op, Flags);
990}
991
994 std::optional<unsigned> Flags) {
995 return buildInstr(TargetOpcode::G_FPTRUNC, Res, Op, Flags);
996}
997
999 const DstOp &Res,
1000 const SrcOp &Op0,
1001 const SrcOp &Op1,
1002 std::optional<unsigned> Flags) {
1003 return buildInstr(TargetOpcode::G_ICMP, Res, {Pred, Op0, Op1}, Flags);
1004}
1005
1007 const DstOp &Res,
1008 const SrcOp &Op0,
1009 const SrcOp &Op1,
1010 std::optional<unsigned> Flags) {
1011
1012 return buildInstr(TargetOpcode::G_FCMP, Res, {Pred, Op0, Op1}, Flags);
1013}
1014
1016 const SrcOp &Op0,
1017 const SrcOp &Op1) {
1018 return buildInstr(TargetOpcode::G_SCMP, Res, {Op0, Op1});
1019}
1020
1022 const SrcOp &Op0,
1023 const SrcOp &Op1) {
1024 return buildInstr(TargetOpcode::G_UCMP, Res, {Op0, Op1});
1025}
1026
1029 const SrcOp &Op0, const SrcOp &Op1,
1030 std::optional<unsigned> Flags) {
1031
1032 return buildInstr(TargetOpcode::G_SELECT, {Res}, {Tst, Op0, Op1}, Flags);
1033}
1034
1036 const SrcOp &Src0,
1037 const SrcOp &Src1,
1038 unsigned Idx) {
1039 return buildInstr(TargetOpcode::G_INSERT_SUBVECTOR, Res,
1040 {Src0, Src1, uint64_t(Idx)});
1041}
1042
1044 const SrcOp &Src,
1045 unsigned Idx) {
1046 return buildInstr(TargetOpcode::G_EXTRACT_SUBVECTOR, Res,
1047 {Src, uint64_t(Idx)});
1048}
1049
1052 const SrcOp &Elt, const SrcOp &Idx) {
1053 return buildInstr(TargetOpcode::G_INSERT_VECTOR_ELT, Res, {Val, Elt, Idx});
1054}
1055
1058 const SrcOp &Idx) {
1059 return buildInstr(TargetOpcode::G_EXTRACT_VECTOR_ELT, Res, {Val, Idx});
1060}
1061
1063 const DstOp &OldValRes, const DstOp &SuccessRes, const SrcOp &Addr,
1064 const SrcOp &CmpVal, const SrcOp &NewVal, MachineMemOperand &MMO) {
1065#ifndef NDEBUG
1066 LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
1067 LLT SuccessResTy = SuccessRes.getLLTTy(*getMRI());
1068 LLT AddrTy = Addr.getLLTTy(*getMRI());
1069 LLT CmpValTy = CmpVal.getLLTTy(*getMRI());
1070 LLT NewValTy = NewVal.getLLTTy(*getMRI());
1071 assert(OldValResTy.isScalar() && "invalid operand type");
1072 assert(SuccessResTy.isScalar() && "invalid operand type");
1073 assert(AddrTy.isPointer() && "invalid operand type");
1074 assert(CmpValTy.isValid() && "invalid operand type");
1075 assert(NewValTy.isValid() && "invalid operand type");
1076 assert(OldValResTy == CmpValTy && "type mismatch");
1077 assert(OldValResTy == NewValTy && "type mismatch");
1078#endif
1079
1080 auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS);
1081 OldValRes.addDefToMIB(*getMRI(), MIB);
1082 SuccessRes.addDefToMIB(*getMRI(), MIB);
1083 Addr.addSrcToMIB(MIB);
1084 CmpVal.addSrcToMIB(MIB);
1085 NewVal.addSrcToMIB(MIB);
1086 MIB.addMemOperand(&MMO);
1087 return MIB;
1088}
1089
1092 const SrcOp &CmpVal, const SrcOp &NewVal,
1093 MachineMemOperand &MMO) {
1094#ifndef NDEBUG
1095 LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
1096 LLT AddrTy = Addr.getLLTTy(*getMRI());
1097 LLT CmpValTy = CmpVal.getLLTTy(*getMRI());
1098 LLT NewValTy = NewVal.getLLTTy(*getMRI());
1099 assert(OldValResTy.isScalar() && "invalid operand type");
1100 assert(AddrTy.isPointer() && "invalid operand type");
1101 assert(CmpValTy.isValid() && "invalid operand type");
1102 assert(NewValTy.isValid() && "invalid operand type");
1103 assert(OldValResTy == CmpValTy && "type mismatch");
1104 assert(OldValResTy == NewValTy && "type mismatch");
1105#endif
1106
1107 auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG);
1108 OldValRes.addDefToMIB(*getMRI(), MIB);
1109 Addr.addSrcToMIB(MIB);
1110 CmpVal.addSrcToMIB(MIB);
1111 NewVal.addSrcToMIB(MIB);
1112 MIB.addMemOperand(&MMO);
1113 return MIB;
1114}
1115
1117 unsigned Opcode, const DstOp &OldValRes,
1118 const SrcOp &Addr, const SrcOp &Val,
1119 MachineMemOperand &MMO) {
1120
1121#ifndef NDEBUG
1122 LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
1123 LLT AddrTy = Addr.getLLTTy(*getMRI());
1124 LLT ValTy = Val.getLLTTy(*getMRI());
1125 assert(AddrTy.isPointer() && "invalid operand type");
1126 assert(ValTy.isValid() && "invalid operand type");
1127 assert(OldValResTy == ValTy && "type mismatch");
1128 assert(MMO.isAtomic() && "not atomic mem operand");
1129#endif
1130
1131 auto MIB = buildInstr(Opcode);
1132 OldValRes.addDefToMIB(*getMRI(), MIB);
1133 Addr.addSrcToMIB(MIB);
1134 Val.addSrcToMIB(MIB);
1135 MIB.addMemOperand(&MMO);
1136 return MIB;
1137}
1138
1141 Register Val, MachineMemOperand &MMO) {
1142 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XCHG, OldValRes, Addr, Val,
1143 MMO);
1144}
1147 Register Val, MachineMemOperand &MMO) {
1148 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_ADD, OldValRes, Addr, Val,
1149 MMO);
1150}
1153 Register Val, MachineMemOperand &MMO) {
1154 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_SUB, OldValRes, Addr, Val,
1155 MMO);
1156}
1159 Register Val, MachineMemOperand &MMO) {
1160 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_AND, OldValRes, Addr, Val,
1161 MMO);
1162}
1165 Register Val, MachineMemOperand &MMO) {
1166 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_NAND, OldValRes, Addr, Val,
1167 MMO);
1168}
1170 Register Addr,
1171 Register Val,
1172 MachineMemOperand &MMO) {
1173 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_OR, OldValRes, Addr, Val,
1174 MMO);
1175}
1178 Register Val, MachineMemOperand &MMO) {
1179 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XOR, OldValRes, Addr, Val,
1180 MMO);
1181}
1184 Register Val, MachineMemOperand &MMO) {
1185 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MAX, OldValRes, Addr, Val,
1186 MMO);
1187}
1190 Register Val, MachineMemOperand &MMO) {
1191 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MIN, OldValRes, Addr, Val,
1192 MMO);
1193}
1196 Register Val, MachineMemOperand &MMO) {
1197 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMAX, OldValRes, Addr, Val,
1198 MMO);
1199}
1202 Register Val, MachineMemOperand &MMO) {
1203 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMIN, OldValRes, Addr, Val,
1204 MMO);
1205}
1206
1209 const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
1210 MachineMemOperand &MMO) {
1211 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FADD, OldValRes, Addr, Val,
1212 MMO);
1213}
1214
1216MachineIRBuilder::buildAtomicRMWFSub(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
1217 MachineMemOperand &MMO) {
1218 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FSUB, OldValRes, Addr, Val,
1219 MMO);
1220}
1221
1224 const SrcOp &Val, MachineMemOperand &MMO) {
1225 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMAX, OldValRes, Addr, Val,
1226 MMO);
1227}
1228
1231 const SrcOp &Val, MachineMemOperand &MMO) {
1232 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMIN, OldValRes, Addr, Val,
1233 MMO);
1234}
1235
1238 const SrcOp &Addr, const SrcOp &Val,
1239 MachineMemOperand &MMO) {
1240 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMAXIMUM, OldValRes, Addr,
1241 Val, MMO);
1242}
1243
1246 const SrcOp &Addr, const SrcOp &Val,
1247 MachineMemOperand &MMO) {
1248 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMINIMUM, OldValRes, Addr,
1249 Val, MMO);
1250}
1251
1253MachineIRBuilder::buildFence(unsigned Ordering, unsigned Scope) {
1254 return buildInstr(TargetOpcode::G_FENCE)
1255 .addImm(Ordering)
1256 .addImm(Scope);
1257}
1258
1260 unsigned RW,
1261 unsigned Locality,
1262 unsigned CacheType,
1263 MachineMemOperand &MMO) {
1264 auto MIB = buildInstr(TargetOpcode::G_PREFETCH);
1265 Addr.addSrcToMIB(MIB);
1266 MIB.addImm(RW).addImm(Locality).addImm(CacheType);
1267 MIB.addMemOperand(&MMO);
1268 return MIB;
1269}
1270
1273#ifndef NDEBUG
1274 assert(getMRI()->getType(Res).isPointer() && "invalid res type");
1275#endif
1276
1277 return buildInstr(TargetOpcode::G_BLOCK_ADDR).addDef(Res).addBlockAddress(BA);
1278}
1279
1280void MachineIRBuilder::validateTruncExt(const LLT DstTy, const LLT SrcTy,
1281 bool IsExtend) {
1282#ifndef NDEBUG
1283 if (DstTy.isVector()) {
1284 assert(SrcTy.isVector() && "mismatched cast between vector and non-vector");
1285 assert(SrcTy.getElementCount() == DstTy.getElementCount() &&
1286 "different number of elements in a trunc/ext");
1287 } else
1288 assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc");
1289
1290 if (IsExtend)
1291 assert(TypeSize::isKnownGT(DstTy.getSizeInBits(), SrcTy.getSizeInBits()) &&
1292 "invalid narrowing extend");
1293 else
1294 assert(TypeSize::isKnownLT(DstTy.getSizeInBits(), SrcTy.getSizeInBits()) &&
1295 "invalid widening trunc");
1296#endif
1297}
1298
1299void MachineIRBuilder::validateSelectOp(const LLT ResTy, const LLT TstTy,
1300 const LLT Op0Ty, const LLT Op1Ty) {
1301#ifndef NDEBUG
1302 assert((ResTy.isScalar() || ResTy.isVector() || ResTy.isPointer()) &&
1303 "invalid operand type");
1304 assert((ResTy == Op0Ty && ResTy == Op1Ty) && "type mismatch");
1305 if (ResTy.isScalar() || ResTy.isPointer())
1306 assert(TstTy.isScalar() && "type mismatch");
1307 else
1308 assert((TstTy.isScalar() ||
1309 (TstTy.isVector() &&
1310 TstTy.getElementCount() == Op0Ty.getElementCount())) &&
1311 "type mismatch");
1312#endif
1313}
1314
1317 ArrayRef<SrcOp> SrcOps,
1318 std::optional<unsigned> Flags) {
1319 switch (Opc) {
1320 default:
1321 break;
1322 case TargetOpcode::G_SELECT: {
1323 assert(DstOps.size() == 1 && "Invalid select");
1324 assert(SrcOps.size() == 3 && "Invalid select");
1326 DstOps[0].getLLTTy(*getMRI()), SrcOps[0].getLLTTy(*getMRI()),
1327 SrcOps[1].getLLTTy(*getMRI()), SrcOps[2].getLLTTy(*getMRI()));
1328 break;
1329 }
1330 case TargetOpcode::G_FNEG:
1331 case TargetOpcode::G_ABS:
1332 // All these are unary ops.
1333 assert(DstOps.size() == 1 && "Invalid Dst");
1334 assert(SrcOps.size() == 1 && "Invalid Srcs");
1335 validateUnaryOp(DstOps[0].getLLTTy(*getMRI()),
1336 SrcOps[0].getLLTTy(*getMRI()));
1337 break;
1338 case TargetOpcode::G_ADD:
1339 case TargetOpcode::G_AND:
1340 case TargetOpcode::G_MUL:
1341 case TargetOpcode::G_OR:
1342 case TargetOpcode::G_SUB:
1343 case TargetOpcode::G_XOR:
1344 case TargetOpcode::G_UDIV:
1345 case TargetOpcode::G_SDIV:
1346 case TargetOpcode::G_UREM:
1347 case TargetOpcode::G_SREM:
1348 case TargetOpcode::G_SMIN:
1349 case TargetOpcode::G_SMAX:
1350 case TargetOpcode::G_UMIN:
1351 case TargetOpcode::G_UMAX:
1352 case TargetOpcode::G_UADDSAT:
1353 case TargetOpcode::G_SADDSAT:
1354 case TargetOpcode::G_USUBSAT:
1355 case TargetOpcode::G_SSUBSAT: {
1356 // All these are binary ops.
1357 assert(DstOps.size() == 1 && "Invalid Dst");
1358 assert(SrcOps.size() == 2 && "Invalid Srcs");
1359 validateBinaryOp(DstOps[0].getLLTTy(*getMRI()),
1360 SrcOps[0].getLLTTy(*getMRI()),
1361 SrcOps[1].getLLTTy(*getMRI()));
1362 break;
1363 }
1364 case TargetOpcode::G_SHL:
1365 case TargetOpcode::G_ASHR:
1366 case TargetOpcode::G_LSHR:
1367 case TargetOpcode::G_USHLSAT:
1368 case TargetOpcode::G_SSHLSAT: {
1369 assert(DstOps.size() == 1 && "Invalid Dst");
1370 assert(SrcOps.size() == 2 && "Invalid Srcs");
1371 validateShiftOp(DstOps[0].getLLTTy(*getMRI()),
1372 SrcOps[0].getLLTTy(*getMRI()),
1373 SrcOps[1].getLLTTy(*getMRI()));
1374 break;
1375 }
1376 case TargetOpcode::G_SEXT:
1377 case TargetOpcode::G_ZEXT:
1378 case TargetOpcode::G_ANYEXT:
1379 assert(DstOps.size() == 1 && "Invalid Dst");
1380 assert(SrcOps.size() == 1 && "Invalid Srcs");
1381 validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
1382 SrcOps[0].getLLTTy(*getMRI()), true);
1383 break;
1384 case TargetOpcode::G_TRUNC:
1385 case TargetOpcode::G_FPTRUNC: {
1386 assert(DstOps.size() == 1 && "Invalid Dst");
1387 assert(SrcOps.size() == 1 && "Invalid Srcs");
1388 validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
1389 SrcOps[0].getLLTTy(*getMRI()), false);
1390 break;
1391 }
1392 case TargetOpcode::G_BITCAST: {
1393 assert(DstOps.size() == 1 && "Invalid Dst");
1394 assert(SrcOps.size() == 1 && "Invalid Srcs");
1395 assert(DstOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1396 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() && "invalid bitcast");
1397 break;
1398 }
1399 case TargetOpcode::COPY:
1400 assert(DstOps.size() == 1 && "Invalid Dst");
1401 // If the caller wants to add a subreg source it has to be done separately
1402 // so we may not have any SrcOps at this point yet.
1403 break;
1404 case TargetOpcode::G_FCMP:
1405 case TargetOpcode::G_ICMP: {
1406 assert(DstOps.size() == 1 && "Invalid Dst Operands");
1407 assert(SrcOps.size() == 3 && "Invalid Src Operands");
1408 // For F/ICMP, the first src operand is the predicate, followed by
1409 // the two comparands.
1410 assert(SrcOps[0].getSrcOpKind() == SrcOp::SrcType::Ty_Predicate &&
1411 "Expecting predicate");
1412 assert([&]() -> bool {
1413 CmpInst::Predicate Pred = SrcOps[0].getPredicate();
1414 return Opc == TargetOpcode::G_ICMP ? CmpInst::isIntPredicate(Pred)
1415 : CmpInst::isFPPredicate(Pred);
1416 }() && "Invalid predicate");
1417 assert(SrcOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
1418 "Type mismatch");
1419 assert([&]() -> bool {
1420 LLT Op0Ty = SrcOps[1].getLLTTy(*getMRI());
1421 LLT DstTy = DstOps[0].getLLTTy(*getMRI());
1422 if (Op0Ty.isScalar() || Op0Ty.isPointer())
1423 return DstTy.isScalar();
1424 else
1425 return DstTy.isVector() &&
1426 DstTy.getElementCount() == Op0Ty.getElementCount();
1427 }() && "Type Mismatch");
1428 break;
1429 }
1430 case TargetOpcode::G_UNMERGE_VALUES: {
1431 assert(!DstOps.empty() && "Invalid trivial sequence");
1432 assert(SrcOps.size() == 1 && "Invalid src for Unmerge");
1433 assert(llvm::all_of(DstOps,
1434 [&, this](const DstOp &Op) {
1435 return Op.getLLTTy(*getMRI()) ==
1436 DstOps[0].getLLTTy(*getMRI());
1437 }) &&
1438 "type mismatch in output list");
1439 assert((TypeSize::ScalarTy)DstOps.size() *
1440 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1441 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1442 "input operands do not cover output register");
1443 break;
1444 }
1445 case TargetOpcode::G_MERGE_VALUES: {
1446 assert(SrcOps.size() >= 2 && "invalid trivial sequence");
1447 assert(DstOps.size() == 1 && "Invalid Dst");
1448 assert(llvm::all_of(SrcOps,
1449 [&, this](const SrcOp &Op) {
1450 return Op.getLLTTy(*getMRI()) ==
1451 SrcOps[0].getLLTTy(*getMRI());
1452 }) &&
1453 "type mismatch in input list");
1454 assert((TypeSize::ScalarTy)SrcOps.size() *
1455 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1456 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1457 "input operands do not cover output register");
1458 assert(!DstOps[0].getLLTTy(*getMRI()).isVector() &&
1459 "vectors should be built with G_CONCAT_VECTOR or G_BUILD_VECTOR");
1460 break;
1461 }
1462 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1463 assert(DstOps.size() == 1 && "Invalid Dst size");
1464 assert(SrcOps.size() == 2 && "Invalid Src size");
1465 assert(SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
1466 assert((DstOps[0].getLLTTy(*getMRI()).isScalar() ||
1467 DstOps[0].getLLTTy(*getMRI()).isPointer()) &&
1468 "Invalid operand type");
1469 assert(SrcOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand type");
1470 assert(SrcOps[0].getLLTTy(*getMRI()).getElementType() ==
1471 DstOps[0].getLLTTy(*getMRI()) &&
1472 "Type mismatch");
1473 break;
1474 }
1475 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1476 assert(DstOps.size() == 1 && "Invalid dst size");
1477 assert(SrcOps.size() == 3 && "Invalid src size");
1478 assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
1479 SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
1480 assert(DstOps[0].getLLTTy(*getMRI()).getElementType() ==
1481 SrcOps[1].getLLTTy(*getMRI()) &&
1482 "Type mismatch");
1483 assert(SrcOps[2].getLLTTy(*getMRI()).isScalar() && "Invalid index");
1484 assert(DstOps[0].getLLTTy(*getMRI()).getElementCount() ==
1485 SrcOps[0].getLLTTy(*getMRI()).getElementCount() &&
1486 "Type mismatch");
1487 break;
1488 }
1489 case TargetOpcode::G_INSERT_SUBVECTOR: {
1490 assert(DstOps.size() == 1 && "Invalid Dst");
1491 assert(SrcOps.size() == 3 && "Invalid Srcs");
1492 [[maybe_unused]] LLT DstTy = DstOps[0].getLLTTy(*getMRI());
1493 [[maybe_unused]] LLT BigVecTy = SrcOps[0].getLLTTy(*getMRI());
1494 [[maybe_unused]] LLT SubVecTy = SrcOps[1].getLLTTy(*getMRI());
1495 assert(DstTy == BigVecTy &&
1496 "Dest and insert subvector source types must match!");
1497 assert(DstTy.isVector() && SubVecTy.isVector() &&
1498 "Insert subvector VTs must be vectors!");
1499 assert(DstTy.getElementType() == SubVecTy.getElementType() &&
1500 "Insert subvector VTs must have the same element type!");
1501 assert((DstTy.isScalable() || !SubVecTy.isScalable()) &&
1502 "Cannot insert a scalable vector into a fixed length vector!");
1503 assert((DstTy.isScalable() != SubVecTy.isScalable() ||
1505 SubVecTy.getElementCount().getKnownMinValue()) &&
1506 "Insert subvector must be from smaller vector to larger vector!");
1507 assert(SrcOps[2].getSrcOpKind() == SrcOp::SrcType::Ty_Imm &&
1508 "Insert subvector index must be constant");
1509 assert((DstTy.isScalable() != SubVecTy.isScalable() ||
1510 (SubVecTy.getElementCount().getKnownMinValue() +
1511 (uint64_t)SrcOps[2].getImm()) <=
1512 DstTy.getElementCount().getKnownMinValue()) &&
1513 "Insert subvector overflow!");
1514 assert((uint64_t)SrcOps[2].getImm() %
1515 SubVecTy.getElementCount().getKnownMinValue() ==
1516 0 &&
1517 "Insert index is not a multiple of the subvector length");
1518 break;
1519 }
1520 case TargetOpcode::G_EXTRACT_SUBVECTOR: {
1521 assert(DstOps.size() == 1 && "Invalid Dst");
1522 assert(SrcOps.size() == 2 && "Invalid Srcs");
1523 [[maybe_unused]] LLT DstTy = DstOps[0].getLLTTy(*getMRI());
1524 [[maybe_unused]] LLT SrcVecTy = SrcOps[0].getLLTTy(*getMRI());
1525 assert(DstTy.isVector() && SrcVecTy.isVector() &&
1526 "Extract subvector VTs must be vectors!");
1527 assert(DstTy.getElementType() == SrcVecTy.getElementType() &&
1528 "Extract subvector VTs must have the same element type!");
1529 assert((!DstTy.isScalable() || SrcVecTy.isScalable()) &&
1530 "Cannot extract a scalable vector from a fixed length vector!");
1531 assert((DstTy.isScalable() != SrcVecTy.isScalable() ||
1533 SrcVecTy.getElementCount().getKnownMinValue()) &&
1534 "Extract subvector must be from larger vector to smaller vector!");
1535 assert(SrcOps[1].getSrcOpKind() == SrcOp::SrcType::Ty_Imm &&
1536 "Extract subvector index must be a constant");
1537 assert((DstTy.isScalable() != SrcVecTy.isScalable() ||
1539 (uint64_t)SrcOps[1].getImm()) <=
1540 SrcVecTy.getElementCount().getKnownMinValue()) &&
1541 "Extract subvector overflow!");
1542 assert((uint64_t)SrcOps[1].getImm() %
1544 0 &&
1545 "Extract index is not a multiple of the output vector length");
1546 break;
1547 }
1548 case TargetOpcode::G_BUILD_VECTOR: {
1549 assert((!SrcOps.empty() || SrcOps.size() < 2) &&
1550 "Must have at least 2 operands");
1551 assert(DstOps.size() == 1 && "Invalid DstOps");
1552 assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
1553 "Res type must be a vector");
1554 assert(llvm::all_of(SrcOps,
1555 [&, this](const SrcOp &Op) {
1556 return Op.getLLTTy(*getMRI()) ==
1557 SrcOps[0].getLLTTy(*getMRI());
1558 }) &&
1559 "type mismatch in input list");
1560 assert((TypeSize::ScalarTy)SrcOps.size() *
1561 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1562 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1563 "input scalars do not exactly cover the output vector register");
1564 break;
1565 }
1566 case TargetOpcode::G_BUILD_VECTOR_TRUNC: {
1567 assert((!SrcOps.empty() || SrcOps.size() < 2) &&
1568 "Must have at least 2 operands");
1569 assert(DstOps.size() == 1 && "Invalid DstOps");
1570 assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
1571 "Res type must be a vector");
1572 assert(llvm::all_of(SrcOps,
1573 [&, this](const SrcOp &Op) {
1574 return Op.getLLTTy(*getMRI()) ==
1575 SrcOps[0].getLLTTy(*getMRI());
1576 }) &&
1577 "type mismatch in input list");
1578 break;
1579 }
1580 case TargetOpcode::G_CONCAT_VECTORS: {
1581 assert(DstOps.size() == 1 && "Invalid DstOps");
1582 assert((!SrcOps.empty() || SrcOps.size() < 2) &&
1583 "Must have at least 2 operands");
1584 assert(llvm::all_of(SrcOps,
1585 [&, this](const SrcOp &Op) {
1586 return (Op.getLLTTy(*getMRI()).isVector() &&
1587 Op.getLLTTy(*getMRI()) ==
1588 SrcOps[0].getLLTTy(*getMRI()));
1589 }) &&
1590 "type mismatch in input list");
1591 assert((TypeSize::ScalarTy)SrcOps.size() *
1592 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1593 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1594 "input vectors do not exactly cover the output vector register");
1595 break;
1596 }
1597 case TargetOpcode::G_UADDE: {
1598 assert(DstOps.size() == 2 && "Invalid no of dst operands");
1599 assert(SrcOps.size() == 3 && "Invalid no of src operands");
1600 assert(DstOps[0].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
1601 assert((DstOps[0].getLLTTy(*getMRI()) == SrcOps[0].getLLTTy(*getMRI())) &&
1602 (DstOps[0].getLLTTy(*getMRI()) == SrcOps[1].getLLTTy(*getMRI())) &&
1603 "Invalid operand");
1604 assert(DstOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
1605 assert(DstOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
1606 "type mismatch");
1607 break;
1608 }
1609 }
1610
1611 auto MIB = buildInstr(Opc);
1612 for (const DstOp &Op : DstOps)
1613 Op.addDefToMIB(*getMRI(), MIB);
1614 for (const SrcOp &Op : SrcOps)
1615 Op.addSrcToMIB(MIB);
1616 if (Flags)
1617 MIB->setFlags(*Flags);
1618 return MIB;
1619}
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
Function Alias Analysis Results
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent)
This file declares the MachineIRBuilder class.
Promote Memory to Register
Definition Mem2Reg.cpp:110
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
static unsigned getScalarSizeInBits(Type *Ty)
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
This file describes how to lower LLVM code to machine code.
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
static LLVM_ABI unsigned getSizeInBits(const fltSemantics &Sem)
Returns the size of the floating point number (in bits) in the given semantics.
Definition APFloat.cpp:399
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:361
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:6045
const fltSemantics & getSemantics() const
Definition APFloat.h:1591
Class for arbitrary precision integers.
Definition APInt.h:78
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:302
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
This class holds the attributes for a particular argument, parameter, function, or return value.
Definition Attributes.h:406
The address of a basic block.
Definition Constants.h:1088
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
bool isFPPredicate() const
Definition InstrTypes.h:845
bool isIntPredicate() const
Definition InstrTypes.h:846
ConstantFP - Floating Point Values [float, double].
Definition Constants.h:420
const APFloat & getValueAPF() const
Definition Constants.h:463
This is the shared class of boolean and integer constants.
Definition Constants.h:87
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
Definition Constants.h:135
unsigned getBitWidth() const
getBitWidth - Return the scalar bitwidth of this constant.
Definition Constants.h:162
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
A signed pointer, in the ptrauth sense.
Definition Constants.h:1223
ConstantInt * getKey() const
The Key ID, an i32 constant.
Definition Constants.h:1254
ConstantInt * getDiscriminator() const
The integer discriminator, an i64 constant, or 0.
Definition Constants.h:1257
This is an important base class in LLVM.
Definition Constant.h:44
static LLVM_ABI void appendOffset(SmallVectorImpl< uint64_t > &Ops, int64_t Offset)
Append Ops with operations to apply the Offset.
static LLVM_ABI DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
void addDefToMIB(MachineRegisterInfo &MRI, MachineInstrBuilder &MIB) const
LLT getLLTTy(const MachineRegisterInfo &MRI) const
Register getReg() const
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:352
PointerType * getType() const
Global values are always pointers.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:338
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
LLT getScalarType() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
constexpr bool isScalable() const
Returns true if the LLT is a scalable vector.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr ElementCount getElementCount() const
constexpr bool isPointerOrPointerVector() const
static LLT integer(unsigned SizeInBits)
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:89
Metadata node.
Definition Metadata.h:1081
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
MachineInstrBundleIterator< MachineInstr > iterator
ArrayRef< int > allocateShuffleMask(ArrayRef< int > Mask)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineInstrBuilder buildBuildVectorFConstant(const DstOp &Res, ArrayRef< APFloat > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ... where each OpN is built with G_FCONSTANT.
MachineInstrBuilder buildLoadFromOffset(const DstOp &Dst, const SrcOp &BasePtr, MachineMemOperand &BaseMMO, int64_t Offset)
Helper to create a load from a constant offset given a base address.
MachineInstrBuilder buildAtomicRMWFMin(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_FMIN Addr, Val, MMO.
MachineInstrBuilder buildBoolExtInReg(const DstOp &Res, const SrcOp &Op, bool IsVector, bool IsFP)
MachineInstrBuilder insertInstr(MachineInstrBuilder MIB)
Insert an existing instruction at the insertion point.
MachineInstrBuilder buildAtomicRMWFMaximum(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_FMAXIMUM Addr, Val, MMO.
MachineInstrBuilder buildAtomicRMWXor(Register OldValRes, Register Addr, Register Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_XOR Addr, Val, MMO.
MachineInstrBuilder buildGlobalValue(const DstOp &Res, const GlobalValue *GV)
Build and insert Res = G_GLOBAL_VALUE GV.
MachineInstrBuilder buildBr(MachineBasicBlock &Dest)
Build and insert G_BR Dest.
LLVMContext & getContext() const
MachineInstrBuilder buildUndef(const DstOp &Res)
Build and insert Res = IMPLICIT_DEF.
MachineInstrBuilder buildUCmp(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1)
Build and insert a Res = G_UCMP Op0, Op1.
MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)
Build and insert Res = G_CONSTANT_POOL Idx.
MachineInstrBuilder buildJumpTable(const LLT PtrTy, unsigned JTI)
Build and insert Res = G_JUMP_TABLE JTI.
MachineInstrBuilder buildBoolExt(const DstOp &Res, const SrcOp &Op, bool IsFP)
MachineInstrBuilder buildUnmerge(ArrayRef< LLT > Res, const SrcOp &Op)
Build and insert Res0, ... = G_UNMERGE_VALUES Op.
MachineInstrBuilder buildSCmp(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1)
Build and insert a Res = G_SCMP Op0, Op1.
MachineInstrBuilder buildFence(unsigned Ordering, unsigned Scope)
Build and insert G_FENCE Ordering, Scope.
MachineInstrBuilder buildSelect(const DstOp &Res, const SrcOp &Tst, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_SELECT Tst, Op0, Op1.
MachineInstrBuilder buildAtomicRMWAnd(Register OldValRes, Register Addr, Register Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_AND Addr, Val, MMO.
MachineInstrBuilder buildZExtInReg(const DstOp &Res, const SrcOp &Op, int64_t ImmOp)
Build and inserts Res = G_AND Op, LowBitsSet(ImmOp) Since there is no G_ZEXT_INREG like G_SEXT_INREG,...
MachineInstrBuilder buildAtomicRMWMin(Register OldValRes, Register Addr, Register Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_MIN Addr, Val, MMO.
MachineInstrBuilder buildExtract(const DstOp &Res, const SrcOp &Src, uint64_t Index)
Build and insert Res0, ... = G_EXTRACT Src, Idx0.
std::optional< MachineInstrBuilder > materializePtrAdd(Register &Res, Register Op0, const LLT ValueTy, uint64_t Value, std::optional< unsigned > Flags=std::nullopt)
Materialize and insert Res = G_PTR_ADD Op0, (G_CONSTANT Value)
MachineInstrBuilder buildInsertSubvector(const DstOp &Res, const SrcOp &Src0, const SrcOp &Src1, unsigned Index)
Build and insert Res = G_INSERT_SUBVECTOR Src0, Src1, Idx.
MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)
Build and insert Res = G_AND Op0, Op1.
MachineInstrBuilder buildCast(const DstOp &Dst, const SrcOp &Src)
Build and insert an appropriate cast between two registers of equal size.
const TargetInstrInfo & getTII()
MachineInstrBuilder buildAtomicRMWFAdd(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_FADD Addr, Val, MMO.
MachineInstrBuilder buildAtomicRMWNand(Register OldValRes, Register Addr, Register Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_NAND Addr, Val, MMO.
MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_ICMP Pred, Op0, Op1.
MachineInstrBuilder buildAnyExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Res = COPY Op depending on the differing sizes of Res and Op.
MachineInstrBuilder buildSExt(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_SEXT Op.
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildSExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_SEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
MachineInstrBuilder buildShuffleSplat(const DstOp &Res, const SrcOp &Src)
Build and insert a vector splat of a scalar Src using a G_INSERT_VECTOR_ELT and G_SHUFFLE_VECTOR idio...
MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_ZEXT Op.
MachineInstrBuilder buildConcatVectors(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_CONCAT_VECTORS Op0, ...
MachineInstrBuilder buildAtomicRMW(unsigned Opcode, const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_<Opcode> Addr, Val, MMO.
MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef< Register > Res, bool HasSideEffects, bool isConvergent)
Build and insert a G_INTRINSIC instruction.
MDNode * getPCSections()
Get the current instruction's PC sections metadata.
MachineInstrBuilder buildVScale(const DstOp &Res, unsigned MinElts)
Build and insert Res = G_VSCALE MinElts.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildIndirectDbgValue(Register Reg, const MDNode *Variable, const MDNode *Expr)
Build and insert a DBG_VALUE instruction expressing the fact that the associated Variable lives in me...
unsigned getBoolExtOp(bool IsVec, bool IsFP) const
MachineInstrBuilder buildObjectPtrOffset(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1)
Build and insert an instruction with appropriate flags for addressing some offset of an object,...
MachineInstrBuilder buildAtomicRMWUmax(Register OldValRes, Register Addr, Register Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_UMAX Addr, Val, MMO.
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
MachineInstrBuilder buildConstDbgValue(const Constant &C, const MDNode *Variable, const MDNode *Expr)
Build and insert a DBG_VALUE instructions specifying that Variable is given by C (suitably modified b...
void recordInsertion(MachineInstr *InsertedInstr) const
MachineInstrBuilder buildBrCond(const SrcOp &Tst, MachineBasicBlock &Dest)
Build and insert G_BRCOND Tst, Dest.
std::optional< MachineInstrBuilder > materializeObjectPtrOffset(Register &Res, Register Op0, const LLT ValueTy, uint64_t Value)
Materialize and insert an instruction with appropriate flags for addressing some offset of an object,...
MachineInstrBuilder buildMergeLikeInstr(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ... or Res = G_BUILD_VECTOR Op0, ... or Res = G_CONCAT_VEC...
MachineInstrBuilder buildAtomicRMWFMinimum(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_FMINIMUM Addr, Val, MMO.
MachineInstrBuilder buildExtractVectorElement(const DstOp &Res, const SrcOp &Val, const SrcOp &Idx)
Build and insert Res = G_EXTRACT_VECTOR_ELT Val, Idx.
MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = G_LOAD Addr, MMO.
MachineInstrBuilder buildPtrAdd(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_PTR_ADD Op0, Op1.
MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...
MachineInstrBuilder buildBuildVectorTrunc(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR_TRUNC Op0, ...
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildPadVectorWithUndefElements(const DstOp &Res, const SrcOp &Op0)
Build and insert a, b, ..., x = G_UNMERGE_VALUES Op0 Res = G_BUILD_VECTOR a, b, .....
void validateSelectOp(const LLT ResTy, const LLT TstTy, const LLT Op0Ty, const LLT Op1Ty)
MachineInstrBuilder buildFrameIndex(const DstOp &Res, int Idx)
Build and insert Res = G_FRAME_INDEX Idx.
MachineInstrBuilder buildDirectDbgValue(Register Reg, const MDNode *Variable, const MDNode *Expr)
Build and insert a DBG_VALUE instruction expressing the fact that the associated Variable lives in Re...
const DebugLoc & getDL()
Getter for DebugLoc.
MachineInstrBuilder buildBuildVectorConstant(const DstOp &Res, ArrayRef< APInt > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ... where each OpN is built with G_CONSTANT.
MachineInstrBuilder buildAtomicRMWUmin(Register OldValRes, Register Addr, Register Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_UMIN Addr, Val, MMO.
void validateBinaryOp(const LLT Res, const LLT Op0, const LLT Op1)
void validateShiftOp(const LLT Res, const LLT Op0, const LLT Op1)
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildDbgLabel(const MDNode *Label)
Build and insert a DBG_LABEL instructions specifying that Label is given.
MachineInstrBuilder buildBrJT(Register TablePtr, unsigned JTI, Register IndexReg)
Build and insert G_BRJT TablePtr, JTI, IndexReg.
MachineInstrBuilder buildInsert(const DstOp &Res, const SrcOp &Src, const SrcOp &Op, unsigned Index)
MachineInstrBuilder buildDynStackAlloc(const DstOp &Res, const SrcOp &Size, Align Alignment)
Build and insert Res = G_DYN_STACKALLOC Size, Align.
MachineInstrBuilder buildFIDbgValue(int FI, const MDNode *Variable, const MDNode *Expr)
Build and insert a DBG_VALUE instruction expressing the fact that the associated Variable lives in th...
MachineInstrBuilder buildExtOrTrunc(unsigned ExtOpc, const DstOp &Res, const SrcOp &Op)
Build and insert Res = ExtOpc, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes of...
MachineInstrBuilder buildAtomicRMWSub(Register OldValRes, Register Addr, Register Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_SUB Addr, Val, MMO.
MachineInstrBuilder buildMergeValues(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_MERGE_VALUES Op0, ...
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildAtomicRMWFMax(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_FMAX Addr, Val, MMO.
MachineInstrBuilder buildAtomicRMWOr(Register OldValRes, Register Addr, Register Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_OR Addr, Val, MMO.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
MachineInstrBuilder buildInsertVectorElement(const DstOp &Res, const SrcOp &Val, const SrcOp &Elt, const SrcOp &Idx)
Build and insert Res = G_INSERT_VECTOR_ELT Val, Elt, Idx.
MachineInstrBuilder buildAnyExt(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ANYEXT Op0.
MachineInstrBuilder buildAtomicCmpXchgWithSuccess(const DstOp &OldValRes, const DstOp &SuccessRes, const SrcOp &Addr, const SrcOp &CmpVal, const SrcOp &NewVal, MachineMemOperand &MMO)
Build and insert OldValRes<def>, SuccessRes<def> = / G_ATOMIC_CMPXCHG_WITH_SUCCESS Addr,...
MachineInstrBuilder buildDeleteTrailingVectorElements(const DstOp &Res, const SrcOp &Op0)
Build and insert a, b, ..., x, y, z = G_UNMERGE_VALUES Op0 Res = G_BUILD_VECTOR a,...
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildAtomicRMWAdd(Register OldValRes, Register Addr, Register Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_ADD Addr, Val, MMO.
MachineInstrBuilder buildFPTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_FPTRUNC Op.
MachineInstrBuilder buildAtomicCmpXchg(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &CmpVal, const SrcOp &NewVal, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal, / MMO.
MachineInstrBuilder buildShuffleVector(const DstOp &Res, const SrcOp &Src1, const SrcOp &Src2, ArrayRef< int > Mask)
Build and insert Res = G_SHUFFLE_VECTOR Src1, Src2, Mask.
void validateTruncExt(const LLT Dst, const LLT Src, bool IsExtend)
MachineInstrBuilder buildInstrNoInsert(unsigned Opcode)
Build but don't insert <empty> = Opcode <empty>.
MachineInstrBuilder buildPtrMask(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1)
Build and insert Res = G_PTRMASK Op0, Op1.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
void validateUnaryOp(const LLT Res, const LLT Op0)
MachineInstrBuilder buildBlockAddress(Register Res, const BlockAddress *BA)
Build and insert Res = G_BLOCK_ADDR BA.
MDNode * getMMRAMetadata()
Get the current instruction's MMRA metadata.
MachineInstrBuilder buildAtomicRMWMax(Register OldValRes, Register Addr, Register Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_MAX Addr, Val, MMO.
MachineInstrBuilder buildPrefetch(const SrcOp &Addr, unsigned RW, unsigned Locality, unsigned CacheType, MachineMemOperand &MMO)
Build and insert G_PREFETCH Addr, RW, Locality, CacheType.
MachineInstrBuilder buildExtractSubvector(const DstOp &Res, const SrcOp &Src, unsigned Index)
Build and insert Res = G_EXTRACT_SUBVECTOR Src, Idx0.
MachineInstrBuilder buildBrIndirect(Register Tgt)
Build and insert G_BRINDIRECT Tgt.
MachineInstrBuilder buildSplatVector(const DstOp &Res, const SrcOp &Val)
Build and insert Res = G_SPLAT_VECTOR Val.
MachineInstrBuilder buildLoadInstr(unsigned Opcode, const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert Res = <opcode> Addr, MMO.
void setMF(MachineFunction &MF)
MachineInstrBuilder buildStoreInstr(unsigned Opcode, const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert <opcode> Val, Addr, MMO.
MachineInstrBuilder buildStepVector(const DstOp &Res, unsigned Step)
Build and insert Res = G_STEP_VECTOR Step.
MachineInstrBuilder buildAtomicRMWFSub(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_FSUB Addr, Val, MMO.
MachineInstrBuilder buildAtomicRMWXchg(Register OldValRes, Register Addr, Register Val, MachineMemOperand &MMO)
Build and insert OldValRes<def> = G_ATOMICRMW_XCHG Addr, Val, MMO.
MachineInstrBuilder buildMaskLowPtrBits(const DstOp &Res, const SrcOp &Op0, uint32_t NumBits)
Build and insert Res = G_PTRMASK Op0, G_CONSTANT (1 << NumBits) - 1.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
MachineInstrBuilder buildFCmp(CmpInst::Predicate Pred, const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert a Res = G_FCMP PredOp0, Op1.
MachineInstrBuilder buildSExtInReg(const DstOp &Res, const SrcOp &Op, int64_t ImmOp)
Build and insert Res = G_SEXT_INREG Op, ImmOp.
MachineInstrBuilder buildConstantPtrAuth(const DstOp &Res, const ConstantPtrAuth *CPA, Register Addr, Register AddrDisc)
Build and insert G_PTRAUTH_GLOBAL_VALUE.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addCImm(const ConstantInt *Val) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addBlockAddress(const BlockAddress *BA, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addFPImm(const ConstantFP *Val) const
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
A description of a memory reference used in the backend.
bool isAtomic() const
Returns true if this operation has an atomic ordering requirement of unordered or higher,...
Flags
Flags values. These may be or'd together.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
void addSrcToMIB(MachineInstrBuilder &MIB) const
Register getReg() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetLowering * getTargetLowering() const
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:217
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:224
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI AttributeSet getFnAttributes(LLVMContext &C, ID id)
Return the function attributes for an intrinsic.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
constexpr T maskTrailingZeros(unsigned N)
Create a bitmask with the N right-most bits set to 0, and all other bits set to 1.
Definition MathExtras.h:95
DWARFExpression::Operation Op
LLVM_ABI const GlobalValue * getDescribableGlobalAddress(const Constant *C, int64_t &Offset, const MachineFunction &MF)
If C is the address of a global, possibly displaced by a constant, return that global and set Offset ...
Definition Analysis.cpp:623
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
Definition Metadata.h:774
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
This class contains a discriminated union of information about pointers in memory operands,...
All attributes(register class or bank and low-level type) a virtual register can have.