LLVM 24.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
21#include "llvm/IR/Module.h"
22
23#define DEBUG_TYPE "inline-asm-lowering"
24
25using namespace llvm;
26
27void InlineAsmLowering::anchor() {}
28
29/// Emit an inline asm error diagnostic and materialize undef values for the
30/// call results so that the rest of the function remains well-formed.
31static void emitInlineAsmError(MachineIRBuilder &MIRBuilder,
32 const CallBase &Call, const Twine &Message,
33 ArrayRef<Register> ResRegs) {
34 Call.getContext().diagnose(DiagnosticInfoInlineAsm(Call, Message));
35 for (Register Reg : ResRegs)
36 MIRBuilder.buildUndef(Reg);
37}
38
39namespace {
40
41/// GISelAsmOperandInfo - This contains information for each constraint that we
42/// are lowering.
43class GISelAsmOperandInfo : public TargetLowering::AsmOperandInfo {
44public:
45 /// Regs - If this is a register or register class operand, this
46 /// contains the set of assigned registers corresponding to the operand.
47 SmallVector<Register, 1> Regs;
48
49 /// The register class selected for this operand's constraint.
50 const TargetRegisterClass *RegClass = nullptr;
51
52 explicit GISelAsmOperandInfo(const TargetLowering::AsmOperandInfo &Info)
53 : TargetLowering::AsmOperandInfo(Info) {}
54};
55
56using GISelAsmOperandInfoVector = SmallVector<GISelAsmOperandInfo, 16>;
57
58class ExtraFlags {
59 unsigned Flags = 0;
60
61public:
62 explicit ExtraFlags(const CallBase &CB) {
63 const InlineAsm *IA = cast<InlineAsm>(CB.getCalledOperand());
64 if (IA->hasSideEffects())
66 if (IA->isAlignStack())
68 if (IA->canThrow())
70 if (CB.isConvergent())
72 Flags |= IA->getDialect() * InlineAsm::Extra_AsmDialect;
73 }
74
75 void update(const TargetLowering::AsmOperandInfo &OpInfo) {
76 // Ideally, we would only check against memory constraints. However, the
77 // meaning of an Other constraint can be target-specific and we can't easily
78 // reason about it. Therefore, be conservative and set MayLoad/MayStore
79 // for Other constraints as well.
82 if (OpInfo.Type == InlineAsm::isInput)
84 else if (OpInfo.Type == InlineAsm::isOutput)
86 else if (OpInfo.Type == InlineAsm::isClobber)
88 }
89 }
90
91 unsigned get() const { return Flags; }
92};
93
94} // namespace
95
96/// Assign virtual/physical registers for the specified register operand.
98 MachineIRBuilder &MIRBuilder,
99 GISelAsmOperandInfo &OpInfo,
100 GISelAsmOperandInfo &RefOpInfo) {
101
102 const TargetLowering &TLI = *MF.getSubtarget().getTargetLowering();
104
105 // No work to do for memory operations.
106 if (OpInfo.ConstraintType == TargetLowering::C_Memory)
107 return;
108
109 // If this is a constraint for a single physreg, or a constraint for a
110 // register class, find it.
111 Register AssignedReg;
112 const TargetRegisterClass *RC;
113 std::tie(AssignedReg, RC) = TLI.getRegForInlineAsmConstraint(
114 &TRI, RefOpInfo.ConstraintCode, RefOpInfo.ConstraintVT);
115 // RC is unset only on failure. Return immediately.
116 if (!RC)
117 return;
118 OpInfo.RegClass = RC;
119
120 // No need to allocate a matching input constraint since the constraint it's
121 // matching to has already been allocated.
122 if (OpInfo.isMatchingInputConstraint())
123 return;
124
125 // Initialize NumRegs.
126 unsigned NumRegs = 1;
127 if (OpInfo.ConstraintVT != MVT::Other)
128 NumRegs =
129 TLI.getNumRegisters(MF.getFunction().getContext(), OpInfo.ConstraintVT);
130
131 // If this is a constraint for a specific physical register, but the type of
132 // the operand requires more than one register to be passed, we allocate the
133 // required amount of physical registers, starting from the selected physical
134 // register.
135 // For this, first retrieve a register iterator for the given register class
138
139 // Advance the iterator to the assigned register (if set)
140 if (AssignedReg) {
141 for (; *I != AssignedReg; ++I)
142 assert(I != RC->end() && "AssignedReg should be a member of provided RC");
143 }
144
145 // Finally, assign the registers. If the AssignedReg isn't set, create virtual
146 // registers with the provided register class
147 for (; NumRegs; --NumRegs, ++I) {
148 assert(I != RC->end() && "Ran out of registers to allocate!");
149 Register R = AssignedReg ? Register(*I) : RegInfo.createVirtualRegister(RC);
150 OpInfo.Regs.push_back(R);
151 }
152}
153
156 assert(!OpInfo.Codes.empty() && "Must have at least one constraint");
157
158 // Single-letter constraints ('r') are very common.
159 if (OpInfo.Codes.size() == 1) {
160 OpInfo.ConstraintCode = OpInfo.Codes[0];
161 OpInfo.ConstraintType = TLI->getConstraintType(OpInfo.ConstraintCode);
162 } else {
164 if (G.empty())
165 return;
166 // FIXME: prefer immediate constraints if the target allows it
167 unsigned BestIdx = 0;
168 for (const unsigned E = G.size();
169 BestIdx < E && (G[BestIdx].second == TargetLowering::C_Other ||
170 G[BestIdx].second == TargetLowering::C_Immediate);
171 ++BestIdx)
172 ;
173 OpInfo.ConstraintCode = G[BestIdx].first;
174 OpInfo.ConstraintType = G[BestIdx].second;
175 }
176
177 // 'X' matches anything.
178 if (OpInfo.ConstraintCode == "X" && OpInfo.CallOperandVal) {
179 // Labels and constants are handled elsewhere ('X' is the only thing
180 // that matches labels). For Functions, the type here is the type of
181 // the result, which is not what we want to look at; leave them alone.
182 Value *Val = OpInfo.CallOperandVal;
183 if (isa<BasicBlock>(Val) || isa<ConstantInt>(Val) || isa<Function>(Val))
184 return;
185
186 // Otherwise, try to resolve it to something we know about by looking at
187 // the actual operand type.
188 if (const char *Repl = TLI->LowerXConstraint(OpInfo.ConstraintVT)) {
189 OpInfo.ConstraintCode = Repl;
190 OpInfo.ConstraintType = TLI->getConstraintType(OpInfo.ConstraintCode);
191 }
192 }
193}
194
195static unsigned getNumOpRegs(const MachineInstr &I, unsigned OpIdx) {
196 const InlineAsm::Flag F(I.getOperand(OpIdx).getImm());
197 return F.getNumOperandRegisters();
198}
199
201 MachineIRBuilder &MIRBuilder) {
202 const TargetRegisterInfo *TRI =
203 MIRBuilder.getMF().getSubtarget().getRegisterInfo();
204 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
205
206 auto SrcTy = MRI->getType(Src);
207 if (!SrcTy.isValid()) {
208 LLVM_DEBUG(dbgs() << "Source type for copy is not valid\n");
209 return false;
210 }
211 unsigned SrcSize = TRI->getRegSizeInBits(Src, *MRI);
212 unsigned DstSize = TRI->getRegSizeInBits(Dst, *MRI);
213
214 if (DstSize < SrcSize) {
215 LLVM_DEBUG(dbgs() << "Input can't fit in destination reg class\n");
216 return false;
217 }
218
219 // Attempt to anyext small scalar sources.
220 if (DstSize > SrcSize) {
221 if (!SrcTy.isScalar()) {
222 LLVM_DEBUG(dbgs() << "Can't extend non-scalar input to size of"
223 "destination register class\n");
224 return false;
225 }
226 Src = MIRBuilder.buildAnyExt(LLT::integer(DstSize), Src).getReg(0);
227 }
228
229 MIRBuilder.buildCopy(Dst, Src);
230 return true;
231}
232
234 MachineIRBuilder &MIRBuilder, const CallBase &Call,
235 std::function<ArrayRef<Register>(const Value &Val)> GetOrCreateVRegs)
236 const {
237 const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand());
238
239 /// ConstraintOperands - Information about all of the constraints.
240 GISelAsmOperandInfoVector ConstraintOperands;
241
242 MachineFunction &MF = MIRBuilder.getMF();
243 const Function &F = MF.getFunction();
244 const DataLayout &DL = F.getDataLayout();
246
247 MachineRegisterInfo *MRI = MIRBuilder.getMRI();
248
249 TargetLowering::AsmOperandInfoVector TargetConstraints =
250 TLI->ParseConstraints(DL, TRI, Call);
251
252 ExtraFlags ExtraInfo(Call);
253 unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
254 unsigned ResNo = 0; // ResNo - The result number of the next output.
255 for (auto &T : TargetConstraints) {
256 ConstraintOperands.push_back(GISelAsmOperandInfo(T));
257 GISelAsmOperandInfo &OpInfo = ConstraintOperands.back();
258
259 // Compute the value type for each operand.
260 if (OpInfo.hasArg()) {
261 OpInfo.CallOperandVal = Call.getArgOperand(ArgNo);
262
263 if (isa<BasicBlock>(OpInfo.CallOperandVal)) {
264 LLVM_DEBUG(dbgs() << "Basic block input operands not supported yet\n");
265 return false;
266 }
267
268 Type *OpTy = OpInfo.CallOperandVal->getType();
269
270 // If this is an indirect operand, the operand is a pointer to the
271 // accessed type.
272 if (OpInfo.isIndirect) {
273 OpTy = Call.getParamElementType(ArgNo);
274 assert(OpTy && "Indirect operand must have elementtype attribute");
275 }
276
277 // FIXME: Support aggregate input operands
278 if (!OpTy->isSingleValueType()) {
280 dbgs() << "Aggregate input operands are not supported yet\n");
281 return false;
282 }
283
284 OpInfo.ConstraintVT =
285 TLI->getAsmOperandValueType(DL, OpTy, true).getSimpleVT();
286 ++ArgNo;
287 } else if (OpInfo.Type == InlineAsm::isOutput && !OpInfo.isIndirect) {
288 assert(!Call.getType()->isVoidTy() && "Bad inline asm!");
289 if (StructType *STy = dyn_cast<StructType>(Call.getType())) {
290 OpInfo.ConstraintVT =
291 TLI->getSimpleValueType(DL, STy->getElementType(ResNo));
292 } else {
293 assert(ResNo == 0 && "Asm only has one result!");
294 OpInfo.ConstraintVT =
295 TLI->getAsmOperandValueType(DL, Call.getType()).getSimpleVT();
296 }
297 ++ResNo;
298 } else {
299 assert(OpInfo.Type != InlineAsm::isLabel &&
300 "GlobalISel currently doesn't support callbr");
301 OpInfo.ConstraintVT = MVT::Other;
302 }
303
304 if (OpInfo.ConstraintVT == MVT::i64x8)
305 return false;
306
307 // Compute the constraint code and ConstraintType to use.
308 computeConstraintToUse(TLI, OpInfo);
309
310 // The selected constraint type might expose new sideeffects
311 ExtraInfo.update(OpInfo);
312 }
313
314 // At this point, all operand types are decided.
315 // Create the MachineInstr, but don't insert it yet since input
316 // operands still need to insert instructions before this one
317 auto Inst = MIRBuilder.buildInstrNoInsert(TargetOpcode::INLINEASM)
318 .addExternalSymbol(IA->getAsmString().data())
319 .addImm(ExtraInfo.get());
320
321 // Starting from this operand: flag followed by register(s) will be added as
322 // operands to Inst for each constraint. Used for matching input constraints.
323 unsigned StartIdx = Inst->getNumOperands();
324
325 // Collects the output operands for later processing
326 GISelAsmOperandInfoVector OutputOperands;
327
328 for (auto &OpInfo : ConstraintOperands) {
329 GISelAsmOperandInfo &RefOpInfo =
330 OpInfo.isMatchingInputConstraint()
331 ? ConstraintOperands[OpInfo.getMatchedOperand()]
332 : OpInfo;
333
334 // Assign registers for register operands
335 getRegistersForValue(MF, MIRBuilder, OpInfo, RefOpInfo);
336
337 switch (OpInfo.Type) {
339 if (OpInfo.ConstraintType == TargetLowering::C_Memory) {
340 const InlineAsm::ConstraintCode ConstraintID =
341 TLI->getInlineAsmMemConstraint(OpInfo.ConstraintCode);
343 "Failed to convert memory constraint code to constraint id.");
344
345 // Add information to the INLINEASM instruction to know about this
346 // output.
348 Flag.setMemConstraint(ConstraintID);
349 Inst.addImm(Flag);
350 ArrayRef<Register> SourceRegs =
351 GetOrCreateVRegs(*OpInfo.CallOperandVal);
352 assert(
353 SourceRegs.size() == 1 &&
354 "Expected the memory output to fit into a single virtual register");
355 Inst.addReg(SourceRegs[0]);
356 } else {
357 // Otherwise, this outputs to a register (directly for C_Register /
358 // C_RegisterClass/C_Other.
359 assert(OpInfo.ConstraintType == TargetLowering::C_Register ||
360 OpInfo.ConstraintType == TargetLowering::C_RegisterClass ||
361 OpInfo.ConstraintType == TargetLowering::C_Other);
362
363 // Find a register that we can use.
364 if (OpInfo.Regs.empty()) {
365 emitInlineAsmError(MIRBuilder, Call,
366 "could not allocate output register for "
367 "constraint '" +
368 Twine(OpInfo.ConstraintCode) + "'",
369 GetOrCreateVRegs(Call));
370 return true;
371 }
372
373 // Add information to the INLINEASM instruction to know that this
374 // register is set.
375 InlineAsm::Flag Flag(OpInfo.isEarlyClobber
378 OpInfo.Regs.size());
379 if (OpInfo.Regs.front().isVirtual()) {
380 // Put the register class of the virtual registers in the flag word.
381 // That way, later passes can recompute register class constraints for
382 // inline assembly as well as normal instructions. Don't do this for
383 // tied operands that can use the regclass information from the def.
384 const TargetRegisterClass *RC = MRI->getRegClass(OpInfo.Regs.front());
385 Flag.setRegClass(RC->getID());
386 }
387
388 Inst.addImm(Flag);
389
390 for (Register Reg : OpInfo.Regs) {
391 Inst.addReg(Reg, RegState::Define |
392 getImplRegState(Reg.isPhysical()) |
393 getEarlyClobberRegState(OpInfo.isEarlyClobber));
394 }
395
396 // Remember this output operand for later processing
397 OutputOperands.push_back(OpInfo);
398 }
399
400 break;
402 case InlineAsm::isLabel: {
403 if (OpInfo.isMatchingInputConstraint()) {
404 unsigned DefIdx = OpInfo.getMatchedOperand();
405 // Find operand with register def that corresponds to DefIdx.
406 unsigned InstFlagIdx = StartIdx;
407 for (unsigned i = 0; i < DefIdx; ++i)
408 InstFlagIdx += getNumOpRegs(*Inst, InstFlagIdx) + 1;
409 assert(getNumOpRegs(*Inst, InstFlagIdx) == 1 && "Wrong flag");
410
411 const InlineAsm::Flag MatchedOperandFlag(Inst->getOperand(InstFlagIdx).getImm());
412 if (MatchedOperandFlag.isMemKind()) {
413 LLVM_DEBUG(dbgs() << "Matching input constraint to mem operand not "
414 "supported. This should be target specific.\n");
415 return false;
416 }
417 if (!MatchedOperandFlag.isRegDefKind() && !MatchedOperandFlag.isRegDefEarlyClobberKind()) {
418 LLVM_DEBUG(dbgs() << "Unknown matching constraint\n");
419 return false;
420 }
421
422 // We want to tie input to register in next operand.
423 unsigned DefRegIdx = InstFlagIdx + 1;
424 Register Def = Inst->getOperand(DefRegIdx).getReg();
425
426 ArrayRef<Register> SrcRegs = GetOrCreateVRegs(*OpInfo.CallOperandVal);
427 assert(SrcRegs.size() == 1 && "Single register is expected here");
428
429 // We need the tied input to live in the same register class as the def.
430 //
431 // - if Def is a vreg, we can just use its regclass.
432 // - if Def is a physreg, create a vreg in the regclass selected for its
433 // constraint.
434 //
435 // Otherwise RegBankSelect may leave it in the wrong bank (e.g. GPR even
436 // though it's tied to an FP physreg).
437 const TargetRegisterClass *RC =
438 Def.isVirtual() ? MRI->getRegClass(Def) : OpInfo.RegClass;
439 assert(RC && "Expected a register class for matching constraint");
440
441 // Materialize `In` in a new vreg that has a register class that matches
442 // the register class of `Def`.
443 Register In = MRI->createVirtualRegister(RC);
444 if (!buildAnyextOrCopy(In, SrcRegs[0], MIRBuilder))
445 return false;
446
447 // Add Flag and input register operand (In) to Inst. Tie In to Def.
449 UseFlag.setMatchingOp(DefIdx);
450 Inst.addImm(UseFlag);
451 Inst.addReg(In);
452 Inst->tieOperands(DefRegIdx, Inst->getNumOperands() - 1);
453 break;
454 }
455
456 if (OpInfo.ConstraintType == TargetLowering::C_Other &&
457 OpInfo.isIndirect) {
458 LLVM_DEBUG(dbgs() << "Indirect input operands with unknown constraint "
459 "not supported yet\n");
460 return false;
461 }
462
463 if (OpInfo.ConstraintType == TargetLowering::C_Immediate ||
464 OpInfo.ConstraintType == TargetLowering::C_Other) {
465
466 std::vector<MachineOperand> Ops;
467 if (!lowerAsmOperandForConstraint(OpInfo.CallOperandVal,
468 OpInfo.ConstraintCode, Ops,
469 MIRBuilder)) {
470 LLVM_DEBUG(dbgs() << "Don't support constraint: "
471 << OpInfo.ConstraintCode << " yet\n");
472 return false;
473 }
474
475 assert(Ops.size() > 0 &&
476 "Expected constraint to be lowered to at least one operand");
477
478 // Add information to the INLINEASM node to know about this input.
479 const unsigned OpFlags =
481 Inst.addImm(OpFlags);
482 Inst.add(Ops);
483 break;
484 }
485
486 if (OpInfo.ConstraintType == TargetLowering::C_Memory) {
487 const InlineAsm::ConstraintCode ConstraintID =
488 TLI->getInlineAsmMemConstraint(OpInfo.ConstraintCode);
490 OpFlags.setMemConstraint(ConstraintID);
491 Inst.addImm(OpFlags);
492
493 if (OpInfo.isIndirect) {
494 // already indirect
495 ArrayRef<Register> SourceRegs =
496 GetOrCreateVRegs(*OpInfo.CallOperandVal);
497 if (SourceRegs.size() != 1) {
498 LLVM_DEBUG(dbgs() << "Expected the memory input to fit into a "
499 "single virtual register "
500 "for constraint '"
501 << OpInfo.ConstraintCode << "'\n");
502 return false;
503 }
504 Inst.addReg(SourceRegs[0]);
505 break;
506 }
507
508 // Needs to be made indirect. Store the value on the stack and use
509 // a pointer to it.
510 Value *OpVal = OpInfo.CallOperandVal;
511 TypeSize Bytes = DL.getTypeStoreSize(OpVal->getType());
512 Align Alignment = DL.getPrefTypeAlign(OpVal->getType());
513 int FrameIdx =
514 MF.getFrameInfo().CreateStackObject(Bytes, Alignment, false);
515
516 unsigned AddrSpace = DL.getAllocaAddrSpace();
517 LLT FramePtrTy =
518 LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace));
519 auto Ptr = MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx).getReg(0);
520 ArrayRef<Register> SourceRegs =
521 GetOrCreateVRegs(*OpInfo.CallOperandVal);
522 if (SourceRegs.size() != 1) {
523 LLVM_DEBUG(dbgs() << "Expected the memory input to fit into a single "
524 "virtual register "
525 "for constraint '"
526 << OpInfo.ConstraintCode << "'\n");
527 return false;
528 }
529 MIRBuilder.buildStore(SourceRegs[0], Ptr,
531 Alignment);
532 Inst.addReg(Ptr);
533 break;
534 }
535
536 assert((OpInfo.ConstraintType == TargetLowering::C_RegisterClass ||
537 OpInfo.ConstraintType == TargetLowering::C_Register) &&
538 "Unknown constraint type!");
539
540 if (OpInfo.isIndirect) {
541 LLVM_DEBUG(dbgs() << "Can't handle indirect register inputs yet "
542 "for constraint '"
543 << OpInfo.ConstraintCode << "'\n");
544 return false;
545 }
546
547 // Copy the input into the appropriate registers.
548 if (OpInfo.Regs.empty()) {
549 emitInlineAsmError(MIRBuilder, Call,
550 "could not allocate input reg for constraint '" +
551 Twine(OpInfo.ConstraintCode) + "'",
552 GetOrCreateVRegs(Call));
553 return true;
554 }
555
556 unsigned NumRegs = OpInfo.Regs.size();
557 ArrayRef<Register> SourceRegs = GetOrCreateVRegs(*OpInfo.CallOperandVal);
558 if (NumRegs != 1 || SourceRegs.size() != 1) {
559 LLVM_DEBUG(dbgs() << "Input operands with multiple input registers are "
560 "not supported yet\n");
561 return false;
562 }
563
565 if (OpInfo.Regs.front().isVirtual()) {
566 // Put the register class of the virtual registers in the flag word.
567 const TargetRegisterClass *RC = MRI->getRegClass(OpInfo.Regs.front());
568 Flag.setRegClass(RC->getID());
569 }
570 Inst.addImm(Flag);
571 if (!buildAnyextOrCopy(OpInfo.Regs[0], SourceRegs[0], MIRBuilder))
572 return false;
573 Inst.addReg(OpInfo.Regs[0]);
574 break;
575 }
576
578
579 const unsigned NumRegs = OpInfo.Regs.size();
580 if (NumRegs > 0) {
581 unsigned Flag = InlineAsm::Flag(InlineAsm::Kind::Clobber, NumRegs);
582 Inst.addImm(Flag);
583
584 for (Register Reg : OpInfo.Regs) {
585 Inst.addReg(Reg, RegState::Define | RegState::EarlyClobber |
586 getImplRegState(Reg.isPhysical()));
587 }
588 }
589 break;
590 }
591 }
592 }
593
594 if (auto Bundle = Call.getOperandBundle(LLVMContext::OB_convergencectrl)) {
595 auto *Token = Bundle->Inputs[0].get();
596 ArrayRef<Register> SourceRegs = GetOrCreateVRegs(*Token);
597 assert(SourceRegs.size() == 1 &&
598 "Expected the control token to fit into a single virtual register");
599 Inst.addUse(SourceRegs[0], RegState::Implicit);
600 }
601
602 if (const MDNode *SrcLoc = Call.getMetadata("srcloc"))
603 Inst.addMetadata(SrcLoc);
604
605 // Add rounding control registers as implicit def for inline asm.
606 if (MF.getFunction().hasFnAttribute(Attribute::StrictFP)) {
607 ArrayRef<MCPhysReg> RCRegs = TLI->getRoundingControlRegisters();
608 for (MCPhysReg Reg : RCRegs)
609 Inst.addReg(Reg, RegState::ImplicitDefine);
610 }
611
612 // All inputs are handled, insert the instruction now
613 MIRBuilder.insertInstr(Inst);
614
615 // Finally, copy the output operands into the output registers
616 ArrayRef<Register> ResRegs = GetOrCreateVRegs(Call);
617 if (ResRegs.size() != OutputOperands.size()) {
618 LLVM_DEBUG(dbgs() << "Expected the number of output registers to match the "
619 "number of destination registers\n");
620 return false;
621 }
622 for (unsigned int i = 0, e = ResRegs.size(); i < e; i++) {
623 GISelAsmOperandInfo &OpInfo = OutputOperands[i];
624
625 if (OpInfo.Regs.empty())
626 continue;
627
628 switch (OpInfo.ConstraintType) {
631 if (OpInfo.Regs.size() > 1) {
632 LLVM_DEBUG(dbgs() << "Output operands with multiple defining "
633 "registers are not supported yet\n");
634 return false;
635 }
636
637 Register SrcReg = OpInfo.Regs[0];
638 unsigned SrcSize = TRI->getRegSizeInBits(SrcReg, *MRI);
639 LLT ResTy = MRI->getType(ResRegs[i]);
640 if (ResTy.isScalar() && ResTy.getSizeInBits() < SrcSize) {
641 // First copy the non-typed virtual register into a generic virtual
642 // register
643 auto Copy = MIRBuilder.buildCopy(LLT::integer(SrcSize), SrcReg);
644 // Need to truncate the result of the register
645 MIRBuilder.buildTrunc(ResRegs[i], Copy);
646 } else if (ResTy.getSizeInBits() == SrcSize) {
647 MIRBuilder.buildCopy(ResRegs[i], SrcReg);
648 } else {
649 LLVM_DEBUG(dbgs() << "Unhandled output operand with "
650 "mismatched register size\n");
651 return false;
652 }
653
654 break;
655 }
659 dbgs() << "Cannot lower target specific output constraints yet\n");
660 return false;
662 break; // Already handled.
664 break; // Silence warning.
666 LLVM_DEBUG(dbgs() << "Unexpected unknown constraint\n");
667 return false;
668 }
669 }
670
671 return true;
672}
673
675 Value *Val, StringRef Constraint, std::vector<MachineOperand> &Ops,
676 MachineIRBuilder &MIRBuilder) const {
677 if (Constraint.size() > 1)
678 return false;
679
680 char ConstraintLetter = Constraint[0];
681 switch (ConstraintLetter) {
682 default:
683 return false;
684 case 's': // Integer immediate not known at compile time
685 if (const auto *GV = dyn_cast<GlobalValue>(Val)) {
686 Ops.push_back(MachineOperand::CreateGA(GV, /*Offset=*/0));
687 return true;
688 }
689 return false;
690 case 'i': // Simple Integer or Relocatable Constant
691 if (const auto *GV = dyn_cast<GlobalValue>(Val)) {
692 Ops.push_back(MachineOperand::CreateGA(GV, /*Offset=*/0));
693 return true;
694 }
695 [[fallthrough]];
696 case 'n': // immediate integer with a known value.
697 if (ConstantInt *CI = dyn_cast<ConstantInt>(Val)) {
698 assert(CI->getBitWidth() <= 64 &&
699 "expected immediate to fit into 64-bits");
700 // Boolean constants should be zero-extended, others are sign-extended
701 bool IsBool = CI->getBitWidth() == 1;
702 int64_t ExtVal = IsBool ? CI->getZExtValue() : CI->getSExtValue();
703 Ops.push_back(MachineOperand::CreateImm(ExtVal));
704 return true;
705 }
706 return false;
707 }
708}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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 emitInlineAsmError(MachineIRBuilder &MIRBuilder, const CallBase &Call, const Twine &Message, ArrayRef< Register > ResRegs)
Emit an inline asm error diagnostic and materialize undef values for the call results so that the res...
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.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
This file declares the MachineIRBuilder class.
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
MachineInstr unsigned OpIdx
#define LLVM_DEBUG(...)
Definition Debug.h:119
This file describes how to lower LLVM code to machine code.
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
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Value * getCalledOperand() const
bool isConvergent() const
Determine if the invoke is convergent.
This is the shared class of boolean and integer constants.
Definition Constants.h:87
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
Diagnostic information for inline asm reporting.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:353
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:727
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:338
void setMatchingOp(unsigned OperandNo)
setMatchingOp - Augment an existing flag with information indicating that this input operand is tied ...
Definition InlineAsm.h:395
void setMemConstraint(ConstraintCode C)
setMemConstraint - Augment an existing flag with the constraint code for a memory constraint.
Definition InlineAsm.h:414
bool isRegDefEarlyClobberKind() const
Definition InlineAsm.h:333
bool isRegDefKind() const
Definition InlineAsm.h:332
constexpr bool isScalar() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
static LLT integer(unsigned SizeInBits)
unsigned getID() const
getID() - Return the register class ID number.
const MCPhysReg * iterator
iterator begin() const
begin/end - Return all of the registers in this class.
iterator end() const
Metadata node.
Definition Metadata.h:1069
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
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.
MachineInstrBuilder buildUndef(const DstOp &Res)
Build and insert Res = IMPLICIT_DEF.
MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)
Build and insert G_STORE Val, Addr, MMO.
MachineInstrBuilder buildFrameIndex(const DstOp &Res, int Idx)
Build and insert Res = G_FRAME_INDEX Idx.
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 & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
unsigned getNumOperands() const
Retuns the total number of operands.
static MachineOperand CreateImm(int64_t Val)
static MachineOperand CreateGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
Class to represent struct types.
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.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
SmallVector< ConstraintPair > ConstraintGroup
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.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const TargetLowering * getTargetLowering() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
CallInst * Call
This is an optimization pass for GlobalISel generic memory operations.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ EarlyClobber
Register definition happens before uses.
@ Define
Register definition.
constexpr RegState getImplRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
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 RegState getEarlyClobberRegState(bool B)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
ConstraintPrefix Type
Type - The basic type of the constraint: input/output/clobber/label.
Definition InlineAsm.h:128
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This contains information for each constraint that we are lowering.
TargetLowering::ConstraintType ConstraintType
Information about the constraint code, e.g.