From b2d3f2e5da501e8d3eea6ddaaad07fc6dc924114 Mon Sep 17 00:00:00 2001 From: Roman Tereshin Date: Tue, 12 Jun 2018 18:30:37 +0000 Subject: [MIR][MachineCSE] Implementing proper MachineInstr::getNumExplicitDefs() Apparently, MachineInstr class definition as well as pretty much all of the machine passes assume that the only kind of MachineInstr's operands that is variadic for variadic opcodes is explicit non-definitions. In particular, this assumption is made by MachineInstr::defs(), uses(), and explicit_uses() methods, as well as by MachineCSE pass. The assumption is incorrect judging from at least TableGen backend implementation, that recognizes variable_ops in OutOperandList, and the very existence of G_UNMERGE_VALUES generic opcode, or ARM load multiple instructions, all of which have variadic defs. In particular, MachineCSE pass breaks MIR with CSE'able G_UNMERGE_VALUES instructions in it. This commit implements MachineInstr::getNumExplicitDefs() similar to pre-existing MachineInstr::getNumExplicitOperands(), fixes MachineInstr::defs(), uses(), and explicit_uses(), and fixes MachineCSE pass. As the issue addressed seems to affect only machine passes that could be ran mid-GlobalISel pipeline at the moment, the other passes aren't fixed by this commit, like MachineLICM: that could be done on per-pass basis when (if ever) they get adopted for GlobalISel. Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D45640 llvm-svn: 334520 --- llvm/lib/CodeGen/MachineCSE.cpp | 3 +-- llvm/lib/CodeGen/MachineInstr.cpp | 30 ++++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'llvm/lib/CodeGen') diff --git a/llvm/lib/CodeGen/MachineCSE.cpp b/llvm/lib/CodeGen/MachineCSE.cpp index cca4aa86bb0..6c92b1d426d 100644 --- a/llvm/lib/CodeGen/MachineCSE.cpp +++ b/llvm/lib/CodeGen/MachineCSE.cpp @@ -550,8 +550,7 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) { // Check if it's profitable to perform this CSE. bool DoCSE = true; - unsigned NumDefs = MI->getDesc().getNumDefs() + - MI->getDesc().getNumImplicitDefs(); + unsigned NumDefs = MI->getNumDefs(); for (unsigned i = 0, e = MI->getNumOperands(); NumDefs && i != e; ++i) { MachineOperand &MO = MI->getOperand(i); diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index 9686018b1fe..e4a3c5b0470 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -519,21 +519,39 @@ void MachineInstr::eraseFromBundle() { getParent()->erase_instr(this); } -/// getNumExplicitOperands - Returns the number of non-implicit operands. -/// unsigned MachineInstr::getNumExplicitOperands() const { unsigned NumOperands = MCID->getNumOperands(); if (!MCID->isVariadic()) return NumOperands; - for (unsigned i = NumOperands, e = getNumOperands(); i != e; ++i) { - const MachineOperand &MO = getOperand(i); - if (!MO.isReg() || !MO.isImplicit()) - NumOperands++; + for (unsigned I = NumOperands, E = getNumOperands(); I != E; ++I) { + const MachineOperand &MO = getOperand(I); + // The operands must always be in the following order: + // - explicit reg defs, + // - other explicit operands (reg uses, immediates, etc.), + // - implicit reg defs + // - implicit reg uses + if (MO.isReg() && MO.isImplicit()) + break; + ++NumOperands; } return NumOperands; } +unsigned MachineInstr::getNumExplicitDefs() const { + unsigned NumDefs = MCID->getNumDefs(); + if (!MCID->isVariadic()) + return NumDefs; + + for (unsigned I = NumDefs, E = getNumOperands(); I != E; ++I) { + const MachineOperand &MO = getOperand(I); + if (!MO.isReg() || !MO.isDef() || MO.isImplicit()) + break; + ++NumDefs; + } + return NumDefs; +} + void MachineInstr::bundleWithPred() { assert(!isBundledWithPred() && "MI is already bundled with its predecessor"); setFlag(BundledPred); -- cgit v1.2.3