106c3fb27SDimitry Andric //===- llvm/CodeGen/GlobalISel/GIMatchTableExecutor.cpp -------------------===//
206c3fb27SDimitry Andric //
306c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
506c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606c3fb27SDimitry Andric //
706c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
806c3fb27SDimitry Andric //
906c3fb27SDimitry Andric /// \file
1006c3fb27SDimitry Andric /// This file implements the GIMatchTableExecutor class.
1106c3fb27SDimitry Andric //
1206c3fb27SDimitry Andric //===----------------------------------------------------------------------===//
1306c3fb27SDimitry Andric
1406c3fb27SDimitry Andric #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
1506c3fb27SDimitry Andric #include "llvm/CodeGen/GlobalISel/Utils.h"
1606c3fb27SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
1706c3fb27SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
1806c3fb27SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
1906c3fb27SDimitry Andric
2006c3fb27SDimitry Andric #define DEBUG_TYPE "gi-match-table-executor"
2106c3fb27SDimitry Andric
2206c3fb27SDimitry Andric using namespace llvm;
2306c3fb27SDimitry Andric
MatcherState(unsigned MaxRenderers)2406c3fb27SDimitry Andric GIMatchTableExecutor::MatcherState::MatcherState(unsigned MaxRenderers)
2506c3fb27SDimitry Andric : Renderers(MaxRenderers) {}
2606c3fb27SDimitry Andric
2706c3fb27SDimitry Andric GIMatchTableExecutor::GIMatchTableExecutor() = default;
2806c3fb27SDimitry Andric
isOperandImmEqual(const MachineOperand & MO,int64_t Value,const MachineRegisterInfo & MRI,bool Splat) const29*5f757f3fSDimitry Andric bool GIMatchTableExecutor::isOperandImmEqual(const MachineOperand &MO,
30*5f757f3fSDimitry Andric int64_t Value,
31*5f757f3fSDimitry Andric const MachineRegisterInfo &MRI,
32*5f757f3fSDimitry Andric bool Splat) const {
33*5f757f3fSDimitry Andric if (MO.isReg() && MO.getReg()) {
3406c3fb27SDimitry Andric if (auto VRegVal = getIConstantVRegValWithLookThrough(MO.getReg(), MRI))
3506c3fb27SDimitry Andric return VRegVal->Value.getSExtValue() == Value;
36*5f757f3fSDimitry Andric
37*5f757f3fSDimitry Andric if (Splat) {
38*5f757f3fSDimitry Andric if (auto VRegVal = getIConstantSplatVal(MO.getReg(), MRI))
39*5f757f3fSDimitry Andric return VRegVal->getSExtValue() == Value;
40*5f757f3fSDimitry Andric }
41*5f757f3fSDimitry Andric }
4206c3fb27SDimitry Andric return false;
4306c3fb27SDimitry Andric }
4406c3fb27SDimitry Andric
isBaseWithConstantOffset(const MachineOperand & Root,const MachineRegisterInfo & MRI) const4506c3fb27SDimitry Andric bool GIMatchTableExecutor::isBaseWithConstantOffset(
4606c3fb27SDimitry Andric const MachineOperand &Root, const MachineRegisterInfo &MRI) const {
4706c3fb27SDimitry Andric if (!Root.isReg())
4806c3fb27SDimitry Andric return false;
4906c3fb27SDimitry Andric
5006c3fb27SDimitry Andric MachineInstr *RootI = MRI.getVRegDef(Root.getReg());
5106c3fb27SDimitry Andric if (RootI->getOpcode() != TargetOpcode::G_PTR_ADD)
5206c3fb27SDimitry Andric return false;
5306c3fb27SDimitry Andric
5406c3fb27SDimitry Andric MachineOperand &RHS = RootI->getOperand(2);
5506c3fb27SDimitry Andric MachineInstr *RHSI = MRI.getVRegDef(RHS.getReg());
5606c3fb27SDimitry Andric if (RHSI->getOpcode() != TargetOpcode::G_CONSTANT)
5706c3fb27SDimitry Andric return false;
5806c3fb27SDimitry Andric
5906c3fb27SDimitry Andric return true;
6006c3fb27SDimitry Andric }
6106c3fb27SDimitry Andric
isObviouslySafeToFold(MachineInstr & MI,MachineInstr & IntoMI) const6206c3fb27SDimitry Andric bool GIMatchTableExecutor::isObviouslySafeToFold(MachineInstr &MI,
6306c3fb27SDimitry Andric MachineInstr &IntoMI) const {
6406c3fb27SDimitry Andric // Immediate neighbours are already folded.
6506c3fb27SDimitry Andric if (MI.getParent() == IntoMI.getParent() &&
6606c3fb27SDimitry Andric std::next(MI.getIterator()) == IntoMI.getIterator())
6706c3fb27SDimitry Andric return true;
6806c3fb27SDimitry Andric
6906c3fb27SDimitry Andric // Convergent instructions cannot be moved in the CFG.
7006c3fb27SDimitry Andric if (MI.isConvergent() && MI.getParent() != IntoMI.getParent())
7106c3fb27SDimitry Andric return false;
7206c3fb27SDimitry Andric
7306c3fb27SDimitry Andric return !MI.mayLoadOrStore() && !MI.mayRaiseFPException() &&
7406c3fb27SDimitry Andric !MI.hasUnmodeledSideEffects() && MI.implicit_operands().empty();
7506c3fb27SDimitry Andric }
76