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//===----------------------------------------------------------------------===//
21
22using namespace llvm;
23
25 State.MF = &MF;
26 State.MBB = nullptr;
27 State.MRI = &MF.getRegInfo();
28 State.TII = MF.getSubtarget().getInstrInfo();
29 State.DL = DebugLoc();
30 State.PCSections = nullptr;
31 State.MMRA = nullptr;
32 State.II = MachineBasicBlock::iterator();
33 State.Observer = nullptr;
34}
35
36//------------------------------------------------------------------------------
37// Build instruction variants.
38//------------------------------------------------------------------------------
39
46
52
55 const MDNode *Expr) {
56 assert(isa<DILocalVariable>(Variable) && "not a variable");
57 assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
58 assert(
59 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
60 "Expected inlined-at fields to agree");
61 return insertInstr(BuildMI(getMF(), getDL(),
62 getTII().get(TargetOpcode::DBG_VALUE),
63 /*IsIndirect*/ false, Reg, Variable, Expr));
64}
65
68 const MDNode *Expr) {
69 assert(isa<DILocalVariable>(Variable) && "not a variable");
70 assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
71 assert(
72 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
73 "Expected inlined-at fields to agree");
74 return insertInstr(BuildMI(getMF(), getDL(),
75 getTII().get(TargetOpcode::DBG_VALUE),
76 /*IsIndirect*/ true, Reg, Variable, Expr));
77}
78
80 const MDNode *Variable,
81 const MDNode *Expr) {
82 assert(isa<DILocalVariable>(Variable) && "not a variable");
83 assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
84 assert(
85 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
86 "Expected inlined-at fields to agree");
87 return insertInstr(buildInstrNoInsert(TargetOpcode::DBG_VALUE)
88 .addFrameIndex(FI)
89 .addImm(0)
90 .addMetadata(Variable)
91 .addMetadata(Expr));
92}
93
95 const MDNode *Variable,
96 const MDNode *Expr) {
97 assert(isa<DILocalVariable>(Variable) && "not a variable");
98 assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
99 assert(
100 cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(getDL()) &&
101 "Expected inlined-at fields to agree");
102 auto MIB = buildInstrNoInsert(TargetOpcode::DBG_VALUE);
103
104 auto *NumericConstant = [&] () -> const Constant* {
105 if (const auto *CE = dyn_cast<ConstantExpr>(&C))
106 if (CE->getOpcode() == Instruction::IntToPtr)
107 return CE->getOperand(0);
108 return &C;
109 }();
110
111 if (auto *CI = dyn_cast<ConstantInt>(NumericConstant)) {
112 if (CI->getBitWidth() > 64)
113 MIB.addCImm(CI);
114 else if (CI->getBitWidth() == 1)
115 MIB.addImm(CI->getZExtValue());
116 else
117 MIB.addImm(CI->getSExtValue());
118 } else if (auto *CFP = dyn_cast<ConstantFP>(NumericConstant)) {
119 MIB.addFPImm(CFP);
120 } else if (isa<ConstantPointerNull>(NumericConstant)) {
121 MIB.addImm(0);
122 } else {
123 // Insert $noreg if we didn't find a usable constant and had to drop it.
124 MIB.addReg(Register());
125 }
126
127 MIB.addImm(0).addMetadata(Variable).addMetadata(Expr);
128 return insertInstr(MIB);
129}
130
132 assert(isa<DILabel>(Label) && "not a label");
133 assert(cast<DILabel>(Label)->isValidLocationForIntrinsic(State.DL) &&
134 "Expected inlined-at fields to agree");
135 auto MIB = buildInstr(TargetOpcode::DBG_LABEL);
136
137 return MIB.addMetadata(Label);
138}
139
141 const SrcOp &Size,
142 Align Alignment) {
143 assert(Res.getLLTTy(*getMRI()).isPointer() && "expected ptr dst type");
144 auto MIB = buildInstr(TargetOpcode::G_DYN_STACKALLOC);
145 Res.addDefToMIB(*getMRI(), MIB);
146 Size.addSrcToMIB(MIB);
147 MIB.addImm(Alignment.value());
148 return MIB;
149}
150
152 int Idx) {
153 assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
154 auto MIB = buildInstr(TargetOpcode::G_FRAME_INDEX);
155 Res.addDefToMIB(*getMRI(), MIB);
156 MIB.addFrameIndex(Idx);
157 return MIB;
158}
159
161 const GlobalValue *GV) {
162 assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
164 GV->getType()->getAddressSpace() &&
165 "address space mismatch");
166
167 auto MIB = buildInstr(TargetOpcode::G_GLOBAL_VALUE);
168 Res.addDefToMIB(*getMRI(), MIB);
169 MIB.addGlobalAddress(GV);
170 return MIB;
171}
172
174 unsigned Idx) {
175 assert(Res.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
176 auto MIB = buildInstr(TargetOpcode::G_CONSTANT_POOL);
177 Res.addDefToMIB(*getMRI(), MIB);
178 MIB.addConstantPoolIndex(Idx);
179 return MIB;
180}
181
183 unsigned JTI) {
184 return buildInstr(TargetOpcode::G_JUMP_TABLE, {PtrTy}, {})
185 .addJumpTableIndex(JTI);
186}
187
188void MachineIRBuilder::validateUnaryOp(const LLT Res, const LLT Op0) {
189 assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
190 assert((Res == Op0) && "type mismatch");
191}
192
194 const LLT Op1) {
195 assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
196 assert((Res == Op0 && Res == Op1) && "type mismatch");
197}
198
199void MachineIRBuilder::validateShiftOp(const LLT Res, const LLT Op0,
200 const LLT Op1) {
201 assert((Res.isScalar() || Res.isVector()) && "invalid operand type");
202 assert((Res == Op0) && "type mismatch");
203}
204
207 const SrcOp &Op1, std::optional<unsigned> Flags) {
208 assert(Res.getLLTTy(*getMRI()).isPointerOrPointerVector() &&
209 Res.getLLTTy(*getMRI()) == Op0.getLLTTy(*getMRI()) && "type mismatch");
210 assert(Op1.getLLTTy(*getMRI()).getScalarType().isScalar() && "invalid offset type");
211
212 return buildInstr(TargetOpcode::G_PTR_ADD, {Res}, {Op0, Op1}, Flags);
213}
214
222
223std::optional<MachineInstrBuilder>
225 const LLT ValueTy, uint64_t Value,
226 std::optional<unsigned> Flags) {
227 assert(Res == 0 && "Res is a result argument");
228 assert(ValueTy.isScalar() && "invalid offset type");
229
230 if (Value == 0) {
231 Res = Op0;
232 return std::nullopt;
233 }
234
236 auto Cst = buildConstant(ValueTy, Value);
237 return buildPtrAdd(Res, Op0, Cst.getReg(0), Flags);
238}
239
240std::optional<MachineInstrBuilder> MachineIRBuilder::materializeObjectPtrOffset(
241 Register &Res, Register Op0, const LLT ValueTy, uint64_t Value) {
242 return materializePtrAdd(Res, Op0, ValueTy, Value,
245}
246
248 const SrcOp &Op0,
249 uint32_t NumBits) {
250 LLT PtrTy = Res.getLLTTy(*getMRI());
251 LLT MaskTy = LLT::scalar(PtrTy.getSizeInBits());
252 Register MaskReg = getMRI()->createGenericVirtualRegister(MaskTy);
254 return buildPtrMask(Res, Op0, MaskReg);
255}
256
259 const SrcOp &Op0) {
260 LLT ResTy = Res.getLLTTy(*getMRI());
261 LLT Op0Ty = Op0.getLLTTy(*getMRI());
262
263 assert(ResTy.isVector() && "Res non vector type");
264
266 if (Op0Ty.isVector()) {
267 assert((ResTy.getElementType() == Op0Ty.getElementType()) &&
268 "Different vector element types");
269 assert((ResTy.getNumElements() > Op0Ty.getNumElements()) &&
270 "Op0 has more elements");
271 auto Unmerge = buildUnmerge(Op0Ty.getElementType(), Op0);
272
273 for (auto Op : Unmerge.getInstr()->defs())
274 Regs.push_back(Op.getReg());
275 } else {
276 assert((ResTy.getSizeInBits() > Op0Ty.getSizeInBits()) &&
277 "Op0 has more size");
278 Regs.push_back(Op0.getReg());
279 }
281 buildUndef(Op0Ty.isVector() ? Op0Ty.getElementType() : Op0Ty).getReg(0);
282 unsigned NumberOfPadElts = ResTy.getNumElements() - Regs.size();
283 for (unsigned i = 0; i < NumberOfPadElts; ++i)
284 Regs.push_back(Undef);
285 return buildMergeLikeInstr(Res, Regs);
286}
287
290 const SrcOp &Op0) {
291 LLT ResTy = Res.getLLTTy(*getMRI());
292 LLT Op0Ty = Op0.getLLTTy(*getMRI());
293
294 assert(Op0Ty.isVector() && "Non vector type");
295 assert(((ResTy.isScalar() && (ResTy == Op0Ty.getElementType())) ||
296 (ResTy.isVector() &&
297 (ResTy.getElementType() == Op0Ty.getElementType()))) &&
298 "Different vector element types");
299 assert(
300 (ResTy.isScalar() || (ResTy.getNumElements() < Op0Ty.getNumElements())) &&
301 "Op0 has fewer elements");
302
303 auto Unmerge = buildUnmerge(Op0Ty.getElementType(), Op0);
304 if (ResTy.isScalar())
305 return buildCopy(Res, Unmerge.getReg(0));
307 for (unsigned i = 0; i < ResTy.getNumElements(); ++i)
308 Regs.push_back(Unmerge.getReg(i));
309 return buildMergeLikeInstr(Res, Regs);
310}
311
313 return buildInstr(TargetOpcode::G_BR).addMBB(&Dest);
314}
315
317 assert(getMRI()->getType(Tgt).isPointer() && "invalid branch destination");
318 return buildInstr(TargetOpcode::G_BRINDIRECT).addUse(Tgt);
319}
320
322 unsigned JTI,
323 Register IndexReg) {
324 assert(getMRI()->getType(TablePtr).isPointer() &&
325 "Table reg must be a pointer");
326 return buildInstr(TargetOpcode::G_BRJT)
327 .addUse(TablePtr)
329 .addUse(IndexReg);
330}
331
333 const SrcOp &Op) {
334 return buildInstr(TargetOpcode::COPY, Res, Op);
335}
336
338 const ConstantInt &Val) {
339 assert(!isa<VectorType>(Val.getType()) && "Unexpected vector constant!");
340 LLT Ty = Res.getLLTTy(*getMRI());
341 LLT EltTy = Ty.getScalarType();
342 assert(EltTy.getScalarSizeInBits() == Val.getBitWidth() &&
343 "creating constant with the wrong size");
344
345 assert(!Ty.isScalableVector() &&
346 "unexpected scalable vector in buildConstant");
347
348 if (Ty.isFixedVector()) {
349 auto Const = buildInstr(TargetOpcode::G_CONSTANT)
350 .addDef(getMRI()->createGenericVirtualRegister(EltTy))
351 .addCImm(&Val);
352 return buildSplatBuildVector(Res, Const);
353 }
354
355 auto Const = buildInstr(TargetOpcode::G_CONSTANT);
356 Const->setDebugLoc(DebugLoc());
357 Res.addDefToMIB(*getMRI(), Const);
358 Const.addCImm(&Val);
359 return Const;
360}
361
363 int64_t Val) {
366 // TODO: Avoid implicit trunc?
367 // See https://github.com/llvm/llvm-project/issues/112510.
368 ConstantInt *CI = ConstantInt::getSigned(IntN, Val, /*implicitTrunc=*/true);
369 return buildConstant(Res, *CI);
370}
371
373 const ConstantFP &Val) {
374 assert(!isa<VectorType>(Val.getType()) && "Unexpected vector constant!");
375 LLT Ty = Res.getLLTTy(*getMRI());
376 LLT EltTy = Ty.getScalarType();
377
379 == EltTy.getSizeInBits() &&
380 "creating fconstant with the wrong size");
381
382 assert(!Ty.isPointer() && "invalid operand type");
383
384 assert(!Ty.isScalableVector() &&
385 "unexpected scalable vector in buildFConstant");
386
387 if (Ty.isFixedVector()) {
388 auto Const = buildInstr(TargetOpcode::G_FCONSTANT)
389 .addDef(getMRI()->createGenericVirtualRegister(EltTy))
390 .addFPImm(&Val);
391
392 return buildSplatBuildVector(Res, Const);
393 }
394
395 auto Const = buildInstr(TargetOpcode::G_FCONSTANT);
396 Const->setDebugLoc(DebugLoc());
397 Res.addDefToMIB(*getMRI(), Const);
398 Const.addFPImm(&Val);
399 return Const;
400}
401
403 const APInt &Val) {
404 ConstantInt *CI = ConstantInt::get(getMF().getFunction().getContext(), Val);
405 return buildConstant(Res, *CI);
406}
407
409 double Val) {
410 LLT DstTy = Res.getLLTTy(*getMRI());
411 auto &Ctx = getMF().getFunction().getContext();
412 APFloat APF(Val);
413 bool Ignored;
416 return buildFConstant(Res, *ConstantFP::get(Ctx, APF));
417}
418
420 const APFloat &Val) {
421 auto &Ctx = getMF().getFunction().getContext();
422 auto *CFP = ConstantFP::get(Ctx, Val);
423 return buildFConstant(Res, *CFP);
424}
425
428 const ConstantPtrAuth *CPA,
429 Register Addr, Register AddrDisc) {
430 auto MIB = buildInstr(TargetOpcode::G_PTRAUTH_GLOBAL_VALUE);
431 Res.addDefToMIB(*getMRI(), MIB);
432 MIB.addUse(Addr);
433 MIB.addImm(CPA->getKey()->getZExtValue());
434 MIB.addUse(AddrDisc);
435 MIB.addImm(CPA->getDiscriminator()->getZExtValue());
436 return MIB;
437}
438
440 MachineBasicBlock &Dest) {
441 assert(Tst.getLLTTy(*getMRI()).isScalar() && "invalid operand type");
442
443 auto MIB = buildInstr(TargetOpcode::G_BRCOND);
444 Tst.addSrcToMIB(MIB);
445 MIB.addMBB(&Dest);
446 return MIB;
447}
448
451 MachinePointerInfo PtrInfo, Align Alignment,
453 const AAMDNodes &AAInfo) {
454 MMOFlags |= MachineMemOperand::MOLoad;
455 assert((MMOFlags & MachineMemOperand::MOStore) == 0);
456
457 LLT Ty = Dst.getLLTTy(*getMRI());
458 MachineMemOperand *MMO =
459 getMF().getMachineMemOperand(PtrInfo, MMOFlags, Ty, Alignment, AAInfo);
460 return buildLoad(Dst, Addr, *MMO);
461}
462
464 const DstOp &Res,
465 const SrcOp &Addr,
466 MachineMemOperand &MMO) {
467 assert(Res.getLLTTy(*getMRI()).isValid() && "invalid operand type");
468 assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
469
470 auto MIB = buildInstr(Opcode);
471 Res.addDefToMIB(*getMRI(), MIB);
472 Addr.addSrcToMIB(MIB);
473 MIB.addMemOperand(&MMO);
474 return MIB;
475}
476
478 const DstOp &Dst, const SrcOp &BasePtr,
479 MachineMemOperand &BaseMMO, int64_t Offset) {
480 LLT LoadTy = Dst.getLLTTy(*getMRI());
481 MachineMemOperand *OffsetMMO =
482 getMF().getMachineMemOperand(&BaseMMO, Offset, LoadTy);
483
484 if (Offset == 0) // This may be a size or type changing load.
485 return buildLoad(Dst, BasePtr, *OffsetMMO);
486
487 LLT PtrTy = BasePtr.getLLTTy(*getMRI());
488 LLT OffsetTy = LLT::scalar(PtrTy.getSizeInBits());
489 auto ConstOffset = buildConstant(OffsetTy, Offset);
490 auto Ptr = buildPtrAdd(PtrTy, BasePtr, ConstOffset);
491 return buildLoad(Dst, Ptr, *OffsetMMO);
492}
493
495 const SrcOp &Addr,
496 MachineMemOperand &MMO) {
497 assert(Val.getLLTTy(*getMRI()).isValid() && "invalid operand type");
498 assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
499
500 auto MIB = buildInstr(TargetOpcode::G_STORE);
501 Val.addSrcToMIB(MIB);
502 Addr.addSrcToMIB(MIB);
503 MIB.addMemOperand(&MMO);
504 return MIB;
505}
506
508 const SrcOp &Val,
509 const SrcOp &Addr,
510 MachineMemOperand &MMO) {
511 assert(Val.getLLTTy(*getMRI()).isValid() && "invalid operand type");
512 assert(Addr.getLLTTy(*getMRI()).isPointer() && "invalid operand type");
513
514 auto MIB = buildInstr(Opcode);
515 Val.addSrcToMIB(MIB);
516 Addr.addSrcToMIB(MIB);
517 MIB.addMemOperand(&MMO);
518 return MIB;
519}
520
523 MachinePointerInfo PtrInfo, Align Alignment,
525 const AAMDNodes &AAInfo) {
526 MMOFlags |= MachineMemOperand::MOStore;
527 assert((MMOFlags & MachineMemOperand::MOLoad) == 0);
528
529 LLT Ty = Val.getLLTTy(*getMRI());
530 MachineMemOperand *MMO =
531 getMF().getMachineMemOperand(PtrInfo, MMOFlags, Ty, Alignment, AAInfo);
532 return buildStore(Val, Addr, *MMO);
533}
534
536 const SrcOp &Op) {
537 return buildInstr(TargetOpcode::G_ANYEXT, Res, Op);
538}
539
541 const SrcOp &Op) {
542 return buildInstr(TargetOpcode::G_SEXT, Res, Op);
543}
544
546 const SrcOp &Op,
547 std::optional<unsigned> Flags) {
548 return buildInstr(TargetOpcode::G_ZEXT, Res, Op, Flags);
549}
550
551unsigned MachineIRBuilder::getBoolExtOp(bool IsVec, bool IsFP) const {
552 const auto *TLI = getMF().getSubtarget().getTargetLowering();
553 switch (TLI->getBooleanContents(IsVec, IsFP)) {
555 return TargetOpcode::G_SEXT;
557 return TargetOpcode::G_ZEXT;
558 default:
559 return TargetOpcode::G_ANYEXT;
560 }
561}
562
564 const SrcOp &Op,
565 bool IsFP) {
566 unsigned ExtOp = getBoolExtOp(getMRI()->getType(Op.getReg()).isVector(), IsFP);
567 return buildInstr(ExtOp, Res, Op);
568}
569
571 const SrcOp &Op,
572 bool IsVector,
573 bool IsFP) {
574 const auto *TLI = getMF().getSubtarget().getTargetLowering();
575 switch (TLI->getBooleanContents(IsVector, IsFP)) {
577 return buildSExtInReg(Res, Op, 1);
579 return buildZExtInReg(Res, Op, 1);
581 return buildCopy(Res, Op);
582 }
583
584 llvm_unreachable("unexpected BooleanContent");
585}
586
588 const DstOp &Res,
589 const SrcOp &Op) {
590 assert((TargetOpcode::G_ANYEXT == ExtOpc || TargetOpcode::G_ZEXT == ExtOpc ||
591 TargetOpcode::G_SEXT == ExtOpc) &&
592 "Expecting Extending Opc");
593 assert(Res.getLLTTy(*getMRI()).isScalar() ||
594 Res.getLLTTy(*getMRI()).isVector());
595 assert(Res.getLLTTy(*getMRI()).isScalar() ==
596 Op.getLLTTy(*getMRI()).isScalar());
597
598 unsigned Opcode = TargetOpcode::COPY;
599 if (Res.getLLTTy(*getMRI()).getSizeInBits() >
600 Op.getLLTTy(*getMRI()).getSizeInBits())
601 Opcode = ExtOpc;
602 else if (Res.getLLTTy(*getMRI()).getSizeInBits() <
603 Op.getLLTTy(*getMRI()).getSizeInBits())
604 Opcode = TargetOpcode::G_TRUNC;
605 else
606 assert(Res.getLLTTy(*getMRI()).getSizeInBits() ==
607 Op.getLLTTy(*getMRI()).getSizeInBits());
608
609 return buildInstr(Opcode, Res, Op);
610}
611
613 const SrcOp &Op) {
614 return buildExtOrTrunc(TargetOpcode::G_SEXT, Res, Op);
615}
616
618 const SrcOp &Op) {
619 return buildExtOrTrunc(TargetOpcode::G_ZEXT, Res, Op);
620}
621
623 const SrcOp &Op) {
624 return buildExtOrTrunc(TargetOpcode::G_ANYEXT, Res, Op);
625}
626
628 const SrcOp &Op,
629 int64_t ImmOp) {
630 LLT ResTy = Res.getLLTTy(*getMRI());
631 auto Mask = buildConstant(
632 ResTy, APInt::getLowBitsSet(ResTy.getScalarSizeInBits(), ImmOp));
633 return buildAnd(Res, Op, Mask);
634}
635
637 const SrcOp &Src) {
638 LLT SrcTy = Src.getLLTTy(*getMRI());
639 LLT DstTy = Dst.getLLTTy(*getMRI());
640 if (SrcTy == DstTy)
641 return buildCopy(Dst, Src);
642
643 unsigned Opcode;
644 if (SrcTy.isPointerOrPointerVector())
645 Opcode = TargetOpcode::G_PTRTOINT;
646 else if (DstTy.isPointerOrPointerVector())
647 Opcode = TargetOpcode::G_INTTOPTR;
648 else {
649 assert(!SrcTy.isPointerOrPointerVector() &&
650 !DstTy.isPointerOrPointerVector() && "no G_ADDRCAST yet");
651 Opcode = TargetOpcode::G_BITCAST;
652 }
653
654 return buildInstr(Opcode, Dst, Src);
655}
656
658 const SrcOp &Src,
659 uint64_t Index) {
660 LLT SrcTy = Src.getLLTTy(*getMRI());
661 LLT DstTy = Dst.getLLTTy(*getMRI());
662
663#ifndef NDEBUG
664 assert(SrcTy.isValid() && "invalid operand type");
665 assert(DstTy.isValid() && "invalid operand type");
666 assert(Index + DstTy.getSizeInBits() <= SrcTy.getSizeInBits() &&
667 "extracting off end of register");
668#endif
669
670 if (DstTy.getSizeInBits() == SrcTy.getSizeInBits()) {
671 assert(Index == 0 && "insertion past the end of a register");
672 return buildCast(Dst, Src);
673 }
674
675 auto Extract = buildInstr(TargetOpcode::G_EXTRACT);
676 Dst.addDefToMIB(*getMRI(), Extract);
677 Src.addSrcToMIB(Extract);
678 Extract.addImm(Index);
679 return Extract;
680}
681
683 return buildInstr(TargetOpcode::G_IMPLICIT_DEF, {Res}, {});
684}
685
688 // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
689 // we need some temporary storage for the DstOp objects. Here we use a
690 // sufficiently large SmallVector to not go through the heap.
692 assert(TmpVec.size() > 1);
693 return buildInstr(TargetOpcode::G_MERGE_VALUES, Res, TmpVec);
694}
695
699 // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<SrcOp>,
700 // we need some temporary storage for the DstOp objects. Here we use a
701 // sufficiently large SmallVector to not go through the heap.
703 assert(TmpVec.size() > 1);
704 return buildInstr(getOpcodeForMerge(Res, TmpVec), Res, TmpVec);
705}
706
709 std::initializer_list<SrcOp> Ops) {
710 assert(Ops.size() > 1);
711 return buildInstr(getOpcodeForMerge(Res, Ops), Res, Ops);
712}
713
714unsigned MachineIRBuilder::getOpcodeForMerge(const DstOp &DstOp,
715 ArrayRef<SrcOp> SrcOps) const {
716 if (DstOp.getLLTTy(*getMRI()).isVector()) {
717 if (SrcOps[0].getLLTTy(*getMRI()).isVector())
718 return TargetOpcode::G_CONCAT_VECTORS;
719 return TargetOpcode::G_BUILD_VECTOR;
720 }
721
722 return TargetOpcode::G_MERGE_VALUES;
723}
724
726 const SrcOp &Op) {
727 // Unfortunately to convert from ArrayRef<LLT> to ArrayRef<DstOp>,
728 // we need some temporary storage for the DstOp objects. Here we use a
729 // sufficiently large SmallVector to not go through the heap.
730 SmallVector<DstOp, 8> TmpVec(Res);
731 assert(TmpVec.size() > 1);
732 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
733}
734
736 const SrcOp &Op) {
737 unsigned NumReg = Op.getLLTTy(*getMRI()).getSizeInBits() / Res.getSizeInBits();
738 SmallVector<DstOp, 8> TmpVec(NumReg, Res);
739 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
740}
741
744 const SrcOp &Op) {
745 LLT OpTy = Op.getLLTTy(*getMRI());
746 unsigned NumRegs = OpTy.getSizeInBits() / Attrs.Ty.getSizeInBits();
747 SmallVector<DstOp, 8> TmpVec(NumRegs, Attrs);
748 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
749}
750
752 const SrcOp &Op) {
753 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<DstOp>,
754 // we need some temporary storage for the DstOp objects. Here we use a
755 // sufficiently large SmallVector to not go through the heap.
756 SmallVector<DstOp, 8> TmpVec(Res);
757 assert(TmpVec.size() > 1);
758 return buildInstr(TargetOpcode::G_UNMERGE_VALUES, TmpVec, Op);
759}
760
763 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
764 // we need some temporary storage for the DstOp objects. Here we use a
765 // sufficiently large SmallVector to not go through the heap.
767 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
768}
769
773 SmallVector<SrcOp> TmpVec;
774 TmpVec.reserve(Ops.size());
775 LLT EltTy = Res.getLLTTy(*getMRI()).getElementType();
776 for (const auto &Op : Ops)
777 TmpVec.push_back(buildConstant(EltTy, Op));
778 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
779}
780
782 const SrcOp &Src) {
783 SmallVector<SrcOp, 8> TmpVec(Res.getLLTTy(*getMRI()).getNumElements(), Src);
784 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
785}
786
790 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
791 // we need some temporary storage for the DstOp objects. Here we use a
792 // sufficiently large SmallVector to not go through the heap.
794 if (TmpVec[0].getLLTTy(*getMRI()).getSizeInBits() ==
795 Res.getLLTTy(*getMRI()).getElementType().getSizeInBits())
796 return buildInstr(TargetOpcode::G_BUILD_VECTOR, Res, TmpVec);
797 return buildInstr(TargetOpcode::G_BUILD_VECTOR_TRUNC, Res, TmpVec);
798}
799
801 const SrcOp &Src) {
802 LLT DstTy = Res.getLLTTy(*getMRI());
803 assert(Src.getLLTTy(*getMRI()) == DstTy.getElementType() &&
804 "Expected Src to match Dst elt ty");
805 auto UndefVec = buildUndef(DstTy);
806 auto Zero = buildConstant(LLT::integer(64), 0);
807 auto InsElt = buildInsertVectorElement(DstTy, UndefVec, Src, Zero);
808 SmallVector<int, 16> ZeroMask(DstTy.getNumElements());
809 return buildShuffleVector(DstTy, InsElt, UndefVec, ZeroMask);
810}
811
813 const SrcOp &Src) {
814 assert(Src.getLLTTy(*getMRI()) == Res.getLLTTy(*getMRI()).getElementType() &&
815 "Expected Src to match Dst elt ty");
816 return buildInstr(TargetOpcode::G_SPLAT_VECTOR, Res, Src);
817}
818
820 const SrcOp &Src1,
821 const SrcOp &Src2,
822 ArrayRef<int> Mask) {
823 LLT DstTy = Res.getLLTTy(*getMRI());
824 LLT Src1Ty = Src1.getLLTTy(*getMRI());
825 LLT Src2Ty = Src2.getLLTTy(*getMRI());
826 const LLT DstElemTy = DstTy.getScalarType();
827 const LLT ElemTy1 = Src1Ty.getScalarType();
828 const LLT ElemTy2 = Src2Ty.getScalarType();
829 assert(DstElemTy == ElemTy1 && DstElemTy == ElemTy2);
830 assert(Mask.size() > 1 && "Scalar G_SHUFFLE_VECTOR are not supported");
831 (void)DstElemTy;
832 (void)ElemTy1;
833 (void)ElemTy2;
834 ArrayRef<int> MaskAlloc = getMF().allocateShuffleMask(Mask);
835 return buildInstr(TargetOpcode::G_SHUFFLE_VECTOR, {Res}, {Src1, Src2})
836 .addShuffleMask(MaskAlloc);
837}
838
841 // Unfortunately to convert from ArrayRef<Register> to ArrayRef<SrcOp>,
842 // we need some temporary storage for the DstOp objects. Here we use a
843 // sufficiently large SmallVector to not go through the heap.
845 return buildInstr(TargetOpcode::G_CONCAT_VECTORS, Res, TmpVec);
846}
847
849 const SrcOp &Src,
850 const SrcOp &Op,
851 unsigned Index) {
852 assert(Index + Op.getLLTTy(*getMRI()).getSizeInBits() <=
853 Res.getLLTTy(*getMRI()).getSizeInBits() &&
854 "insertion past the end of a register");
855
856 if (Res.getLLTTy(*getMRI()).getSizeInBits() ==
857 Op.getLLTTy(*getMRI()).getSizeInBits()) {
858 return buildCast(Res, Op);
859 }
860
861 return buildInstr(TargetOpcode::G_INSERT, Res, {Src, Op, uint64_t(Index)});
862}
863
865 unsigned Step) {
866 unsigned Bitwidth = Res.getLLTTy(*getMRI()).getElementType().getSizeInBits();
867 ConstantInt *CI = ConstantInt::get(getMF().getFunction().getContext(),
868 APInt(Bitwidth, Step));
869 auto StepVector = buildInstr(TargetOpcode::G_STEP_VECTOR);
870 StepVector->setDebugLoc(DebugLoc());
871 Res.addDefToMIB(*getMRI(), StepVector);
872 StepVector.addCImm(CI);
873 return StepVector;
874}
875
877 unsigned MinElts) {
878
881 ConstantInt *CI = ConstantInt::get(IntN, MinElts);
882 return buildVScale(Res, *CI);
883}
884
886 const ConstantInt &MinElts) {
887 auto VScale = buildInstr(TargetOpcode::G_VSCALE);
888 VScale->setDebugLoc(DebugLoc());
889 Res.addDefToMIB(*getMRI(), VScale);
890 VScale.addCImm(&MinElts);
891 return VScale;
892}
893
895 const APInt &MinElts) {
896 ConstantInt *CI =
897 ConstantInt::get(getMF().getFunction().getContext(), MinElts);
898 return buildVScale(Res, *CI);
899}
900
901static unsigned getIntrinsicOpcode(bool HasSideEffects, bool IsConvergent) {
902 if (HasSideEffects && IsConvergent)
903 return TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS;
904 if (HasSideEffects)
905 return TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS;
906 if (IsConvergent)
907 return TargetOpcode::G_INTRINSIC_CONVERGENT;
908 return TargetOpcode::G_INTRINSIC;
909}
910
913 ArrayRef<Register> ResultRegs,
914 bool HasSideEffects, bool isConvergent) {
915 auto MIB = buildInstr(getIntrinsicOpcode(HasSideEffects, isConvergent));
916 for (Register ResultReg : ResultRegs)
917 MIB.addDef(ResultReg);
918 MIB.addIntrinsicID(ID);
919 return MIB;
920}
921
924 ArrayRef<Register> ResultRegs) {
926 bool HasSideEffects = !Attrs.getMemoryEffects().doesNotAccessMemory();
927 bool isConvergent = Attrs.hasAttribute(Attribute::Convergent);
928 return buildIntrinsic(ID, ResultRegs, HasSideEffects, isConvergent);
929}
930
933 bool HasSideEffects,
934 bool isConvergent) {
935 auto MIB = buildInstr(getIntrinsicOpcode(HasSideEffects, isConvergent));
936 for (DstOp Result : Results)
937 Result.addDefToMIB(*getMRI(), MIB);
938 MIB.addIntrinsicID(ID);
939 return MIB;
940}
941
945 bool HasSideEffects = !Attrs.getMemoryEffects().doesNotAccessMemory();
946 bool isConvergent = Attrs.hasAttribute(Attribute::Convergent);
947 return buildIntrinsic(ID, Results, HasSideEffects, isConvergent);
948}
949
952 std::optional<unsigned> Flags) {
953 return buildInstr(TargetOpcode::G_TRUNC, Res, Op, Flags);
954}
955
958 std::optional<unsigned> Flags) {
959 return buildInstr(TargetOpcode::G_FPTRUNC, Res, Op, Flags);
960}
961
963 const DstOp &Res,
964 const SrcOp &Op0,
965 const SrcOp &Op1,
966 std::optional<unsigned> Flags) {
967 return buildInstr(TargetOpcode::G_ICMP, Res, {Pred, Op0, Op1}, Flags);
968}
969
971 const DstOp &Res,
972 const SrcOp &Op0,
973 const SrcOp &Op1,
974 std::optional<unsigned> Flags) {
975
976 return buildInstr(TargetOpcode::G_FCMP, Res, {Pred, Op0, Op1}, Flags);
977}
978
980 const SrcOp &Op0,
981 const SrcOp &Op1) {
982 return buildInstr(TargetOpcode::G_SCMP, Res, {Op0, Op1});
983}
984
986 const SrcOp &Op0,
987 const SrcOp &Op1) {
988 return buildInstr(TargetOpcode::G_UCMP, Res, {Op0, Op1});
989}
990
993 const SrcOp &Op0, const SrcOp &Op1,
994 std::optional<unsigned> Flags) {
995
996 return buildInstr(TargetOpcode::G_SELECT, {Res}, {Tst, Op0, Op1}, Flags);
997}
998
1000 const SrcOp &Src0,
1001 const SrcOp &Src1,
1002 unsigned Idx) {
1003 return buildInstr(TargetOpcode::G_INSERT_SUBVECTOR, Res,
1004 {Src0, Src1, uint64_t(Idx)});
1005}
1006
1008 const SrcOp &Src,
1009 unsigned Idx) {
1010 return buildInstr(TargetOpcode::G_EXTRACT_SUBVECTOR, Res,
1011 {Src, uint64_t(Idx)});
1012}
1013
1016 const SrcOp &Elt, const SrcOp &Idx) {
1017 return buildInstr(TargetOpcode::G_INSERT_VECTOR_ELT, Res, {Val, Elt, Idx});
1018}
1019
1022 const SrcOp &Idx) {
1023 return buildInstr(TargetOpcode::G_EXTRACT_VECTOR_ELT, Res, {Val, Idx});
1024}
1025
1027 const DstOp &OldValRes, const DstOp &SuccessRes, const SrcOp &Addr,
1028 const SrcOp &CmpVal, const SrcOp &NewVal, MachineMemOperand &MMO) {
1029#ifndef NDEBUG
1030 LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
1031 LLT SuccessResTy = SuccessRes.getLLTTy(*getMRI());
1032 LLT AddrTy = Addr.getLLTTy(*getMRI());
1033 LLT CmpValTy = CmpVal.getLLTTy(*getMRI());
1034 LLT NewValTy = NewVal.getLLTTy(*getMRI());
1035 assert(OldValResTy.isScalar() && "invalid operand type");
1036 assert(SuccessResTy.isScalar() && "invalid operand type");
1037 assert(AddrTy.isPointer() && "invalid operand type");
1038 assert(CmpValTy.isValid() && "invalid operand type");
1039 assert(NewValTy.isValid() && "invalid operand type");
1040 assert(OldValResTy == CmpValTy && "type mismatch");
1041 assert(OldValResTy == NewValTy && "type mismatch");
1042#endif
1043
1044 auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS);
1045 OldValRes.addDefToMIB(*getMRI(), MIB);
1046 SuccessRes.addDefToMIB(*getMRI(), MIB);
1047 Addr.addSrcToMIB(MIB);
1048 CmpVal.addSrcToMIB(MIB);
1049 NewVal.addSrcToMIB(MIB);
1050 MIB.addMemOperand(&MMO);
1051 return MIB;
1052}
1053
1056 const SrcOp &CmpVal, const SrcOp &NewVal,
1057 MachineMemOperand &MMO) {
1058#ifndef NDEBUG
1059 LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
1060 LLT AddrTy = Addr.getLLTTy(*getMRI());
1061 LLT CmpValTy = CmpVal.getLLTTy(*getMRI());
1062 LLT NewValTy = NewVal.getLLTTy(*getMRI());
1063 assert(OldValResTy.isScalar() && "invalid operand type");
1064 assert(AddrTy.isPointer() && "invalid operand type");
1065 assert(CmpValTy.isValid() && "invalid operand type");
1066 assert(NewValTy.isValid() && "invalid operand type");
1067 assert(OldValResTy == CmpValTy && "type mismatch");
1068 assert(OldValResTy == NewValTy && "type mismatch");
1069#endif
1070
1071 auto MIB = buildInstr(TargetOpcode::G_ATOMIC_CMPXCHG);
1072 OldValRes.addDefToMIB(*getMRI(), MIB);
1073 Addr.addSrcToMIB(MIB);
1074 CmpVal.addSrcToMIB(MIB);
1075 NewVal.addSrcToMIB(MIB);
1076 MIB.addMemOperand(&MMO);
1077 return MIB;
1078}
1079
1081 unsigned Opcode, const DstOp &OldValRes,
1082 const SrcOp &Addr, const SrcOp &Val,
1083 MachineMemOperand &MMO) {
1084
1085#ifndef NDEBUG
1086 LLT OldValResTy = OldValRes.getLLTTy(*getMRI());
1087 LLT AddrTy = Addr.getLLTTy(*getMRI());
1088 LLT ValTy = Val.getLLTTy(*getMRI());
1089 assert(AddrTy.isPointer() && "invalid operand type");
1090 assert(ValTy.isValid() && "invalid operand type");
1091 assert(OldValResTy == ValTy && "type mismatch");
1092 assert(MMO.isAtomic() && "not atomic mem operand");
1093#endif
1094
1095 auto MIB = buildInstr(Opcode);
1096 OldValRes.addDefToMIB(*getMRI(), MIB);
1097 Addr.addSrcToMIB(MIB);
1098 Val.addSrcToMIB(MIB);
1099 MIB.addMemOperand(&MMO);
1100 return MIB;
1101}
1102
1105 Register Val, MachineMemOperand &MMO) {
1106 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XCHG, OldValRes, Addr, Val,
1107 MMO);
1108}
1111 Register Val, MachineMemOperand &MMO) {
1112 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_ADD, OldValRes, Addr, Val,
1113 MMO);
1114}
1117 Register Val, MachineMemOperand &MMO) {
1118 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_SUB, OldValRes, Addr, Val,
1119 MMO);
1120}
1123 Register Val, MachineMemOperand &MMO) {
1124 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_AND, OldValRes, Addr, Val,
1125 MMO);
1126}
1129 Register Val, MachineMemOperand &MMO) {
1130 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_NAND, OldValRes, Addr, Val,
1131 MMO);
1132}
1134 Register Addr,
1135 Register Val,
1136 MachineMemOperand &MMO) {
1137 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_OR, OldValRes, Addr, Val,
1138 MMO);
1139}
1142 Register Val, MachineMemOperand &MMO) {
1143 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_XOR, OldValRes, Addr, Val,
1144 MMO);
1145}
1148 Register Val, MachineMemOperand &MMO) {
1149 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MAX, OldValRes, Addr, Val,
1150 MMO);
1151}
1154 Register Val, MachineMemOperand &MMO) {
1155 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_MIN, OldValRes, Addr, Val,
1156 MMO);
1157}
1160 Register Val, MachineMemOperand &MMO) {
1161 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMAX, OldValRes, Addr, Val,
1162 MMO);
1163}
1166 Register Val, MachineMemOperand &MMO) {
1167 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_UMIN, OldValRes, Addr, Val,
1168 MMO);
1169}
1170
1173 const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
1174 MachineMemOperand &MMO) {
1175 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FADD, OldValRes, Addr, Val,
1176 MMO);
1177}
1178
1180MachineIRBuilder::buildAtomicRMWFSub(const DstOp &OldValRes, const SrcOp &Addr, const SrcOp &Val,
1181 MachineMemOperand &MMO) {
1182 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FSUB, OldValRes, Addr, Val,
1183 MMO);
1184}
1185
1188 const SrcOp &Val, MachineMemOperand &MMO) {
1189 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMAX, OldValRes, Addr, Val,
1190 MMO);
1191}
1192
1195 const SrcOp &Val, MachineMemOperand &MMO) {
1196 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMIN, OldValRes, Addr, Val,
1197 MMO);
1198}
1199
1202 const SrcOp &Addr, const SrcOp &Val,
1203 MachineMemOperand &MMO) {
1204 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMAXIMUM, OldValRes, Addr,
1205 Val, MMO);
1206}
1207
1210 const SrcOp &Addr, const SrcOp &Val,
1211 MachineMemOperand &MMO) {
1212 return buildAtomicRMW(TargetOpcode::G_ATOMICRMW_FMINIMUM, OldValRes, Addr,
1213 Val, MMO);
1214}
1215
1217MachineIRBuilder::buildFence(unsigned Ordering, unsigned Scope) {
1218 return buildInstr(TargetOpcode::G_FENCE)
1219 .addImm(Ordering)
1220 .addImm(Scope);
1221}
1222
1224 unsigned RW,
1225 unsigned Locality,
1226 unsigned CacheType,
1227 MachineMemOperand &MMO) {
1228 auto MIB = buildInstr(TargetOpcode::G_PREFETCH);
1229 Addr.addSrcToMIB(MIB);
1230 MIB.addImm(RW).addImm(Locality).addImm(CacheType);
1231 MIB.addMemOperand(&MMO);
1232 return MIB;
1233}
1234
1237#ifndef NDEBUG
1238 assert(getMRI()->getType(Res).isPointer() && "invalid res type");
1239#endif
1240
1241 return buildInstr(TargetOpcode::G_BLOCK_ADDR).addDef(Res).addBlockAddress(BA);
1242}
1243
1244void MachineIRBuilder::validateTruncExt(const LLT DstTy, const LLT SrcTy,
1245 bool IsExtend) {
1246#ifndef NDEBUG
1247 if (DstTy.isVector()) {
1248 assert(SrcTy.isVector() && "mismatched cast between vector and non-vector");
1249 assert(SrcTy.getElementCount() == DstTy.getElementCount() &&
1250 "different number of elements in a trunc/ext");
1251 } else
1252 assert(DstTy.isScalar() && SrcTy.isScalar() && "invalid extend/trunc");
1253
1254 if (IsExtend)
1255 assert(TypeSize::isKnownGT(DstTy.getSizeInBits(), SrcTy.getSizeInBits()) &&
1256 "invalid narrowing extend");
1257 else
1258 assert(TypeSize::isKnownLT(DstTy.getSizeInBits(), SrcTy.getSizeInBits()) &&
1259 "invalid widening trunc");
1260#endif
1261}
1262
1263void MachineIRBuilder::validateSelectOp(const LLT ResTy, const LLT TstTy,
1264 const LLT Op0Ty, const LLT Op1Ty) {
1265#ifndef NDEBUG
1266 assert((ResTy.isScalar() || ResTy.isVector() || ResTy.isPointer()) &&
1267 "invalid operand type");
1268 assert((ResTy == Op0Ty && ResTy == Op1Ty) && "type mismatch");
1269 if (ResTy.isScalar() || ResTy.isPointer())
1270 assert(TstTy.isScalar() && "type mismatch");
1271 else
1272 assert((TstTy.isScalar() ||
1273 (TstTy.isVector() &&
1274 TstTy.getElementCount() == Op0Ty.getElementCount())) &&
1275 "type mismatch");
1276#endif
1277}
1278
1281 ArrayRef<SrcOp> SrcOps,
1282 std::optional<unsigned> Flags) {
1283 switch (Opc) {
1284 default:
1285 break;
1286 case TargetOpcode::G_SELECT: {
1287 assert(DstOps.size() == 1 && "Invalid select");
1288 assert(SrcOps.size() == 3 && "Invalid select");
1290 DstOps[0].getLLTTy(*getMRI()), SrcOps[0].getLLTTy(*getMRI()),
1291 SrcOps[1].getLLTTy(*getMRI()), SrcOps[2].getLLTTy(*getMRI()));
1292 break;
1293 }
1294 case TargetOpcode::G_FNEG:
1295 case TargetOpcode::G_ABS:
1296 // All these are unary ops.
1297 assert(DstOps.size() == 1 && "Invalid Dst");
1298 assert(SrcOps.size() == 1 && "Invalid Srcs");
1299 validateUnaryOp(DstOps[0].getLLTTy(*getMRI()),
1300 SrcOps[0].getLLTTy(*getMRI()));
1301 break;
1302 case TargetOpcode::G_ADD:
1303 case TargetOpcode::G_AND:
1304 case TargetOpcode::G_MUL:
1305 case TargetOpcode::G_OR:
1306 case TargetOpcode::G_SUB:
1307 case TargetOpcode::G_XOR:
1308 case TargetOpcode::G_UDIV:
1309 case TargetOpcode::G_SDIV:
1310 case TargetOpcode::G_UREM:
1311 case TargetOpcode::G_SREM:
1312 case TargetOpcode::G_SMIN:
1313 case TargetOpcode::G_SMAX:
1314 case TargetOpcode::G_UMIN:
1315 case TargetOpcode::G_UMAX:
1316 case TargetOpcode::G_UADDSAT:
1317 case TargetOpcode::G_SADDSAT:
1318 case TargetOpcode::G_USUBSAT:
1319 case TargetOpcode::G_SSUBSAT: {
1320 // All these are binary ops.
1321 assert(DstOps.size() == 1 && "Invalid Dst");
1322 assert(SrcOps.size() == 2 && "Invalid Srcs");
1323 validateBinaryOp(DstOps[0].getLLTTy(*getMRI()),
1324 SrcOps[0].getLLTTy(*getMRI()),
1325 SrcOps[1].getLLTTy(*getMRI()));
1326 break;
1327 }
1328 case TargetOpcode::G_SHL:
1329 case TargetOpcode::G_ASHR:
1330 case TargetOpcode::G_LSHR:
1331 case TargetOpcode::G_USHLSAT:
1332 case TargetOpcode::G_SSHLSAT: {
1333 assert(DstOps.size() == 1 && "Invalid Dst");
1334 assert(SrcOps.size() == 2 && "Invalid Srcs");
1335 validateShiftOp(DstOps[0].getLLTTy(*getMRI()),
1336 SrcOps[0].getLLTTy(*getMRI()),
1337 SrcOps[1].getLLTTy(*getMRI()));
1338 break;
1339 }
1340 case TargetOpcode::G_SEXT:
1341 case TargetOpcode::G_ZEXT:
1342 case TargetOpcode::G_ANYEXT:
1343 assert(DstOps.size() == 1 && "Invalid Dst");
1344 assert(SrcOps.size() == 1 && "Invalid Srcs");
1345 validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
1346 SrcOps[0].getLLTTy(*getMRI()), true);
1347 break;
1348 case TargetOpcode::G_TRUNC:
1349 case TargetOpcode::G_FPTRUNC: {
1350 assert(DstOps.size() == 1 && "Invalid Dst");
1351 assert(SrcOps.size() == 1 && "Invalid Srcs");
1352 validateTruncExt(DstOps[0].getLLTTy(*getMRI()),
1353 SrcOps[0].getLLTTy(*getMRI()), false);
1354 break;
1355 }
1356 case TargetOpcode::G_BITCAST: {
1357 assert(DstOps.size() == 1 && "Invalid Dst");
1358 assert(SrcOps.size() == 1 && "Invalid Srcs");
1359 assert(DstOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1360 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() && "invalid bitcast");
1361 break;
1362 }
1363 case TargetOpcode::COPY:
1364 assert(DstOps.size() == 1 && "Invalid Dst");
1365 // If the caller wants to add a subreg source it has to be done separately
1366 // so we may not have any SrcOps at this point yet.
1367 break;
1368 case TargetOpcode::G_FCMP:
1369 case TargetOpcode::G_ICMP: {
1370 assert(DstOps.size() == 1 && "Invalid Dst Operands");
1371 assert(SrcOps.size() == 3 && "Invalid Src Operands");
1372 // For F/ICMP, the first src operand is the predicate, followed by
1373 // the two comparands.
1374 assert(SrcOps[0].getSrcOpKind() == SrcOp::SrcType::Ty_Predicate &&
1375 "Expecting predicate");
1376 assert([&]() -> bool {
1377 CmpInst::Predicate Pred = SrcOps[0].getPredicate();
1378 return Opc == TargetOpcode::G_ICMP ? CmpInst::isIntPredicate(Pred)
1379 : CmpInst::isFPPredicate(Pred);
1380 }() && "Invalid predicate");
1381 assert(SrcOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
1382 "Type mismatch");
1383 assert([&]() -> bool {
1384 LLT Op0Ty = SrcOps[1].getLLTTy(*getMRI());
1385 LLT DstTy = DstOps[0].getLLTTy(*getMRI());
1386 if (Op0Ty.isScalar() || Op0Ty.isPointer())
1387 return DstTy.isScalar();
1388 else
1389 return DstTy.isVector() &&
1390 DstTy.getElementCount() == Op0Ty.getElementCount();
1391 }() && "Type Mismatch");
1392 break;
1393 }
1394 case TargetOpcode::G_UNMERGE_VALUES: {
1395 assert(!DstOps.empty() && "Invalid trivial sequence");
1396 assert(SrcOps.size() == 1 && "Invalid src for Unmerge");
1397 assert(llvm::all_of(DstOps,
1398 [&, this](const DstOp &Op) {
1399 return Op.getLLTTy(*getMRI()) ==
1400 DstOps[0].getLLTTy(*getMRI());
1401 }) &&
1402 "type mismatch in output list");
1403 assert((TypeSize::ScalarTy)DstOps.size() *
1404 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1405 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1406 "input operands do not cover output register");
1407 break;
1408 }
1409 case TargetOpcode::G_MERGE_VALUES: {
1410 assert(SrcOps.size() >= 2 && "invalid trivial sequence");
1411 assert(DstOps.size() == 1 && "Invalid Dst");
1412 assert(llvm::all_of(SrcOps,
1413 [&, this](const SrcOp &Op) {
1414 return Op.getLLTTy(*getMRI()) ==
1415 SrcOps[0].getLLTTy(*getMRI());
1416 }) &&
1417 "type mismatch in input list");
1418 assert((TypeSize::ScalarTy)SrcOps.size() *
1419 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1420 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1421 "input operands do not cover output register");
1422 assert(!DstOps[0].getLLTTy(*getMRI()).isVector() &&
1423 "vectors should be built with G_CONCAT_VECTOR or G_BUILD_VECTOR");
1424 break;
1425 }
1426 case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
1427 assert(DstOps.size() == 1 && "Invalid Dst size");
1428 assert(SrcOps.size() == 2 && "Invalid Src size");
1429 assert(SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
1430 assert((DstOps[0].getLLTTy(*getMRI()).isScalar() ||
1431 DstOps[0].getLLTTy(*getMRI()).isPointer()) &&
1432 "Invalid operand type");
1433 assert(SrcOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand type");
1434 assert(SrcOps[0].getLLTTy(*getMRI()).getElementType() ==
1435 DstOps[0].getLLTTy(*getMRI()) &&
1436 "Type mismatch");
1437 break;
1438 }
1439 case TargetOpcode::G_INSERT_VECTOR_ELT: {
1440 assert(DstOps.size() == 1 && "Invalid dst size");
1441 assert(SrcOps.size() == 3 && "Invalid src size");
1442 assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
1443 SrcOps[0].getLLTTy(*getMRI()).isVector() && "Invalid operand type");
1444 assert(DstOps[0].getLLTTy(*getMRI()).getElementType() ==
1445 SrcOps[1].getLLTTy(*getMRI()) &&
1446 "Type mismatch");
1447 assert(SrcOps[2].getLLTTy(*getMRI()).isScalar() && "Invalid index");
1448 assert(DstOps[0].getLLTTy(*getMRI()).getElementCount() ==
1449 SrcOps[0].getLLTTy(*getMRI()).getElementCount() &&
1450 "Type mismatch");
1451 break;
1452 }
1453 case TargetOpcode::G_INSERT_SUBVECTOR: {
1454 assert(DstOps.size() == 1 && "Invalid Dst");
1455 assert(SrcOps.size() == 3 && "Invalid Srcs");
1456 [[maybe_unused]] LLT DstTy = DstOps[0].getLLTTy(*getMRI());
1457 [[maybe_unused]] LLT BigVecTy = SrcOps[0].getLLTTy(*getMRI());
1458 [[maybe_unused]] LLT SubVecTy = SrcOps[1].getLLTTy(*getMRI());
1459 assert(DstTy == BigVecTy &&
1460 "Dest and insert subvector source types must match!");
1461 assert(DstTy.isVector() && SubVecTy.isVector() &&
1462 "Insert subvector VTs must be vectors!");
1463 assert(DstTy.getElementType() == SubVecTy.getElementType() &&
1464 "Insert subvector VTs must have the same element type!");
1465 assert((DstTy.isScalable() || !SubVecTy.isScalable()) &&
1466 "Cannot insert a scalable vector into a fixed length vector!");
1467 assert((DstTy.isScalable() != SubVecTy.isScalable() ||
1469 SubVecTy.getElementCount().getKnownMinValue()) &&
1470 "Insert subvector must be from smaller vector to larger vector!");
1471 assert(SrcOps[2].getSrcOpKind() == SrcOp::SrcType::Ty_Imm &&
1472 "Insert subvector index must be constant");
1473 assert((DstTy.isScalable() != SubVecTy.isScalable() ||
1474 (SubVecTy.getElementCount().getKnownMinValue() +
1475 (uint64_t)SrcOps[2].getImm()) <=
1476 DstTy.getElementCount().getKnownMinValue()) &&
1477 "Insert subvector overflow!");
1478 assert((uint64_t)SrcOps[2].getImm() %
1479 SubVecTy.getElementCount().getKnownMinValue() ==
1480 0 &&
1481 "Insert index is not a multiple of the subvector length");
1482 break;
1483 }
1484 case TargetOpcode::G_EXTRACT_SUBVECTOR: {
1485 assert(DstOps.size() == 1 && "Invalid Dst");
1486 assert(SrcOps.size() == 2 && "Invalid Srcs");
1487 [[maybe_unused]] LLT DstTy = DstOps[0].getLLTTy(*getMRI());
1488 [[maybe_unused]] LLT SrcVecTy = SrcOps[0].getLLTTy(*getMRI());
1489 assert(DstTy.isVector() && SrcVecTy.isVector() &&
1490 "Extract subvector VTs must be vectors!");
1491 assert(DstTy.getElementType() == SrcVecTy.getElementType() &&
1492 "Extract subvector VTs must have the same element type!");
1493 assert((!DstTy.isScalable() || SrcVecTy.isScalable()) &&
1494 "Cannot extract a scalable vector from a fixed length vector!");
1495 assert((DstTy.isScalable() != SrcVecTy.isScalable() ||
1497 SrcVecTy.getElementCount().getKnownMinValue()) &&
1498 "Extract subvector must be from larger vector to smaller vector!");
1499 assert(SrcOps[1].getSrcOpKind() == SrcOp::SrcType::Ty_Imm &&
1500 "Extract subvector index must be a constant");
1501 assert((DstTy.isScalable() != SrcVecTy.isScalable() ||
1503 (uint64_t)SrcOps[1].getImm()) <=
1504 SrcVecTy.getElementCount().getKnownMinValue()) &&
1505 "Extract subvector overflow!");
1506 assert((uint64_t)SrcOps[1].getImm() %
1508 0 &&
1509 "Extract index is not a multiple of the output vector length");
1510 break;
1511 }
1512 case TargetOpcode::G_BUILD_VECTOR: {
1513 assert((!SrcOps.empty() || SrcOps.size() < 2) &&
1514 "Must have at least 2 operands");
1515 assert(DstOps.size() == 1 && "Invalid DstOps");
1516 assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
1517 "Res type must be a vector");
1518 assert(llvm::all_of(SrcOps,
1519 [&, this](const SrcOp &Op) {
1520 return Op.getLLTTy(*getMRI()) ==
1521 SrcOps[0].getLLTTy(*getMRI());
1522 }) &&
1523 "type mismatch in input list");
1524 assert((TypeSize::ScalarTy)SrcOps.size() *
1525 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1526 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1527 "input scalars do not exactly cover the output vector register");
1528 break;
1529 }
1530 case TargetOpcode::G_BUILD_VECTOR_TRUNC: {
1531 assert((!SrcOps.empty() || SrcOps.size() < 2) &&
1532 "Must have at least 2 operands");
1533 assert(DstOps.size() == 1 && "Invalid DstOps");
1534 assert(DstOps[0].getLLTTy(*getMRI()).isVector() &&
1535 "Res type must be a vector");
1536 assert(llvm::all_of(SrcOps,
1537 [&, this](const SrcOp &Op) {
1538 return Op.getLLTTy(*getMRI()) ==
1539 SrcOps[0].getLLTTy(*getMRI());
1540 }) &&
1541 "type mismatch in input list");
1542 break;
1543 }
1544 case TargetOpcode::G_CONCAT_VECTORS: {
1545 assert(DstOps.size() == 1 && "Invalid DstOps");
1546 assert((!SrcOps.empty() || SrcOps.size() < 2) &&
1547 "Must have at least 2 operands");
1548 assert(llvm::all_of(SrcOps,
1549 [&, this](const SrcOp &Op) {
1550 return (Op.getLLTTy(*getMRI()).isVector() &&
1551 Op.getLLTTy(*getMRI()) ==
1552 SrcOps[0].getLLTTy(*getMRI()));
1553 }) &&
1554 "type mismatch in input list");
1555 assert((TypeSize::ScalarTy)SrcOps.size() *
1556 SrcOps[0].getLLTTy(*getMRI()).getSizeInBits() ==
1557 DstOps[0].getLLTTy(*getMRI()).getSizeInBits() &&
1558 "input vectors do not exactly cover the output vector register");
1559 break;
1560 }
1561 case TargetOpcode::G_UADDE: {
1562 assert(DstOps.size() == 2 && "Invalid no of dst operands");
1563 assert(SrcOps.size() == 3 && "Invalid no of src operands");
1564 assert(DstOps[0].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
1565 assert((DstOps[0].getLLTTy(*getMRI()) == SrcOps[0].getLLTTy(*getMRI())) &&
1566 (DstOps[0].getLLTTy(*getMRI()) == SrcOps[1].getLLTTy(*getMRI())) &&
1567 "Invalid operand");
1568 assert(DstOps[1].getLLTTy(*getMRI()).isScalar() && "Invalid operand");
1569 assert(DstOps[1].getLLTTy(*getMRI()) == SrcOps[2].getLLTTy(*getMRI()) &&
1570 "type mismatch");
1571 break;
1572 }
1573 }
1574
1575 auto MIB = buildInstr(Opc);
1576 for (const DstOp &Op : DstOps)
1577 Op.addDefToMIB(*getMRI(), MIB);
1578 for (const SrcOp &Op : SrcOps)
1579 Op.addSrcToMIB(MIB);
1580 if (Flags)
1581 MIB->setFlags(*Flags);
1582 return MIB;
1583}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis Results
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:303
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:345
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:5920
const fltSemantics & getSemantics() const
Definition APFloat.h:1573
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:307
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:407
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
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:353
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:348
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:1069
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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
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:255
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
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:578
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:1739
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
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:763
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
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.