diff --git a/include/llvm/Target/TargetInstrDesc.h b/include/llvm/Target/TargetInstrDesc.h index b0ed0bf0c8b..9efb6833fb8 100644 --- a/include/llvm/Target/TargetInstrDesc.h +++ b/include/llvm/Target/TargetInstrDesc.h @@ -25,9 +25,10 @@ class TargetRegisterInfo; //===----------------------------------------------------------------------===// namespace TOI { - // Operand constraints: only "tied_to" for now. + // Operand constraints enum OperandConstraint { - TIED_TO = 0 // Must be allocated the same register as. + TIED_TO = 0, // Must be allocated the same register as. + EARLY_CLOBBER // Operand is an early clobber register operand }; /// OperandFlags - These are flags set on operands, but should be considered diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 12b974d30be..e3b870927a8 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -555,8 +555,13 @@ void MachineInstr::addOperand(const MachineOperand &Op) { Operands.back().ParentMI = this; // If the operand is a register, update the operand's use list. - if (Op.isReg()) + if (Op.isReg()) { Operands.back().AddRegOperandToRegInfo(RegInfo); + // If the register operand is flagged as early, mark the operand as such + unsigned OpNo = Operands.size() - 1; + if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + Operands[OpNo].setIsEarlyClobber(true); + } return; } } @@ -573,8 +578,12 @@ void MachineInstr::addOperand(const MachineOperand &Op) { // Do explicitly set the reginfo for this operand though, to ensure the // next/prev fields are properly nulled out. - if (Operands[OpNo].isReg()) + if (Operands[OpNo].isReg()) { Operands[OpNo].AddRegOperandToRegInfo(0); + // If the register operand is flagged as early, mark the operand as such + if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + Operands[OpNo].setIsEarlyClobber(true); + } } else if (Operands.size()+1 <= Operands.capacity()) { // Otherwise, we have to remove register operands from their register use @@ -594,8 +603,12 @@ void MachineInstr::addOperand(const MachineOperand &Op) { Operands.insert(Operands.begin()+OpNo, Op); Operands[OpNo].ParentMI = this; - if (Operands[OpNo].isReg()) + if (Operands[OpNo].isReg()) { Operands[OpNo].AddRegOperandToRegInfo(RegInfo); + // If the register operand is flagged as early, mark the operand as such + if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + Operands[OpNo].setIsEarlyClobber(true); + } // Re-add all the implicit ops. for (unsigned i = OpNo+1, e = Operands.size(); i != e; ++i) { @@ -613,6 +626,11 @@ void MachineInstr::addOperand(const MachineOperand &Op) { // Re-add all the operands. AddRegOperandsToUseLists(*RegInfo); + + // If the register operand is flagged as early, mark the operand as such + if (Operands[OpNo].isReg() + && TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1) + Operands[OpNo].setIsEarlyClobber(true); } } diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index e6ed709d6e8..c69ce962ffc 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -18,14 +18,35 @@ using namespace llvm; static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) { - // FIXME: Only supports TIED_TO for now. + // EARLY_CLOBBER: @early $reg + std::string::size_type wpos = CStr.find_first_of(" \t"); + std::string::size_type start = CStr.find_first_not_of(" \t"); + std::string Tok = CStr.substr(start, wpos - start); + if (Tok == "@earlyclobber") { + std::string Name = CStr.substr(wpos+1); + wpos = Name.find_first_not_of(" \t"); + if (wpos == std::string::npos) + throw "Illegal format for @earlyclobber constraint: '" + CStr + "'"; + Name = Name.substr(wpos); + std::pair Op = + I->ParseOperandName(Name, false); + + // Build the string for the operand + std::string OpConstraint = "(1 << TOI::EARLY_CLOBBER)"; + if (!I->OperandList[Op.first].Constraints[Op.second].empty()) + throw "Operand '" + Name + "' cannot have multiple constraints!"; + I->OperandList[Op.first].Constraints[Op.second] = OpConstraint; + return; + } + + // Only other constraint is "TIED_TO" for now. std::string::size_type pos = CStr.find_first_of('='); assert(pos != std::string::npos && "Unrecognized constraint"); - std::string::size_type start = CStr.find_first_not_of(" \t"); + start = CStr.find_first_not_of(" \t"); std::string Name = CStr.substr(start, pos - start); // TIED_TO: $src1 = $dst - std::string::size_type wpos = Name.find_first_of(" \t"); + wpos = Name.find_first_of(" \t"); if (wpos == std::string::npos) throw "Illegal format for tied-to constraint: '" + CStr + "'"; std::string DestOpName = Name.substr(0, wpos); @@ -47,7 +68,6 @@ static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) { std::string OpConstraint = "((" + utostr(FlatOpNo) + " << 16) | (1 << TOI::TIED_TO))"; - if (!I->OperandList[DestOp.first].Constraints[DestOp.second].empty()) throw "Operand '" + DestOpName + "' cannot have multiple constraints!"; I->OperandList[DestOp.first].Constraints[DestOp.second] = OpConstraint;