11fe7d9c7Spvanhout //===- llvm/CodeGen/GlobalISel/GIMatchTableExecutor.cpp -------------------===// 21fe7d9c7Spvanhout // 31fe7d9c7Spvanhout // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41fe7d9c7Spvanhout // See https://llvm.org/LICENSE.txt for license information. 51fe7d9c7Spvanhout // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61fe7d9c7Spvanhout // 71fe7d9c7Spvanhout //===----------------------------------------------------------------------===// 81fe7d9c7Spvanhout // 91fe7d9c7Spvanhout /// \file 101fe7d9c7Spvanhout /// This file implements the GIMatchTableExecutor class. 111fe7d9c7Spvanhout // 121fe7d9c7Spvanhout //===----------------------------------------------------------------------===// 131fe7d9c7Spvanhout 141fe7d9c7Spvanhout #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h" 151fe7d9c7Spvanhout #include "llvm/CodeGen/GlobalISel/Utils.h" 161fe7d9c7Spvanhout #include "llvm/CodeGen/MachineInstr.h" 171fe7d9c7Spvanhout #include "llvm/CodeGen/MachineOperand.h" 181fe7d9c7Spvanhout #include "llvm/CodeGen/MachineRegisterInfo.h" 191fe7d9c7Spvanhout 201fe7d9c7Spvanhout #define DEBUG_TYPE "gi-match-table-executor" 211fe7d9c7Spvanhout 221fe7d9c7Spvanhout using namespace llvm; 231fe7d9c7Spvanhout 241fe7d9c7Spvanhout GIMatchTableExecutor::MatcherState::MatcherState(unsigned MaxRenderers) 251fe7d9c7Spvanhout : Renderers(MaxRenderers) {} 261fe7d9c7Spvanhout 271fe7d9c7Spvanhout GIMatchTableExecutor::GIMatchTableExecutor() = default; 281fe7d9c7Spvanhout 2963afb705Spvanhout bool GIMatchTableExecutor::isOperandImmEqual(const MachineOperand &MO, 3063afb705Spvanhout int64_t Value, 3163afb705Spvanhout const MachineRegisterInfo &MRI, 3263afb705Spvanhout bool Splat) const { 3363afb705Spvanhout if (MO.isReg() && MO.getReg()) { 341fe7d9c7Spvanhout if (auto VRegVal = getIConstantVRegValWithLookThrough(MO.getReg(), MRI)) 351fe7d9c7Spvanhout return VRegVal->Value.getSExtValue() == Value; 3663afb705Spvanhout 3763afb705Spvanhout if (Splat) { 3863afb705Spvanhout if (auto VRegVal = getIConstantSplatVal(MO.getReg(), MRI)) 3963afb705Spvanhout return VRegVal->getSExtValue() == Value; 4063afb705Spvanhout } 4163afb705Spvanhout } 421fe7d9c7Spvanhout return false; 431fe7d9c7Spvanhout } 441fe7d9c7Spvanhout 451fe7d9c7Spvanhout bool GIMatchTableExecutor::isBaseWithConstantOffset( 461fe7d9c7Spvanhout const MachineOperand &Root, const MachineRegisterInfo &MRI) const { 471fe7d9c7Spvanhout if (!Root.isReg()) 481fe7d9c7Spvanhout return false; 491fe7d9c7Spvanhout 501fe7d9c7Spvanhout MachineInstr *RootI = MRI.getVRegDef(Root.getReg()); 511fe7d9c7Spvanhout if (RootI->getOpcode() != TargetOpcode::G_PTR_ADD) 521fe7d9c7Spvanhout return false; 531fe7d9c7Spvanhout 541fe7d9c7Spvanhout MachineOperand &RHS = RootI->getOperand(2); 551fe7d9c7Spvanhout MachineInstr *RHSI = MRI.getVRegDef(RHS.getReg()); 561fe7d9c7Spvanhout if (RHSI->getOpcode() != TargetOpcode::G_CONSTANT) 571fe7d9c7Spvanhout return false; 581fe7d9c7Spvanhout 591fe7d9c7Spvanhout return true; 601fe7d9c7Spvanhout } 611fe7d9c7Spvanhout 621fe7d9c7Spvanhout bool GIMatchTableExecutor::isObviouslySafeToFold(MachineInstr &MI, 631fe7d9c7Spvanhout MachineInstr &IntoMI) const { 64d58bd211Schuongg3 auto IntoMIIter = IntoMI.getIterator(); 65d58bd211Schuongg3 661fe7d9c7Spvanhout // Immediate neighbours are already folded. 671fe7d9c7Spvanhout if (MI.getParent() == IntoMI.getParent() && 68d58bd211Schuongg3 std::next(MI.getIterator()) == IntoMIIter) 691fe7d9c7Spvanhout return true; 701fe7d9c7Spvanhout 711fe7d9c7Spvanhout // Convergent instructions cannot be moved in the CFG. 721fe7d9c7Spvanhout if (MI.isConvergent() && MI.getParent() != IntoMI.getParent()) 731fe7d9c7Spvanhout return false; 741fe7d9c7Spvanhout 75d58bd211Schuongg3 if (MI.isLoadFoldBarrier()) 76d58bd211Schuongg3 return false; 77d58bd211Schuongg3 78d58bd211Schuongg3 // If the load is simple, check instructions between MI and IntoMI 79d58bd211Schuongg3 if (MI.mayLoad() && MI.getParent() == IntoMI.getParent()) { 80d58bd211Schuongg3 if (MI.memoperands_empty()) 81d58bd211Schuongg3 return false; 82d58bd211Schuongg3 auto &MMO = **(MI.memoperands_begin()); 83d58bd211Schuongg3 if (MMO.isAtomic() || MMO.isVolatile()) 84d58bd211Schuongg3 return false; 85d58bd211Schuongg3 86d58bd211Schuongg3 // Ensure instructions between MI and IntoMI are not affected when combined 87d58bd211Schuongg3 unsigned Iter = 0; 88d58bd211Schuongg3 const unsigned MaxIter = 20; 89d58bd211Schuongg3 for (auto &CurrMI : 90d58bd211Schuongg3 instructionsWithoutDebug(MI.getIterator(), IntoMI.getIterator())) { 91d58bd211Schuongg3 if (CurrMI.isLoadFoldBarrier()) 92d58bd211Schuongg3 return false; 93d58bd211Schuongg3 94d58bd211Schuongg3 if (Iter++ == MaxIter) 95d58bd211Schuongg3 return false; 96d58bd211Schuongg3 } 97d58bd211Schuongg3 98d58bd211Schuongg3 return true; 99d58bd211Schuongg3 } 100d58bd211Schuongg3 101*549413faSDavid Green return !MI.mayLoad(); 1021fe7d9c7Spvanhout } 103