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/MIPatternMatch.h"
16#include "llvm/CodeGen/GlobalISel/Utils.h"
17#include "llvm/CodeGen/MachineInstr.h"
18#include "llvm/CodeGen/MachineOperand.h"
19#include "llvm/CodeGen/MachineRegisterInfo.h"
20
21#define DEBUG_TYPE "gi-match-table-executor"
22
23using namespace llvm;
24using namespace MIPatternMatch;
25
26GIMatchTableExecutor::MatcherState::MatcherState(unsigned MaxRenderers)
27 : Renderers(MaxRenderers) {}
28
29GIMatchTableExecutor::GIMatchTableExecutor() = default;
30
31bool GIMatchTableExecutor::isOperandImmEqual(const MachineOperand &MO,
32 int64_t Value,
33 const MachineRegisterInfo &MRI,
34 bool Splat) const {
35 if (MO.isReg() && MO.getReg()) {
36 if (auto VRegVal = getIConstantVRegValWithLookThrough(VReg: MO.getReg(), MRI))
37 return VRegVal->Value.getSExtValue() == Value;
38
39 if (Splat) {
40 if (auto VRegVal = getIConstantSplatVal(Reg: MO.getReg(), MRI))
41 return VRegVal->getSExtValue() == Value;
42 }
43 }
44 return false;
45}
46
47bool GIMatchTableExecutor::isBaseWithConstantOffset(
48 const MachineOperand &Root, const MachineRegisterInfo &MRI) const {
49 if (!Root.isReg())
50 return false;
51
52 GConstant *RHSI;
53 return mi_match(R: Root.getReg(), MRI, P: m_GPtrAdd(L: m_Reg(), R: m_GConstant(Inst&: RHSI)));
54}
55
56bool GIMatchTableExecutor::isObviouslySafeToFold(MachineInstr &MI,
57 MachineInstr &IntoMI) const {
58 auto IntoMIIter = IntoMI.getIterator();
59
60 // Immediate neighbours are already folded.
61 if (MI.getParent() == IntoMI.getParent() &&
62 std::next(x: MI.getIterator()) == IntoMIIter)
63 return true;
64
65 // Convergent instructions cannot be moved in the CFG.
66 if (MI.isConvergent() && MI.getParent() != IntoMI.getParent())
67 return false;
68
69 if (MI.isLoadFoldBarrier())
70 return false;
71
72 // If the load is simple, check instructions between MI and IntoMI
73 if (MI.mayLoad() && MI.getParent() == IntoMI.getParent()) {
74 if (MI.memoperands_empty())
75 return false;
76 auto &MMO = **(MI.memoperands_begin());
77 if (MMO.isAtomic() || MMO.isVolatile())
78 return false;
79
80 // Ensure instructions between MI and IntoMI are not affected when combined
81 unsigned Iter = 0;
82 const unsigned MaxIter = 20;
83 for (auto &CurrMI :
84 instructionsWithoutDebug(It: MI.getIterator(), End: IntoMI.getIterator())) {
85 if (CurrMI.isLoadFoldBarrier())
86 return false;
87
88 if (Iter++ == MaxIter)
89 return false;
90 }
91
92 return true;
93 }
94
95 return !MI.mayLoad();
96}
97