mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 19:12:56 +02:00
For inline asm output operand that matches an input. Encode the input operand index in the high bits.
llvm-svn: 67387
This commit is contained in:
parent
d5c51dc50c
commit
0c629db2aa
@ -128,6 +128,24 @@ public:
|
|||||||
static inline bool classof(const Value *V) {
|
static inline bool classof(const Value *V) {
|
||||||
return V->getValueID() == Value::InlineAsmVal;
|
return V->getValueID() == Value::InlineAsmVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getNumOperandRegisters - Extract the number of registers field from the
|
||||||
|
/// inline asm operand flag.
|
||||||
|
static unsigned getNumOperandRegisters(unsigned Flag) {
|
||||||
|
return (Flag & 0xffff) >> 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// isOutputOperandTiedToUse - Return true if the flag of the inline asm
|
||||||
|
/// operand indicates it is an output that's matched to an input operand.
|
||||||
|
static bool isOutputOperandTiedToUse(unsigned Flag, unsigned &UseIdx) {
|
||||||
|
if (Flag & 0x80000000) {
|
||||||
|
UseIdx = Flag >> 16;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
@ -1401,7 +1401,7 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
|
|||||||
for (; Val; --Val) {
|
for (; Val; --Val) {
|
||||||
if (OpNo >= MI->getNumOperands()) break;
|
if (OpNo >= MI->getNumOperands()) break;
|
||||||
unsigned OpFlags = MI->getOperand(OpNo).getImm();
|
unsigned OpFlags = MI->getOperand(OpNo).getImm();
|
||||||
OpNo += (OpFlags >> 3) + 1;
|
OpNo += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OpNo >= MI->getNumOperands()) {
|
if (OpNo >= MI->getNumOperands()) {
|
||||||
|
@ -1974,7 +1974,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
|||||||
|
|
||||||
bool HasInFlag = Ops.back().getValueType() == MVT::Flag;
|
bool HasInFlag = Ops.back().getValueType() == MVT::Flag;
|
||||||
for (unsigned i = 2, e = Ops.size()-HasInFlag; i < e; ) {
|
for (unsigned i = 2, e = Ops.size()-HasInFlag; i < e; ) {
|
||||||
unsigned NumVals = cast<ConstantSDNode>(Ops[i])->getZExtValue() >> 3;
|
unsigned NumVals = InlineAsm::
|
||||||
|
getNumOperandRegisters(cast<ConstantSDNode>(Ops[i])->getZExtValue());
|
||||||
for (++i; NumVals; ++i, --NumVals) {
|
for (++i; NumVals; ++i, --NumVals) {
|
||||||
SDValue Op = LegalizeOp(Ops[i]);
|
SDValue Op = LegalizeOp(Ops[i]);
|
||||||
if (Op != Ops[i]) {
|
if (Op != Ops[i]) {
|
||||||
|
@ -632,7 +632,7 @@ bool ScheduleDAGRRList::DelayForLiveRegsBottomUp(SUnit *SU,
|
|||||||
for (unsigned i = 2; i != NumOps;) {
|
for (unsigned i = 2; i != NumOps;) {
|
||||||
unsigned Flags =
|
unsigned Flags =
|
||||||
cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
|
cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
|
||||||
unsigned NumVals = Flags >> 3;
|
unsigned NumVals = (Flags & 0xffff) >> 3;
|
||||||
|
|
||||||
++i; // Skip the ID value.
|
++i; // Skip the ID value.
|
||||||
if ((Flags & 7) == 2 || (Flags & 7) == 6) {
|
if ((Flags & 7) == 2 || (Flags & 7) == 6) {
|
||||||
|
@ -561,7 +561,7 @@ void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
|
|||||||
for (unsigned i = 2; i != NumOps;) {
|
for (unsigned i = 2; i != NumOps;) {
|
||||||
unsigned Flags =
|
unsigned Flags =
|
||||||
cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
|
cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
|
||||||
unsigned NumVals = Flags >> 3;
|
unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
|
||||||
|
|
||||||
MI->addOperand(MachineOperand::CreateImm(Flags));
|
MI->addOperand(MachineOperand::CreateImm(Flags));
|
||||||
++i; // Skip the ID value.
|
++i; // Skip the ID value.
|
||||||
|
@ -228,10 +228,11 @@ namespace llvm {
|
|||||||
SDValue &Chain, SDValue *Flag) const;
|
SDValue &Chain, SDValue *Flag) const;
|
||||||
|
|
||||||
/// AddInlineAsmOperands - Add this value to the specified inlineasm node
|
/// AddInlineAsmOperands - Add this value to the specified inlineasm node
|
||||||
/// operand list. This adds the code marker and includes the number of
|
/// operand list. This adds the code marker, matching input operand index
|
||||||
/// values added into it.
|
/// (if applicable), and includes the number of values added into it.
|
||||||
void AddInlineAsmOperands(unsigned Code, SelectionDAG &DAG,
|
void AddInlineAsmOperands(unsigned Code,
|
||||||
std::vector<SDValue> &Ops) const;
|
bool HasMatching, unsigned MatchingIdx,
|
||||||
|
SelectionDAG &DAG, std::vector<SDValue> &Ops) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4659,10 +4660,16 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl,
|
|||||||
/// AddInlineAsmOperands - Add this value to the specified inlineasm node
|
/// AddInlineAsmOperands - Add this value to the specified inlineasm node
|
||||||
/// operand list. This adds the code marker and includes the number of
|
/// operand list. This adds the code marker and includes the number of
|
||||||
/// values added into it.
|
/// values added into it.
|
||||||
void RegsForValue::AddInlineAsmOperands(unsigned Code, SelectionDAG &DAG,
|
void RegsForValue::AddInlineAsmOperands(unsigned Code,
|
||||||
|
bool HasMatching,unsigned MatchingIdx,
|
||||||
|
SelectionDAG &DAG,
|
||||||
std::vector<SDValue> &Ops) const {
|
std::vector<SDValue> &Ops) const {
|
||||||
MVT IntPtrTy = DAG.getTargetLoweringInfo().getPointerTy();
|
MVT IntPtrTy = DAG.getTargetLoweringInfo().getPointerTy();
|
||||||
Ops.push_back(DAG.getTargetConstant(Code | (Regs.size() << 3), IntPtrTy));
|
assert(Regs.size() < (1 << 13) && "Too many inline asm outputs!");
|
||||||
|
unsigned Flag = Code | (Regs.size() << 3);
|
||||||
|
if (HasMatching)
|
||||||
|
Flag |= 0x80000000 | (MatchingIdx << 16);
|
||||||
|
Ops.push_back(DAG.getTargetConstant(Flag, IntPtrTy));
|
||||||
for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) {
|
for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) {
|
||||||
unsigned NumRegs = TLI->getNumRegisters(ValueVTs[Value]);
|
unsigned NumRegs = TLI->getNumRegisters(ValueVTs[Value]);
|
||||||
MVT RegisterVT = RegVTs[Value];
|
MVT RegisterVT = RegVTs[Value];
|
||||||
@ -5230,6 +5237,8 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
|
|||||||
OpInfo.AssignedRegs.AddInlineAsmOperands(OpInfo.isEarlyClobber ?
|
OpInfo.AssignedRegs.AddInlineAsmOperands(OpInfo.isEarlyClobber ?
|
||||||
6 /* EARLYCLOBBER REGDEF */ :
|
6 /* EARLYCLOBBER REGDEF */ :
|
||||||
2 /* REGDEF */ ,
|
2 /* REGDEF */ ,
|
||||||
|
OpInfo.hasMatchingInput(),
|
||||||
|
OpInfo.MatchingInput,
|
||||||
DAG, AsmNodeOperands);
|
DAG, AsmNodeOperands);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -5246,25 +5255,26 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
|
|||||||
unsigned CurOp = 2; // The first operand.
|
unsigned CurOp = 2; // The first operand.
|
||||||
for (; OperandNo; --OperandNo) {
|
for (; OperandNo; --OperandNo) {
|
||||||
// Advance to the next operand.
|
// Advance to the next operand.
|
||||||
unsigned NumOps =
|
unsigned OpFlag =
|
||||||
cast<ConstantSDNode>(AsmNodeOperands[CurOp])->getZExtValue();
|
cast<ConstantSDNode>(AsmNodeOperands[CurOp])->getZExtValue();
|
||||||
assert(((NumOps & 7) == 2 /*REGDEF*/ ||
|
assert(((OpFlag & 7) == 2 /*REGDEF*/ ||
|
||||||
(NumOps & 7) == 6 /*EARLYCLOBBER REGDEF*/ ||
|
(OpFlag & 7) == 6 /*EARLYCLOBBER REGDEF*/ ||
|
||||||
(NumOps & 7) == 4 /*MEM*/) &&
|
(OpFlag & 7) == 4 /*MEM*/) &&
|
||||||
"Skipped past definitions?");
|
"Skipped past definitions?");
|
||||||
CurOp += (NumOps>>3)+1;
|
CurOp += InlineAsm::getNumOperandRegisters(OpFlag)+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned NumOps =
|
unsigned OpFlag =
|
||||||
cast<ConstantSDNode>(AsmNodeOperands[CurOp])->getZExtValue();
|
cast<ConstantSDNode>(AsmNodeOperands[CurOp])->getZExtValue();
|
||||||
if ((NumOps & 7) == 2 /*REGDEF*/
|
if ((OpFlag & 7) == 2 /*REGDEF*/
|
||||||
|| (NumOps & 7) == 6 /* EARLYCLOBBER REGDEF */) {
|
|| (OpFlag & 7) == 6 /* EARLYCLOBBER REGDEF */) {
|
||||||
// Add NumOps>>3 registers to MatchedRegs.
|
// Add (OpFlag&0xffff)>>3 registers to MatchedRegs.
|
||||||
RegsForValue MatchedRegs;
|
RegsForValue MatchedRegs;
|
||||||
MatchedRegs.TLI = &TLI;
|
MatchedRegs.TLI = &TLI;
|
||||||
MatchedRegs.ValueVTs.push_back(InOperandVal.getValueType());
|
MatchedRegs.ValueVTs.push_back(InOperandVal.getValueType());
|
||||||
MatchedRegs.RegVTs.push_back(AsmNodeOperands[CurOp+1].getValueType());
|
MatchedRegs.RegVTs.push_back(AsmNodeOperands[CurOp+1].getValueType());
|
||||||
for (unsigned i = 0, e = NumOps>>3; i != e; ++i) {
|
for (unsigned i = 0, e = InlineAsm::getNumOperandRegisters(OpFlag);
|
||||||
|
i != e; ++i) {
|
||||||
unsigned Reg =
|
unsigned Reg =
|
||||||
cast<RegisterSDNode>(AsmNodeOperands[++CurOp])->getReg();
|
cast<RegisterSDNode>(AsmNodeOperands[++CurOp])->getReg();
|
||||||
MatchedRegs.Regs.push_back(Reg);
|
MatchedRegs.Regs.push_back(Reg);
|
||||||
@ -5273,13 +5283,15 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
|
|||||||
// Use the produced MatchedRegs object to
|
// Use the produced MatchedRegs object to
|
||||||
MatchedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(),
|
MatchedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(),
|
||||||
Chain, &Flag);
|
Chain, &Flag);
|
||||||
MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/, DAG, AsmNodeOperands);
|
MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/, false, 0,
|
||||||
|
DAG, AsmNodeOperands);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
assert(((NumOps & 7) == 4) && "Unknown matching constraint!");
|
assert(((OpFlag & 7) == 4) && "Unknown matching constraint!");
|
||||||
assert((NumOps >> 3) == 1 && "Unexpected number of operands");
|
assert((InlineAsm::getNumOperandRegisters(OpFlag)) == 1 &&
|
||||||
|
"Unexpected number of operands");
|
||||||
// Add information to the INLINEASM node to know about this input.
|
// Add information to the INLINEASM node to know about this input.
|
||||||
AsmNodeOperands.push_back(DAG.getTargetConstant(NumOps,
|
AsmNodeOperands.push_back(DAG.getTargetConstant(OpFlag,
|
||||||
TLI.getPointerTy()));
|
TLI.getPointerTy()));
|
||||||
AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]);
|
AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]);
|
||||||
break;
|
break;
|
||||||
@ -5334,7 +5346,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
|
|||||||
OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(),
|
OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(),
|
||||||
Chain, &Flag);
|
Chain, &Flag);
|
||||||
|
|
||||||
OpInfo.AssignedRegs.AddInlineAsmOperands(1/*REGUSE*/,
|
OpInfo.AssignedRegs.AddInlineAsmOperands(1/*REGUSE*/, false, 0,
|
||||||
DAG, AsmNodeOperands);
|
DAG, AsmNodeOperands);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -5343,7 +5355,7 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
|
|||||||
// allocator is aware that the physreg got clobbered.
|
// allocator is aware that the physreg got clobbered.
|
||||||
if (!OpInfo.AssignedRegs.Regs.empty())
|
if (!OpInfo.AssignedRegs.Regs.empty())
|
||||||
OpInfo.AssignedRegs.AddInlineAsmOperands(6 /* EARLYCLOBBER REGDEF */,
|
OpInfo.AssignedRegs.AddInlineAsmOperands(6 /* EARLYCLOBBER REGDEF */,
|
||||||
DAG, AsmNodeOperands);
|
false, 0, DAG,AsmNodeOperands);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1168,10 +1168,12 @@ SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops) {
|
|||||||
unsigned Flags = cast<ConstantSDNode>(InOps[i])->getZExtValue();
|
unsigned Flags = cast<ConstantSDNode>(InOps[i])->getZExtValue();
|
||||||
if ((Flags & 7) != 4 /*MEM*/) {
|
if ((Flags & 7) != 4 /*MEM*/) {
|
||||||
// Just skip over this operand, copying the operands verbatim.
|
// Just skip over this operand, copying the operands verbatim.
|
||||||
Ops.insert(Ops.end(), InOps.begin()+i, InOps.begin()+i+(Flags >> 3) + 1);
|
Ops.insert(Ops.end(), InOps.begin()+i,
|
||||||
i += (Flags >> 3) + 1;
|
InOps.begin()+i+InlineAsm::getNumOperandRegisters(Flags) + 1);
|
||||||
|
i += InlineAsm::getNumOperandRegisters(Flags) + 1;
|
||||||
} else {
|
} else {
|
||||||
assert((Flags >> 3) == 1 && "Memory operand with multiple values?");
|
assert(InlineAsm::getNumOperandRegisters(Flags) == 1 &&
|
||||||
|
"Memory operand with multiple values?");
|
||||||
// Otherwise, this is a memory operand. Ask the target to select it.
|
// Otherwise, this is a memory operand. Ask the target to select it.
|
||||||
std::vector<SDValue> SelOps;
|
std::vector<SDValue> SelOps;
|
||||||
if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps)) {
|
if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user