From 190e342cbcb1456ebb21b53a35cfefa99435bd65 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 28 Aug 2012 18:05:48 +0000 Subject: Don't allow TargetFlags on MO_Register MachineOperands. Register operands are manipulated by a lot of target-independent code, and it is not always possible to preserve target flags. That means it is not safe to use target flags on register operands. None of the targets in the tree are using register operand target flags. External targets should be using immediate operands to annotate instructions with operand modifiers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162770 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index b166849..e106004 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -208,8 +208,8 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { hash_code llvm::hash_value(const MachineOperand &MO) { switch (MO.getType()) { case MachineOperand::MO_Register: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getReg(), - MO.getSubReg(), MO.isDef()); + // Register operands don't have target flags. + return hash_combine(MO.getType(), MO.getReg(), MO.getSubReg(), MO.isDef()); case MachineOperand::MO_Immediate: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm()); case MachineOperand::MO_CImmediate: -- cgit v1.1 From 4ba6916a98fffd9dedac5945ac51d40c8948069e Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 28 Aug 2012 18:34:41 +0000 Subject: Add a MachineOperand::isTied() flag. While in SSA form, a MachineInstr can have pairs of tied defs and uses. The tied operands are used to represent read-modify-write operands that must be assigned the same physical register. Previously, tied operand pairs were computed from fixed MCInstrDesc fields, or by using black magic on inline assembly instructions. The isTied flag makes it possible to add tied operands to any instruction while getting rid of (some of) the inlineasm magic. Tied operands on normal instructions are needed to represent predicated individual instructions in SSA form. An extra operand is required to represent the output value when the instruction predicate is false. Adding a predicate to: %vreg0 = ADD %vreg1, %vreg2 Will look like: %vreg0 = ADD %vreg1, %vreg2, pred:3, %vreg7 The virtual register %vreg7 is the value given to %vreg0 when the predicate is false. It will be assigned the same physreg as %vreg0. This commit adds the isTied flag and sets it based on MCInstrDesc when building an instruction. The flag is not used for anything yet. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162774 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 55 +++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 21 deletions(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index e106004..24078f8 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); -- cgit v1.1 From 699ac049517285d978ed607b2735976c5ae97ac0 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 29 Aug 2012 00:37:58 +0000 Subject: Maintain a vaild isTied bit as operands are added and removed. The isTied bit is set automatically when a tied use is added and MCInstrDesc indicates a tied operand. The tie is broken when one of the tied operands is removed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162814 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 24078f8..bfb722b 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -111,6 +111,7 @@ void MachineOperand::setIsDef(bool Val) { /// the specified value. If an operand is known to be an immediate already, /// the setImm method should be used. void MachineOperand::ChangeToImmediate(int64_t ImmVal) { + assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm"); // If this operand is currently a register operand, and if this is in a // function, deregister the operand from the register's use/def list. if (isReg() && isOnRegUseList()) @@ -136,7 +137,8 @@ void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, RegInfo = &MF->getRegInfo(); // If this operand is already a register operand, remove it from the // register's use/def lists. - if (RegInfo && isReg()) + bool WasReg = isReg(); + if (RegInfo && WasReg) RegInfo->removeRegOperandFromUseList(this); // Change this to a register and set the reg#. @@ -153,6 +155,9 @@ void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, IsDebug = isDebug; // Ensure isOnRegUseList() returns false. Contents.Reg.Prev = 0; + // Preserve the tie bit when the operand was already a register. + if (!WasReg) + IsTied = false; // If this operand is embedded in a function, add the operand to the // register's use/def list. @@ -711,6 +716,8 @@ void MachineInstr::addOperand(const MachineOperand &Op) { if (Operands[OpNo].isReg()) { // Ensure isOnRegUseList() returns false, regardless of Op's status. Operands[OpNo].Contents.Reg.Prev = 0; + // Ignore existing IsTied bit. This is not a property that can be copied. + Operands[OpNo].IsTied = false; // Add the new operand to RegInfo. if (RegInfo) RegInfo->addRegOperandToUseList(&Operands[OpNo]); @@ -743,6 +750,7 @@ void MachineInstr::addOperand(const MachineOperand &Op) { /// void MachineInstr::RemoveOperand(unsigned OpNo) { assert(OpNo < Operands.size() && "Invalid operand number"); + untieRegOperand(OpNo); MachineRegisterInfo *RegInfo = getRegInfo(); // Special case removing the last one. @@ -1127,6 +1135,36 @@ int MachineInstr::findFirstPredOperandIdx() const { return -1; } +/// Given the index of a tied register operand, find the operand it is tied to. +/// Defs are tied to uses and vice versa. Returns the index of the tied operand +/// which must exist. +unsigned MachineInstr::findTiedOperandIdx(unsigned OpIdx) const { + // It doesn't usually happen, but an instruction can have multiple pairs of + // tied operands. + SmallVector Uses, Defs; + unsigned PairNo = ~0u; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + if (!MO.isReg() || !MO.isTied()) + continue; + if (MO.isUse()) { + if (i == OpIdx) + PairNo = Uses.size(); + Uses.push_back(i); + } else { + if (i == OpIdx) + PairNo = Defs.size(); + Defs.push_back(i); + } + } + // For each tied use there must be a tied def and vice versa. + assert(Uses.size() == Defs.size() && "Tied uses and defs don't match"); + assert(PairNo < Uses.size() && "OpIdx must be a tied register operand"); + + // Find the matching operand. + return (getOperand(OpIdx).isDef() ? Uses : Defs)[PairNo]; +} + /// isRegTiedToUseOperand - Given the index of a register def operand, /// check if the register def is tied to a source operand, due to either /// two-address elimination or inline assembly constraints. Returns the -- cgit v1.1 From 0d7585839540abb9ab661a741dc3e0c2c860bceb Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 29 Aug 2012 20:48:45 +0000 Subject: Don't move normal loads across volatile/atomic loads. It is technically allowed to move a normal load across a volatile load, but probably not a good idea. It is not allowed to move a load across an atomic load with Ordering > Monotonic, and we model those with MOVolatile as well. I recently removed the mayStore flag from atomic load instructions, so they don't need a pseudo-opcode. This patch makes up for the difference. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162857 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index bfb722b..7ff79b3 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -1343,7 +1343,12 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, AliasAnalysis *AA, bool &SawStore) const { // Ignore stuff that we obviously can't move. - if (mayStore() || isCall()) { + // + // Treat volatile loads as stores. This is not strictly necessary for + // volatiles, but it is required for atomic loads. It is now allowed to move + // a load across an atomic load with Ordering > Monotonic. + if (mayStore() || isCall() || + (mayLoad() && hasVolatileMemoryRef())) { SawStore = true; return false; } @@ -1359,8 +1364,8 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, // load. if (mayLoad() && !isInvariantLoad(AA)) // Otherwise, this is a real load. If there is a store between the load and - // end of block, or if the load is volatile, we can't move it. - return !SawStore && !hasVolatileMemoryRef(); + // end of block, we can't move it. + return !SawStore; return true; } -- cgit v1.1 From f036f7a1e79910bf5b5b6f37d2e512b4f01155a0 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 29 Aug 2012 21:19:21 +0000 Subject: Rename hasVolatileMemoryRef() to hasOrderedMemoryRef(). Ordered memory operations are more constrained than volatile loads and stores because they must be ordered with respect to all other memory operations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162861 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 7ff79b3..4a4c721 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -1348,7 +1348,7 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, // volatiles, but it is required for atomic loads. It is now allowed to move // a load across an atomic load with Ordering > Monotonic. if (mayStore() || isCall() || - (mayLoad() && hasVolatileMemoryRef())) { + (mayLoad() && hasOrderedMemoryRef())) { SawStore = true; return false; } @@ -1396,11 +1396,11 @@ bool MachineInstr::isSafeToReMat(const TargetInstrInfo *TII, return true; } -/// hasVolatileMemoryRef - Return true if this instruction may have a -/// volatile memory reference, or if the information describing the -/// memory reference is not available. Return false if it is known to -/// have no volatile memory references. -bool MachineInstr::hasVolatileMemoryRef() const { +/// hasOrderedMemoryRef - Return true if this instruction may have an ordered +/// or volatile memory reference, or if the information describing the memory +/// reference is not available. Return false if it is known to have no ordered +/// memory references. +bool MachineInstr::hasOrderedMemoryRef() const { // An instruction known never to access memory won't have a volatile access. if (!mayStore() && !mayLoad() && @@ -1413,9 +1413,9 @@ bool MachineInstr::hasVolatileMemoryRef() const { if (memoperands_empty()) return true; - // Check the memory reference information for volatile references. + // Check the memory reference information for ordered references. for (mmo_iterator I = memoperands_begin(), E = memoperands_end(); I != E; ++I) - if ((*I)->isVolatile()) + if (!(*I)->isUnordered()) return true; return false; -- cgit v1.1 From e941df5e354ff7d327bab8e59af687ec90fdd149 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 30 Aug 2012 14:39:06 +0000 Subject: Don't use MCInstrDesc flags for implicit operands. When a MachineInstr is constructed, its implicit operands are added first, then the explicit operands are inserted before the implicits. MCInstrDesc has oprand flags like early clobber and operand ties that apply to the explicit operands. Don't look at those flags when the implicit operands are first added in the explicit operands's positions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162910 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 4a4c721..ae205f6 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -721,19 +721,24 @@ 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; + // The MCID operand information isn't accurate until we start adding + // explicit operands. The implicit operands are added first, then the + // explicits are inserted before them. + if (!isImpReg) { + // 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); } - // 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); } // Re-add all the implicit ops. -- cgit v1.1 From 94083149fd6891c8a72472cf1814fa6600a75979 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 31 Aug 2012 20:50:53 +0000 Subject: Add MachineInstr::tieOperands, remove setIsTied(). Manage tied operands entirely internally to MachineInstr. This makes it possible to change the representation of tied operands, as I will do shortly. The constraint that tied uses and defs must be in the same order was too restrictive. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163021 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index ae205f6..5a395fd 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -728,12 +728,8 @@ void MachineInstr::addOperand(const MachineOperand &Op) { // 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 (DefIdx != -1) + tieOperands(DefIdx, OpNo); } // If the register operand is flagged as early, mark the operand as such. if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1) @@ -1140,6 +1136,20 @@ int MachineInstr::findFirstPredOperandIdx() const { return -1; } +/// Mark operands at DefIdx and UseIdx as tied to each other. +void MachineInstr::tieOperands(unsigned DefIdx, unsigned UseIdx) { + assert(DefIdx < UseIdx && "Tied defs must precede the use"); + MachineOperand &DefMO = getOperand(DefIdx); + MachineOperand &UseMO = getOperand(UseIdx); + assert(DefMO.isDef() && "DefIdx must be a def operand"); + assert(UseMO.isUse() && "UseIdx must be a use operand"); + assert(!DefMO.isTied() && "Def is already tied to another use"); + assert(!UseMO.isTied() && "Use is already tied to another def"); + + DefMO.IsTied = true; + UseMO.IsTied = true; +} + /// Given the index of a tied register operand, find the operand it is tied to. /// Defs are tied to uses and vice versa. Returns the index of the tied operand /// which must exist. -- cgit v1.1 From 9c130672761e006c47ea23b34a7bd414f2cd8368 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 4 Sep 2012 18:36:28 +0000 Subject: Allow tied uses and defs in different orders. After much agonizing, use a full 4 bits of precious MachineOperand space to encode this. This uses existing padding, and doesn't grow MachineOperand beyond its current 32 bytes. This allows tied defs among the first 15 operands on a normal instruction, just like the current MCInstrDesc constraint encoding. Inline assembly needs to be able to tie more than the first 15 operands, and gets special treatment. Tied uses can appear beyond 15 operands, as long as they are tied to a def that's in range. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163151 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 121 ++++++++++++++++++++++++++++++++----------- 1 file changed, 91 insertions(+), 30 deletions(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 5a395fd..941847f 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -155,9 +155,9 @@ void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, IsDebug = isDebug; // Ensure isOnRegUseList() returns false. Contents.Reg.Prev = 0; - // Preserve the tie bit when the operand was already a register. + // Preserve the tie when the operand was already a register. if (!WasReg) - IsTied = false; + TiedTo = 0; // If this operand is embedded in a function, add the operand to the // register's use/def list. @@ -310,6 +310,8 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { if (isTied()) { if (NeedComma) OS << ','; OS << "tied"; + if (TiedTo != 15) + OS << unsigned(TiedTo - 1); NeedComma = true; } OS << '>'; @@ -681,6 +683,7 @@ void MachineInstr::addOperand(const MachineOperand &Op) { if (!isImpReg && !isInlineAsm()) { while (OpNo && Operands[OpNo-1].isReg() && Operands[OpNo-1].isImplicit()) { --OpNo; + assert(!Operands[OpNo].isTied() && "Cannot move tied operands"); if (RegInfo) RegInfo->removeRegOperandFromUseList(&Operands[OpNo]); } @@ -716,8 +719,8 @@ void MachineInstr::addOperand(const MachineOperand &Op) { if (Operands[OpNo].isReg()) { // Ensure isOnRegUseList() returns false, regardless of Op's status. Operands[OpNo].Contents.Reg.Prev = 0; - // Ignore existing IsTied bit. This is not a property that can be copied. - Operands[OpNo].IsTied = false; + // Ignore existing ties. This is not a property that can be copied. + Operands[OpNo].TiedTo = 0; // Add the new operand to RegInfo. if (RegInfo) RegInfo->addRegOperandToUseList(&Operands[OpNo]); @@ -725,7 +728,7 @@ void MachineInstr::addOperand(const MachineOperand &Op) { // explicit operands. The implicit operands are added first, then the // explicits are inserted before them. if (!isImpReg) { - // Set the IsTied bit if MC indicates this use is tied to a def. + // Tie uses to defs as indicated in MCInstrDesc. if (Operands[OpNo].isUse()) { int DefIdx = MCID->getOperandConstraint(OpNo, MCOI::TIED_TO); if (DefIdx != -1) @@ -774,6 +777,13 @@ void MachineInstr::RemoveOperand(unsigned OpNo) { } } +#ifndef NDEBUG + // Moving tied operands would break the ties. + for (unsigned i = OpNo + 1, e = Operands.size(); i != e; ++i) + if (Operands[i].isReg()) + assert(!Operands[i].isTied() && "Cannot move tied operands"); +#endif + Operands.erase(Operands.begin()+OpNo); if (RegInfo) { @@ -1136,9 +1146,22 @@ int MachineInstr::findFirstPredOperandIdx() const { return -1; } -/// Mark operands at DefIdx and UseIdx as tied to each other. +// MachineOperand::TiedTo is 4 bits wide. +const unsigned TiedMax = 15; + +/// tieOperands - Mark operands at DefIdx and UseIdx as tied to each other. +/// +/// Use and def operands can be tied together, indicated by a non-zero TiedTo +/// field. TiedTo can have these values: +/// +/// 0: Operand is not tied to anything. +/// 1 to TiedMax-1: Tied to getOperand(TiedTo-1). +/// TiedMax: Tied to an operand >= TiedMax-1. +/// +/// The tied def must be one of the first TiedMax operands on a normal +/// instruction. INLINEASM instructions allow more tied defs. +/// void MachineInstr::tieOperands(unsigned DefIdx, unsigned UseIdx) { - assert(DefIdx < UseIdx && "Tied defs must precede the use"); MachineOperand &DefMO = getOperand(DefIdx); MachineOperand &UseMO = getOperand(UseIdx); assert(DefMO.isDef() && "DefIdx must be a def operand"); @@ -1146,38 +1169,76 @@ void MachineInstr::tieOperands(unsigned DefIdx, unsigned UseIdx) { assert(!DefMO.isTied() && "Def is already tied to another use"); assert(!UseMO.isTied() && "Use is already tied to another def"); - DefMO.IsTied = true; - UseMO.IsTied = true; + if (DefIdx < TiedMax) + UseMO.TiedTo = DefIdx + 1; + else { + // Inline asm can use the group descriptors to find tied operands, but on + // normal instruction, the tied def must be within the first TiedMax + // operands. + assert(isInlineAsm() && "DefIdx out of range"); + UseMO.TiedTo = TiedMax; + } + + // UseIdx can be out of range, we'll search for it in findTiedOperandIdx(). + DefMO.TiedTo = std::min(UseIdx + 1, TiedMax); } /// Given the index of a tied register operand, find the operand it is tied to. /// Defs are tied to uses and vice versa. Returns the index of the tied operand /// which must exist. unsigned MachineInstr::findTiedOperandIdx(unsigned OpIdx) const { - // It doesn't usually happen, but an instruction can have multiple pairs of - // tied operands. - SmallVector Uses, Defs; - unsigned PairNo = ~0u; - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { - const MachineOperand &MO = getOperand(i); - if (!MO.isReg() || !MO.isTied()) - continue; - if (MO.isUse()) { - if (i == OpIdx) - PairNo = Uses.size(); - Uses.push_back(i); - } else { - if (i == OpIdx) - PairNo = Defs.size(); - Defs.push_back(i); + const MachineOperand &MO = getOperand(OpIdx); + assert(MO.isTied() && "Operand isn't tied"); + + // Normally TiedTo is in range. + if (MO.TiedTo < TiedMax) + return MO.TiedTo - 1; + + // Uses on normal instructions can be out of range. + if (!isInlineAsm()) { + // Normal tied defs must be in the 0..TiedMax-1 range. + if (MO.isUse()) + return TiedMax - 1; + // MO is a def. Search for the tied use. + for (unsigned i = TiedMax - 1, e = getNumOperands(); i != e; ++i) { + const MachineOperand &UseMO = getOperand(i); + if (UseMO.isReg() && UseMO.isUse() && UseMO.TiedTo == OpIdx + 1) + return i; } + llvm_unreachable("Can't find tied use"); } - // For each tied use there must be a tied def and vice versa. - assert(Uses.size() == Defs.size() && "Tied uses and defs don't match"); - assert(PairNo < Uses.size() && "OpIdx must be a tied register operand"); - // Find the matching operand. - return (getOperand(OpIdx).isDef() ? Uses : Defs)[PairNo]; + // Now deal with inline asm by parsing the operand group descriptor flags. + // Find the beginning of each operand group. + SmallVector GroupIdx; + unsigned OpIdxGroup = ~0u; + unsigned NumOps; + for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); i < e; + i += NumOps) { + const MachineOperand &FlagMO = getOperand(i); + assert(FlagMO.isImm() && "Invalid tied operand on inline asm"); + unsigned CurGroup = GroupIdx.size(); + GroupIdx.push_back(i); + NumOps = 1 + InlineAsm::getNumOperandRegisters(FlagMO.getImm()); + // OpIdx belongs to this operand group. + if (OpIdx > i && OpIdx < i + NumOps) + OpIdxGroup = CurGroup; + unsigned TiedGroup; + if (!InlineAsm::isUseOperandTiedToDef(FlagMO.getImm(), TiedGroup)) + continue; + // Operands in this group are tied to operands in TiedGroup which must be + // earlier. Find the number of operands between the two groups. + unsigned Delta = i - GroupIdx[TiedGroup]; + + // OpIdx is a use tied to TiedGroup. + if (OpIdxGroup == CurGroup) + return OpIdx - Delta; + + // OpIdx is a def tied to this use group. + if (OpIdxGroup == TiedGroup) + return OpIdx + Delta; + } + llvm_unreachable("Invalid tied operand on inline asm"); } /// isRegTiedToUseOperand - Given the index of a register def operand, -- cgit v1.1 From 99c416c9f7e8a9d7d1038d03cafebec730280398 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 4 Sep 2012 18:43:25 +0000 Subject: Actually use the MachineOperand field for isRegTiedToDefOperand(). The MachineOperand::TiedTo field was maintained, but not used. This patch enables it in isRegTiedToDefOperand() and isRegTiedToUseOperand() which are the actual functions use by the register allocator. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163153 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 103 ------------------------------------------- 1 file changed, 103 deletions(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 941847f..235cf96 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -1241,109 +1241,6 @@ unsigned MachineInstr::findTiedOperandIdx(unsigned OpIdx) const { llvm_unreachable("Invalid tied operand on inline asm"); } -/// isRegTiedToUseOperand - Given the index of a register def operand, -/// check if the register def is tied to a source operand, due to either -/// two-address elimination or inline assembly constraints. Returns the -/// first tied use operand index by reference is UseOpIdx is not null. -bool MachineInstr:: -isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const { - if (isInlineAsm()) { - assert(DefOpIdx > InlineAsm::MIOp_FirstOperand); - const MachineOperand &MO = getOperand(DefOpIdx); - if (!MO.isReg() || !MO.isDef() || MO.getReg() == 0) - return false; - // Determine the actual operand index that corresponds to this index. - unsigned DefNo = 0; - int FlagIdx = findInlineAsmFlagIdx(DefOpIdx, &DefNo); - if (FlagIdx < 0) - return false; - - // Which part of the group is DefOpIdx? - unsigned DefPart = DefOpIdx - (FlagIdx + 1); - - for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); - i != e; ++i) { - const MachineOperand &FMO = getOperand(i); - if (!FMO.isImm()) - continue; - if (i+1 >= e || !getOperand(i+1).isReg() || !getOperand(i+1).isUse()) - continue; - unsigned Idx; - if (InlineAsm::isUseOperandTiedToDef(FMO.getImm(), Idx) && - Idx == DefNo) { - if (UseOpIdx) - *UseOpIdx = (unsigned)i + 1 + DefPart; - return true; - } - } - return false; - } - - assert(getOperand(DefOpIdx).isDef() && "DefOpIdx is not a def!"); - const MCInstrDesc &MCID = getDesc(); - for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) { - const MachineOperand &MO = getOperand(i); - if (MO.isReg() && MO.isUse() && - MCID.getOperandConstraint(i, MCOI::TIED_TO) == (int)DefOpIdx) { - if (UseOpIdx) - *UseOpIdx = (unsigned)i; - return true; - } - } - return false; -} - -/// isRegTiedToDefOperand - Return true if the operand of the specified index -/// is a register use and it is tied to an def operand. It also returns the def -/// operand index by reference. -bool MachineInstr:: -isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx) const { - if (isInlineAsm()) { - const MachineOperand &MO = getOperand(UseOpIdx); - if (!MO.isReg() || !MO.isUse() || MO.getReg() == 0) - return false; - - // Find the flag operand corresponding to UseOpIdx - int FlagIdx = findInlineAsmFlagIdx(UseOpIdx); - if (FlagIdx < 0) - return false; - - const MachineOperand &UFMO = getOperand(FlagIdx); - unsigned DefNo; - if (InlineAsm::isUseOperandTiedToDef(UFMO.getImm(), DefNo)) { - if (!DefOpIdx) - return true; - - unsigned DefIdx = InlineAsm::MIOp_FirstOperand; - // Remember to adjust the index. First operand is asm string, second is - // the HasSideEffects and AlignStack bits, then there is a flag for each. - while (DefNo) { - const MachineOperand &FMO = getOperand(DefIdx); - assert(FMO.isImm()); - // Skip over this def. - DefIdx += InlineAsm::getNumOperandRegisters(FMO.getImm()) + 1; - --DefNo; - } - *DefOpIdx = DefIdx + UseOpIdx - FlagIdx; - return true; - } - return false; - } - - const MCInstrDesc &MCID = getDesc(); - if (UseOpIdx >= MCID.getNumOperands()) - return false; - const MachineOperand &MO = getOperand(UseOpIdx); - if (!MO.isReg() || !MO.isUse()) - return false; - int DefIdx = MCID.getOperandConstraint(UseOpIdx, MCOI::TIED_TO); - if (DefIdx == -1) - return false; - if (DefOpIdx) - *DefOpIdx = (unsigned)DefIdx; - return true; -} - /// clearKillInfo - Clears kill flags on all operands. /// void MachineInstr::clearKillInfo() { -- cgit v1.1 From 4f1a56ce3c08763c89e9cf50e9503a87247ac4e9 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 4 Sep 2012 18:44:43 +0000 Subject: Typo. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163154 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 235cf96..5e5ed0b 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -1318,7 +1318,7 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, // Ignore stuff that we obviously can't move. // // Treat volatile loads as stores. This is not strictly necessary for - // volatiles, but it is required for atomic loads. It is now allowed to move + // volatiles, but it is required for atomic loads. It is not allowed to move // a load across an atomic load with Ordering > Monotonic. if (mayStore() || isCall() || (mayLoad() && hasOrderedMemoryRef())) { -- cgit v1.1 From 576cd11ab8035d4240f7e6ea8d7c6c2e45154f86 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Wed, 5 Sep 2012 21:00:58 +0000 Subject: [ms-inline asm] Propagate the asm dialect into the MachineInstr representation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163243 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 5e5ed0b..dad6840 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -967,6 +967,16 @@ bool MachineInstr::isStackAligningInlineAsm() const { return false; } +InlineAsm::AsmDialect MachineInstr::getInlineAsmDialect() const { + assert(isInlineAsm() && "getInlineAsmDialect() only works for inline asms!"); + unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); + if (ExtraInfo & InlineAsm::Extra_IntelDialect) + return InlineAsm::AD_Intel; + + assert((ExtraInfo & InlineAsm::Extra_ATTDialect) && "Expected AT&T dialect!"); + return InlineAsm::AD_ATT; // The default. +} + int MachineInstr::findInlineAsmFlagIdx(unsigned OpIdx, unsigned *GroupNo) const { assert(isInlineAsm() && "Expected an inline asm instruction"); @@ -1569,6 +1579,10 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { OS << " [sideeffect]"; if (ExtraInfo & InlineAsm::Extra_IsAlignStack) OS << " [alignstack]"; + if (ExtraInfo & InlineAsm::Extra_ATTDialect) + OS << " [attdialect]"; + if (ExtraInfo & InlineAsm::Extra_IntelDialect) + OS << " [inteldialect]"; StartOp = AsmDescOp = InlineAsm::MIOp_FirstOperand; FirstOp = false; -- cgit v1.1 From 77fffa6fdd389ad6d70a42b36c1c36c768c2de41 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Wed, 5 Sep 2012 22:17:43 +0000 Subject: [ms-inline asm] We only need one bit to represent the AsmDialect in the MachineInstr. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163257 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index dad6840..362d99a 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -970,11 +970,7 @@ bool MachineInstr::isStackAligningInlineAsm() const { InlineAsm::AsmDialect MachineInstr::getInlineAsmDialect() const { assert(isInlineAsm() && "getInlineAsmDialect() only works for inline asms!"); unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); - if (ExtraInfo & InlineAsm::Extra_IntelDialect) - return InlineAsm::AD_Intel; - - assert((ExtraInfo & InlineAsm::Extra_ATTDialect) && "Expected AT&T dialect!"); - return InlineAsm::AD_ATT; // The default. + return InlineAsm::AsmDialect((ExtraInfo >> 2) & 1); } int MachineInstr::findInlineAsmFlagIdx(unsigned OpIdx, @@ -1579,9 +1575,9 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { OS << " [sideeffect]"; if (ExtraInfo & InlineAsm::Extra_IsAlignStack) OS << " [alignstack]"; - if (ExtraInfo & InlineAsm::Extra_ATTDialect) + if (getInlineAsmDialect() == InlineAsm::AD_ATT) OS << " [attdialect]"; - if (ExtraInfo & InlineAsm::Extra_IntelDialect) + if (getInlineAsmDialect() == InlineAsm::AD_Intel) OS << " [inteldialect]"; StartOp = AsmDescOp = InlineAsm::MIOp_FirstOperand; -- cgit v1.1 From 2f1d8154795ad82e500fda27d75ec1449e7a0648 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Wed, 5 Sep 2012 22:40:13 +0000 Subject: Cleanup a few magic numbers. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163263 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 362d99a..e40aee5 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -970,7 +970,7 @@ bool MachineInstr::isStackAligningInlineAsm() const { InlineAsm::AsmDialect MachineInstr::getInlineAsmDialect() const { assert(isInlineAsm() && "getInlineAsmDialect() only works for inline asms!"); unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); - return InlineAsm::AsmDialect((ExtraInfo >> 2) & 1); + return InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect) != 0); } int MachineInstr::findInlineAsmFlagIdx(unsigned OpIdx, -- cgit v1.1 From 77e300e8f0b8db8eec448cae9c87d7c5bfad9757 Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Thu, 6 Sep 2012 19:06:06 +0000 Subject: Release build: guard dump functions with "ifndef NDEBUG" No functional change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163339 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineInstr.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/CodeGen/MachineInstr.cpp') diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index e40aee5..0508b9f 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -1496,7 +1496,9 @@ void MachineInstr::copyImplicitOps(const MachineInstr *MI) { } void MachineInstr::dump() const { +#ifndef NDEBUG dbgs() << " " << *this; +#endif } static void printDebugLoc(DebugLoc DL, const MachineFunction *MF, -- cgit v1.1