1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 20:23:11 +01:00

Record all of the expanded registers in the DAG and machine instr, fixing

several bugs in inline asm expanded operands.

llvm-svn: 26332
This commit is contained in:
Chris Lattner 2006-02-23 19:21:04 +00:00
parent 1ee7e91e5c
commit b4951fbe82
3 changed files with 137 additions and 79 deletions

View File

@ -569,19 +569,26 @@ void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
exit(1);
}
char ExtraCode = 0; // FIXME:
// Okay, we finally have an operand number. Ask the target to print this
// Okay, we finally have a value number. Ask the target to print this
// operand!
if (CurVariant == -1 || CurVariant == AsmPrinterVariant)
if (CurVariant == -1 || CurVariant == AsmPrinterVariant) {
unsigned OpNo = 1;
// Scan to find the machine operand number for the operand.
for (; Val; --Val)
OpNo += MI->getOperand(OpNo).getImmedValue()+1;
++OpNo; // Skip over the ID number.
if (const_cast<AsmPrinter*>(this)->
PrintAsmOperand(MI, Val+1, AsmPrinterVariant,
PrintAsmOperand(MI, OpNo, AsmPrinterVariant,
Modifier[0] ? Modifier : 0)) {
std::cerr << "Invalid operand found in inline asm: '"
<< AsmStr << "'\n";
MI->dump();
exit(1);
}
}
break;
}
case '{':

View File

@ -309,23 +309,32 @@ void ScheduleDAG::EmitNode(NodeInfo *NI) {
MI->addExternalSymbolOperand(AsmStr, false);
// Add all of the operand registers to the instruction.
for (unsigned i = 2; i != NumOps; i += 2) {
unsigned Flags =cast<ConstantSDNode>(Node->getOperand(i+1))->getValue();
switch (Flags) {
for (unsigned i = 2; i != NumOps;) {
unsigned Flags = cast<ConstantSDNode>(Node->getOperand(i))->getValue();
unsigned NumOps = Flags >> 3;
MI->addZeroExtImm64Operand(NumOps);
++i; // Skip the ID value.
switch (Flags & 7) {
default: assert(0 && "Bad flags!");
case 1: { // Use of register.
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
MI->addMachineRegOperand(Reg, MachineOperand::Use);
case 1: // Use of register.
for (; NumOps; --NumOps, ++i) {
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
MI->addMachineRegOperand(Reg, MachineOperand::Use);
}
break;
}
case 2: { // Def of register.
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
MI->addMachineRegOperand(Reg, MachineOperand::Def);
case 2: // Def of register.
for (; NumOps; --NumOps, ++i) {
unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
MI->addMachineRegOperand(Reg, MachineOperand::Def);
}
break;
}
case 3: { // Immediate.
assert(NumOps == 1 && "Unknown immediate value!");
uint64_t Val = cast<ConstantSDNode>(Node->getOperand(i))->getValue();
MI->addZeroExtImm64Operand(Val);
++i;
break;
}
}

View File

@ -113,6 +113,18 @@ namespace {
/// Chain/Flag as the input and updates them for the output Chain/Flag.
SDOperand getCopyFromRegs(SelectionDAG &DAG,
SDOperand &Chain, SDOperand &Flag);
/// getCopyToRegs - Emit a series of CopyToReg nodes that copies the
/// specified value into the registers specified by this object. This uses
/// Chain/Flag as the input and updates them for the output Chain/Flag.
void getCopyToRegs(SDOperand Val, SelectionDAG &DAG,
SDOperand &Chain, SDOperand &Flag);
/// AddInlineAsmOperands - Add this value to the specified inlineasm node
/// operand list. This adds the code marker and includes the number of
/// values added into it.
void AddInlineAsmOperands(unsigned Code, SelectionDAG &DAG,
std::vector<SDOperand> &Ops);
};
}
@ -1195,7 +1207,41 @@ SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
return DAG.getNode(ISD::FP_ROUND, ValueVT, Val);
}
/// getCopyToRegs - Emit a series of CopyToReg nodes that copies the
/// specified value into the registers specified by this object. This uses
/// Chain/Flag as the input and updates them for the output Chain/Flag.
void RegsForValue::getCopyToRegs(SDOperand Val, SelectionDAG &DAG,
SDOperand &Chain, SDOperand &Flag) {
if (Regs.size() == 1) {
// If there is a single register and the types differ, this must be
// a promotion.
if (RegVT != ValueVT) {
if (MVT::isInteger(RegVT))
Val = DAG.getNode(ISD::ANY_EXTEND, RegVT, Val);
else
Val = DAG.getNode(ISD::FP_EXTEND, RegVT, Val);
}
Chain = DAG.getCopyToReg(Chain, Regs[0], Val, Flag);
Flag = Chain.getValue(1);
} else {
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
SDOperand Part = DAG.getNode(ISD::EXTRACT_ELEMENT, RegVT, Val,
DAG.getConstant(i, MVT::i32));
Chain = DAG.getCopyToReg(Chain, Regs[i], Part, Flag);
Flag = Chain.getValue(1);
}
}
}
/// AddInlineAsmOperands - Add this value to the specified inlineasm node
/// operand list. This adds the code marker and includes the number of
/// values added into it.
void RegsForValue::AddInlineAsmOperands(unsigned Code, SelectionDAG &DAG,
std::vector<SDOperand> &Ops) {
Ops.push_back(DAG.getConstant(Code | (Regs.size() << 3), MVT::i32));
for (unsigned i = 0, e = Regs.size(); i != e; ++i)
Ops.push_back(DAG.getRegister(Regs[i], RegVT));
}
/// isAllocatableRegister - If the specified register is safe to allocate,
/// i.e. it isn't a stack pointer or some other special register, return the
@ -1453,96 +1499,92 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
// Add information to the INLINEASM node to know that this register is
// set.
// FIXME:
// FIXME: Handle multiple regs here.
// FIXME:
unsigned DestReg = Regs.Regs[0];
AsmNodeOperands.push_back(DAG.getRegister(DestReg, Regs.RegVT));
AsmNodeOperands.push_back(DAG.getConstant(2, MVT::i32)); // ISDEF
Regs.AddInlineAsmOperands(2 /*REGDEF*/, DAG, AsmNodeOperands);
break;
}
case InlineAsm::isInput: {
Value *CallOperand = I.getOperand(OpNum);
OpNum++; // Consumes a call operand.
SDOperand ResOp;
unsigned ResOpType;
SDOperand InOperandVal = getValue(CallOperand);
if (isdigit(ConstraintCode[0])) { // Matching constraint?
// If this is required to match an output register we have already set,
// just use its register.
unsigned OperandNo = atoi(ConstraintCode.c_str());
unsigned SrcReg;
SrcReg = cast<RegisterSDNode>(AsmNodeOperands[OperandNo*2+2])->getReg();
ResOp = DAG.getRegister(SrcReg, ConstraintVTs[i]);
ResOpType = 1;
Chain = DAG.getCopyToReg(Chain, SrcReg, InOperandVal, Flag);
Flag = Chain.getValue(1);
// Scan until we find the definition we already emitted of this operand.
// When we find it, create a RegsForValue operand.
unsigned CurOp = 2; // The first operand.
for (; OperandNo; --OperandNo) {
// Advance to the next operand.
unsigned NumOps =
cast<ConstantSDNode>(AsmNodeOperands[CurOp])->getValue();
assert((NumOps & 7) == 2 /*REGDEF*/ &&
"Skipped past definitions?");
CurOp += (NumOps>>3)+1;
}
unsigned NumOps =
cast<ConstantSDNode>(AsmNodeOperands[CurOp])->getValue();
assert((NumOps & 7) == 2 /*REGDEF*/ &&
"Skipped past definitions?");
// Add NumOps>>3 registers to MatchedRegs.
RegsForValue MatchedRegs;
MatchedRegs.ValueVT = InOperandVal.getValueType();
MatchedRegs.RegVT = AsmNodeOperands[CurOp+1].getValueType();
for (unsigned i = 0, e = NumOps>>3; i != e; ++i) {
unsigned Reg=cast<RegisterSDNode>(AsmNodeOperands[++CurOp])->getReg();
MatchedRegs.Regs.push_back(Reg);
}
// Use the produced MatchedRegs object to
MatchedRegs.getCopyToRegs(InOperandVal, DAG, Chain, Flag);
MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/, DAG, AsmNodeOperands);
} else {
TargetLowering::ConstraintType CTy = TargetLowering::C_RegisterClass;
if (ConstraintCode.size() == 1) // not a physreg name.
CTy = TLI.getConstraintType(ConstraintCode[0]);
switch (CTy) {
default: assert(0 && "Unknown constraint type! FAIL!");
case TargetLowering::C_RegisterClass: {
// Copy the input into the appropriate registers.
RegsForValue InRegs =
GetRegistersForValue(ConstraintCode, ConstraintVTs[i],
false, true, OutputRegs, InputRegs);
// FIXME: should be match fail.
assert(!InRegs.Regs.empty() && "Couldn't allocate input reg!");
if (InRegs.Regs.size() == 1) {
// If there is a single register and the types differ, this must be
// a promotion.
if (InRegs.RegVT != InRegs.ValueVT) {
if (MVT::isInteger(InRegs.RegVT))
InOperandVal = DAG.getNode(ISD::ANY_EXTEND, InRegs.RegVT,
InOperandVal);
else
InOperandVal = DAG.getNode(ISD::FP_EXTEND, InRegs.RegVT,
InOperandVal);
}
Chain = DAG.getCopyToReg(Chain, InRegs.Regs[0], InOperandVal, Flag);
Flag = Chain.getValue(1);
ResOp = DAG.getRegister(InRegs.Regs[0], InRegs.RegVT);
} else {
for (unsigned i = 0, e = InRegs.Regs.size(); i != e; ++i) {
SDOperand Part = DAG.getNode(ISD::EXTRACT_ELEMENT, InRegs.RegVT,
InOperandVal,
DAG.getConstant(i, MVT::i32));
Chain = DAG.getCopyToReg(Chain, InRegs.Regs[i], Part, Flag);
Flag = Chain.getValue(1);
}
ResOp = DAG.getRegister(InRegs.Regs[0], InRegs.RegVT);
}
ResOpType = 1;
break;
}
case TargetLowering::C_Other:
if (CTy == TargetLowering::C_Other) {
if (!TLI.isOperandValidForConstraint(InOperandVal, ConstraintCode[0]))
assert(0 && "MATCH FAIL!");
ResOp = InOperandVal;
ResOpType = 3;
// Add information to the INLINEASM node to know about this input.
unsigned ResOpType = 3 /*imm*/ | (1 << 3);
AsmNodeOperands.push_back(DAG.getConstant(ResOpType, MVT::i32));
AsmNodeOperands.push_back(InOperandVal);
break;
}
assert(CTy == TargetLowering::C_RegisterClass && "Unknown op type!");
// Copy the input into the appropriate registers.
RegsForValue InRegs =
GetRegistersForValue(ConstraintCode, ConstraintVTs[i],
false, true, OutputRegs, InputRegs);
// FIXME: should be match fail.
assert(!InRegs.Regs.empty() && "Couldn't allocate input reg!");
InRegs.getCopyToRegs(InOperandVal, DAG, Chain, Flag);
InRegs.AddInlineAsmOperands(1/*REGUSE*/, DAG, AsmNodeOperands);
break;
}
// Add information to the INLINEASM node to know about this input.
AsmNodeOperands.push_back(ResOp);
AsmNodeOperands.push_back(DAG.getConstant(ResOpType, MVT::i32));
break;
}
case InlineAsm::isClobber:
// Nothing to do.
case InlineAsm::isClobber: {
RegsForValue ClobberedRegs =
GetRegistersForValue(ConstraintCode, MVT::Other, false, false,
OutputRegs, InputRegs);
// Add the clobbered value to the operand list, so that the register
// allocator is aware that the physreg got clobbered.
if (!ClobberedRegs.Regs.empty())
ClobberedRegs.AddInlineAsmOperands(2/*REGDEF*/, DAG, AsmNodeOperands);
break;
}
}
}
// Finish up input operands.