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.
103 lines
3.2 KiB
C++
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;
|
|
}
|