1 //===- llvm/CodeGen/GlobalISel/GIMatchTableExecutor.cpp -------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file 10 /// This file implements the GIMatchTableExecutor class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" 15 #include "llvm/CodeGen/GlobalISel/Utils.h" 16 #include "llvm/CodeGen/MachineInstr.h" 17 #include "llvm/CodeGen/MachineOperand.h" 18 #include "llvm/CodeGen/MachineRegisterInfo.h" 19 20 #define DEBUG_TYPE "gi-match-table-executor" 21 22 using namespace llvm; 23 24 GIMatchTableExecutor::MatcherState::MatcherState(unsigned MaxRenderers) 25 : Renderers(MaxRenderers) {} 26 27 GIMatchTableExecutor::GIMatchTableExecutor() = default; 28 29 bool GIMatchTableExecutor::isOperandImmEqual(const MachineOperand &MO, 30 int64_t Value, 31 const MachineRegisterInfo &MRI, 32 bool Splat) const { 33 if (MO.isReg() && MO.getReg()) { 34 if (auto VRegVal = getIConstantVRegValWithLookThrough(MO.getReg(), MRI)) 35 return VRegVal->Value.getSExtValue() == Value; 36 37 if (Splat) { 38 if (auto VRegVal = getIConstantSplatVal(MO.getReg(), MRI)) 39 return VRegVal->getSExtValue() == Value; 40 } 41 } 42 return false; 43 } 44 45 bool GIMatchTableExecutor::isBaseWithConstantOffset( 46 const MachineOperand &Root, const MachineRegisterInfo &MRI) const { 47 if (!Root.isReg()) 48 return false; 49 50 MachineInstr *RootI = MRI.getVRegDef(Root.getReg()); 51 if (RootI->getOpcode() != TargetOpcode::G_PTR_ADD) 52 return false; 53 54 MachineOperand &RHS = RootI->getOperand(2); 55 MachineInstr *RHSI = MRI.getVRegDef(RHS.getReg()); 56 if (RHSI->getOpcode() != TargetOpcode::G_CONSTANT) 57 return false; 58 59 return true; 60 } 61 62 bool GIMatchTableExecutor::isObviouslySafeToFold(MachineInstr &MI, 63 MachineInstr &IntoMI) const { 64 auto IntoMIIter = IntoMI.getIterator(); 65 66 // Immediate neighbours are already folded. 67 if (MI.getParent() == IntoMI.getParent() && 68 std::next(MI.getIterator()) == IntoMIIter) 69 return true; 70 71 // Convergent instructions cannot be moved in the CFG. 72 if (MI.isConvergent() && MI.getParent() != IntoMI.getParent()) 73 return false; 74 75 if (MI.isLoadFoldBarrier()) 76 return false; 77 78 // If the load is simple, check instructions between MI and IntoMI 79 if (MI.mayLoad() && MI.getParent() == IntoMI.getParent()) { 80 if (MI.memoperands_empty()) 81 return false; 82 auto &MMO = **(MI.memoperands_begin()); 83 if (MMO.isAtomic() || MMO.isVolatile()) 84 return false; 85 86 // Ensure instructions between MI and IntoMI are not affected when combined 87 unsigned Iter = 0; 88 const unsigned MaxIter = 20; 89 for (auto &CurrMI : 90 instructionsWithoutDebug(MI.getIterator(), IntoMI.getIterator())) { 91 if (CurrMI.isLoadFoldBarrier()) 92 return false; 93 94 if (Iter++ == MaxIter) 95 return false; 96 } 97 98 return true; 99 } 100 101 return !MI.mayLoad(); 102 } 103