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(buildInstrNoInsert(TargetOpcode::DBG_VALUE)
89 .addFrameIndex(FI)
90 .addImm(0)
91 .addMetadata(Variable)
92 .addMetadata(Expr));
93}
94
96 const MDNode *Variable,
97 const MDNode *Expr) {
98 assert(isa<DILocalVariable>(Variable) && "not a variable");
99 assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
100 assert(
101 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
102 "Expected inlined-at fields to agree");
103 auto MIB = buildInstrNoInsert(TargetOpcode::DBG_VALUE);
104
105 auto *NumericConstant = [&] () -> const Constant* {
106 if (const auto *CE = dyn_cast<ConstantExpr>(&C))
107 if (CE->getOpcode() == Instruction::IntToPtr)
108 return CE->getOperand(0);
109 return &C;
110 }();
111
112 bool IsIndirect = true;
113 int64_t GlobalOffset;
114 if (auto *CI = dyn_cast<ConstantInt>(NumericConstant)) {
115 if (CI->getBitWidth() > 64)
116 MIB.addCImm(CI);
117 else if (CI->getBitWidth() == 1)
118 MIB.addImm(CI->getZExtValue());
119 else
120 MIB.addImm(CI->getSExtValue());
121 } else if (auto *CFP = dyn_cast<ConstantFP>(NumericConstant)) {
122 MIB.addFPImm(CFP);
123 } else if (isa<ConstantPointerNull>(NumericConstant)) {
124 MIB.addImm(0);
125 } else if (const GlobalValue *GV = getDescribableGlobalAddress(
126 NumericConstant, GlobalOffset, getMF())) {
127 // The address of a global is a direct link-time constant. A displacement
128 // from it rides along in the expression rather than in the operand.
129 MIB.addGlobalAddress(GV);
130 if (GlobalOffset) {
132 DIExpression::appendOffset(Ops, GlobalOffset);
134 /*StackValue=*/false);
135 }
136 IsIndirect = false;
137 } else {
138 // Insert $noreg if we didn't find a usable constant and had to drop it.
139 MIB.addReg(Register());
140 }
141
142 // DBG_VALUE spells an indirect location with a zero immediate offset operand
143 // and a direct one with $noreg. isIndirectDebugValue() ignores the offset for
144 // a non-register location operand, but isDebugOffsetImm() does not, and
145 // several consumers ask that instead.
146 if (IsIndirect)
147 MIB.addImm(0);
148 else
149 MIB.addReg(Register());
150 MIB.addMetadata(Variable).addMetadata(Expr);
151 return insertInstr(MIB);
152}
153
155 assert(isa<DILabel>(Label) && "not a label");
156 assert(cast<DILabel>(Label)->isValidLocationForIntrinsic(State.DL) &&
157 "Expected inlined-at fields to agree");
158 auto MIB = buildInstr(TargetOpcode::DBG_LABEL);
159
160 return MIB.addMetadata(Label);
161}
162
164 const SrcOp &Size,
165 Align Alignment) {
166 assert(Res.getLLTTy(*getMRI()).isPointer() && "expected ptr dst type");
167 auto MIB = buildInstr(TargetOpcode::G_DYN_STACKALLOC);
168 Res.addDefToMIB(*getMRI(), MIB);
169 Size.addSrcToMIB(MIB);
170 MIB.addImm(Alignment.value());
171 return MIB;
172}
173
175 int Idx) {
176 assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
177 auto MIB = buildInstr(TargetOpcode::G_FRAME_INDEX);
178 Res.addDefToMIB(*getMRI(), MIB);
179 MIB.addFrameIndex(Idx);
180 return MIB;
181}
182
184 const GlobalValue *GV) {
185 assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
187 GV->getType()->getAddressSpace() &&
188 "address space mismatch");
189
190 auto MIB = buildInstr(TargetOpcode::G_GLOBAL_VALUE);
191 Res.addDefToMIB(*getMRI(), MIB);
192 MIB.addGlobalAddress(GV);
193 return MIB;
194}
195
197 unsigned Idx) {
198 assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
199 auto MIB = buildInstr(TargetOpcode::G_CONSTANT_POOL);
200 Res.addDefToMIB(*getMRI(), MIB);
201 MIB.addConstantPoolIndex(Idx);
202 return MIB;
203}
204
206 unsigned JTI) {
207 return buildInstr(TargetOpcode::G_JUMP_TABLE, {PtrTy}, {})
208 .addJumpTableIndex(JTI);
209}
210
211void MachineIRBuilder::validateUnaryOp(const LLT Res, const LLT Op0) {
212 assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
213 assert((Res == Op0) && "type mismatch");
214}
215
217 const LLT Op1) {
218 assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
219 assert((Res == Op0 && Res == Op1) && "type mismatch");
220}
221
222void MachineIRBuilder::validateShiftOp(const LLT Res, const LLT Op0,
223 const LLT Op1) {
224 assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
225 assert((Res == Op0) && "type mismatch");
226}
227
230 const SrcOp &Op1, std::optional<unsigned> Flags) {
231 assert(Res.getLLTTy(*getMRI()).isPointerOrPointerVector() &&
232 Res.getLLTTy(*getMRI()) == Op0.getLLTTy(*getMRI()) && "type mismatch");
233 assert(Op1.getLLTTy(*getMRI()).getScalarType().isScalar() && "invalid offset type");
234
235 return buildInstr(TargetOpcode::G_PTR_ADD, {Res}, {Op0, Op1}, Flags);
236}
237
245
246std::optional<MachineInstrBuilder>
248 const LLT ValueTy, uint64_t Value,
249 std::optional<unsigned> Flags) {
250 assert(Res == 0 && "Res is a result argument");
251 assert(ValueTy.isScalar() && "invalid offset type");
252
253 if (Value == 0) {
254 Res = Op0;
255 return std::nullopt;
256 }
257
259 auto Cst = buildConstant(ValueTy, Value);
260 return buildPtrAdd(Res, Op0, Cst.getReg(0), Flags);
261}
262
263std::optional<MachineInstrBuilder> MachineIRBuilder::materializeObjectPtrOffset(
264 Register &Res, Register Op0, const LLT ValueTy, uint64_t Value) {
265 return materializePtrAdd(Res, Op0, ValueTy, Value,
268}
269
271 const SrcOp &Op0,
272 uint32_t NumBits) {
273 LLT PtrTy = Res.getLLTTy(*getMRI());
274 LLT MaskTy = LLT::integer(PtrTy.getSizeInBits());
275 Register MaskReg = getMRI()->createGenericVirtualRegister(MaskTy);
277 return buildPtrMask(Res, Op0, MaskReg);
278}
279
282 const SrcOp &Op0) {
283 LLT ResTy = Res.getLLTTy(*getMRI());
284 LLT Op0Ty = Op0.getLLTTy(*getMRI());
285
286 assert(ResTy.isVector() && "Res non vector type");
287
289 if (Op0Ty.isVector()) {
290 assert((ResTy.getElementType() == Op0Ty.getElementType()) &&
291 "Different vector element types");
292 assert((ResTy.getNumElements() > Op0Ty.getNumElements()) &&
293 "Op0 has more elements");
294 auto Unmerge = buildUnmerge(Op0Ty.getElementType(), Op0);
295
296 for (auto Op : Unmerge.getInstr()->defs())
297 Regs.push_back(Op.getReg());
298 } else {
299 assert((ResTy.getSizeInBits() > Op0Ty.getSizeInBits()) &&
300 "Op0 has more size");
301 Regs.push_back(Op0.getReg());
302 }
304 buildUndef(Op0Ty.isVector() ? Op0Ty.getElementType() : Op0Ty).getReg(0);
305 unsigned NumberOfPadElts = ResTy.getNumElements() - Regs.size();
306 for (unsigned i = 0; i < NumberOfPadElts; ++i)
307 Regs.push_back(Undef);
308 return buildMergeLikeInstr(Res, Regs);
309}
310
313 const SrcOp &Op0) {
314 LLT ResTy = Res.getLLTTy(*getMRI());
315 LLT Op0Ty = Op0.getLLTTy(*getMRI());
316
317 assert(Op0Ty.isVector() && "Non vector type");
318 assert(((ResTy.isScalar() && (ResTy == Op0Ty.getElementType())) ||
319 (ResTy.isVector() &&
320 (ResTy.getElementType() == Op0Ty.getElementType()))) &&
321 "Different vector element types");
322 assert(
323 (ResTy.isScalar() || (ResTy.getNumElements() < Op0Ty.getNumElements())) &&
324 "Op0 has fewer elements");
325
326 auto Unmerge = buildUnmerge(Op0Ty.getElementType(), Op0);
327 if (ResTy.isScalar())
328 return buildCopy(Res, Unmerge.getReg(0));
330 for (unsigned i = 0; i < ResTy.getNumElements(); ++i)
331 Regs.push_back(Unmerge.getReg(i));
332 return buildMergeLikeInstr(Res, Regs);
333}
334
336 return buildInstr(TargetOpcode::G_BR).addMBB(&Dest);
337}
338
340 assert(getMRI()->getType(Tgt).isPointer() && "invalid branch destination");
341 return buildInstr(TargetOpcode::G_BRINDIRECT).addUse(Tgt);
342}
343
345 unsigned JTI,
346 Register IndexReg) {
347 assert(getMRI()->getType(TablePtr).isPointer() &&
348 "Table reg must be a pointer");
349 return buildInstr(TargetOpcode::G_BRJT)
350 .addUse(TablePtr)
352 .addUse(IndexReg);
353}
354
356 const SrcOp &Op) {
357 return buildInstr(TargetOpcode::COPY, Res, Op);
358}
359
361 const ConstantInt &Val) {
362 assert(!isa<VectorType>(Val.getType()) && "Unexpected vector constant!");
363 LLT Ty = Res.getLLTTy(*getMRI());
364 LLT EltTy = Ty.getScalarType();
365 assert(EltTy.getScalarSizeInBits() == Val.getBitWidth() &&
366 "creating constant with the wrong size");
367
368 assert(!Ty.isScalableVector() &&
369 "unexpected scalable vector in buildConstant");
370
371 if (Ty.isFixedVector()) {
372 auto Const = buildInstr(TargetOpcode::G_CONSTANT)
373 .addDef(getMRI()->createGenericVirtualRegister(EltTy))
374 .addCImm(&Val);
375 return buildSplatBuildVector(Res, Const);
376 }
377
378 auto Const = buildInstr(TargetOpcode::G_CONSTANT);
379 Const->setDebugLoc(DebugLoc());
380 Res.addDefToMIB(*getMRI(), Const);
381 Const.addCImm(&Val);
382 return Const;
383}
384
386 int64_t Val) {
389 // TODO: Avoid implicit trunc?
390 // See https://github.com/llvm/llvm-project/issues/112510.
391 ConstantInt *CI = ConstantInt::getSigned(IntN, Val, /*implicitTrunc=*/true);
392 return buildConstant(Res, *CI);
393}
394
396 const ConstantFP &Val) {
397 assert(!isa<VectorType>(Val.getType()) && "Unexpected vector constant!");
398 LLT Ty = Res.getLLTTy(*getMRI());
399 LLT EltTy = Ty.getScalarType();
400
402 == EltTy.getSizeInBits() &&
403 "creating fconstant with the wrong size");
404
405 assert(!Ty.isPointer() && "invalid operand type");
406
407 assert(!Ty.isScalableVector() &&
408 "unexpected scalable vector in buildFConstant");
409
410 if (Ty.isFixedVector()) {
411 auto Const = buildInstr(TargetOpcode::G_FCONSTANT)
412 .addDef(getMRI()->createGenericVirtualRegister(EltTy))
413 .addFPImm(&Val);
414
415 return buildSplatBuildVector(Res, Const);
416 }
417
418 auto Const = buildInstr(TargetOpcode::G_FCONSTANT);
419 Const->setDebugLoc(DebugLoc());
420 Res.addDefToMIB(*getMRI(), Const);
421 Const.addFPImm(&Val);
422 return Const;
423}
424
426 const APInt &Val) {
427 ConstantInt *CI = ConstantInt::get(getMF().getFunction().getContext(), Val);
428 return buildConstant(Res, *CI);
429}
430
432 double Val) {
433 LLT DstTy = Res.getLLTTy(*getMRI());
434 auto &Ctx = getMF().getFunction().getContext();
435 APFloat APF(Val);
436 bool Ignored;
439 return buildFConstant(Res, *ConstantFP::get(Ctx, APF));
440}
441
443 const APFloat &Val) {
444 auto &Ctx = getMF().getFunction().getContext();
445 auto *CFP = ConstantFP::get(Ctx, Val);
446 return buildFConstant(Res, *CFP);
447}
448
451 const ConstantPtrAuth *CPA,
452 Register Addr, Register AddrDisc) {
453 auto MIB = buildInstr(TargetOpcode::G_PTRAUTH_GLOBAL_VALUE);
454 Res.addDefToMIB(*getMRI(), MIB);
455 MIB.addUse(Addr);
456 MIB.addImm(CPA->getKey()->getZExtValue());
457 MIB.addUse(AddrDisc);
458 MIB.addImm(CPA->getDiscriminator()->getZExtValue());
459 return MIB;
460}
461
463 MachineBasicBlock &Dest) {
464 assert(Tst.getLLTTy(*getMRI()).isScalar() && "invalid operand type");
465
466 auto MIB = buildInstr(TargetOpcode::G_BRCOND);
467 Tst.addSrcToMIB(MIB);
468 MIB.addMBB(&Dest);
469 return MIB;
470}
471
474 MachinePointerInfo PtrInfo, Align Alignment,
476 const AAMDNodes &AAInfo) {
477 MMOFlags |= MachineMemOperand::MOLoad;
478 assert((MMOFlags & MachineMemOperand::MOStore) == 0);
479
480 LLT Ty = Dst.getLLTTy(*getMRI());
481 MachineMemOperand *MMO =
482 getMF().getMachineMemOperand(PtrInfo, MMOFlags, Ty, Alignment, AAInfo);
483 return buildLoad(Dst, Addr, *MMO);
484}
485
487 const DstOp &Res,
488 const SrcOp &Addr,
489 MachineMemOperand &MMO) {
490 assert(Res.getLLTTy(*getMRI()).isValid() && "invalid operand type");
491 assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
492
493 auto MIB = buildInstr(Opcode);
494 Res.addDefToMIB(*getMRI(), MIB);
495 Addr.addSrcToMIB(MIB);
496 MIB.addMemOperand(&MMO);
497 return MIB;
498}
499
501 const DstOp &Dst, const SrcOp &BasePtr,
502 MachineMemOperand &BaseMMO, int64_t Offset) {
503 LLT LoadTy = Dst.getLLTTy(*getMRI());
504 MachineMemOperand *OffsetMMO =
505 getMF().getMachineMemOperand(&BaseMMO, Offset, LoadTy);
506
507 if (Offset == 0) // This may be a size or type changing load.
508 return buildLoad(Dst, BasePtr, *OffsetMMO);
509
510 LLT PtrTy = BasePtr.getLLTTy(*getMRI());
511 LLT OffsetTy = LLT::scalar(PtrTy.getSizeInBits());
512 auto ConstOffset = buildConstant(OffsetTy, Offset);
513 auto Ptr = buildPtrAdd(PtrTy, BasePtr, ConstOffset);
514 return buildLoad(Dst, Ptr, *OffsetMMO);
515}
516
518 const SrcOp &Addr,
519 MachineMemOperand &MMO) {
520 assert(Val.getLLTTy(*getMRI()).isValid() && "invalid operand type");
521 assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
522
523 auto MIB = buildInstr(TargetOpcode::G_STORE);
524 Val.addSrcToMIB(MIB);
525 Addr.addSrcToMIB(MIB);
526 MIB.addMemOperand(&MMO);
527 return MIB;
528}
529
531 const SrcOp &Val,
532 const SrcOp &Addr,
533 MachineMemOperand &MMO) {
534 assert(Val.getLLTTy(*getMRI()).isValid() && "invalid operand type");
535 assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
536
537 auto MIB = buildInstr(Opcode);
538 Val.addSrcToMIB(MIB);
539 Addr.addSrcToMIB(MIB);
540 MIB.addMemOperand(&MMO);
541 return MIB;
542}
543
546 MachinePointerInfo PtrInfo, Align Alignment,
548 const AAMDNodes &AAInfo) {
549 MMOFlags |= MachineMemOperand::MOStore;
550 assert((MMOFlags & MachineMemOperand::MOLoad) == 0);
551
552 LLT Ty = Val.getLLTTy(*getMRI());
553 MachineMemOperand *MMO =
554 getMF().getMachineMemOperand(PtrInfo, MMOFlags, Ty, Alignment, AAInfo);
555 return buildStore(Val, Addr, *MMO);
556}
557
559 const SrcOp &Op) {
560 return buildInstr(TargetOpcode::G_ANYEXT, Res, Op);
561}
562
564 const SrcOp &Op) {
565 return buildInstr(TargetOpcode::G_SEXT, Res, Op);
566}
567
569 const SrcOp &Op,
570 std::optional<unsigned> Flags) {
571 return buildInstr(TargetOpcode::G_ZEXT, Res, Op, Flags);
572}
573
574unsigned MachineIRBuilder::getBoolExtOp(bool IsVec, bool IsFP) const {
575 const auto *TLI = getMF().getSubtarget().getTargetLowering();
576 switch (TLI->getBooleanContents(IsVec, IsFP)) {
578 return TargetOpcode::G_SEXT;
580 return TargetOpcode::G_ZEXT;
581 default:
582 return TargetOpcode::G_ANYEXT;
583 }
584}
585
587 const SrcOp &Op,
588 bool IsFP) {
589 unsigned ExtOp = getBoolExtOp(getMRI()->getType(Op.getReg()).isVector(), IsFP);
590 return buildInstr(ExtOp, Res, Op);
591}
592
594 const SrcOp &Op,
595 bool IsVector,
596 bool IsFP) {
597 const auto *TLI = getMF().getSubtarget().getTargetLowering();
598 switch (TLI->getBooleanContents(IsVector, IsFP)) {
600 return buildSExtInReg(Res, Op, 1);
602 return buildZExtInReg(Res, Op, 1);
604 return buildCopy(Res, Op);
605 }
606
607 llvm_unreachable("unexpected BooleanContent");
608}
609
611 const DstOp &Res,
612 const SrcOp &Op) {
613 assert((TargetOpcode::G_ANYEXT == ExtOpc || TargetOpcode::G_ZEXT == ExtOpc ||
614 TargetOpcode::G_SEXT == ExtOpc) &&
615 "Expecting Extending Opc");
616 assert(Res.getLLTTy(*getMRI()).isScalar() ||
617 Res.getLLTTy(*getMRI()).isVector());
618 assert(Res.getLLTTy(*getMRI()).isScalar() ==
619 Op.getLLTTy(*getMRI()).isScalar());
620
621 unsigned Opcode = TargetOpcode::COPY;
622 if (Res.getLLTTy(*getMRI()).getSizeInBits() >
623 Op.getLLTTy(*getMRI()).getSizeInBits())
624 Opcode = ExtOpc;
625 else if (Res.getLLTTy(*getMRI()).getSizeInBits() <
626 Op.getLLTTy(*getMRI()).getSizeInBits())
627 Opcode = TargetOpcode::G_TRUNC;
628 else
629 assert(Res.getLLTTy(*getMRI()).getSizeInBits() ==
630 Op.getLLTTy(*getMRI()).getSizeInBits());
631
632 return buildInstr(Opcode, Res, Op);
633}
634
636 const SrcOp &Op) {
637 return buildExtOrTrunc(TargetOpcode::G_SEXT, Res, Op);
638}
639
641 const SrcOp &Op) {
642 return buildExtOrTrunc(TargetOpcode::G_ZEXT, Res, Op);
643}
644
646 const SrcOp &Op) {
647 return buildExtOrTrunc(TargetOpcode::G_ANYEXT, Res, Op);
648}
649
651 const SrcOp &Op,
652 int64_t ImmOp) {
653 LLT ResTy = Res.getLLTTy(*getMRI());
654 auto Mask = buildConstant(
655 ResTy, APInt::getLowBitsSet(ResTy.getScalarSizeInBits(), ImmOp));
656 return buildAnd(Res, Op, Mask);
657}
658
660 const SrcOp &Src) {
661 LLT SrcTy = Src.getLLTTy(*getMRI());
662 LLT DstTy = Dst.getLLTTy(*getMRI());
663 if (SrcTy == DstTy)
664 return buildCopy(Dst, Src);
665
666 unsigned Opcode;
667 if (SrcTy.isPointerOrPointerVector())
668 Opcode = TargetOpcode::G_PTRTOINT;
669 else if (DstTy.isPointerOrPointerVector())
670 Opcode = TargetOpcode::G_INTTOPTR;
671 else {
672 assert(!SrcTy.isPointerOrPointerVector() &&
673 !DstTy.isPointerOrPointerVector() && "no G_ADDRCAST yet");
674 Opcode = TargetOpcode::G_BITCAST;
675 }
676
677 return buildInstr(Opcode, Dst, Src);
678}
679
681 const SrcOp &Src,
682 uint64_t Index) {
683 LLT SrcTy = Src.getLLTTy(*getMRI());
684 LLT DstTy = Dst.getLLTTy(*getMRI());
685
686#ifndef NDEBUG
687 assert(SrcTy.isValid() && "invalid operand type");
688 assert(DstTy.isValid() && "invalid operand type");
689 assert(Index + DstTy.getSizeInBits() <= SrcTy.getSizeInBits() &&
690 "extracting off end of register");
691#endif
692
693 if (DstTy.getSizeInBits() == SrcTy.getSizeInBits()) {
694 assert(Index == 0 && "insertion past the end of a register");
695 return buildCast(Dst, Src);
696 }
697
698 auto Extract = buildInstr(TargetOpcode::G_EXTRACT);
699 Dst.addDefToMIB(*getMRI(), Extract);
700 Src.addSrcToMIB(Extract);
701 Extract.addImm(Index);
702 return Extract;
703}
704
706 return buildInstr(TargetOpcode::G_IMPLICIT_DEF, {Res}, {});
707}
708
711 // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
712 // we need some temporary storage for the DstOp objects. Here we use a
713 // sufficiently large SmallVector to not go through the heap.
715 assert(TmpVec.size() > 1);
716 return buildInstr(TargetOpcode::G_MERGE_VALUES, Res, TmpVec);
717}
718
722 // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
723 // we need some temporary storage for the DstOp objects. Here we use a
724 // sufficiently large SmallVector to not go through the heap.
726 assert(TmpVec.size() > 1);
727 return buildInstr(getOpcodeForMerge(Res, TmpVec), Res, TmpVec);
728}
729
732 std::initializer_list<SrcOp> Ops) {
733 assert(Ops.size() > 1);
734 return buildInstr(getOpcodeForMerge(Res, Ops), Res, Ops);
735}
736
737unsigned MachineIRBuilder::getOpcodeForMerge(const DstOp &DstOp,
738 ArrayRef<SrcOp> SrcOps) const {
739 if (DstOp.getLLTTy(*getMRI()).isVector()) {
740 if (SrcOps[0].getLLTTy(*getMRI()).isVector())
741 return TargetOpcode::G_CONCAT_VECTORS;
742 return TargetOpcode::G_BUILD_VECTOR;
743 }
744
745 return TargetOpcode::G_MERGE_VALUES;
746}
747
749 const SrcOp &Op) {
750 // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<DstOp>,
751 // we need some temporary storage for the DstOp objects. Here we use a
752 // sufficiently large SmallVector to not go through the heap.
753 SmallVector<DstOp, 8> TmpVec(Res);
754 assert(TmpVec.size() > 1);
755 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
756}
757
759 const SrcOp &Op) {
760 unsigned NumReg = Op.getLLTTy(*getMRI()).getSizeInBits() / Res.getSizeInBits();
761 SmallVector<DstOp, 8> TmpVec(NumReg, Res);
762 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
763}
764
767 const SrcOp &Op) {
768 LLT OpTy = Op.getLLTTy(*getMRI());
769 unsigned NumRegs = OpTy.getSizeInBits() / Attrs.Ty.getSizeInBits();
770 SmallVector<DstOp, 8> TmpVec(NumRegs, Attrs);
771 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
772}
773
775 const SrcOp &Op) {
776 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<DstOp>,
777 // we need some temporary storage for the DstOp objects. Here we use a
778 // sufficiently large SmallVector to not go through the heap.
779 SmallVector<DstOp, 8> TmpVec(Res);
780 assert(TmpVec.size() > 1);
781 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
782}
783
786 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
787 // we need some temporary storage for the DstOp objects. Here we use a
788 // sufficiently large SmallVector to not go through the heap.
790 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
791}
792
796 SmallVector<SrcOp> TmpVec;
797 TmpVec.reserve(Ops.size());
798 LLT EltTy = Res.getLLTTy(*getMRI()).getElementType();
799 for (const auto &Op : Ops)
800 TmpVec.push_back(buildConstant(EltTy, Op));
801 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
802}
803
805 const SrcOp &Src) {
806 SmallVector<SrcOp, 8> TmpVec(Res.getLLTTy(*getMRI()).getNumElements(), Src);
807 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
808}
809
813 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
814 // we need some temporary storage for the DstOp objects. Here we use a
815 // sufficiently large SmallVector to not go through the heap.
817 if (TmpVec[0].getLLTTy(*getMRI()).getSizeInBits() ==
818 Res.getLLTTy(*getMRI()).getElementType().getSizeInBits())
819 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
820 return buildInstr(TargetOpcode::G_BUILD_VECTOR_TRUNC, Res, TmpVec);
821}
822
824 const SrcOp &Src) {
825 LLT DstTy = Res.getLLTTy(*getMRI());
826 assert(Src.getLLTTy(*getMRI()) == DstTy.getElementType() &&
827 "Expected Src to match Dst elt ty");
828 auto UndefVec = buildUndef(DstTy);
829 auto Zero = buildConstant(LLT::integer(64), 0);
830 auto InsElt = buildInsertVectorElement(DstTy, UndefVec, Src, Zero);
831 SmallVector<int, 16> ZeroMask(DstTy.getNumElements());
832 return buildShuffleVector(DstTy, InsElt, UndefVec, ZeroMask);
833}
834
836 const SrcOp &Src) {
837 assert(Src.getLLTTy(*getMRI()) == Res.getLLTTy(*getMRI()).getElementType() &&
838 "Expected Src to match Dst elt ty");
839 return buildInstr(TargetOpcode::G_SPLAT_VECTOR, Res, Src);
840}
841
843 const SrcOp &Src1,
844 const SrcOp &Src2,
845 ArrayRef<int> Mask) {
846 LLT DstTy = Res.getLLTTy(*getMRI());
847 LLT Src1Ty = Src1.getLLTTy(*getMRI());
848 LLT Src2Ty = Src2.getLLTTy(*getMRI());
849 const LLT DstElemTy = DstTy.getScalarType();
850 const LLT ElemTy1 = Src1Ty.getScalarType();
851 const LLT ElemTy2 = Src2Ty.getScalarType();
852 assert(DstElemTy == ElemTy1 && DstElemTy == ElemTy2);
853 assert(Mask.size() > 1 && "Scalar G_SHUFFLE_VECTOR are not supported");
854 (void)DstElemTy;
855 (void)ElemTy1;
856 (void)ElemTy2;
857 ArrayRef<int> MaskAlloc = getMF().allocateShuffleMask(Mask);
858 return buildInstr(TargetOpcode::G_SHUFFLE_VECTOR, {Res}, {Src1, Src2})
859 .addShuffleMask(MaskAlloc);
860}
861
864 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
865 // we need some temporary storage for the DstOp objects. Here we use a
866 // sufficiently large SmallVector to not go through the heap.
868 return buildInstr(TargetOpcode::G_CONCAT_VECTORS, Res, TmpVec);
869}
870
872 const SrcOp &Src,
873 const SrcOp &Op,
874 unsigned Index) {
875 assert(Index + Op.getLLTTy(*getMRI()).getSizeInBits() <=
876 Res.getLLTTy(*getMRI()).getSizeInBits() &&
877 "insertion past the end of a register");
878
879 if (Res.getLLTTy(*getMRI()).getSizeInBits() ==
880 Op.getLLTTy(*getMRI()).getSizeInBits()) {
881 return buildCast(Res, Op);
882 }
883
884 return buildInstr(TargetOpcode::G_INSERT, Res, {Src, Op, uint64_t(Index)});
885}
886
888 unsigned Step) {
889 unsigned Bitwidth = Res.getLLTTy(*getMRI()).getElementType().getSizeInBits();
890 ConstantInt *CI = ConstantInt::get(getMF().getFunction().getContext(),
891 APInt(Bitwidth, Step));
892 auto StepVector = buildInstr(TargetOpcode::G_STEP_VECTOR);
893 StepVector->setDebugLoc(DebugLoc());
894 Res.addDefToMIB(*getMRI(), StepVector);
895 StepVector.addCImm(CI);
896 return StepVector;
897}
898
900 unsigned MinElts) {
901
904 ConstantInt *CI = ConstantInt::get(IntN, MinElts);
905 return buildVScale(Res, *CI);
906}
907
909 const ConstantInt &MinElts) {
910 auto VScale = buildInstr(TargetOpcode::G_VSCALE);
911 VScale->setDebugLoc(DebugLoc());
912 Res.addDefToMIB(*getMRI(), VScale);
913 VScale.addCImm(&MinElts);
914 return VScale;
915}
916
918 const APInt &MinElts) {
919 ConstantInt *CI =
920 ConstantInt::get(getMF().getFunction().getContext(), MinElts);
921 return buildVScale(Res, *CI);
922}
923
924static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) {
925 if (HasSideEffects && IsConvergent)
926 return TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS;
927 if (HasSideEffects)
928 return TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS;
929 if (IsConvergent)
930 return TargetOpcode::G_INTRINSIC_CONVERGENT;
931 return TargetOpcode::G_INTRINSIC;
932}
933
936 ArrayRef<Register> ResultRegs,
937 bool HasSideEffects, bool isConvergent) {
938 auto MIB = buildInstr(getIntrinsicOpcode(HasSideEffects, isConvergent));
939 for (Register ResultReg : ResultRegs)
940 MIB.addDef(ResultReg);
941 MIB.addIntrinsicID(ID);
942 return MIB;
943}
944
947 ArrayRef<Register> ResultRegs) {
949 bool HasSideEffects = !Attrs.getMemoryEffects().doesNotAccessMemory();
950 bool isConvergent = Attrs.hasAttribute(Attribute::Convergent);
951 return buildIntrinsic(ID, ResultRegs, HasSideEffects, isConvergent);
952}
953
956 bool HasSideEffects,
957 bool isConvergent) {
958 auto MIB = buildInstr(getIntrinsicOpcode(HasSideEffects, isConvergent));
959 for (DstOp Result : Results)
960 Result.addDefToMIB(*getMRI(), MIB);
961 MIB.addIntrinsicID(ID);
962 return MIB;
963}
964
968 bool HasSideEffects = !Attrs.getMemoryEffects().doesNotAccessMemory();
969 bool isConvergent = Attrs.hasAttribute(Attribute::Convergent);
970 return buildIntrinsic(ID, Results, HasSideEffects, isConvergent);
971}
972
975 std::optional<unsigned> Flags) {
976 return buildInstr(TargetOpcode::G_TRUNC, Res, Op, Flags);
977}
978
981 std::optional<unsigned> Flags) {
982 return buildInstr(TargetOpcode::G_FPTRUNC, Res, Op, Flags);
983}
984
986 const DstOp &Res,
987 const SrcOp &Op0,
988 const SrcOp &Op1,
989 std::optional<unsigned> Flags) {
990 return buildInstr(TargetOpcode::G_ICMP, Res, {Pred, Op0, Op1}, Flags);
991}
992
994 const DstOp &Res,
995 const SrcOp &Op0,
996 const SrcOp &Op1,
997 std::optional<unsigned> Flags) {
998
999 return buildInstr(TargetOpcode::G_FCMP, Res, {Pred, Op0, Op1}, Flags);
1000}
1001
1003 const SrcOp &Op0,
1004 const SrcOp &Op1) {
1005 return buildInstr(TargetOpcode::G_SCMP, Res, {Op0, Op1});
1006}
1007
1009 const SrcOp &Op0,
1010 const SrcOp &Op1) {
1011 return buildInstr(TargetOpcode::G_UCMP, Res, {Op0, Op1});
1012}
1013
1016 const SrcOp &Op0, const SrcOp &Op1,
1017 std::optional<unsigned> Flags) {
1018
1019 return buildInstr(TargetOpcode::G_SELECT, {Res}, {Tst, Op0, Op1}, Flags);
1020}
1021
1023 const SrcOp &Src0,
1024 const SrcOp &Src1,
1025 unsigned Idx) {
1026 return buildInstr(TargetOpcode::G_INSERT_SUBVECTOR, Res,
1027 {Src0, Src1, uint64_t(Idx)});
1028}
1029
1031 const SrcOp &Src,
1032 unsigned Idx) {
1033 return buildInstr(TargetOpcode::G_EXTRACT_SUBVECTOR, Res,
1034 {Src, uint64_t(Idx)});
1035}
1036
1039 const SrcOp &Elt, const SrcOp &Idx) {
1040 return buildInstr(TargetOpcode::G_INSERT_VECTOR_ELT, Res, {Val, Elt, Idx});
1041}
1042
1045 const SrcOp &Idx) {
1046 return buildInstr(TargetOpcode::G_EXTRACT_VECTOR_ELT, Res, {Val, Idx});
1047}
1048
1050 const DstOp &OldValRes, const DstOp &SuccessRes, const SrcOp &Addr,
1051 const SrcOp &CmpVal, const SrcOp &NewVal, MachineMemOperand &MMO) {
1052#ifndef NDEBUG
1053 LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
1054 LLT SuccessResTy = SuccessRes.getLLTTy(*getMRI());
1055 LLT AddrTy = Addr.getLLTTy(*getMRI());
1056 LLT CmpValTy = CmpVal.getLLTTy(*getMRI());
1057 LLT NewValTy = NewVal.getLLTTy(*getMRI());
1058 assert(OldValResTy.isScalar() && "invalid operand type");
1059 assert(SuccessResTy.isScalar() && "invalid operand type");
1060 assert(AddrTy.isPointer() && "invalid operand type");
1061 assert(CmpValTy.isValid() && "invalid operand type");
1062 assert(NewValTy.isValid() && "invalid operand type");
1063 assert(OldValResTy == CmpValTy && "type mismatch");
1064 assert(OldValResTy == NewValTy && "type mismatch");
1065#endif
1066
1067 auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS);
1068 OldValRes.addDefToMIB(*getMRI(), MIB);
1069 SuccessRes.addDefToMIB(*getMRI(), MIB);
1070 Addr.addSrcToMIB(MIB);
1071 CmpVal.addSrcToMIB(MIB);
1072 NewVal.addSrcToMIB(MIB);
1073 MIB.addMemOperand(&MMO);
1074 return MIB;
1075}
1076
1079 const SrcOp &CmpVal, const SrcOp &NewVal,
1080 MachineMemOperand &MMO) {
1081#ifndef NDEBUG
1082 LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
1083 LLT AddrTy = Addr.getLLTTy(*getMRI());
1084 LLT CmpValTy = CmpVal.getLLTTy(*getMRI());
1085 LLT NewValTy = NewVal.getLLTTy(*getMRI());
1086 assert(OldValResTy.isScalar() && "invalid operand type");
1087 assert(AddrTy.isPointer() && "invalid operand type");
1088 assert(CmpValTy.isValid() && "invalid operand type");
1089 assert(NewValTy.isValid() && "invalid operand type");
1090 assert(OldValResTy == CmpValTy && "type mismatch");
1091 assert(OldValResTy == NewValTy && "type mismatch");
1092#endif
1093
1094 auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG);
1095 OldValRes.addDefToMIB(*getMRI(), MIB);
1096 Addr.addSrcToMIB(MIB);
1097 CmpVal.addSrcToMIB(MIB);
1098 NewVal.addSrcToMIB(MIB);
1099 MIB.addMemOperand(&MMO);
1100 return MIB;
1101}
1102
1104 unsigned Opcode, const DstOp &OldValRes,
1105 const SrcOp &Addr, const SrcOp &Val,
1106 MachineMemOperand &MMO) {
1107
1108#ifndef NDEBUG
1109 LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
1110 LLT AddrTy = Addr.getLLTTy(*getMRI());
1111 LLT ValTy = Val.getLLTTy(*getMRI());
1112 assert(AddrTy.isPointer() && "invalid operand type");
1113 assert(ValTy.isValid() && "invalid operand type");
1114 assert(OldValResTy == ValTy && "type mismatch");
1115 assert(MMO.isAtomic() && "not atomic mem operand");
1116#endif
1117
1118 auto MIB = buildInstr(Opcode);
1119 OldValRes.addDefToMIB(*getMRI(), MIB);
1120 Addr.addSrcToMIB(MIB);
1121 Val.addSrcToMIB(MIB);
1122 MIB.addMemOperand(&MMO);
1123 return MIB;
1124}
1125
1128 Register Val, MachineMemOperand &MMO) {
1129 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XCHG, OldValRes, Addr, Val,
1130 MMO);
1131}
1134 Register Val, MachineMemOperand &MMO) {
1135 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_ADD, OldValRes, Addr, Val,
1136 MMO);
1137}
1140 Register Val, MachineMemOperand &MMO) {
1141 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_SUB, OldValRes, Addr, Val,
1142 MMO);
1143}
1146 Register Val, MachineMemOperand &MMO) {
1147 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_AND, OldValRes, Addr, Val,
1148 MMO);
1149}
1152 Register Val, MachineMemOperand &MMO) {
1153 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_NAND, OldValRes, Addr, Val,
1154 MMO);
1155}
1157 Register Addr,
1158 Register Val,
1159 MachineMemOperand &MMO) {
1160 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_OR, OldValRes, Addr, Val,
1161 MMO);
1162}
1165 Register Val, MachineMemOperand &MMO) {
1166 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XOR, OldValRes, Addr, Val,
1167 MMO);
1168}
1171 Register Val, MachineMemOperand &MMO) {
1172 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MAX, OldValRes, Addr, Val,
1173 MMO);
1174}
1177 Register Val, MachineMemOperand &MMO) {
1178 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MIN, OldValRes, Addr, Val,
1179 MMO);
1180}
1183 Register Val, MachineMemOperand &MMO) {
1184 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMAX, OldValRes, Addr, Val,
1185 MMO);
1186}
1189 Register Val, MachineMemOperand &MMO) {
1190 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMIN, OldValRes, Addr, Val,
1191 MMO);
1192}
1193
1196 const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
1197 MachineMemOperand &MMO) {
1198 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FADD, OldValRes, Addr, Val,
1199 MMO);
1200}
1201
1203MachineIRBuilder::buildAtomicRMWFSub(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
1204 MachineMemOperand &MMO) {
1205 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FSUB, OldValRes, Addr, Val,
1206 MMO);
1207}
1208
1211 const SrcOp &Val, MachineMemOperand &MMO) {
1212 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMAX, OldValRes, Addr, Val,
1213 MMO);
1214}
1215
1218 const SrcOp &Val, MachineMemOperand &MMO) {
1219 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMIN, OldValRes, Addr, Val,
1220 MMO);
1221}
1222
1225 const SrcOp &Addr, const SrcOp &Val,
1226 MachineMemOperand &MMO) {
1227 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMAXIMUM, OldValRes, Addr,
1228 Val, MMO);
1229}
1230
1233 const SrcOp &Addr, const SrcOp &Val,
1234 MachineMemOperand &MMO) {
1235 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMINIMUM, OldValRes, Addr,
1236 Val, MMO);
1237}
1238
1240MachineIRBuilder::buildFence(unsigned Ordering, unsigned Scope) {
1241 return buildInstr(TargetOpcode::G_FENCE)
1242 .addImm(Ordering)
1243 .addImm(Scope);
1244}
1245
1247 unsigned RW,
1248 unsigned Locality,
1249 unsigned CacheType,
1250 MachineMemOperand &MMO) {
1251 auto MIB = buildInstr(TargetOpcode::G_PREFETCH);
1252 Addr.addSrcToMIB(MIB);
1253 MIB.addImm(RW).addImm(Locality).addImm(CacheType);
1254 MIB.addMemOperand(&MMO);
1255 return MIB;
1256}
1257
1260#ifndef NDEBUG
1261 assert(getMRI()->getType(Res).isPointer() && "invalid res type");
1262#endif
1263
1264 return buildInstr(TargetOpcode::G_BLOCK_ADDR).addDef(Res).addBlockAddress(BA);
1265}
1266
1267void MachineIRBuilder::validateTruncExt(const LLT DstTy, const LLT SrcTy,
1268 bool IsExtend) {
1269#ifndef NDEBUG
1270 if (DstTy.isVector()) {
1271 assert(SrcTy.isVector() && "mismatched cast between vector and non-vector");
1272 assert(SrcTy.getElementCount() == DstTy.getElementCount() &&
1273 "different number of elements in a trunc/ext");
1274 } else
1275 assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc");
1276
1277 if (IsExtend)
1278 assert(TypeSize::isKnownGT(DstTy.getSizeInBits(), SrcTy.getSizeInBits()) &&
1279 "invalid narrowing extend");
1280 else
1281 assert(TypeSize::isKnownLT(DstTy.getSizeInBits(), SrcTy.getSizeInBits()) &&
1282 "invalid widening trunc");
1283#endif
1284}
1285
1286void MachineIRBuilder::validateSelectOp(const LLT ResTy, const LLT TstTy,
1287 const LLT Op0Ty, const LLT Op1Ty) {
1288#ifndef NDEBUG
1289 assert((ResTy.isScalar() || ResTy.isVector() || ResTy.isPointer()) &&
1290 "invalid operand type");
1291 assert((ResTy == Op0Ty && ResTy == Op1Ty) && "type mismatch");
1292 if (ResTy.isScalar() || ResTy.isPointer())
1293 assert(TstTy.isScalar() && "type mismatch");
1294 else
1295 assert((TstTy.isScalar() ||
1296 (TstTy.isVector() &&
1297 TstTy.getElementCount() == Op0Ty.getElementCount())) &&
1298 "type mismatch");
1299#endif
1300}
1301
1304 ArrayRef<SrcOp> SrcOps,
1305 std::optional<unsigned> Flags) {
1306 switch (Opc) {
1307 default:
1308 break;
1309 case TargetOpcode::G_SELECT: {
1310 assert(DstOps.size() == 1 && "Invalid select");
1311 assert(SrcOps.size() == 3 && "Invalid select");
1313 DstOps[0].getLLTTy(*getMRI()), SrcOps[0].getLLTTy(*getMRI()),
1314 SrcOps[1].getLLTTy(*getMRI()), SrcOps[2].getLLTTy(*getMRI()));
1315 break;
1316 }
1317 case TargetOpcode::G_FNEG:
1318 case TargetOpcode::G_ABS:
1319 // All these are unary ops.
1320 assert(DstOps.size() == 1 && "Invalid Dst");
1321 assert(SrcOps.size() == 1 && "Invalid Srcs");
1322 validateUnaryOp(DstOps[0].getLLTTy(*getMRI()),
1323 SrcOps[0].getLLTTy(*getMRI()));
1324 break;
1325 case TargetOpcode::G_ADD:
1326 case TargetOpcode::G_AND:
1327 case TargetOpcode::G_MUL:
1328 case TargetOpcode::G_OR:
1329 case TargetOpcode::G_SUB:
1330 case TargetOpcode::G_XOR:
1331 case TargetOpcode::G_UDIV:
1332 case TargetOpcode::G_SDIV:
1333 case TargetOpcode::G_UREM:
1334 case TargetOpcode::G_SREM:
1335 case TargetOpcode::G_SMIN:
1336 case TargetOpcode::G_SMAX:
1337 case TargetOpcode::G_UMIN:
1338 case TargetOpcode::G_UMAX:
1339 case TargetOpcode::G_UADDSAT:
1340 case TargetOpcode::G_SADDSAT:
1341 case TargetOpcode::G_USUBSAT:
1342 case TargetOpcode::G_SSUBSAT: {
1343 // All these are binary ops.
1344 assert(DstOps.size() == 1 && "Invalid Dst");
1345 assert(SrcOps.size() == 2 && "Invalid Srcs");
1346 validateBinaryOp(DstOps[0].getLLTTy(*getMRI()),
1347 SrcOps[0].getLLTTy(*getMRI()),
1348 SrcOps[1].getLLTTy(*getMRI()));
1349 break;
1350 }
1351 case TargetOpcode::G_SHL:
1352 case TargetOpcode::G_ASHR:
1353 case TargetOpcode::G_LSHR:
1354 case TargetOpcode::G_USHLSAT:
1355 case TargetOpcode::G_SSHLSAT: {
1356 assert(DstOps.size() == 1 && "Invalid Dst");
1357 assert(SrcOps.size() == 2 && "Invalid Srcs");
1358 validateShiftOp(DstOps[0].getLLTTy(*getMRI()),
1359 SrcOps[0].getLLTTy(*getMRI()),
1360 SrcOps[1].getLLTTy(*getMRI()));
1361 break;
1362 }
1363 case TargetOpcode::G_SEXT:
1364 case TargetOpcode::G_ZEXT:
1365 case TargetOpcode::G_ANYEXT:
1366 assert(DstOps.size() == 1 && "Invalid Dst");
1367 assert(SrcOps.size() == 1 && "Invalid Srcs");
1368 validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
1369 SrcOps[0].getLLTTy(*getMRI()), true);
1370 break;
1371 case TargetOpcode::G_TRUNC:
1372 case TargetOpcode::G_FPTRUNC: {
1373 assert(DstOps.size() == 1 && "Invalid Dst");
1374 assert(SrcOps.size() == 1 && "Invalid Srcs");
1375 validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
1376 SrcOps[0].getLLTTy(*getMRI()), false);
1377 break;
1378 }
1379 case TargetOpcode::G_BITCAST: {
1380 assert(DstOps.size() == 1 && "Invalid Dst");
1381 assert(SrcOps.size() == 1 && "Invalid Srcs");
1382 assert(DstOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1383 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() && "invalid bitcast");
1384 break;
1385 }
1386 case TargetOpcode::COPY:
1387 assert(DstOps.size() == 1 && "Invalid Dst");
1388 // If the caller wants to add a subreg source it has to be done separately
1389 // so we may not have any SrcOps at this point yet.
1390 break;
1391 case TargetOpcode::G_FCMP:
1392 case TargetOpcode::G_ICMP: {
1393 assert(DstOps.size() == 1 && "Invalid Dst Operands");
1394 assert(SrcOps.size() == 3 && "Invalid Src Operands");
1395 // For F/ICMP, the first src operand is the predicate, followed by
1396 // the two comparands.
1397 assert(SrcOps[0].getSrcOpKind() == SrcOp::SrcType::Ty_Predicate &&
1398 "Expecting predicate");
1399 assert([&]() -> bool {
1400 CmpInst::Predicate Pred = SrcOps[0].getPredicate();
1401 return Opc == TargetOpcode::G_ICMP ? CmpInst::isIntPredicate(Pred)
1402 : CmpInst::isFPPredicate(Pred);
1403 }() && "Invalid predicate");
1404 assert(SrcOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
1405 "Type mismatch");
1406 assert([&]() -> bool {
1407 LLT Op0Ty = SrcOps[1].getLLTTy(*getMRI());
1408 LLT DstTy = DstOps[0].getLLTTy(*getMRI());
1409 if (Op0Ty.isScalar() || Op0Ty.isPointer())
1410 return DstTy.isScalar();
1411 else
1412 return DstTy.isVector() &&
1413 DstTy.getElementCount() == Op0Ty.getElementCount();
1414 }() && "Type Mismatch");
1415 break;
1416 }
1417 case TargetOpcode::G_UNMERGE_VALUES: {
1418 assert(!DstOps.empty() && "Invalid trivial sequence");
1419 assert(SrcOps.size() == 1 && "Invalid src for Unmerge");
1420 assert(llvm::all_of(DstOps,
1421 [&, this](const DstOp &Op) {
1422 return Op.getLLTTy(*getMRI()) ==
1423 DstOps[0].getLLTTy(*getMRI());
1424 }) &&
1425 "type mismatch in output list");
1426 assert((TypeSize::ScalarTy)DstOps.size() *
1427 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1428 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1429 "input operands do not cover output register");
1430 break;
1431 }
1432 case TargetOpcode::G_MERGE_VALUES: {
1433 assert(SrcOps.size() >= 2 && "invalid trivial sequence");
1434 assert(DstOps.size() == 1 && "Invalid Dst");
1435 assert(llvm::all_of(SrcOps,
1436 [&, this](const SrcOp &Op) {
1437 return Op.getLLTTy(*getMRI()) ==
1438 SrcOps[0].getLLTTy(*getMRI());
1439 }) &&
1440 "type mismatch in input list");
1441 assert((TypeSize::ScalarTy)SrcOps.size() *
1442 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1443 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1444 "input operands do not cover output register");
1445 assert(!DstOps[0].getLLTTy(*getMRI()).isVector() &&
1446 "vectors should be built with G_CONCAT_VECTOR or G_BUILD_VECTOR");
1447 break;
1448 }
1449 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1450 assert(DstOps.size() == 1 && "Invalid Dst size");
1451 assert(SrcOps.size() == 2 && "Invalid Src size");
1452 assert(SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
1453 assert((DstOps[0].getLLTTy(*getMRI()).isScalar() ||
1454 DstOps[0].getLLTTy(*getMRI()).isPointer()) &&
1455 "Invalid operand type");
1456 assert(SrcOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand type");
1457 assert(SrcOps[0].getLLTTy(*getMRI()).getElementType() ==
1458 DstOps[0].getLLTTy(*getMRI()) &&
1459 "Type mismatch");
1460 break;
1461 }
1462 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1463 assert(DstOps.size() == 1 && "Invalid dst size");
1464 assert(SrcOps.size() == 3 && "Invalid src size");
1465 assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
1466 SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
1467 assert(DstOps[0].getLLTTy(*getMRI()).getElementType() ==
1468 SrcOps[1].getLLTTy(*getMRI()) &&
1469 "Type mismatch");
1470 assert(SrcOps[2].getLLTTy(*getMRI()).isScalar() && "Invalid index");
1471 assert(DstOps[0].getLLTTy(*getMRI()).getElementCount() ==
1472 SrcOps[0].getLLTTy(*getMRI()).getElementCount() &&
1473 "Type mismatch");
1474 break;
1475 }
1476 case TargetOpcode::G_INSERT_SUBVECTOR: {
1477 assert(DstOps.size() == 1 && "Invalid Dst");
1478 assert(SrcOps.size() == 3 && "Invalid Srcs");
1479 [[maybe_unused]] LLT DstTy = DstOps[0].getLLTTy(*getMRI());
1480 [[maybe_unused]] LLT BigVecTy = SrcOps[0].getLLTTy(*getMRI());
1481 [[maybe_unused]] LLT SubVecTy = SrcOps[1].getLLTTy(*getMRI());
1482 assert(DstTy == BigVecTy &&
1483 "Dest and insert subvector source types must match!");
1484 assert(DstTy.isVector() && SubVecTy.isVector() &&
1485 "Insert subvector VTs must be vectors!");
1486 assert(DstTy.getElementType() == SubVecTy.getElementType() &&
1487 "Insert subvector VTs must have the same element type!");
1488 assert((DstTy.isScalable() || !SubVecTy.isScalable()) &&
1489 "Cannot insert a scalable vector into a fixed length vector!");
1490 assert((DstTy.isScalable() != SubVecTy.isScalable() ||
1492 SubVecTy.getElementCount().getKnownMinValue()) &&
1493 "Insert subvector must be from smaller vector to larger vector!");
1494 assert(SrcOps[2].getSrcOpKind() == SrcOp::SrcType::Ty_Imm &&
1495 "Insert subvector index must be constant");
1496 assert((DstTy.isScalable() != SubVecTy.isScalable() ||
1497 (SubVecTy.getElementCount().getKnownMinValue() +
1498 (uint64_t)SrcOps[2].getImm()) <=
1499 DstTy.getElementCount().getKnownMinValue()) &&
1500 "Insert subvector overflow!");
1501 assert((uint64_t)SrcOps[2].getImm() %
1502 SubVecTy.getElementCount().getKnownMinValue() ==
1503 0 &&
1504 "Insert index is not a multiple of the subvector length");
1505 break;
1506 }
1507 case TargetOpcode::G_EXTRACT_SUBVECTOR: {
1508 assert(DstOps.size() == 1 && "Invalid Dst");
1509 assert(SrcOps.size() == 2 && "Invalid Srcs");
1510 [[maybe_unused]] LLT DstTy = DstOps[0].getLLTTy(*getMRI());
1511 [[maybe_unused]] LLT SrcVecTy = SrcOps[0].getLLTTy(*getMRI());
1512 assert(DstTy.isVector() && SrcVecTy.isVector() &&
1513 "Extract subvector VTs must be vectors!");
1514 assert(DstTy.getElementType() == SrcVecTy.getElementType() &&
1515 "Extract subvector VTs must have the same element type!");
1516 assert((!DstTy.isScalable() || SrcVecTy.isScalable()) &&
1517 "Cannot extract a scalable vector from a fixed length vector!");
1518 assert((DstTy.isScalable() != SrcVecTy.isScalable() ||
1520 SrcVecTy.getElementCount().getKnownMinValue()) &&
1521 "Extract subvector must be from larger vector to smaller vector!");
1522 assert(SrcOps[1].getSrcOpKind() == SrcOp::SrcType::Ty_Imm &&
1523 "Extract subvector index must be a constant");
1524 assert((DstTy.isScalable() != SrcVecTy.isScalable() ||
1526 (uint64_t)SrcOps[1].getImm()) <=
1527 SrcVecTy.getElementCount().getKnownMinValue()) &&
1528 "Extract subvector overflow!");
1529 assert((uint64_t)SrcOps[1].getImm() %
1531 0 &&
1532 "Extract index is not a multiple of the output vector length");
1533 break;
1534 }
1535 case TargetOpcode::G_BUILD_VECTOR: {
1536 assert((!SrcOps.empty() || SrcOps.size() < 2) &&
1537 "Must have at least 2 operands");
1538 assert(DstOps.size() == 1 && "Invalid DstOps");
1539 assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
1540 "Res type must be a vector");
1541 assert(llvm::all_of(SrcOps,
1542 [&, this](const SrcOp &Op) {
1543 return Op.getLLTTy(*getMRI()) ==
1544 SrcOps[0].getLLTTy(*getMRI());
1545 }) &&
1546 "type mismatch in input list");
1547 assert((TypeSize::ScalarTy)SrcOps.size() *
1548 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1549 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1550 "input scalars do not exactly cover the output vector register");
1551 break;
1552 }
1553 case TargetOpcode::G_BUILD_VECTOR_TRUNC: {
1554 assert((!SrcOps.empty() || SrcOps.size() < 2) &&
1555 "Must have at least 2 operands");
1556 assert(DstOps.size() == 1 && "Invalid DstOps");
1557 assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
1558 "Res type must be a vector");
1559 assert(llvm::all_of(SrcOps,
1560 [&, this](const SrcOp &Op) {
1561 return Op.getLLTTy(*getMRI()) ==
1562 SrcOps[0].getLLTTy(*getMRI());
1563 }) &&
1564 "type mismatch in input list");
1565 break;
1566 }
1567 case TargetOpcode::G_CONCAT_VECTORS: {
1568 assert(DstOps.size() == 1 && "Invalid DstOps");
1569 assert((!SrcOps.empty() || SrcOps.size() < 2) &&
1570 "Must have at least 2 operands");
1571 assert(llvm::all_of(SrcOps,
1572 [&, this](const SrcOp &Op) {
1573 return (Op.getLLTTy(*getMRI()).isVector() &&
1574 Op.getLLTTy(*getMRI()) ==
1575 SrcOps[0].getLLTTy(*getMRI()));
1576 }) &&
1577 "type mismatch in input list");
1578 assert((TypeSize::ScalarTy)SrcOps.size() *
1579 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1580 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1581 "input vectors do not exactly cover the output vector register");
1582 break;
1583 }
1584 case TargetOpcode::G_UADDE: {
1585 assert(DstOps.size() == 2 && "Invalid no of dst operands");
1586 assert(SrcOps.size() == 3 && "Invalid no of src operands");
1587 assert(DstOps[0].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
1588 assert((DstOps[0].getLLTTy(*getMRI()) == SrcOps[0].getLLTTy(*getMRI())) &&
1589 (DstOps[0].getLLTTy(*getMRI()) == SrcOps[1].getLLTTy(*getMRI())) &&
1590 "Invalid operand");
1591 assert(DstOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
1592 assert(DstOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
1593 "type mismatch");
1594 break;
1595 }
1596 }
1597
1598 auto MIB = buildInstr(Opc);
1599 for (const DstOp &Op : DstOps)
1600 Op.addDefToMIB(*getMRI(), MIB);
1601 for (const SrcOp &Op : SrcOps)
1602 Op.addSrcToMIB(MIB);
1603 if (Flags)
1604 MIB->setFlags(*Flags);
1605 return MIB;
1606}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned 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:393
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:361
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:6034
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:410
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:43
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:356
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 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:216
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:223
#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.