LLVM API Documentation

SystemZElimCompare.cpp
Go to the documentation of this file.
00001 //===-- SystemZElimCompare.cpp - Eliminate comparison instructions --------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This pass:
00011 // (1) tries to remove compares if CC already contains the required information
00012 // (2) fuses compares and branches into COMPARE AND BRANCH instructions
00013 //
00014 //===----------------------------------------------------------------------===//
00015 
00016 #include "SystemZTargetMachine.h"
00017 #include "llvm/ADT/Statistic.h"
00018 #include "llvm/CodeGen/MachineFunctionPass.h"
00019 #include "llvm/CodeGen/MachineInstrBuilder.h"
00020 #include "llvm/IR/Function.h"
00021 #include "llvm/Support/CommandLine.h"
00022 #include "llvm/Support/MathExtras.h"
00023 #include "llvm/Target/TargetInstrInfo.h"
00024 #include "llvm/Target/TargetMachine.h"
00025 #include "llvm/Target/TargetRegisterInfo.h"
00026 
00027 using namespace llvm;
00028 
00029 #define DEBUG_TYPE "systemz-elim-compare"
00030 
00031 STATISTIC(BranchOnCounts, "Number of branch-on-count instructions");
00032 STATISTIC(EliminatedComparisons, "Number of eliminated comparisons");
00033 STATISTIC(FusedComparisons, "Number of fused compare-and-branch instructions");
00034 
00035 namespace {
00036 // Represents the references to a particular register in one or more
00037 // instructions.
00038 struct Reference {
00039   Reference()
00040     : Def(false), Use(false), IndirectDef(false), IndirectUse(false) {}
00041 
00042   Reference &operator|=(const Reference &Other) {
00043     Def |= Other.Def;
00044     IndirectDef |= Other.IndirectDef;
00045     Use |= Other.Use;
00046     IndirectUse |= Other.IndirectUse;
00047     return *this;
00048   }
00049 
00050   operator bool() const { return Def || Use; }
00051 
00052   // True if the register is defined or used in some form, either directly or
00053   // via a sub- or super-register.
00054   bool Def;
00055   bool Use;
00056 
00057   // True if the register is defined or used indirectly, by a sub- or
00058   // super-register.
00059   bool IndirectDef;
00060   bool IndirectUse;
00061 };
00062 
00063 class SystemZElimCompare : public MachineFunctionPass {
00064 public:
00065   static char ID;
00066   SystemZElimCompare(const SystemZTargetMachine &tm)
00067     : MachineFunctionPass(ID), TII(nullptr), TRI(nullptr) {}
00068 
00069   const char *getPassName() const override {
00070     return "SystemZ Comparison Elimination";
00071   }
00072 
00073   bool processBlock(MachineBasicBlock &MBB);
00074   bool runOnMachineFunction(MachineFunction &F) override;
00075 
00076 private:
00077   Reference getRegReferences(MachineInstr *MI, unsigned Reg);
00078   bool convertToBRCT(MachineInstr *MI, MachineInstr *Compare,
00079                      SmallVectorImpl<MachineInstr *> &CCUsers);
00080   bool convertToLoadAndTest(MachineInstr *MI);
00081   bool adjustCCMasksForInstr(MachineInstr *MI, MachineInstr *Compare,
00082                              SmallVectorImpl<MachineInstr *> &CCUsers);
00083   bool optimizeCompareZero(MachineInstr *Compare,
00084                            SmallVectorImpl<MachineInstr *> &CCUsers);
00085   bool fuseCompareAndBranch(MachineInstr *Compare,
00086                             SmallVectorImpl<MachineInstr *> &CCUsers);
00087 
00088   const SystemZInstrInfo *TII;
00089   const TargetRegisterInfo *TRI;
00090 };
00091 
00092 char SystemZElimCompare::ID = 0;
00093 } // end anonymous namespace
00094 
00095 FunctionPass *llvm::createSystemZElimComparePass(SystemZTargetMachine &TM) {
00096   return new SystemZElimCompare(TM);
00097 }
00098 
00099 // Return true if CC is live out of MBB.
00100 static bool isCCLiveOut(MachineBasicBlock &MBB) {
00101   for (auto SI = MBB.succ_begin(), SE = MBB.succ_end(); SI != SE; ++SI)
00102     if ((*SI)->isLiveIn(SystemZ::CC))
00103       return true;
00104   return false;
00105 }
00106 
00107 // Return true if any CC result of MI would reflect the value of subreg
00108 // SubReg of Reg.
00109 static bool resultTests(MachineInstr *MI, unsigned Reg, unsigned SubReg) {
00110   if (MI->getNumOperands() > 0 &&
00111       MI->getOperand(0).isReg() &&
00112       MI->getOperand(0).isDef() &&
00113       MI->getOperand(0).getReg() == Reg &&
00114       MI->getOperand(0).getSubReg() == SubReg)
00115     return true;
00116 
00117   switch (MI->getOpcode()) {
00118   case SystemZ::LR:
00119   case SystemZ::LGR:
00120   case SystemZ::LGFR:
00121   case SystemZ::LTR:
00122   case SystemZ::LTGR:
00123   case SystemZ::LTGFR:
00124   case SystemZ::LER:
00125   case SystemZ::LDR:
00126   case SystemZ::LXR:
00127   case SystemZ::LTEBR:
00128   case SystemZ::LTDBR:
00129   case SystemZ::LTXBR:
00130     if (MI->getOperand(1).getReg() == Reg &&
00131         MI->getOperand(1).getSubReg() == SubReg)
00132       return true;
00133   }
00134 
00135   return false;
00136 }
00137 
00138 // Describe the references to Reg in MI, including sub- and super-registers.
00139 Reference SystemZElimCompare::getRegReferences(MachineInstr *MI, unsigned Reg) {
00140   Reference Ref;
00141   for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
00142     const MachineOperand &MO = MI->getOperand(I);
00143     if (MO.isReg()) {
00144       if (unsigned MOReg = MO.getReg()) {
00145         if (MOReg == Reg || TRI->regsOverlap(MOReg, Reg)) {
00146           if (MO.isUse()) {
00147             Ref.Use = true;
00148             Ref.IndirectUse |= (MOReg != Reg);
00149           }
00150           if (MO.isDef()) {
00151             Ref.Def = true;
00152             Ref.IndirectDef |= (MOReg != Reg);
00153           }
00154         }
00155       }
00156     }
00157   }
00158   return Ref;
00159 }
00160 
00161 // Compare compares the result of MI against zero.  If MI is an addition
00162 // of -1 and if CCUsers is a single branch on nonzero, eliminate the addition
00163 // and convert the branch to a BRCT(G).  Return true on success.
00164 bool
00165 SystemZElimCompare::convertToBRCT(MachineInstr *MI, MachineInstr *Compare,
00166                                   SmallVectorImpl<MachineInstr *> &CCUsers) {
00167   // Check whether we have an addition of -1.
00168   unsigned Opcode = MI->getOpcode();
00169   unsigned BRCT;
00170   if (Opcode == SystemZ::AHI)
00171     BRCT = SystemZ::BRCT;
00172   else if (Opcode == SystemZ::AGHI)
00173     BRCT = SystemZ::BRCTG;
00174   else
00175     return false;
00176   if (MI->getOperand(2).getImm() != -1)
00177     return false;
00178 
00179   // Check whether we have a single JLH.
00180   if (CCUsers.size() != 1)
00181     return false;
00182   MachineInstr *Branch = CCUsers[0];
00183   if (Branch->getOpcode() != SystemZ::BRC ||
00184       Branch->getOperand(0).getImm() != SystemZ::CCMASK_ICMP ||
00185       Branch->getOperand(1).getImm() != SystemZ::CCMASK_CMP_NE)
00186     return false;
00187 
00188   // We already know that there are no references to the register between
00189   // MI and Compare.  Make sure that there are also no references between
00190   // Compare and Branch.
00191   unsigned SrcReg = Compare->getOperand(0).getReg();
00192   MachineBasicBlock::iterator MBBI = Compare, MBBE = Branch;
00193   for (++MBBI; MBBI != MBBE; ++MBBI)
00194     if (getRegReferences(MBBI, SrcReg))
00195       return false;
00196 
00197   // The transformation is OK.  Rebuild Branch as a BRCT(G).
00198   MachineOperand Target(Branch->getOperand(2));
00199   Branch->RemoveOperand(2);
00200   Branch->RemoveOperand(1);
00201   Branch->RemoveOperand(0);
00202   Branch->setDesc(TII->get(BRCT));
00203   MachineInstrBuilder(*Branch->getParent()->getParent(), Branch)
00204     .addOperand(MI->getOperand(0))
00205     .addOperand(MI->getOperand(1))
00206     .addOperand(Target)
00207     .addReg(SystemZ::CC, RegState::ImplicitDefine);
00208   MI->removeFromParent();
00209   return true;
00210 }
00211 
00212 // If MI is a load instruction, try to convert it into a LOAD AND TEST.
00213 // Return true on success.
00214 bool SystemZElimCompare::convertToLoadAndTest(MachineInstr *MI) {
00215   unsigned Opcode = TII->getLoadAndTest(MI->getOpcode());
00216   if (!Opcode)
00217     return false;
00218 
00219   MI->setDesc(TII->get(Opcode));
00220   MachineInstrBuilder(*MI->getParent()->getParent(), MI)
00221     .addReg(SystemZ::CC, RegState::ImplicitDefine);
00222   return true;
00223 }
00224 
00225 // The CC users in CCUsers are testing the result of a comparison of some
00226 // value X against zero and we know that any CC value produced by MI
00227 // would also reflect the value of X.  Try to adjust CCUsers so that
00228 // they test the result of MI directly, returning true on success.
00229 // Leave everything unchanged on failure.
00230 bool SystemZElimCompare::
00231 adjustCCMasksForInstr(MachineInstr *MI, MachineInstr *Compare,
00232                       SmallVectorImpl<MachineInstr *> &CCUsers) {
00233   int Opcode = MI->getOpcode();
00234   const MCInstrDesc &Desc = TII->get(Opcode);
00235   unsigned MIFlags = Desc.TSFlags;
00236 
00237   // See which compare-style condition codes are available.
00238   unsigned ReusableCCMask = SystemZII::getCompareZeroCCMask(MIFlags);
00239 
00240   // For unsigned comparisons with zero, only equality makes sense.
00241   unsigned CompareFlags = Compare->getDesc().TSFlags;
00242   if (CompareFlags & SystemZII::IsLogical)
00243     ReusableCCMask &= SystemZ::CCMASK_CMP_EQ;
00244 
00245   if (ReusableCCMask == 0)
00246     return false;
00247 
00248   unsigned CCValues = SystemZII::getCCValues(MIFlags);
00249   assert((ReusableCCMask & ~CCValues) == 0 && "Invalid CCValues");
00250 
00251   // Now check whether these flags are enough for all users.
00252   SmallVector<MachineOperand *, 4> AlterMasks;
00253   for (unsigned int I = 0, E = CCUsers.size(); I != E; ++I) {
00254     MachineInstr *MI = CCUsers[I];
00255 
00256     // Fail if this isn't a use of CC that we understand.
00257     unsigned Flags = MI->getDesc().TSFlags;
00258     unsigned FirstOpNum;
00259     if (Flags & SystemZII::CCMaskFirst)
00260       FirstOpNum = 0;
00261     else if (Flags & SystemZII::CCMaskLast)
00262       FirstOpNum = MI->getNumExplicitOperands() - 2;
00263     else
00264       return false;
00265 
00266     // Check whether the instruction predicate treats all CC values
00267     // outside of ReusableCCMask in the same way.  In that case it
00268     // doesn't matter what those CC values mean.
00269     unsigned CCValid = MI->getOperand(FirstOpNum).getImm();
00270     unsigned CCMask = MI->getOperand(FirstOpNum + 1).getImm();
00271     unsigned OutValid = ~ReusableCCMask & CCValid;
00272     unsigned OutMask = ~ReusableCCMask & CCMask;
00273     if (OutMask != 0 && OutMask != OutValid)
00274       return false;
00275 
00276     AlterMasks.push_back(&MI->getOperand(FirstOpNum));
00277     AlterMasks.push_back(&MI->getOperand(FirstOpNum + 1));
00278   }
00279 
00280   // All users are OK.  Adjust the masks for MI.
00281   for (unsigned I = 0, E = AlterMasks.size(); I != E; I += 2) {
00282     AlterMasks[I]->setImm(CCValues);
00283     unsigned CCMask = AlterMasks[I + 1]->getImm();
00284     if (CCMask & ~ReusableCCMask)
00285       AlterMasks[I + 1]->setImm((CCMask & ReusableCCMask) |
00286                                 (CCValues & ~ReusableCCMask));
00287   }
00288 
00289   // CC is now live after MI.
00290   int CCDef = MI->findRegisterDefOperandIdx(SystemZ::CC, false, true, TRI);
00291   assert(CCDef >= 0 && "Couldn't find CC set");
00292   MI->getOperand(CCDef).setIsDead(false);
00293 
00294   // Clear any intervening kills of CC.
00295   MachineBasicBlock::iterator MBBI = MI, MBBE = Compare;
00296   for (++MBBI; MBBI != MBBE; ++MBBI)
00297     MBBI->clearRegisterKills(SystemZ::CC, TRI);
00298 
00299   return true;
00300 }
00301 
00302 // Return true if Compare is a comparison against zero.
00303 static bool isCompareZero(MachineInstr *Compare) {
00304   switch (Compare->getOpcode()) {
00305   case SystemZ::LTEBRCompare:
00306   case SystemZ::LTDBRCompare:
00307   case SystemZ::LTXBRCompare:
00308     return true;
00309 
00310   default:
00311     return (Compare->getNumExplicitOperands() == 2 &&
00312             Compare->getOperand(1).isImm() &&
00313             Compare->getOperand(1).getImm() == 0);
00314   }
00315 }
00316 
00317 // Try to optimize cases where comparison instruction Compare is testing
00318 // a value against zero.  Return true on success and if Compare should be
00319 // deleted as dead.  CCUsers is the list of instructions that use the CC
00320 // value produced by Compare.
00321 bool SystemZElimCompare::
00322 optimizeCompareZero(MachineInstr *Compare,
00323                     SmallVectorImpl<MachineInstr *> &CCUsers) {
00324   if (!isCompareZero(Compare))
00325     return false;
00326 
00327   // Search back for CC results that are based on the first operand.
00328   unsigned SrcReg = Compare->getOperand(0).getReg();
00329   unsigned SrcSubReg = Compare->getOperand(0).getSubReg();
00330   MachineBasicBlock &MBB = *Compare->getParent();
00331   MachineBasicBlock::iterator MBBI = Compare, MBBE = MBB.begin();
00332   Reference CCRefs;
00333   Reference SrcRefs;
00334   while (MBBI != MBBE) {
00335     --MBBI;
00336     MachineInstr *MI = MBBI;
00337     if (resultTests(MI, SrcReg, SrcSubReg)) {
00338       // Try to remove both MI and Compare by converting a branch to BRCT(G).
00339       // We don't care in this case whether CC is modified between MI and
00340       // Compare.
00341       if (!CCRefs.Use && !SrcRefs && convertToBRCT(MI, Compare, CCUsers)) {
00342         BranchOnCounts += 1;
00343         return true;
00344       }
00345       // Try to eliminate Compare by reusing a CC result from MI.
00346       if ((!CCRefs && convertToLoadAndTest(MI)) ||
00347           (!CCRefs.Def && adjustCCMasksForInstr(MI, Compare, CCUsers))) {
00348         EliminatedComparisons += 1;
00349         return true;
00350       }
00351     }
00352     SrcRefs |= getRegReferences(MI, SrcReg);
00353     if (SrcRefs.Def)
00354       return false;
00355     CCRefs |= getRegReferences(MI, SystemZ::CC);
00356     if (CCRefs.Use && CCRefs.Def)
00357       return false;
00358   }
00359   return false;
00360 }
00361 
00362 // Try to fuse comparison instruction Compare into a later branch.
00363 // Return true on success and if Compare is therefore redundant.
00364 bool SystemZElimCompare::
00365 fuseCompareAndBranch(MachineInstr *Compare,
00366                      SmallVectorImpl<MachineInstr *> &CCUsers) {
00367   // See whether we have a comparison that can be fused.
00368   unsigned FusedOpcode = TII->getCompareAndBranch(Compare->getOpcode(),
00369                                                   Compare);
00370   if (!FusedOpcode)
00371     return false;
00372 
00373   // See whether we have a single branch with which to fuse.
00374   if (CCUsers.size() != 1)
00375     return false;
00376   MachineInstr *Branch = CCUsers[0];
00377   if (Branch->getOpcode() != SystemZ::BRC)
00378     return false;
00379 
00380   // Make sure that the operands are available at the branch.
00381   unsigned SrcReg = Compare->getOperand(0).getReg();
00382   unsigned SrcReg2 = (Compare->getOperand(1).isReg() ?
00383                       Compare->getOperand(1).getReg() : 0);
00384   MachineBasicBlock::iterator MBBI = Compare, MBBE = Branch;
00385   for (++MBBI; MBBI != MBBE; ++MBBI)
00386     if (MBBI->modifiesRegister(SrcReg, TRI) ||
00387         (SrcReg2 && MBBI->modifiesRegister(SrcReg2, TRI)))
00388       return false;
00389 
00390   // Read the branch mask and target.
00391   MachineOperand CCMask(MBBI->getOperand(1));
00392   MachineOperand Target(MBBI->getOperand(2));
00393   assert((CCMask.getImm() & ~SystemZ::CCMASK_ICMP) == 0 &&
00394          "Invalid condition-code mask for integer comparison");
00395 
00396   // Clear out all current operands.
00397   int CCUse = MBBI->findRegisterUseOperandIdx(SystemZ::CC, false, TRI);
00398   assert(CCUse >= 0 && "BRC must use CC");
00399   Branch->RemoveOperand(CCUse);
00400   Branch->RemoveOperand(2);
00401   Branch->RemoveOperand(1);
00402   Branch->RemoveOperand(0);
00403 
00404   // Rebuild Branch as a fused compare and branch.
00405   Branch->setDesc(TII->get(FusedOpcode));
00406   MachineInstrBuilder(*Branch->getParent()->getParent(), Branch)
00407     .addOperand(Compare->getOperand(0))
00408     .addOperand(Compare->getOperand(1))
00409     .addOperand(CCMask)
00410     .addOperand(Target)
00411     .addReg(SystemZ::CC, RegState::ImplicitDefine);
00412 
00413   // Clear any intervening kills of SrcReg and SrcReg2.
00414   MBBI = Compare;
00415   for (++MBBI; MBBI != MBBE; ++MBBI) {
00416     MBBI->clearRegisterKills(SrcReg, TRI);
00417     if (SrcReg2)
00418       MBBI->clearRegisterKills(SrcReg2, TRI);
00419   }
00420   FusedComparisons += 1;
00421   return true;
00422 }
00423 
00424 // Process all comparison instructions in MBB.  Return true if something
00425 // changed.
00426 bool SystemZElimCompare::processBlock(MachineBasicBlock &MBB) {
00427   bool Changed = false;
00428 
00429   // Walk backwards through the block looking for comparisons, recording
00430   // all CC users as we go.  The subroutines can delete Compare and
00431   // instructions before it.
00432   bool CompleteCCUsers = !isCCLiveOut(MBB);
00433   SmallVector<MachineInstr *, 4> CCUsers;
00434   MachineBasicBlock::iterator MBBI = MBB.end();
00435   while (MBBI != MBB.begin()) {
00436     MachineInstr *MI = --MBBI;
00437     if (CompleteCCUsers &&
00438         MI->isCompare() &&
00439         (optimizeCompareZero(MI, CCUsers) ||
00440          fuseCompareAndBranch(MI, CCUsers))) {
00441       ++MBBI;
00442       MI->removeFromParent();
00443       Changed = true;
00444       CCUsers.clear();
00445       CompleteCCUsers = true;
00446       continue;
00447     }
00448 
00449     Reference CCRefs(getRegReferences(MI, SystemZ::CC));
00450     if (CCRefs.Def) {
00451       CCUsers.clear();
00452       CompleteCCUsers = !CCRefs.IndirectDef;
00453     }
00454     if (CompleteCCUsers && CCRefs.Use)
00455       CCUsers.push_back(MI);
00456   }
00457   return Changed;
00458 }
00459 
00460 bool SystemZElimCompare::runOnMachineFunction(MachineFunction &F) {
00461   TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo());
00462   TRI = &TII->getRegisterInfo();
00463 
00464   bool Changed = false;
00465   for (auto &MBB : F)
00466     Changed |= processBlock(MBB);
00467 
00468   return Changed;
00469 }