LLVM 20.0.0git
InlineAsmLowering.cpp
Go to the documentation of this file.
1//===-- lib/CodeGen/GlobalISel/InlineAsmLowering.cpp ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements the lowering from LLVM IR inline asm to MIR INLINEASM
11///
12//===----------------------------------------------------------------------===//
13
19#include "llvm/IR/Module.h"
20
21#define DEBUG_TYPE "inline-asm-lowering"
22
23using namespace llvm;
24
25void InlineAsmLowering::anchor() {}
26
27namespace {
28
29/// GISelAsmOperandInfo - This contains information for each constraint that we
30/// are lowering.
31class GISelAsmOperandInfo : public TargetLowering::AsmOperandInfo {
32public:
33 /// Regs - If this is a register or register class operand, this
34 /// contains the set of assigned registers corresponding to the operand.
36
37 explicit GISelAsmOperandInfo(const TargetLowering::AsmOperandInfo &Info)
38 : TargetLowering::AsmOperandInfo(Info) {}
39};
40
41using GISelAsmOperandInfoVector = SmallVector<GISelAsmOperandInfo, 16>;
42
43class ExtraFlags {
44 unsigned Flags = 0;
45
46public:
47 explicit ExtraFlags(const CallBase &CB) {
48 const InlineAsm *IA = cast<InlineAsm>(CB.getCalledOperand());
49 if (IA->hasSideEffects())
51 if (IA->isAlignStack())
53 if (CB.isConvergent())
55 Flags |= IA->getDialect() * InlineAsm::Extra_AsmDialect;
56 }
57
58 void update(const TargetLowering::AsmOperandInfo &OpInfo) {
59 // Ideally, we would only check against memory constraints. However, the
60 // meaning of an Other constraint can be target-specific and we can't easily
61 // reason about it. Therefore, be conservative and set MayLoad/MayStore
62 // for Other constraints as well.
65 if (OpInfo.Type == InlineAsm::isInput)
67 else if (OpInfo.Type == InlineAsm::isOutput)
69 else if (OpInfo.Type == InlineAsm::isClobber)
71 }
72 }
73
74 unsigned get() const { return Flags; }
75};
76
77} // namespace
78
79/// Assign virtual/physical registers for the specified register operand.
81 MachineIRBuilder &MIRBuilder,
82 GISelAsmOperandInfo &OpInfo,
83 GISelAsmOperandInfo &RefOpInfo) {
84
87
88 // No work to do for memory operations.
89 if (OpInfo.ConstraintType == TargetLowering::C_Memory)
90 return;
91
92 // If this is a constraint for a single physreg, or a constraint for a
93 // register class, find it.
94 Register AssignedReg;
95 const TargetRegisterClass *RC;
96 std::tie(AssignedReg, RC) = TLI.getRegForInlineAsmConstraint(
97 &TRI, RefOpInfo.ConstraintCode, RefOpInfo.ConstraintVT);
98 // RC is unset only on failure. Return immediately.
99 if (!RC)
100 return;
101
102 // No need to allocate a matching input constraint since the constraint it's
103 // matching to has already been allocated.
104 if (OpInfo.isMatchingInputConstraint())
105 return;
106
107 // Initialize NumRegs.
108 unsigned NumRegs = 1;
109 if (OpInfo.ConstraintVT != MVT::Other)
110 NumRegs =
111 TLI.getNumRegisters(MF.getFunction().getContext(), OpInfo.ConstraintVT);
112
113 // If this is a constraint for a specific physical register, but the type of
114 // the operand requires more than one register to be passed, we allocate the
115 // required amount of physical registers, starting from the selected physical
116 // register.
117 // For this, first retrieve a register iterator for the given register class
120
121 // Advance the iterator to the assigned register (if set)
122 if (AssignedReg) {
123 for (; *I != AssignedReg; ++I)
124 assert(I != RC->end() && "AssignedReg should be a member of provided RC");
125 }
126
127 // Finally, assign the registers. If the AssignedReg isn't set, create virtual
128 // registers with the provided register class
129 for (; NumRegs; --NumRegs, ++I) {
130 assert(I != RC->end() && "Ran out of registers to allocate!");
131 Register R = AssignedReg ? Register(*I) : RegInfo.createVirtualRegister(RC);
132 OpInfo.Regs.push_back(R);
133 }
134}
135
138 assert(!OpInfo.Codes.empty() && "Must have at least one constraint");
139
140 // Single-letter constraints ('r') are very common.
141 if (OpInfo.Codes.size() == 1) {
142 OpInfo.ConstraintCode = OpInfo.Codes[0];
143 OpInfo.ConstraintType = TLI->getConstraintType(OpInfo.ConstraintCode);
144 } else {
146 if (G.empty())
147 return;
148 // FIXME: prefer immediate constraints if the target allows it
149 unsigned BestIdx = 0;
150 for (const unsigned E = G.size();
151 BestIdx < E && (G[BestIdx].second == TargetLowering::C_Other ||
152 G[BestIdx].second == TargetLowering::C_Immediate);
153 ++BestIdx)
154 ;
155 OpInfo.ConstraintCode = G[BestIdx].first;
156 OpInfo.ConstraintType = G[BestIdx].second;
157 }
158
159 // 'X' matches anything.
160 if (OpInfo.ConstraintCode == "X" && OpInfo.CallOperandVal) {
161 // Labels and constants are handled elsewhere ('X' is the only thing
162 // that matches labels). For Functions, the type here is the type of
163 // the result, which is not what we want to look at; leave them alone.
164 Value *Val = OpInfo.CallOperandVal;
165 if (isa<BasicBlock>(Val) || isa<ConstantInt>(Val) || isa<Function>(Val))
166 return;
167
168 // Otherwise, try to resolve it to something we know about by looking at
169 // the actual operand type.
170 if (const char *Repl = TLI->LowerXConstraint(OpInfo.ConstraintVT)) {
171 OpInfo.ConstraintCode = Repl;
172 OpInfo.ConstraintType = TLI->getConstraintType(OpInfo.ConstraintCode);
173 }
174 }
175}
176
177static unsigned getNumOpRegs(const MachineInstr &I, unsigned OpIdx) {
178 const InlineAsm::Flag F(I.getOperand(OpIdx).getImm());
179 return F.getNumOperandRegisters();
180}
181
183 MachineIRBuilder &MIRBuilder) {
184 const TargetRegisterInfo *TRI =
185 MIRBuilder.getMF().getSubtarget().getRegisterInfo();
186 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
187
188 auto SrcTy = MRI->getType(Src);
189 if (!SrcTy.isValid()) {
190 LLVM_DEBUG(dbgs() << "Source type for copy is not valid\n");
191 return false;
192 }
193 unsigned SrcSize = TRI->getRegSizeInBits(Src, *MRI);
194 unsigned DstSize = TRI->getRegSizeInBits(Dst, *MRI);
195
196 if (DstSize < SrcSize) {
197 LLVM_DEBUG(dbgs() << "Input can't fit in destination reg class\n");
198 return false;
199 }
200
201 // Attempt to anyext small scalar sources.
202 if (DstSize > SrcSize) {
203 if (!SrcTy.isScalar()) {
204 LLVM_DEBUG(dbgs() << "Can't extend non-scalar input to size of"
205 "destination register class\n");
206 return false;
207 }
208 Src = MIRBuilder.buildAnyExt(LLT::scalar(DstSize), Src).getReg(0);
209 }
210
211 MIRBuilder.buildCopy(Dst, Src);
212 return true;
213}
214
216 MachineIRBuilder &MIRBuilder, const CallBase &Call,
217 std::function<ArrayRef<Register>(const Value &Val)> GetOrCreateVRegs)
218 const {
219 const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand());
220
221 /// ConstraintOperands - Information about all of the constraints.
222 GISelAsmOperandInfoVector ConstraintOperands;
223
224 MachineFunction &MF = MIRBuilder.getMF();
225 const Function &F = MF.getFunction();
226 const DataLayout &DL = F.getDataLayout();
228
229 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
230
231 TargetLowering::AsmOperandInfoVector TargetConstraints =
232 TLI->ParseConstraints(DL, TRI, Call);
233
234 ExtraFlags ExtraInfo(Call);
235 unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
236 unsigned ResNo = 0; // ResNo - The result number of the next output.
237 for (auto &T : TargetConstraints) {
238 ConstraintOperands.push_back(GISelAsmOperandInfo(T));
239 GISelAsmOperandInfo &OpInfo = ConstraintOperands.back();
240
241 // Compute the value type for each operand.
242 if (OpInfo.hasArg()) {
243 OpInfo.CallOperandVal = const_cast<Value *>(Call.getArgOperand(ArgNo));
244
245 if (isa<BasicBlock>(OpInfo.CallOperandVal)) {
246 LLVM_DEBUG(dbgs() << "Basic block input operands not supported yet\n");
247 return false;
248 }
249
250 Type *OpTy = OpInfo.CallOperandVal->getType();
251
252 // If this is an indirect operand, the operand is a pointer to the
253 // accessed type.
254 if (OpInfo.isIndirect) {
255 OpTy = Call.getParamElementType(ArgNo);
256 assert(OpTy && "Indirect operand must have elementtype attribute");
257 }
258
259 // FIXME: Support aggregate input operands
260 if (!OpTy->isSingleValueType()) {
262 dbgs() << "Aggregate input operands are not supported yet\n");
263 return false;
264 }
265
266 OpInfo.ConstraintVT =
267 TLI->getAsmOperandValueType(DL, OpTy, true).getSimpleVT();
268 ++ArgNo;
269 } else if (OpInfo.Type == InlineAsm::isOutput && !OpInfo.isIndirect) {
270 assert(!Call.getType()->isVoidTy() && "Bad inline asm!");
271 if (StructType *STy = dyn_cast<StructType>(Call.getType())) {
272 OpInfo.ConstraintVT =
273 TLI->getSimpleValueType(DL, STy->getElementType(ResNo));
274 } else {
275 assert(ResNo == 0 && "Asm only has one result!");
276 OpInfo.ConstraintVT =
277 TLI->getAsmOperandValueType(DL, Call.getType()).getSimpleVT();
278 }
279 ++ResNo;
280 } else {
281 assert(OpInfo.Type != InlineAsm::isLabel &&
282 "GlobalISel currently doesn't support callbr");
283 OpInfo.ConstraintVT = MVT::Other;
284 }
285
286 if (OpInfo.ConstraintVT == MVT::i64x8)
287 return false;
288
289 // Compute the constraint code and ConstraintType to use.
290 computeConstraintToUse(TLI, OpInfo);
291
292 // The selected constraint type might expose new sideeffects
293 ExtraInfo.update(OpInfo);
294 }
295
296 // At this point, all operand types are decided.
297 // Create the MachineInstr, but don't insert it yet since input
298 // operands still need to insert instructions before this one
299 auto Inst = MIRBuilder.buildInstrNoInsert(TargetOpcode::INLINEASM)
300 .addExternalSymbol(IA->getAsmString().c_str())
301 .addImm(ExtraInfo.get());
302
303 // Starting from this operand: flag followed by register(s) will be added as
304 // operands to Inst for each constraint. Used for matching input constraints.
305 unsigned StartIdx = Inst->getNumOperands();
306
307 // Collects the output operands for later processing
308 GISelAsmOperandInfoVector OutputOperands;
309
310 for (auto &OpInfo : ConstraintOperands) {
311 GISelAsmOperandInfo &RefOpInfo =
313 ? ConstraintOperands[OpInfo.getMatchedOperand()]
314 : OpInfo;
315
316 // Assign registers for register operands
317 getRegistersForValue(MF, MIRBuilder, OpInfo, RefOpInfo);
318
319 switch (OpInfo.Type) {
322 const InlineAsm::ConstraintCode ConstraintID =
325 "Failed to convert memory constraint code to constraint id.");
326
327 // Add information to the INLINEASM instruction to know about this
328 // output.
330 Flag.setMemConstraint(ConstraintID);
331 Inst.addImm(Flag);
332 ArrayRef<Register> SourceRegs =
333 GetOrCreateVRegs(*OpInfo.CallOperandVal);
334 assert(
335 SourceRegs.size() == 1 &&
336 "Expected the memory output to fit into a single virtual register");
337 Inst.addReg(SourceRegs[0]);
338 } else {
339 // Otherwise, this outputs to a register (directly for C_Register /
340 // C_RegisterClass/C_Other.
344
345 // Find a register that we can use.
346 if (OpInfo.Regs.empty()) {
348 << "Couldn't allocate output register for constraint\n");
349 return false;
350 }
351
352 // Add information to the INLINEASM instruction to know that this
353 // register is set.
357 OpInfo.Regs.size());
358 if (OpInfo.Regs.front().isVirtual()) {
359 // Put the register class of the virtual registers in the flag word.
360 // That way, later passes can recompute register class constraints for
361 // inline assembly as well as normal instructions. Don't do this for
362 // tied operands that can use the regclass information from the def.
363 const TargetRegisterClass *RC = MRI->getRegClass(OpInfo.Regs.front());
364 Flag.setRegClass(RC->getID());
365 }
366
367 Inst.addImm(Flag);
368
369 for (Register Reg : OpInfo.Regs) {
370 Inst.addReg(Reg,
371 RegState::Define | getImplRegState(Reg.isPhysical()) |
373 }
374
375 // Remember this output operand for later processing
376 OutputOperands.push_back(OpInfo);
377 }
378
379 break;
381 case InlineAsm::isLabel: {
382 if (OpInfo.isMatchingInputConstraint()) {
383 unsigned DefIdx = OpInfo.getMatchedOperand();
384 // Find operand with register def that corresponds to DefIdx.
385 unsigned InstFlagIdx = StartIdx;
386 for (unsigned i = 0; i < DefIdx; ++i)
387 InstFlagIdx += getNumOpRegs(*Inst, InstFlagIdx) + 1;
388 assert(getNumOpRegs(*Inst, InstFlagIdx) == 1 && "Wrong flag");
389
390 const InlineAsm::Flag MatchedOperandFlag(Inst->getOperand(InstFlagIdx).getImm());
391 if (MatchedOperandFlag.isMemKind()) {
392 LLVM_DEBUG(dbgs() << "Matching input constraint to mem operand not "
393 "supported. This should be target specific.\n");
394 return false;
395 }
396 if (!MatchedOperandFlag.isRegDefKind() && !MatchedOperandFlag.isRegDefEarlyClobberKind()) {
397 LLVM_DEBUG(dbgs() << "Unknown matching constraint\n");
398 return false;
399 }
400
401 // We want to tie input to register in next operand.
402 unsigned DefRegIdx = InstFlagIdx + 1;
403 Register Def = Inst->getOperand(DefRegIdx).getReg();
404
405 ArrayRef<Register> SrcRegs = GetOrCreateVRegs(*OpInfo.CallOperandVal);
406 assert(SrcRegs.size() == 1 && "Single register is expected here");
407
408 // When Def is physreg: use given input.
409 Register In = SrcRegs[0];
410 // When Def is vreg: copy input to new vreg with same reg class as Def.
411 if (Def.isVirtual()) {
412 In = MRI->createVirtualRegister(MRI->getRegClass(Def));
413 if (!buildAnyextOrCopy(In, SrcRegs[0], MIRBuilder))
414 return false;
415 }
416
417 // Add Flag and input register operand (In) to Inst. Tie In to Def.
419 UseFlag.setMatchingOp(DefIdx);
420 Inst.addImm(UseFlag);
421 Inst.addReg(In);
422 Inst->tieOperands(DefRegIdx, Inst->getNumOperands() - 1);
423 break;
424 }
425
427 OpInfo.isIndirect) {
428 LLVM_DEBUG(dbgs() << "Indirect input operands with unknown constraint "
429 "not supported yet\n");
430 return false;
431 }
432
435
436 std::vector<MachineOperand> Ops;
438 OpInfo.ConstraintCode, Ops,
439 MIRBuilder)) {
440 LLVM_DEBUG(dbgs() << "Don't support constraint: "
441 << OpInfo.ConstraintCode << " yet\n");
442 return false;
443 }
444
445 assert(Ops.size() > 0 &&
446 "Expected constraint to be lowered to at least one operand");
447
448 // Add information to the INLINEASM node to know about this input.
449 const unsigned OpFlags =
451 Inst.addImm(OpFlags);
452 Inst.add(Ops);
453 break;
454 }
455
457
458 if (!OpInfo.isIndirect) {
460 << "Cannot indirectify memory input operands yet\n");
461 return false;
462 }
463
464 assert(OpInfo.isIndirect && "Operand must be indirect to be a mem!");
465
466 const InlineAsm::ConstraintCode ConstraintID =
469 OpFlags.setMemConstraint(ConstraintID);
470 Inst.addImm(OpFlags);
471 ArrayRef<Register> SourceRegs =
472 GetOrCreateVRegs(*OpInfo.CallOperandVal);
473 assert(
474 SourceRegs.size() == 1 &&
475 "Expected the memory input to fit into a single virtual register");
476 Inst.addReg(SourceRegs[0]);
477 break;
478 }
479
482 "Unknown constraint type!");
483
484 if (OpInfo.isIndirect) {
485 LLVM_DEBUG(dbgs() << "Can't handle indirect register inputs yet "
486 "for constraint '"
487 << OpInfo.ConstraintCode << "'\n");
488 return false;
489 }
490
491 // Copy the input into the appropriate registers.
492 if (OpInfo.Regs.empty()) {
494 dbgs()
495 << "Couldn't allocate input register for register constraint\n");
496 return false;
497 }
498
499 unsigned NumRegs = OpInfo.Regs.size();
500 ArrayRef<Register> SourceRegs = GetOrCreateVRegs(*OpInfo.CallOperandVal);
501 assert(NumRegs == SourceRegs.size() &&
502 "Expected the number of input registers to match the number of "
503 "source registers");
504
505 if (NumRegs > 1) {
506 LLVM_DEBUG(dbgs() << "Input operands with multiple input registers are "
507 "not supported yet\n");
508 return false;
509 }
510
512 if (OpInfo.Regs.front().isVirtual()) {
513 // Put the register class of the virtual registers in the flag word.
514 const TargetRegisterClass *RC = MRI->getRegClass(OpInfo.Regs.front());
515 Flag.setRegClass(RC->getID());
516 }
517 Inst.addImm(Flag);
518 if (!buildAnyextOrCopy(OpInfo.Regs[0], SourceRegs[0], MIRBuilder))
519 return false;
520 Inst.addReg(OpInfo.Regs[0]);
521 break;
522 }
523
525
526 const unsigned NumRegs = OpInfo.Regs.size();
527 if (NumRegs > 0) {
528 unsigned Flag = InlineAsm::Flag(InlineAsm::Kind::Clobber, NumRegs);
529 Inst.addImm(Flag);
530
531 for (Register Reg : OpInfo.Regs) {
532 Inst.addReg(Reg, RegState::Define | RegState::EarlyClobber |
533 getImplRegState(Reg.isPhysical()));
534 }
535 }
536 break;
537 }
538 }
539 }
540
541 // Add rounding control registers as implicit def for inline asm.
542 if (MF.getFunction().hasFnAttribute(Attribute::StrictFP)) {
544 for (MCPhysReg Reg : RCRegs)
545 Inst.addReg(Reg, RegState::ImplicitDefine);
546 }
547
548 if (auto Bundle = Call.getOperandBundle(LLVMContext::OB_convergencectrl)) {
549 auto *Token = Bundle->Inputs[0].get();
550 ArrayRef<Register> SourceRegs = GetOrCreateVRegs(*Token);
551 assert(SourceRegs.size() == 1 &&
552 "Expected the control token to fit into a single virtual register");
553 Inst.addUse(SourceRegs[0], RegState::Implicit);
554 }
555
556 if (const MDNode *SrcLoc = Call.getMetadata("srcloc"))
557 Inst.addMetadata(SrcLoc);
558
559 // All inputs are handled, insert the instruction now
560 MIRBuilder.insertInstr(Inst);
561
562 // Finally, copy the output operands into the output registers
563 ArrayRef<Register> ResRegs = GetOrCreateVRegs(Call);
564 if (ResRegs.size() != OutputOperands.size()) {
565 LLVM_DEBUG(dbgs() << "Expected the number of output registers to match the "
566 "number of destination registers\n");
567 return false;
568 }
569 for (unsigned int i = 0, e = ResRegs.size(); i < e; i++) {
570 GISelAsmOperandInfo &OpInfo = OutputOperands[i];
571
572 if (OpInfo.Regs.empty())
573 continue;
574
575 switch (OpInfo.ConstraintType) {
578 if (OpInfo.Regs.size() > 1) {
579 LLVM_DEBUG(dbgs() << "Output operands with multiple defining "
580 "registers are not supported yet\n");
581 return false;
582 }
583
584 Register SrcReg = OpInfo.Regs[0];
585 unsigned SrcSize = TRI->getRegSizeInBits(SrcReg, *MRI);
586 LLT ResTy = MRI->getType(ResRegs[i]);
587 if (ResTy.isScalar() && ResTy.getSizeInBits() < SrcSize) {
588 // First copy the non-typed virtual register into a generic virtual
589 // register
590 Register Tmp1Reg =
591 MRI->createGenericVirtualRegister(LLT::scalar(SrcSize));
592 MIRBuilder.buildCopy(Tmp1Reg, SrcReg);
593 // Need to truncate the result of the register
594 MIRBuilder.buildTrunc(ResRegs[i], Tmp1Reg);
595 } else if (ResTy.getSizeInBits() == SrcSize) {
596 MIRBuilder.buildCopy(ResRegs[i], SrcReg);
597 } else {
598 LLVM_DEBUG(dbgs() << "Unhandled output operand with "
599 "mismatched register size\n");
600 return false;
601 }
602
603 break;
604 }
608 dbgs() << "Cannot lower target specific output constraints yet\n");
609 return false;
611 break; // Already handled.
613 break; // Silence warning.
615 LLVM_DEBUG(dbgs() << "Unexpected unknown constraint\n");
616 return false;
617 }
618 }
619
620 return true;
621}
622
624 Value *Val, StringRef Constraint, std::vector<MachineOperand> &Ops,
625 MachineIRBuilder &MIRBuilder) const {
626 if (Constraint.size() > 1)
627 return false;
628
629 char ConstraintLetter = Constraint[0];
630 switch (ConstraintLetter) {
631 default:
632 return false;
633 case 'i': // Simple Integer or Relocatable Constant
634 case 'n': // immediate integer with a known value.
635 if (ConstantInt *CI = dyn_cast<ConstantInt>(Val)) {
636 assert(CI->getBitWidth() <= 64 &&
637 "expected immediate to fit into 64-bits");
638 // Boolean constants should be zero-extended, others are sign-extended
639 bool IsBool = CI->getBitWidth() == 1;
640 int64_t ExtVal = IsBool ? CI->getZExtValue() : CI->getSExtValue();
641 Ops.push_back(MachineOperand::CreateImm(ExtVal));
642 return true;
643 }
644 return false;
645 }
646}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define LLVM_DEBUG(...)
Definition: Debug.h:106
Module.h This file contains the declarations for the Module class.
static unsigned getNumOpRegs(const MachineInstr &I, unsigned OpIdx)
static void getRegistersForValue(MachineFunction &MF, MachineIRBuilder &MIRBuilder, GISelAsmOperandInfo &OpInfo, GISelAsmOperandInfo &RefOpInfo)
Assign virtual/physical registers for the specified register operand.
static void computeConstraintToUse(const TargetLowering *TLI, TargetLowering::AsmOperandInfo &OpInfo)
static bool buildAnyextOrCopy(Register Dst, Register Src, MachineIRBuilder &MIRBuilder)
This file describes how to lower LLVM inline asm to machine code INLINEASM.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
This file declares the MachineIRBuilder class.
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file describes how to lower LLVM code to machine code.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:168
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1120
Value * getCalledOperand() const
Definition: InstrTypes.h:1342
bool isConvergent() const
Determine if the invoke is convergent.
Definition: InstrTypes.h:1935
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:369
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:731
bool lowerInlineAsm(MachineIRBuilder &MIRBuilder, const CallBase &CB, std::function< ArrayRef< Register >(const Value &Val)> GetOrCreateVRegs) const
Lower the given inline asm call instruction GetOrCreateVRegs is a callback to materialize a register ...
virtual bool lowerAsmOperandForConstraint(Value *Val, StringRef Constraint, std::vector< MachineOperand > &Ops, MachineIRBuilder &MIRBuilder) const
Lower the specified operand into the Ops vector.
bool isMemKind() const
Definition: InlineAsm.h:334
void setMatchingOp(unsigned OperandNo)
setMatchingOp - Augment an existing flag with information indicating that this input operand is tied ...
Definition: InlineAsm.h:391
void setMemConstraint(ConstraintCode C)
setMemConstraint - Augment an existing flag with the constraint code for a memory constraint.
Definition: InlineAsm.h:410
bool isRegDefEarlyClobberKind() const
Definition: InlineAsm.h:329
bool isRegDefKind() const
Definition: InlineAsm.h:328
constexpr bool isScalar() const
Definition: LowLevelType.h:146
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:190
Metadata node.
Definition: Metadata.h:1069
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.
Helper class to build MachineInstr.
MachineInstrBuilder insertInstr(MachineInstrBuilder MIB)
Insert an existing instruction at the insertion point.
MachineFunction & getMF()
Getter for the function we currently build.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_TRUNC Op.
MachineInstrBuilder buildAnyExt(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ANYEXT Op0.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineInstrBuilder buildInstrNoInsert(unsigned Opcode)
Build but don't insert <empty> = Opcode <empty>.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:578
static MachineOperand CreateImm(int64_t Val)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:150
Class to represent struct types.
Definition: DerivedTypes.h:218
virtual unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const
Return the number of registers that this ValueType will eventually require.
MVT getSimpleValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the MVT corresponding to this LLVM type. See getValueType.
virtual EVT getAsmOperandValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
std::vector< AsmOperandInfo > AsmOperandInfoVector
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
virtual const char * LowerXConstraint(EVT ConstraintVT) const
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
ConstraintGroup getConstraintPreferences(AsmOperandInfo &OpInfo) const
Given an OpInfo with list of constraints codes as strings, return a sorted Vector of pairs of constra...
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
virtual AsmOperandInfoVector ParseConstraints(const DataLayout &DL, const TargetRegisterInfo *TRI, const CallBase &Call) const
Split up the constraint string from the inline assembly value into the specific constraints and their...
virtual ArrayRef< MCPhysReg > getRoundingControlRegisters() const
Returns a 0 terminated array of rounding control registers that can be attached into strict FP call.
unsigned getID() const
Return the register class ID number.
iterator begin() const
begin/end - Return all of the registers in this class.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetLowering * getTargetLowering() const
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
Definition: Type.h:295
LLVM Value Representation.
Definition: Value.h:74
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Define
Register definition.
@ EarlyClobber
Register definition happens before uses.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
unsigned getImplRegState(bool B)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition: ValueTypes.h:311
ConstraintPrefix Type
Type - The basic type of the constraint: input/output/clobber/label.
Definition: InlineAsm.h:126
ConstraintCodeVector Codes
Code - The constraint code, either the register name (in braces) or the constraint letter/number.
Definition: InlineAsm.h:154
bool isIndirect
isIndirect - True if this operand is an indirect operand.
Definition: InlineAsm.h:150
bool isEarlyClobber
isEarlyClobber - "&": output operand writes result before inputs are all read.
Definition: InlineAsm.h:130
This contains information for each constraint that we are lowering.
MVT ConstraintVT
The ValueType for the operand value.
TargetLowering::ConstraintType ConstraintType
Information about the constraint code, e.g.
std::string ConstraintCode
This contains the actual string for the code, like "m".
Value * CallOperandVal
If this is the result output operand or a clobber, this is null, otherwise it is the incoming operand...
unsigned getMatchedOperand() const
If this is an input matching constraint, this method returns the output operand it matches.
bool isMatchingInputConstraint() const
Return true of this is an input operand that is a matching constraint like "4".