aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CodeGen/MachineOperand.h19
-rw-r--r--lib/CodeGen/MachineInstr.cpp55
2 files changed, 53 insertions, 21 deletions
diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h
index 1d3d60bdb2..594dc276b0 100644
--- a/include/llvm/CodeGen/MachineOperand.h
+++ b/include/llvm/CodeGen/MachineOperand.h
@@ -124,6 +124,14 @@ private:
/// model the GCC inline asm '&' constraint modifier.
bool IsEarlyClobber : 1;
+ /// IsTied - True if this MO_Register operand is tied to another operand on
+ /// the instruction. Tied operands form def-use pairs that must be assigned
+ /// the same physical register by the register allocator, but they will have
+ /// different virtual registers while the code is in SSA form.
+ ///
+ /// See MachineInstr::isRegTiedToUseOperand() and isRegTiedToDefOperand().
+ bool IsTied : 1;
+
/// IsDebug - True if this MO_Register 'use' operand is in a debug pseudo,
/// not a real instruction. Such uses should be ignored during codegen.
bool IsDebug : 1;
@@ -299,6 +307,11 @@ public:
return IsEarlyClobber;
}
+ bool isTied() const {
+ assert(isReg() && "Wrong MachineOperand accessor");
+ return IsTied;
+ }
+
bool isDebug() const {
assert(isReg() && "Wrong MachineOperand accessor");
return IsDebug;
@@ -377,6 +390,11 @@ public:
IsEarlyClobber = Val;
}
+ void setIsTied(bool Val = true) {
+ assert(isReg() && "Wrong MachineOperand accessor");
+ IsTied = Val;
+ }
+
void setIsDebug(bool Val = true) {
assert(isReg() && IsDef && "Wrong MachineOperand accessor");
IsDebug = Val;
@@ -559,6 +577,7 @@ public:
Op.IsUndef = isUndef;
Op.IsInternalRead = isInternalRead;
Op.IsEarlyClobber = isEarlyClobber;
+ Op.IsTied = false;
Op.IsDebug = isDebug;
Op.SmallContents.RegNo = Reg;
Op.Contents.Reg.Prev = 0;
diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp
index e1060046e2..24078f8943 100644
--- a/lib/CodeGen/MachineInstr.cpp
+++ b/lib/CodeGen/MachineInstr.cpp
@@ -262,7 +262,7 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const {
OS << PrintReg(getReg(), TRI, getSubReg());
if (isDef() || isKill() || isDead() || isImplicit() || isUndef() ||
- isInternalRead() || isEarlyClobber()) {
+ isInternalRead() || isEarlyClobber() || isTied()) {
OS << '<';
bool NeedComma = false;
if (isDef()) {
@@ -282,27 +282,30 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const {
NeedComma = true;
}
- if (isKill() || isDead() || (isUndef() && isUse()) || isInternalRead()) {
+ if (isKill()) {
if (NeedComma) OS << ',';
- NeedComma = false;
- if (isKill()) {
- OS << "kill";
- NeedComma = true;
- }
- if (isDead()) {
- OS << "dead";
- NeedComma = true;
- }
- if (isUndef() && isUse()) {
- if (NeedComma) OS << ',';
- OS << "undef";
- NeedComma = true;
- }
- if (isInternalRead()) {
- if (NeedComma) OS << ',';
- OS << "internal";
- NeedComma = true;
- }
+ OS << "kill";
+ NeedComma = true;
+ }
+ if (isDead()) {
+ if (NeedComma) OS << ',';
+ OS << "dead";
+ NeedComma = true;
+ }
+ if (isUndef() && isUse()) {
+ if (NeedComma) OS << ',';
+ OS << "undef";
+ NeedComma = true;
+ }
+ if (isInternalRead()) {
+ if (NeedComma) OS << ',';
+ OS << "internal";
+ NeedComma = true;
+ }
+ if (isTied()) {
+ if (NeedComma) OS << ',';
+ OS << "tied";
+ NeedComma = true;
}
OS << '>';
}
@@ -711,6 +714,16 @@ void MachineInstr::addOperand(const MachineOperand &Op) {
// Add the new operand to RegInfo.
if (RegInfo)
RegInfo->addRegOperandToUseList(&Operands[OpNo]);
+ // Set the IsTied bit if MC indicates this use is tied to a def.
+ if (Operands[OpNo].isUse()) {
+ int DefIdx = MCID->getOperandConstraint(OpNo, MCOI::TIED_TO);
+ if (DefIdx != -1) {
+ MachineOperand &DefMO = getOperand(DefIdx);
+ assert(DefMO.isDef() && "Use tied to operand that isn't a def");
+ DefMO.IsTied = true;
+ Operands[OpNo].IsTied = true;
+ }
+ }
// If the register operand is flagged as early, mark the operand as such.
if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
Operands[OpNo].setIsEarlyClobber(true);