mirror of
https://github.com/RPCS3/llvm.git
synced 2026-07-19 15:13:49 -04:00
[GlobalISel] Introduce a CSEConfigBase class to allow targets to define their own CSE configs.
Because CodeGen can't depend on GlobalISel, we need a way to encapsulate the CSE configs that can be passed between TargetPassConfig and the targets' custom pass configs. This CSEConfigBase allows targets to create custom CSE configs which is then used by the GISel passes for the CSEMIRBuilder. This support will be used in a follow up commit to allow constant-only CSE for -O0 compiles in D60580. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358368 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
//===- CSEConfigBase.h - A CSEConfig interface ------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_CSECONFIG_BASE_H
|
||||
#define LLVM_CODEGEN_CSECONFIG_BASE_H
|
||||
|
||||
namespace llvm {
|
||||
// Class representing some configuration that can be done during GlobalISel's
|
||||
// CSEInfo analysis. We define it here because TargetPassConfig can't depend on
|
||||
// the GlobalISel library, and so we use this in the interface between them
|
||||
// so that the derived classes in GISel can reference generic opcodes.
|
||||
class CSEConfigBase {
|
||||
public:
|
||||
virtual ~CSEConfigBase() = default;
|
||||
// Hook for defining which Generic instructions should be CSEd.
|
||||
// GISelCSEInfo currently only calls this hook when dealing with generic
|
||||
// opcodes.
|
||||
virtual bool shouldCSEOpc(unsigned Opc) { return false; }
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CODEGEN_CSECONFIG_BASE_H
|
||||
@@ -13,6 +13,7 @@
|
||||
#define LLVM_CODEGEN_GLOBALISEL_CSEINFO_H
|
||||
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/CodeGen/CSEConfigBase.h"
|
||||
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
|
||||
#include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
|
||||
#include "llvm/CodeGen/GlobalISel/Utils.h"
|
||||
@@ -36,25 +37,27 @@ public:
|
||||
void Profile(FoldingSetNodeID &ID);
|
||||
};
|
||||
|
||||
// Class representing some configuration that can be done during CSE analysis.
|
||||
// Currently it only supports shouldCSE method that each pass can set.
|
||||
class CSEConfig {
|
||||
// A CSE config for fully optimized builds.
|
||||
class CSEConfigFull : public CSEConfigBase {
|
||||
public:
|
||||
virtual ~CSEConfig() = default;
|
||||
// Hook for defining which Generic instructions should be CSEd.
|
||||
// GISelCSEInfo currently only calls this hook when dealing with generic
|
||||
// opcodes.
|
||||
virtual bool shouldCSEOpc(unsigned Opc);
|
||||
virtual ~CSEConfigFull() = default;
|
||||
virtual bool shouldCSEOpc(unsigned Opc) override;
|
||||
};
|
||||
|
||||
// TODO: Find a better place for this.
|
||||
// Commonly used for O0 config.
|
||||
class CSEConfigConstantOnly : public CSEConfig {
|
||||
class CSEConfigConstantOnly : public CSEConfigBase {
|
||||
public:
|
||||
virtual ~CSEConfigConstantOnly() = default;
|
||||
virtual bool shouldCSEOpc(unsigned Opc) override;
|
||||
};
|
||||
|
||||
// Returns the standard expected CSEConfig for the given optimization level.
|
||||
// We have this logic here so targets can make use of it from their derived
|
||||
// TargetPassConfig, but can't put this logic into TargetPassConfig directly
|
||||
// because the CodeGen library can't depend on GlobalISel.
|
||||
std::unique_ptr<CSEConfigBase>
|
||||
getStandardCSEConfigForOpt(CodeGenOpt::Level Level);
|
||||
|
||||
/// The CSE Analysis object.
|
||||
/// This installs itself as a delegate to the MachineFunction to track
|
||||
/// new instructions as well as deletions. It however will not be able to
|
||||
@@ -73,7 +76,7 @@ class GISelCSEInfo : public GISelChangeObserver {
|
||||
FoldingSet<UniqueMachineInstr> CSEMap;
|
||||
MachineRegisterInfo *MRI = nullptr;
|
||||
MachineFunction *MF = nullptr;
|
||||
std::unique_ptr<CSEConfig> CSEOpt;
|
||||
std::unique_ptr<CSEConfigBase> CSEOpt;
|
||||
/// Keep a cache of UniqueInstrs for each MachineInstr. In GISel,
|
||||
/// often instructions are mutated (while their ID has completely changed).
|
||||
/// Whenever mutation happens, invalidate the UniqueMachineInstr for the
|
||||
@@ -138,7 +141,9 @@ public:
|
||||
|
||||
void releaseMemory();
|
||||
|
||||
void setCSEConfig(std::unique_ptr<CSEConfig> Opt) { CSEOpt = std::move(Opt); }
|
||||
void setCSEConfig(std::unique_ptr<CSEConfigBase> Opt) {
|
||||
CSEOpt = std::move(Opt);
|
||||
}
|
||||
|
||||
bool shouldCSE(unsigned Opc) const;
|
||||
|
||||
@@ -198,11 +203,12 @@ class GISelCSEAnalysisWrapper {
|
||||
bool AlreadyComputed = false;
|
||||
|
||||
public:
|
||||
/// Takes a CSEConfig object that defines what opcodes get CSEd.
|
||||
/// Takes a CSEConfigBase object that defines what opcodes get CSEd.
|
||||
/// If CSEConfig is already set, and the CSE Analysis has been preserved,
|
||||
/// it will not use the new CSEOpt(use Recompute to force using the new
|
||||
/// CSEOpt).
|
||||
GISelCSEInfo &get(std::unique_ptr<CSEConfig> CSEOpt, bool ReCompute = false);
|
||||
GISelCSEInfo &get(std::unique_ptr<CSEConfigBase> CSEOpt,
|
||||
bool ReCompute = false);
|
||||
void setMF(MachineFunction &MFunc) { MF = &MFunc; }
|
||||
void setComputed(bool Computed) { AlreadyComputed = Computed; }
|
||||
void releaseMemory() { Info.releaseMemory(); }
|
||||
|
||||
@@ -24,6 +24,7 @@ class LLVMTargetMachine;
|
||||
struct MachineSchedContext;
|
||||
class PassConfigImpl;
|
||||
class ScheduleDAGInstrs;
|
||||
class CSEConfigBase;
|
||||
|
||||
// The old pass manager infrastructure is hidden in a legacy namespace now.
|
||||
namespace legacy {
|
||||
@@ -319,6 +320,9 @@ public:
|
||||
/// By default, it's enabled for non O0 levels.
|
||||
virtual bool isGISelCSEEnabled() const;
|
||||
|
||||
/// Returns the CSEConfig object to use for the current optimization level.
|
||||
virtual std::unique_ptr<CSEConfigBase> getCSEConfig() const;
|
||||
|
||||
protected:
|
||||
// Helper to verify the analysis is really immutable.
|
||||
void setOpt(bool &Opt, bool Val);
|
||||
|
||||
@@ -27,8 +27,8 @@ void UniqueMachineInstr::Profile(FoldingSetNodeID &ID) {
|
||||
}
|
||||
/// -----------------------------------------
|
||||
|
||||
/// --------- CSEConfig ---------- ///
|
||||
bool CSEConfig::shouldCSEOpc(unsigned Opc) {
|
||||
/// --------- CSEConfigFull ---------- ///
|
||||
bool CSEConfigFull::shouldCSEOpc(unsigned Opc) {
|
||||
switch (Opc) {
|
||||
default:
|
||||
break;
|
||||
@@ -60,6 +60,17 @@ bool CSEConfig::shouldCSEOpc(unsigned Opc) {
|
||||
bool CSEConfigConstantOnly::shouldCSEOpc(unsigned Opc) {
|
||||
return Opc == TargetOpcode::G_CONSTANT;
|
||||
}
|
||||
|
||||
std::unique_ptr<CSEConfigBase>
|
||||
llvm::getStandardCSEConfigForOpt(CodeGenOpt::Level Level) {
|
||||
std::unique_ptr<CSEConfigBase> Config;
|
||||
if (Level == CodeGenOpt::None)
|
||||
Config = make_unique<CSEConfigBase>();
|
||||
else
|
||||
Config = make_unique<CSEConfigFull>();
|
||||
return Config;
|
||||
}
|
||||
|
||||
/// -----------------------------------------
|
||||
|
||||
/// -------- GISelCSEInfo -------------//
|
||||
@@ -348,8 +359,9 @@ const GISelInstProfileBuilder &GISelInstProfileBuilder::addNodeIDMachineOperand(
|
||||
return *this;
|
||||
}
|
||||
|
||||
GISelCSEInfo &GISelCSEAnalysisWrapper::get(std::unique_ptr<CSEConfig> CSEOpt,
|
||||
bool Recompute) {
|
||||
GISelCSEInfo &
|
||||
GISelCSEAnalysisWrapper::get(std::unique_ptr<CSEConfigBase> CSEOpt,
|
||||
bool Recompute) {
|
||||
if (!AlreadyComputed || Recompute) {
|
||||
Info.setCSEConfig(std::move(CSEOpt));
|
||||
Info.analyze(*MF);
|
||||
|
||||
@@ -1729,8 +1729,7 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) {
|
||||
|
||||
if (EnableCSE) {
|
||||
EntryBuilder = make_unique<CSEMIRBuilder>(CurMF);
|
||||
std::unique_ptr<CSEConfig> Config = make_unique<CSEConfig>();
|
||||
CSEInfo = &Wrapper.get(std::move(Config));
|
||||
CSEInfo = &Wrapper.get(TPC->getCSEConfig());
|
||||
EntryBuilder->setCSEInfo(CSEInfo);
|
||||
CurBuilder = make_unique<CSEMIRBuilder>(CurMF);
|
||||
CurBuilder->setCSEInfo(CSEInfo);
|
||||
|
||||
@@ -170,8 +170,7 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
|
||||
|
||||
if (EnableCSE) {
|
||||
MIRBuilder = make_unique<CSEMIRBuilder>();
|
||||
std::unique_ptr<CSEConfig> Config = make_unique<CSEConfig>();
|
||||
CSEInfo = &Wrapper.get(std::move(Config));
|
||||
CSEInfo = &Wrapper.get(TPC.getCSEConfig());
|
||||
MIRBuilder->setCSEInfo(CSEInfo);
|
||||
} else
|
||||
MIRBuilder = make_unique<MachineIRBuilder>();
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "llvm/Analysis/ScopedNoAliasAA.h"
|
||||
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
|
||||
#include "llvm/CodeGen/CSEConfigBase.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachinePassRegistry.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
@@ -1227,3 +1228,7 @@ bool TargetPassConfig::reportDiagnosticWhenGlobalISelFallback() const {
|
||||
bool TargetPassConfig::isGISelCSEEnabled() const {
|
||||
return getOptLevel() != CodeGenOpt::Level::None;
|
||||
}
|
||||
|
||||
std::unique_ptr<CSEConfigBase> TargetPassConfig::getCSEConfig() const {
|
||||
return make_unique<CSEConfigBase>();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||
#include "llvm/CodeGen/CSEConfigBase.h"
|
||||
#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
|
||||
#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
|
||||
#include "llvm/CodeGen/GlobalISel/Legalizer.h"
|
||||
@@ -383,6 +384,8 @@ public:
|
||||
void addPostRegAlloc() override;
|
||||
void addPreSched2() override;
|
||||
void addPreEmitPass() override;
|
||||
|
||||
std::unique_ptr<CSEConfigBase> getCSEConfig() const override;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
@@ -396,6 +399,10 @@ TargetPassConfig *AArch64TargetMachine::createPassConfig(PassManagerBase &PM) {
|
||||
return new AArch64PassConfig(*this, PM);
|
||||
}
|
||||
|
||||
std::unique_ptr<CSEConfigBase> AArch64PassConfig::getCSEConfig() const {
|
||||
return getStandardCSEConfigForOpt(TM->getOptLevel());
|
||||
}
|
||||
|
||||
void AArch64PassConfig::addIRPasses() {
|
||||
// Always expand atomic operations, we don't deal with atomicrmw or cmpxchg
|
||||
// ourselves.
|
||||
|
||||
@@ -552,8 +552,14 @@ public:
|
||||
bool addPreISel() override;
|
||||
bool addInstSelector() override;
|
||||
bool addGCPasses() override;
|
||||
|
||||
std::unique_ptr<CSEConfigBase> getCSEConfig() const override;
|
||||
};
|
||||
|
||||
std::unique_ptr<CSEConfigBase> AMDGPUPassConfig::getCSEConfig() const {
|
||||
return getStandardCSEConfigForOpt(TM->getOptLevel());
|
||||
}
|
||||
|
||||
class R600PassConfig final : public AMDGPUPassConfig {
|
||||
public:
|
||||
R600PassConfig(LLVMTargetMachine &TM, PassManagerBase &PM)
|
||||
|
||||
@@ -361,6 +361,8 @@ public:
|
||||
void addPreRegAlloc() override;
|
||||
void addPreSched2() override;
|
||||
void addPreEmitPass() override;
|
||||
|
||||
std::unique_ptr<CSEConfigBase> getCSEConfig() const override;
|
||||
};
|
||||
|
||||
class ARMExecutionDomainFix : public ExecutionDomainFix {
|
||||
@@ -385,6 +387,10 @@ TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
|
||||
return new ARMPassConfig(*this, PM);
|
||||
}
|
||||
|
||||
std::unique_ptr<CSEConfigBase> ARMPassConfig::getCSEConfig() const {
|
||||
return getStandardCSEConfigForOpt(TM->getOptLevel());
|
||||
}
|
||||
|
||||
void ARMPassConfig::addIRPasses() {
|
||||
if (TM->Options.ThreadModel == ThreadModel::Single)
|
||||
addPass(createLowerAtomicPass());
|
||||
|
||||
@@ -239,6 +239,8 @@ public:
|
||||
bool addLegalizeMachineIR() override;
|
||||
bool addRegBankSelect() override;
|
||||
bool addGlobalInstructionSelect() override;
|
||||
|
||||
std::unique_ptr<CSEConfigBase> getCSEConfig() const override;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
@@ -247,6 +249,10 @@ TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) {
|
||||
return new MipsPassConfig(*this, PM);
|
||||
}
|
||||
|
||||
std::unique_ptr<CSEConfigBase> MipsPassConfig::getCSEConfig() const {
|
||||
return getStandardCSEConfigForOpt(TM->getOptLevel());
|
||||
}
|
||||
|
||||
void MipsPassConfig::addIRPasses() {
|
||||
TargetPassConfig::addIRPasses();
|
||||
addPass(createAtomicExpandPass());
|
||||
|
||||
@@ -377,6 +377,8 @@ public:
|
||||
void addPreEmitPass() override;
|
||||
void addPreEmitPass2() override;
|
||||
void addPreSched2() override;
|
||||
|
||||
std::unique_ptr<CSEConfigBase> getCSEConfig() const override;
|
||||
};
|
||||
|
||||
class X86ExecutionDomainFix : public ExecutionDomainFix {
|
||||
@@ -520,3 +522,7 @@ void X86PassConfig::addPreEmitPass2() {
|
||||
if (!TT.isOSDarwin() && !TT.isOSWindows())
|
||||
addPass(createCFIInstrInserter());
|
||||
}
|
||||
|
||||
std::unique_ptr<CSEConfigBase> X86PassConfig::getCSEConfig() const {
|
||||
return getStandardCSEConfigForOpt(TM->getOptLevel());
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ TEST_F(GISelMITest, TestCSE) {
|
||||
auto MIBInput1 = B.buildInstr(TargetOpcode::G_TRUNC, {s16}, {Copies[1]});
|
||||
auto MIBAdd = B.buildInstr(TargetOpcode::G_ADD, {s16}, {MIBInput, MIBInput});
|
||||
GISelCSEInfo CSEInfo;
|
||||
CSEInfo.setCSEConfig(make_unique<CSEConfig>());
|
||||
CSEInfo.setCSEConfig(make_unique<CSEConfigFull>());
|
||||
CSEInfo.analyze(*MF);
|
||||
B.setCSEInfo(&CSEInfo);
|
||||
CSEMIRBuilder CSEB(B.getState());
|
||||
|
||||
Reference in New Issue
Block a user