Go to the documentation of this file.
21 #define DEBUG_TYPE "inline-asm-lowering"
25 void InlineAsmLowering::anchor() {}
47 explicit ExtraFlags(
const CallBase &CB) {
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;
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))
232 unsigned Flag =
I.getOperand(OpIdx).getImm();
243 if (!SrcTy.isValid()) {
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()) {
297 OpInfo.CallOperandVal =
const_cast<Value *
>(Call.getArgOperand(ArgNo));
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 =
345 ExtraInfo.update(OpInfo);
360 GISelAsmOperandInfoVector OutputOperands;
362 for (
auto &OpInfo : ConstraintOperands) {
363 GISelAsmOperandInfo &RefOpInfo =
371 switch (OpInfo.
Type) {
374 unsigned ConstraintID =
377 "Failed to convert memory constraint code to constraint id.");
383 Inst.addImm(OpFlags);
387 SourceRegs.
size() == 1 &&
388 "Expected the memory output to fit into a single virtual register");
389 Inst.addReg(SourceRegs[0]);
396 if (OpInfo.Regs.empty()) {
398 <<
"Couldn't allocate output register for constraint\n");
408 if (OpInfo.Regs.front().isVirtual()) {
426 OutputOperands.push_back(OpInfo);
434 unsigned InstFlagIdx = StartIdx;
435 for (
unsigned i = 0;
i < DefIdx; ++
i)
439 unsigned MatchedOperandFlag = Inst->getOperand(InstFlagIdx).getImm();
441 LLVM_DEBUG(
dbgs() <<
"Matching input constraint to mem operand not "
442 "supported. This should be target specific.\n");
452 unsigned DefRegIdx = InstFlagIdx + 1;
453 Register Def = Inst->getOperand(DefRegIdx).getReg();
456 assert(SrcRegs.
size() == 1 &&
"Single register is expected here");
461 if (
Def.isVirtual()) {
472 Inst->tieOperands(DefRegIdx, Inst->getNumOperands() - 1);
478 LLVM_DEBUG(
dbgs() <<
"Indirect input operands with unknown constraint "
479 "not supported yet\n");
486 std::vector<MachineOperand> Ops;
496 "Expected constraint to be lowered to at least one operand");
501 Inst.addImm(OpFlags);
510 <<
"Cannot indirectify memory input operands yet\n");
516 unsigned ConstraintID =
520 Inst.addImm(OpFlags);
524 SourceRegs.
size() == 1 &&
525 "Expected the memory input to fit into a single virtual register");
526 Inst.addReg(SourceRegs[0]);
532 "Unknown constraint type!");
542 if (OpInfo.Regs.empty()) {
545 <<
"Couldn't allocate input register for register constraint\n");
549 unsigned NumRegs = OpInfo.Regs.size();
552 "Expected the number of input registers to match the number of "
556 LLVM_DEBUG(
dbgs() <<
"Input operands with multiple input registers are "
557 "not supported yet\n");
562 if (OpInfo.Regs.front().isVirtual()) {
570 Inst.addReg(OpInfo.Regs[0]);
576 unsigned NumRegs = OpInfo.Regs.size();
592 if (
const MDNode *SrcLoc = Call.getMetadata(
"srcloc"))
593 Inst.addMetadata(SrcLoc);
600 if (ResRegs.
size() != OutputOperands.size()) {
601 LLVM_DEBUG(
dbgs() <<
"Expected the number of output registers to match the "
602 "number of destination registers\n");
605 for (
unsigned int i = 0,
e = ResRegs.
size();
i <
e;
i++) {
606 GISelAsmOperandInfo &OpInfo = OutputOperands[
i];
608 if (OpInfo.Regs.empty())
611 switch (OpInfo.ConstraintType) {
614 if (OpInfo.Regs.size() > 1) {
616 "registers are not supported yet\n");
635 "mismatched register size\n");
644 dbgs() <<
"Cannot lower target specific output constraints yet\n");
660 Value *Val,
StringRef Constraint, std::vector<MachineOperand> &Ops,
662 if (Constraint.
size() > 1)
665 char ConstraintLetter = Constraint[0];
666 switch (ConstraintLetter) {
671 if (
ConstantInt *CI = dyn_cast<ConstantInt>(Val)) {
672 assert(CI->getBitWidth() <= 64 &&
673 "expected immediate to fit into 64-bits");
675 bool IsBool = CI->getBitWidth() == 1;
676 int64_t ExtVal = IsBool ? CI->getZExtValue() : CI->getSExtValue();
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
unsigned getID() const
Return the register class ID number.
This is an optimization pass for GlobalISel generic memory operations.
A parsed version of the target data layout string in and methods for querying it.
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
const std::string & getAsmString() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static void getRegistersForValue(MachineFunction &MF, MachineIRBuilder &MIRBuilder, GISelAsmOperandInfo &OpInfo, GISelAsmOperandInfo &RefOpInfo)
Assign virtual/physical registers for the specified register operand.
bool isAlignStack() const
bool isIndirect
isIndirect - True if this operand is an indirect operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MachineRegisterInfo * getMRI()
Getter for MRI.
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 ...
Reg
All possible values of the reg field in the ModR/M byte.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
The instances of the Type class are immutable: once they are created, they are never changed.
MachineInstrBuilder buildInstrNoInsert(unsigned Opcode)
Build but don't insert <empty> = Opcode <empty>.
static void chooseConstraint(TargetLowering::AsmOperandInfo &OpInfo, const TargetLowering *TLI)
unsigned const TargetRegisterInfo * TRI
@ EarlyClobber
Register definition happens before uses.
@ INLINEASM
INLINEASM - Represents an inline asm block.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
This is the shared class of boolean and integer constants.
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
TargetLowering::ConstraintType ConstraintType
Information about the constraint code, e.g.
static MachineOperand CreateImm(int64_t Val)
bool hasSideEffects() const
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Value * CallOperandVal
If this is the result output operand or a clobber, this is null, otherwise it is the incoming operand...
bool isConvergent() const
Determine if the invoke is convergent.
static bool isRegDefKind(unsigned Flag)
Flag
These should be considered private to the implementation of the MCInstrDesc class.
MachineFunction & getMF()
Getter for the function we currently build.
Analysis containing CSE Info
AsmDialect getDialect() const
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
Register getReg(unsigned Idx) const
Get the register for the operand index.
static bool isMemKind(unsigned Flag)
static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT)
Return an integer indicating how general CT is.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Helper class to build MachineInstr.
static bool isRegDefEarlyClobberKind(unsigned Flag)
Representation of each machine instruction.
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...
bool isEarlyClobber
isEarlyClobber - "&": output operand writes result before inputs are all read.
This contains information for each constraint that we are lowering.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ConstraintCodeVector Codes
Code - The constraint code, either the register name (in braces) or the constraint letter/number.
print Print MemDeps of function
ConstraintPrefix Type
Type - The basic type of the constraint: input/output/clobber.
Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
std::string ConstraintCode
This contains the actual string for the code, like "m".
static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC)
getFlagWordForRegClass - Augment an existing flag word returned by getFlagWord with the required regi...
MVT getSimpleValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the MVT corresponding to this LLVM type. See getValueType.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Class to represent struct types.
@ Kind_RegDefEarlyClobber
StringRef - Represent a constant reference to a string, i.e.
MachineInstrBuilder insertInstr(MachineInstrBuilder MIB)
Insert an existing instruction at the insertion point.
static unsigned getFlagWord(unsigned Kind, unsigned NumOps)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
unsigned getMatchedOperand() const
If this is an input matching constraint, this method returns the output operand it matches.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder buildAnyExt(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_ANYEXT Op0.
Wrapper class representing virtual and physical registers.
static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint)
Augment an existing flag word returned by getFlagWord with the constraint code for a memory constrain...
static unsigned getFlagWordForMatchingOp(unsigned InputFlag, unsigned MatchedOperandNo)
getFlagWordForMatchingOp - Augment an existing flag word returned by getFlagWord with information ind...
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
static void computeConstraintToUse(const TargetLowering *TLI, TargetLowering::AsmOperandInfo &OpInfo)
MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op)
Build and insert Res = G_TRUNC Op.
iterator begin() const
begin/end - Return all of the registers in this class.
Function & getFunction()
Return the LLVM function that this machine code represents.
unsigned getRegSizeInBits(const TargetRegisterClass &RC) const
Return the size in bits of a register from class RC.
Should compile to something r4 addze r3 instead we get
bool isMatchingInputConstraint() const
Return true of this is an input operand that is a matching constraint like "4".
@ Define
Register definition.
MVT ConstraintVT
The ValueType for the operand value.
Value * getCalledOperand() const
virtual const TargetLowering * getTargetLowering() const
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
static unsigned getNumOperandRegisters(unsigned Flag)
getNumOperandRegisters - Extract the number of registers field from the inline asm operand flag.
unsigned getNumOperands() const
Retuns the total number of operands.
size_t size() const
size - Get the array size.
virtual unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const
static unsigned getNumOpRegs(const MachineInstr &I, unsigned OpIdx)
virtual unsigned getNumRegisters(LLVMContext &Context, EVT VT, Optional< MVT > RegisterVT=None) const
Return the number of registers that this ValueType will eventually require.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
virtual bool lowerAsmOperandForConstraint(Value *Val, StringRef Constraint, std::vector< MachineOperand > &Ops, MachineIRBuilder &MIRBuilder) const
Lower the specified operand into the Ops vector.
static LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
unsigned getImplRegState(bool B)
virtual EVT getAsmOperandValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
LLVM Value Representation.
virtual const char * LowerXConstraint(EVT ConstraintVT) const
Try to replace an X constraint, which matches anything, with another that has more specific requireme...
bool hasMatchingInput() const
hasMatchingInput - Return true if this is an output constraint that has a matching input constraint.
static bool buildAnyextOrCopy(Register Dst, Register Src, MachineIRBuilder &MIRBuilder)
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::vector< AsmOperandInfo > AsmOperandInfoVector
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.