LLVM 18.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
136/// Return an integer indicating how general CT is.
138 switch (CT) {
142 return 0;
144 return 1;
146 return 2;
149 return 3;
150 }
151 llvm_unreachable("Invalid constraint type");
152}
153
155 const TargetLowering *TLI) {
156 assert(OpInfo.Codes.size() > 1 && "Doesn't have multiple constraint options");
157 unsigned BestIdx = 0;
159 int BestGenerality = -1;
160
161 // Loop over the options, keeping track of the most general one.
162 for (unsigned i = 0, e = OpInfo.Codes.size(); i != e; ++i) {
164 TLI->getConstraintType(OpInfo.Codes[i]);
165
166 // Indirect 'other' or 'immediate' constraints are not allowed.
167 if (OpInfo.isIndirect && !(CType == TargetLowering::C_Memory ||
170 continue;
171
172 // If this is an 'other' or 'immediate' constraint, see if the operand is
173 // valid for it. For example, on X86 we might have an 'rI' constraint. If
174 // the operand is an integer in the range [0..31] we want to use I (saving a
175 // load of a register), otherwise we must use 'r'.
176 if (CType == TargetLowering::C_Other ||
178 assert(OpInfo.Codes[i].size() == 1 &&
179 "Unhandled multi-letter 'other' constraint");
180 // FIXME: prefer immediate constraints if the target allows it
181 }
182
183 // Things with matching constraints can only be registers, per gcc
184 // documentation. This mainly affects "g" constraints.
185 if (CType == TargetLowering::C_Memory && OpInfo.hasMatchingInput())
186 continue;
187
188 // This constraint letter is more general than the previous one, use it.
189 int Generality = getConstraintGenerality(CType);
190 if (Generality > BestGenerality) {
191 BestType = CType;
192 BestIdx = i;
193 BestGenerality = Generality;
194 }
195 }
196
197 OpInfo.ConstraintCode = OpInfo.Codes[BestIdx];
198 OpInfo.ConstraintType = BestType;
199}
200
203 assert(!OpInfo.Codes.empty() && "Must have at least one constraint");
204
205 // Single-letter constraints ('r') are very common.
206 if (OpInfo.Codes.size() == 1) {
207 OpInfo.ConstraintCode = OpInfo.Codes[0];
208 OpInfo.ConstraintType = TLI->getConstraintType(OpInfo.ConstraintCode);
209 } else {
210 chooseConstraint(OpInfo, TLI);
211 }
212
213 // 'X' matches anything.
214 if (OpInfo.ConstraintCode == "X" && OpInfo.CallOperandVal) {
215 // Labels and constants are handled elsewhere ('X' is the only thing
216 // that matches labels). For Functions, the type here is the type of
217 // the result, which is not what we want to look at; leave them alone.
218 Value *Val = OpInfo.CallOperandVal;
219 if (isa<BasicBlock>(Val) || isa<ConstantInt>(Val) || isa<Function>(Val))
220 return;
221
222 // Otherwise, try to resolve it to something we know about by looking at
223 // the actual operand type.
224 if (const char *Repl = TLI->LowerXConstraint(OpInfo.ConstraintVT)) {
225 OpInfo.ConstraintCode = Repl;
226 OpInfo.ConstraintType = TLI->getConstraintType(OpInfo.ConstraintCode);
227 }
228 }
229}
230
231static unsigned getNumOpRegs(const MachineInstr &I, unsigned OpIdx) {
232 const InlineAsm::Flag F(I.getOperand(OpIdx).getImm());
233 return F.getNumOperandRegisters();
234}
235
237 MachineIRBuilder &MIRBuilder) {
238 const TargetRegisterInfo *TRI =
239 MIRBuilder.getMF().getSubtarget().getRegisterInfo();
240 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
241
242 auto SrcTy = MRI->getType(Src);
243 if (!SrcTy.isValid()) {
244 LLVM_DEBUG(dbgs() << "Source type for copy is not valid\n");
245 return false;
246 }
247 unsigned SrcSize = TRI->getRegSizeInBits(Src, *MRI);
248 unsigned DstSize = TRI->getRegSizeInBits(Dst, *MRI);
249
250 if (DstSize < SrcSize) {
251 LLVM_DEBUG(dbgs() << "Input can't fit in destination reg class\n");
252 return false;
253 }
254
255 // Attempt to anyext small scalar sources.
256 if (DstSize > SrcSize) {
257 if (!SrcTy.isScalar()) {
258 LLVM_DEBUG(dbgs() << "Can't extend non-scalar input to size of"
259 "destination register class\n");
260 return false;
261 }
262 Src = MIRBuilder.buildAnyExt(LLT::scalar(DstSize), Src).getReg(0);
263 }
264
265 MIRBuilder.buildCopy(Dst, Src);
266 return true;
267}
268
270 MachineIRBuilder &MIRBuilder, const CallBase &Call,
271 std::function<ArrayRef<Register>(const Value &Val)> GetOrCreateVRegs)
272 const {
273 const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand());
274
275 /// ConstraintOperands - Information about all of the constraints.
276 GISelAsmOperandInfoVector ConstraintOperands;
277
278 MachineFunction &MF = MIRBuilder.getMF();
279 const Function &F = MF.getFunction();
280 const DataLayout &DL = F.getParent()->getDataLayout();
282
283 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
284
285 TargetLowering::AsmOperandInfoVector TargetConstraints =
286 TLI->ParseConstraints(DL, TRI, Call);
287
288 ExtraFlags ExtraInfo(Call);
289 unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
290 unsigned ResNo = 0; // ResNo - The result number of the next output.
291 for (auto &T : TargetConstraints) {
292 ConstraintOperands.push_back(GISelAsmOperandInfo(T));
293 GISelAsmOperandInfo &OpInfo = ConstraintOperands.back();
294
295 // Compute the value type for each operand.
296 if (OpInfo.hasArg()) {
297 OpInfo.CallOperandVal = const_cast<Value *>(Call.getArgOperand(ArgNo));
298
299 if (isa<BasicBlock>(OpInfo.CallOperandVal)) {
300 LLVM_DEBUG(dbgs() << "Basic block input operands not supported yet\n");
301 return false;
302 }
303
304 Type *OpTy = OpInfo.CallOperandVal->getType();
305
306 // If this is an indirect operand, the operand is a pointer to the
307 // accessed type.
308 if (OpInfo.isIndirect) {
309 OpTy = Call.getParamElementType(ArgNo);
310 assert(OpTy && "Indirect operand must have elementtype attribute");
311 }
312
313 // FIXME: Support aggregate input operands
314 if (!OpTy->isSingleValueType()) {
316 dbgs() << "Aggregate input operands are not supported yet\n");
317 return false;
318 }
319
320 OpInfo.ConstraintVT =
321 TLI->getAsmOperandValueType(DL, OpTy, true).getSimpleVT();
322 ++ArgNo;
323 } else if (OpInfo.Type == InlineAsm::isOutput && !OpInfo.isIndirect) {
324 assert(!Call.getType()->isVoidTy() && "Bad inline asm!");
325 if (StructType *STy = dyn_cast<StructType>(Call.getType())) {
326 OpInfo.ConstraintVT =
327 TLI->getSimpleValueType(DL, STy->getElementType(ResNo));
328 } else {
329 assert(ResNo == 0 && "Asm only has one result!");
330 OpInfo.ConstraintVT =
331 TLI->getAsmOperandValueType(DL, Call.getType()).getSimpleVT();
332 }
333 ++ResNo;
334 } else {
335 assert(OpInfo.Type != InlineAsm::isLabel &&
336 "GlobalISel currently doesn't support callbr");
337 OpInfo.ConstraintVT = MVT::Other;
338 }
339
340 if (OpInfo.ConstraintVT == MVT::i64x8)
341 return false;
342
343 // Compute the constraint code and ConstraintType to use.
344 computeConstraintToUse(TLI, OpInfo);
345
346 // The selected constraint type might expose new sideeffects
347 ExtraInfo.update(OpInfo);
348 }
349
350 // At this point, all operand types are decided.
351 // Create the MachineInstr, but don't insert it yet since input
352 // operands still need to insert instructions before this one
353 auto Inst = MIRBuilder.buildInstrNoInsert(TargetOpcode::INLINEASM)
354 .addExternalSymbol(IA->getAsmString().c_str())
355 .addImm(ExtraInfo.get());
356
357 // Starting from this operand: flag followed by register(s) will be added as
358 // operands to Inst for each constraint. Used for matching input constraints.
359 unsigned StartIdx = Inst->getNumOperands();
360
361 // Collects the output operands for later processing
362 GISelAsmOperandInfoVector OutputOperands;
363
364 for (auto &OpInfo : ConstraintOperands) {
365 GISelAsmOperandInfo &RefOpInfo =
367 ? ConstraintOperands[OpInfo.getMatchedOperand()]
368 : OpInfo;
369
370 // Assign registers for register operands
371 getRegistersForValue(MF, MIRBuilder, OpInfo, RefOpInfo);
372
373 switch (OpInfo.Type) {
376 const InlineAsm::ConstraintCode ConstraintID =
379 "Failed to convert memory constraint code to constraint id.");
380
381 // Add information to the INLINEASM instruction to know about this
382 // output.
384 Flag.setMemConstraint(ConstraintID);
385 Inst.addImm(Flag);
386 ArrayRef<Register> SourceRegs =
387 GetOrCreateVRegs(*OpInfo.CallOperandVal);
388 assert(
389 SourceRegs.size() == 1 &&
390 "Expected the memory output to fit into a single virtual register");
391 Inst.addReg(SourceRegs[0]);
392 } else {
393 // Otherwise, this outputs to a register (directly for C_Register /
394 // C_RegisterClass/C_Other.
398
399 // Find a register that we can use.
400 if (OpInfo.Regs.empty()) {
402 << "Couldn't allocate output register for constraint\n");
403 return false;
404 }
405
406 // Add information to the INLINEASM instruction to know that this
407 // register is set.
411 OpInfo.Regs.size());
412 if (OpInfo.Regs.front().isVirtual()) {
413 // Put the register class of the virtual registers in the flag word.
414 // That way, later passes can recompute register class constraints for
415 // inline assembly as well as normal instructions. Don't do this for
416 // tied operands that can use the regclass information from the def.
417 const TargetRegisterClass *RC = MRI->getRegClass(OpInfo.Regs.front());
418 Flag.setRegClass(RC->getID());
419 }
420
421 Inst.addImm(Flag);
422
423 for (Register Reg : OpInfo.Regs) {
424 Inst.addReg(Reg,
425 RegState::Define | getImplRegState(Reg.isPhysical()) |
427 }
428
429 // Remember this output operand for later processing
430 OutputOperands.push_back(OpInfo);
431 }
432
433 break;
435 case InlineAsm::isLabel: {
436 if (OpInfo.isMatchingInputConstraint()) {
437 unsigned DefIdx = OpInfo.getMatchedOperand();
438 // Find operand with register def that corresponds to DefIdx.
439 unsigned InstFlagIdx = StartIdx;
440 for (unsigned i = 0; i < DefIdx; ++i)
441 InstFlagIdx += getNumOpRegs(*Inst, InstFlagIdx) + 1;
442 assert(getNumOpRegs(*Inst, InstFlagIdx) == 1 && "Wrong flag");
443
444 const InlineAsm::Flag MatchedOperandFlag(Inst->getOperand(InstFlagIdx).getImm());
445 if (MatchedOperandFlag.isMemKind()) {
446 LLVM_DEBUG(dbgs() << "Matching input constraint to mem operand not "
447 "supported. This should be target specific.\n");
448 return false;
449 }
450 if (!MatchedOperandFlag.isRegDefKind() && !MatchedOperandFlag.isRegDefEarlyClobberKind()) {
451 LLVM_DEBUG(dbgs() << "Unknown matching constraint\n");
452 return false;
453 }
454
455 // We want to tie input to register in next operand.
456 unsigned DefRegIdx = InstFlagIdx + 1;
457 Register Def = Inst->getOperand(DefRegIdx).getReg();
458
459 ArrayRef<Register> SrcRegs = GetOrCreateVRegs(*OpInfo.CallOperandVal);
460 assert(SrcRegs.size() == 1 && "Single register is expected here");
461
462 // When Def is physreg: use given input.
463 Register In = SrcRegs[0];
464 // When Def is vreg: copy input to new vreg with same reg class as Def.
465 if (Def.isVirtual()) {
466 In = MRI->createVirtualRegister(MRI->getRegClass(Def));
467 if (!buildAnyextOrCopy(In, SrcRegs[0], MIRBuilder))
468 return false;
469 }
470
471 // Add Flag and input register operand (In) to Inst. Tie In to Def.
473 UseFlag.setMatchingOp(DefIdx);
474 Inst.addImm(UseFlag);
475 Inst.addReg(In);
476 Inst->tieOperands(DefRegIdx, Inst->getNumOperands() - 1);
477 break;
478 }
479
481 OpInfo.isIndirect) {
482 LLVM_DEBUG(dbgs() << "Indirect input operands with unknown constraint "
483 "not supported yet\n");
484 return false;
485 }
486
489
490 std::vector<MachineOperand> Ops;
492 OpInfo.ConstraintCode, Ops,
493 MIRBuilder)) {
494 LLVM_DEBUG(dbgs() << "Don't support constraint: "
495 << OpInfo.ConstraintCode << " yet\n");
496 return false;
497 }
498
499 assert(Ops.size() > 0 &&
500 "Expected constraint to be lowered to at least one operand");
501
502 // Add information to the INLINEASM node to know about this input.
503 const unsigned OpFlags =
505 Inst.addImm(OpFlags);
506 Inst.add(Ops);
507 break;
508 }
509
511
512 if (!OpInfo.isIndirect) {
514 << "Cannot indirectify memory input operands yet\n");
515 return false;
516 }
517
518 assert(OpInfo.isIndirect && "Operand must be indirect to be a mem!");
519
520 const InlineAsm::ConstraintCode ConstraintID =
523 OpFlags.setMemConstraint(ConstraintID);
524 Inst.addImm(OpFlags);
525 ArrayRef<Register> SourceRegs =
526 GetOrCreateVRegs(*OpInfo.CallOperandVal);
527 assert(
528 SourceRegs.size() == 1 &&
529 "Expected the memory input to fit into a single virtual register");
530 Inst.addReg(SourceRegs[0]);
531 break;
532 }
533
536 "Unknown constraint type!");
537
538 if (OpInfo.isIndirect) {
539 LLVM_DEBUG(dbgs() << "Can't handle indirect register inputs yet "
540 "for constraint '"
541 << OpInfo.ConstraintCode << "'\n");
542 return false;
543 }
544
545 // Copy the input into the appropriate registers.
546 if (OpInfo.Regs.empty()) {
548 dbgs()
549 << "Couldn't allocate input register for register constraint\n");
550 return false;
551 }
552
553 unsigned NumRegs = OpInfo.Regs.size();
554 ArrayRef<Register> SourceRegs = GetOrCreateVRegs(*OpInfo.CallOperandVal);
555 assert(NumRegs == SourceRegs.size() &&
556 "Expected the number of input registers to match the number of "
557 "source registers");
558
559 if (NumRegs > 1) {
560 LLVM_DEBUG(dbgs() << "Input operands with multiple input registers are "
561 "not supported yet\n");
562 return false;
563 }
564
566 if (OpInfo.Regs.front().isVirtual()) {
567 // Put the register class of the virtual registers in the flag word.
568 const TargetRegisterClass *RC = MRI->getRegClass(OpInfo.Regs.front());
569 Flag.setRegClass(RC->getID());
570 }
571 Inst.addImm(Flag);
572 if (!buildAnyextOrCopy(OpInfo.Regs[0], SourceRegs[0], MIRBuilder))
573 return false;
574 Inst.addReg(OpInfo.Regs[0]);
575 break;
576 }
577
579
580 const unsigned NumRegs = OpInfo.Regs.size();
581 if (NumRegs > 0) {
582 unsigned Flag = InlineAsm::Flag(InlineAsm::Kind::Clobber, NumRegs);
583 Inst.addImm(Flag);
584
585 for (Register Reg : OpInfo.Regs) {
586 Inst.addReg(Reg, RegState::Define | RegState::EarlyClobber |
587 getImplRegState(Reg.isPhysical()));
588 }
589 }
590 break;
591 }
592 }
593 }
594
595 if (const MDNode *SrcLoc = Call.getMetadata("srcloc"))
596 Inst.addMetadata(SrcLoc);
597
598 // All inputs are handled, insert the instruction now
599 MIRBuilder.insertInstr(Inst);
600
601 // Finally, copy the output operands into the output registers
602 ArrayRef<Register> ResRegs = GetOrCreateVRegs(Call);
603 if (ResRegs.size() != OutputOperands.size()) {
604 LLVM_DEBUG(dbgs() << "Expected the number of output registers to match the "
605 "number of destination registers\n");
606 return false;
607 }
608 for (unsigned int i = 0, e = ResRegs.size(); i < e; i++) {
609 GISelAsmOperandInfo &OpInfo = OutputOperands[i];
610
611 if (OpInfo.Regs.empty())
612 continue;
613
614 switch (OpInfo.ConstraintType) {
617 if (OpInfo.Regs.size() > 1) {
618 LLVM_DEBUG(dbgs() << "Output operands with multiple defining "
619 "registers are not supported yet\n");
620 return false;
621 }
622
623 Register SrcReg = OpInfo.Regs[0];
624 unsigned SrcSize = TRI->getRegSizeInBits(SrcReg, *MRI);
625 LLT ResTy = MRI->getType(ResRegs[i]);
626 if (ResTy.isScalar() && ResTy.getSizeInBits() < SrcSize) {
627 // First copy the non-typed virtual register into a generic virtual
628 // register
629 Register Tmp1Reg =
630 MRI->createGenericVirtualRegister(LLT::scalar(SrcSize));
631 MIRBuilder.buildCopy(Tmp1Reg, SrcReg);
632 // Need to truncate the result of the register
633 MIRBuilder.buildTrunc(ResRegs[i], Tmp1Reg);
634 } else if (ResTy.getSizeInBits() == SrcSize) {
635 MIRBuilder.buildCopy(ResRegs[i], SrcReg);
636 } else {
637 LLVM_DEBUG(dbgs() << "Unhandled output operand with "
638 "mismatched register size\n");
639 return false;
640 }
641
642 break;
643 }
647 dbgs() << "Cannot lower target specific output constraints yet\n");
648 return false;
650 break; // Already handled.
652 break; // Silence warning.
654 LLVM_DEBUG(dbgs() << "Unexpected unknown constraint\n");
655 return false;
656 }
657 }
658
659 return true;
660}
661
663 Value *Val, StringRef Constraint, std::vector<MachineOperand> &Ops,
664 MachineIRBuilder &MIRBuilder) const {
665 if (Constraint.size() > 1)
666 return false;
667
668 char ConstraintLetter = Constraint[0];
669 switch (ConstraintLetter) {
670 default:
671 return false;
672 case 'i': // Simple Integer or Relocatable Constant
673 case 'n': // immediate integer with a known value.
674 if (ConstantInt *CI = dyn_cast<ConstantInt>(Val)) {
675 assert(CI->getBitWidth() <= 64 &&
676 "expected immediate to fit into 64-bits");
677 // Boolean constants should be zero-extended, others are sign-extended
678 bool IsBool = CI->getBitWidth() == 1;
679 int64_t ExtVal = IsBool ? CI->getZExtValue() : CI->getSExtValue();
680 Ops.push_back(MachineOperand::CreateImm(ExtVal));
681 return true;
682 }
683 return false;
684 }
685}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
#define LLVM_DEBUG(X)
Definition: Debug.h:101
static void chooseConstraint(TargetLowering::AsmOperandInfo &OpInfo, const TargetLowering *TLI)
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 unsigned getConstraintGenerality(TargetLowering::ConstraintType CT)
Return an integer indicating how general CT is.
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
This file declares the MachineIRBuilder class.
unsigned const TargetRegisterInfo * TRI
Module.h This file contains the declarations for the Module class.
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:165
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1190
Value * getCalledOperand() const
Definition: InstrTypes.h:1405
bool isConvergent() const
Determine if the invoke is convergent.
Definition: InstrTypes.h:1938
This is the shared class of boolean and integer constants.
Definition: Constants.h:78
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:110
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:320
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:324
void setMatchingOp(unsigned OperandNo)
setMatchingOp - Augment an existing flag with information indicating that this input operand is tied ...
Definition: InlineAsm.h:381
void setMemConstraint(ConstraintCode C)
setMemConstraint - Augment an existing flag with the constraint code for a memory constraint.
Definition: InlineAsm.h:400
bool isRegDefEarlyClobberKind() const
Definition: InlineAsm.h:319
bool isRegDefKind() const
Definition: InlineAsm.h:318
constexpr bool isScalar() const
Definition: LowLevelType.h:139
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:175
Metadata node.
Definition: Metadata.h:950
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 buildAnyExt(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ANYEXT Op0.
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_TRUNC Op.
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:68
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:546
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:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
Class to represent struct types.
Definition: DerivedTypes.h:213
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...
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...
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:287
LLVM Value Representation.
Definition: Value.h:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ 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:299
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
bool hasMatchingInput() const
hasMatchingInput - Return true if this is an output constraint that has a matching input constraint.
Definition: InlineAsm.h:140
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".