Files
clang-p2996/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp
chuongg3 d58bd21150 [GlobalISel] Look between instructions to be matched (#101675)
When a pattern is matched in TableGen, a check is run called
isObviouslySafeToFold(). One of the condition that it checks for is
whether the instructions that are being matched are consecutive, so the
instruction's insertion point does not change.

This patch allows the movement of the insertion point of a load
instruction if none of the intervening instructions are stores or have
side-effects.
2024-08-27 16:56:40 +01:00

103 lines
3.2 KiB
C++

//===- llvm/CodeGen/GlobalISel/GIMatchTableExecutor.cpp -------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// \file
/// This file implements the GIMatchTableExecutor class.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#define DEBUG_TYPE "gi-match-table-executor"
using namespace llvm;
GIMatchTableExecutor::MatcherState::MatcherState(unsigned MaxRenderers)
: Renderers(MaxRenderers) {}
GIMatchTableExecutor::GIMatchTableExecutor() = default;
bool GIMatchTableExecutor::isOperandImmEqual(const MachineOperand &MO,
int64_t Value,
const MachineRegisterInfo &MRI,
bool Splat) const {
if (MO.isReg() && MO.getReg()) {
if (auto VRegVal = getIConstantVRegValWithLookThrough(MO.getReg(), MRI))
return VRegVal->Value.getSExtValue() == Value;
if (Splat) {
if (auto VRegVal = getIConstantSplatVal(MO.getReg(), MRI))
return VRegVal->getSExtValue() == Value;
}
}
return false;
}
bool GIMatchTableExecutor::isBaseWithConstantOffset(
const MachineOperand &Root, const MachineRegisterInfo &MRI) const {
if (!Root.isReg())
return false;
MachineInstr *RootI = MRI.getVRegDef(Root.getReg());
if (RootI->getOpcode() != TargetOpcode::G_PTR_ADD)
return false;
MachineOperand &RHS = RootI->getOperand(2);
MachineInstr *RHSI = MRI.getVRegDef(RHS.getReg());
if (RHSI->getOpcode() != TargetOpcode::G_CONSTANT)
return false;
return true;
}
bool GIMatchTableExecutor::isObviouslySafeToFold(MachineInstr &MI,
MachineInstr &IntoMI) const {
auto IntoMIIter = IntoMI.getIterator();
// Immediate neighbours are already folded.
if (MI.getParent() == IntoMI.getParent() &&
std::next(MI.getIterator()) == IntoMIIter)
return true;
// Convergent instructions cannot be moved in the CFG.
if (MI.isConvergent() && MI.getParent() != IntoMI.getParent())
return false;
if (MI.isLoadFoldBarrier())
return false;
// If the load is simple, check instructions between MI and IntoMI
if (MI.mayLoad() && MI.getParent() == IntoMI.getParent()) {
if (MI.memoperands_empty())
return false;
auto &MMO = **(MI.memoperands_begin());
if (MMO.isAtomic() || MMO.isVolatile())
return false;
// Ensure instructions between MI and IntoMI are not affected when combined
unsigned Iter = 0;
const unsigned MaxIter = 20;
for (auto &CurrMI :
instructionsWithoutDebug(MI.getIterator(), IntoMI.getIterator())) {
if (CurrMI.isLoadFoldBarrier())
return false;
if (Iter++ == MaxIter)
return false;
}
return true;
}
return true;
}