21#define DEBUG_TYPE "inline-asm-lowering"
25void InlineAsmLowering::anchor() {}
47 explicit ExtraFlags(
const CallBase &CB) {
49 if (
IA->hasSideEffects())
51 if (
IA->isAlignStack())
74 unsigned get()
const {
return Flags; }
82 GISelAsmOperandInfo &OpInfo,
83 GISelAsmOperandInfo &RefOpInfo) {
97 &
TRI, RefOpInfo.ConstraintCode, RefOpInfo.ConstraintVT);
104 if (OpInfo.isMatchingInputConstraint())
108 unsigned NumRegs = 1;
109 if (OpInfo.ConstraintVT != MVT::Other)
123 for (; *
I != AssignedReg; ++
I)
124 assert(
I != RC->
end() &&
"AssignedReg should be a member of provided RC");
129 for (; NumRegs; --NumRegs, ++
I) {
130 assert(
I != RC->
end() &&
"Ran out of registers to allocate!");
132 OpInfo.Regs.push_back(R);
156 assert(OpInfo.
Codes.size() > 1 &&
"Doesn't have multiple constraint options");
157 unsigned BestIdx = 0;
159 int BestGenerality = -1;
162 for (
unsigned i = 0, e = OpInfo.
Codes.size(); i != e; ++i) {
179 "Unhandled multi-letter 'other' constraint");
190 if (Generality > BestGenerality) {
193 BestGenerality = Generality;
203 assert(!OpInfo.
Codes.empty() &&
"Must have at least one constraint");
206 if (OpInfo.
Codes.size() == 1) {
219 if (isa<BasicBlock>(Val) || isa<ConstantInt>(Val) || isa<Function>(Val))
233 return F.getNumOperandRegisters();
242 auto SrcTy =
MRI->getType(Src);
243 if (!SrcTy.isValid()) {
247 unsigned SrcSize =
TRI->getRegSizeInBits(Src, *
MRI);
248 unsigned DstSize =
TRI->getRegSizeInBits(Dst, *
MRI);
250 if (DstSize < SrcSize) {
251 LLVM_DEBUG(
dbgs() <<
"Input can't fit in destination reg class\n");
256 if (DstSize > SrcSize) {
257 if (!SrcTy.isScalar()) {
259 "destination register class\n");
273 const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand());
276 GISelAsmOperandInfoVector ConstraintOperands;
288 ExtraFlags ExtraInfo(Call);
291 for (
auto &
T : TargetConstraints) {
292 ConstraintOperands.push_back(GISelAsmOperandInfo(
T));
293 GISelAsmOperandInfo &OpInfo = ConstraintOperands.back();
296 if (OpInfo.hasArg()) {
299 if (isa<BasicBlock>(OpInfo.CallOperandVal)) {
300 LLVM_DEBUG(
dbgs() <<
"Basic block input operands not supported yet\n");
304 Type *OpTy = OpInfo.CallOperandVal->getType();
308 if (OpInfo.isIndirect) {
309 OpTy = Call.getParamElementType(ArgNo);
310 assert(OpTy &&
"Indirect operand must have elementtype attribute");
316 dbgs() <<
"Aggregate input operands are not supported yet\n");
320 OpInfo.ConstraintVT =
324 assert(!Call.getType()->isVoidTy() &&
"Bad inline asm!");
325 if (
StructType *STy = dyn_cast<StructType>(Call.getType())) {
326 OpInfo.ConstraintVT =
329 assert(ResNo == 0 &&
"Asm only has one result!");
330 OpInfo.ConstraintVT =
336 "GlobalISel currently doesn't support callbr");
337 OpInfo.ConstraintVT = MVT::Other;
340 if (OpInfo.ConstraintVT == MVT::i64x8)
347 ExtraInfo.update(OpInfo);
362 GISelAsmOperandInfoVector OutputOperands;
364 for (
auto &OpInfo : ConstraintOperands) {
365 GISelAsmOperandInfo &RefOpInfo =
373 switch (OpInfo.
Type) {
379 "Failed to convert memory constraint code to constraint id.");
384 Flag.setMemConstraint(ConstraintID);
389 SourceRegs.
size() == 1 &&
390 "Expected the memory output to fit into a single virtual register");
391 Inst.addReg(SourceRegs[0]);
400 if (OpInfo.Regs.empty()) {
402 <<
"Couldn't allocate output register for constraint\n");
412 if (OpInfo.Regs.front().isVirtual()) {
418 Flag.setRegClass(RC->
getID());
430 OutputOperands.push_back(OpInfo);
439 unsigned InstFlagIdx = StartIdx;
440 for (
unsigned i = 0; i < DefIdx; ++i)
444 const InlineAsm::Flag MatchedOperandFlag(Inst->getOperand(InstFlagIdx).getImm());
446 LLVM_DEBUG(
dbgs() <<
"Matching input constraint to mem operand not "
447 "supported. This should be target specific.\n");
456 unsigned DefRegIdx = InstFlagIdx + 1;
457 Register Def = Inst->getOperand(DefRegIdx).getReg();
460 assert(SrcRegs.
size() == 1 &&
"Single register is expected here");
465 if (Def.isVirtual()) {
466 In =
MRI->createVirtualRegister(
MRI->getRegClass(Def));
474 Inst.addImm(UseFlag);
476 Inst->tieOperands(DefRegIdx, Inst->getNumOperands() - 1);
482 LLVM_DEBUG(
dbgs() <<
"Indirect input operands with unknown constraint "
483 "not supported yet\n");
490 std::vector<MachineOperand> Ops;
500 "Expected constraint to be lowered to at least one operand");
503 const unsigned OpFlags =
505 Inst.addImm(OpFlags);
514 <<
"Cannot indirectify memory input operands yet\n");
524 Inst.addImm(OpFlags);
528 SourceRegs.
size() == 1 &&
529 "Expected the memory input to fit into a single virtual register");
530 Inst.addReg(SourceRegs[0]);
536 "Unknown constraint type!");
546 if (OpInfo.Regs.empty()) {
549 <<
"Couldn't allocate input register for register constraint\n");
553 unsigned NumRegs = OpInfo.Regs.size();
556 "Expected the number of input registers to match the number of "
560 LLVM_DEBUG(
dbgs() <<
"Input operands with multiple input registers are "
561 "not supported yet\n");
566 if (OpInfo.Regs.front().isVirtual()) {
569 Flag.setRegClass(RC->
getID());
574 Inst.addReg(OpInfo.Regs[0]);
580 const unsigned NumRegs = OpInfo.Regs.size();
595 if (
const MDNode *SrcLoc = Call.getMetadata(
"srcloc"))
596 Inst.addMetadata(SrcLoc);
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");
608 for (
unsigned int i = 0, e = ResRegs.
size(); i < e; i++) {
609 GISelAsmOperandInfo &OpInfo = OutputOperands[i];
611 if (OpInfo.Regs.empty())
614 switch (OpInfo.ConstraintType) {
617 if (OpInfo.Regs.size() > 1) {
619 "registers are not supported yet\n");
624 unsigned SrcSize =
TRI->getRegSizeInBits(SrcReg, *
MRI);
625 LLT ResTy =
MRI->getType(ResRegs[i]);
635 MIRBuilder.
buildCopy(ResRegs[i], SrcReg);
638 "mismatched register size\n");
647 dbgs() <<
"Cannot lower target specific output constraints yet\n");
663 Value *Val,
StringRef Constraint, std::vector<MachineOperand> &Ops,
665 if (Constraint.
size() > 1)
668 char ConstraintLetter = Constraint[0];
669 switch (ConstraintLetter) {
674 if (
ConstantInt *CI = dyn_cast<ConstantInt>(Val)) {
675 assert(CI->getBitWidth() <= 64 &&
676 "expected immediate to fit into 64-bits");
678 bool IsBool = CI->getBitWidth() == 1;
679 int64_t ExtVal = IsBool ? CI->getZExtValue() : CI->getSExtValue();
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Analysis containing CSE Info
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.
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),...
size_t size() const
size - Get the array size.
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.
A parsed version of the target data layout string in and methods for querying it.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
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.
void setMatchingOp(unsigned OperandNo)
setMatchingOp - Augment an existing flag with information indicating that this input operand is tied ...
void setMemConstraint(ConstraintCode C)
setMemConstraint - Augment an existing flag with the constraint code for a memory constraint.
bool isRegDefEarlyClobberKind() const
bool isRegDefKind() const
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
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.
unsigned getNumOperands() const
Retuns the total number of operands.
static MachineOperand CreateImm(int64_t Val)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
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.
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.
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
LLVM Value Representation.
#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.
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.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
ConstraintPrefix Type
Type - The basic type of the constraint: input/output/clobber/label.
ConstraintCodeVector Codes
Code - The constraint code, either the register name (in braces) or the constraint letter/number.
bool isIndirect
isIndirect - True if this operand is an indirect operand.
bool isEarlyClobber
isEarlyClobber - "&": output operand writes result before inputs are all read.
bool hasMatchingInput() const
hasMatchingInput - Return true if this is an output constraint that has a matching input constraint.
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".