From: Amara Emerson Date: Mon, 15 Apr 2019 04:53:46 +0000 (+0000) Subject: [GlobalISel] Introduce a CSEConfigBase class to allow targets to define their own... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3d4f91d8d07a589fd89ce28669c1c8f67420c8aa;p=llvm [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 --- diff --git a/include/llvm/CodeGen/CSEConfigBase.h b/include/llvm/CodeGen/CSEConfigBase.h new file mode 100644 index 00000000000..70b5e5c17eb --- /dev/null +++ b/include/llvm/CodeGen/CSEConfigBase.h @@ -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 diff --git a/include/llvm/CodeGen/GlobalISel/CSEInfo.h b/include/llvm/CodeGen/GlobalISel/CSEInfo.h index 97f3cd5c95b..5a44e67992a 100644 --- a/include/llvm/CodeGen/GlobalISel/CSEInfo.h +++ b/include/llvm/CodeGen/GlobalISel/CSEInfo.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 +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 CSEMap; MachineRegisterInfo *MRI = nullptr; MachineFunction *MF = nullptr; - std::unique_ptr CSEOpt; + std::unique_ptr 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 Opt) { CSEOpt = std::move(Opt); } + void setCSEConfig(std::unique_ptr 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 CSEOpt, bool ReCompute = false); + GISelCSEInfo &get(std::unique_ptr CSEOpt, + bool ReCompute = false); void setMF(MachineFunction &MFunc) { MF = &MFunc; } void setComputed(bool Computed) { AlreadyComputed = Computed; } void releaseMemory() { Info.releaseMemory(); } diff --git a/include/llvm/CodeGen/TargetPassConfig.h b/include/llvm/CodeGen/TargetPassConfig.h index 80a26845eeb..8623e7bb079 100644 --- a/include/llvm/CodeGen/TargetPassConfig.h +++ b/include/llvm/CodeGen/TargetPassConfig.h @@ -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 getCSEConfig() const; + protected: // Helper to verify the analysis is really immutable. void setOpt(bool &Opt, bool Val); diff --git a/lib/CodeGen/GlobalISel/CSEInfo.cpp b/lib/CodeGen/GlobalISel/CSEInfo.cpp index aaf09c8c938..a87ef20a3be 100644 --- a/lib/CodeGen/GlobalISel/CSEInfo.cpp +++ b/lib/CodeGen/GlobalISel/CSEInfo.cpp @@ -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 +llvm::getStandardCSEConfigForOpt(CodeGenOpt::Level Level) { + std::unique_ptr Config; + if (Level == CodeGenOpt::None) + Config = make_unique(); + else + Config = make_unique(); + return Config; +} + /// ----------------------------------------- /// -------- GISelCSEInfo -------------// @@ -348,8 +359,9 @@ const GISelInstProfileBuilder &GISelInstProfileBuilder::addNodeIDMachineOperand( return *this; } -GISelCSEInfo &GISelCSEAnalysisWrapper::get(std::unique_ptr CSEOpt, - bool Recompute) { +GISelCSEInfo & +GISelCSEAnalysisWrapper::get(std::unique_ptr CSEOpt, + bool Recompute) { if (!AlreadyComputed || Recompute) { Info.setCSEConfig(std::move(CSEOpt)); Info.analyze(*MF); diff --git a/lib/CodeGen/GlobalISel/IRTranslator.cpp b/lib/CodeGen/GlobalISel/IRTranslator.cpp index 290d592339f..2e268ed27a9 100644 --- a/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1729,8 +1729,7 @@ bool IRTranslator::runOnMachineFunction(MachineFunction &CurMF) { if (EnableCSE) { EntryBuilder = make_unique(CurMF); - std::unique_ptr Config = make_unique(); - CSEInfo = &Wrapper.get(std::move(Config)); + CSEInfo = &Wrapper.get(TPC->getCSEConfig()); EntryBuilder->setCSEInfo(CSEInfo); CurBuilder = make_unique(CurMF); CurBuilder->setCSEInfo(CSEInfo); diff --git a/lib/CodeGen/GlobalISel/Legalizer.cpp b/lib/CodeGen/GlobalISel/Legalizer.cpp index 4db86761cdb..efdae5790ab 100644 --- a/lib/CodeGen/GlobalISel/Legalizer.cpp +++ b/lib/CodeGen/GlobalISel/Legalizer.cpp @@ -170,8 +170,7 @@ bool Legalizer::runOnMachineFunction(MachineFunction &MF) { if (EnableCSE) { MIRBuilder = make_unique(); - std::unique_ptr Config = make_unique(); - CSEInfo = &Wrapper.get(std::move(Config)); + CSEInfo = &Wrapper.get(TPC.getCSEConfig()); MIRBuilder->setCSEInfo(CSEInfo); } else MIRBuilder = make_unique(); diff --git a/lib/CodeGen/TargetPassConfig.cpp b/lib/CodeGen/TargetPassConfig.cpp index 8ddde4b8f99..e5c7ceff112 100644 --- a/lib/CodeGen/TargetPassConfig.cpp +++ b/lib/CodeGen/TargetPassConfig.cpp @@ -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 TargetPassConfig::getCSEConfig() const { + return make_unique(); +} diff --git a/lib/Target/AArch64/AArch64TargetMachine.cpp b/lib/Target/AArch64/AArch64TargetMachine.cpp index d213f20755f..d657fd414f3 100644 --- a/lib/Target/AArch64/AArch64TargetMachine.cpp +++ b/lib/Target/AArch64/AArch64TargetMachine.cpp @@ -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 getCSEConfig() const override; }; } // end anonymous namespace @@ -396,6 +399,10 @@ TargetPassConfig *AArch64TargetMachine::createPassConfig(PassManagerBase &PM) { return new AArch64PassConfig(*this, PM); } +std::unique_ptr AArch64PassConfig::getCSEConfig() const { + return getStandardCSEConfigForOpt(TM->getOptLevel()); +} + void AArch64PassConfig::addIRPasses() { // Always expand atomic operations, we don't deal with atomicrmw or cmpxchg // ourselves. diff --git a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index 8dd467b8d96..f2408819ce9 100644 --- a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -552,8 +552,14 @@ public: bool addPreISel() override; bool addInstSelector() override; bool addGCPasses() override; + + std::unique_ptr getCSEConfig() const override; }; +std::unique_ptr AMDGPUPassConfig::getCSEConfig() const { + return getStandardCSEConfigForOpt(TM->getOptLevel()); +} + class R600PassConfig final : public AMDGPUPassConfig { public: R600PassConfig(LLVMTargetMachine &TM, PassManagerBase &PM) diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp index d2663ac912d..3c38b4584e8 100644 --- a/lib/Target/ARM/ARMTargetMachine.cpp +++ b/lib/Target/ARM/ARMTargetMachine.cpp @@ -361,6 +361,8 @@ public: void addPreRegAlloc() override; void addPreSched2() override; void addPreEmitPass() override; + + std::unique_ptr getCSEConfig() const override; }; class ARMExecutionDomainFix : public ExecutionDomainFix { @@ -385,6 +387,10 @@ TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) { return new ARMPassConfig(*this, PM); } +std::unique_ptr ARMPassConfig::getCSEConfig() const { + return getStandardCSEConfigForOpt(TM->getOptLevel()); +} + void ARMPassConfig::addIRPasses() { if (TM->Options.ThreadModel == ThreadModel::Single) addPass(createLowerAtomicPass()); diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index 92ba00db1c3..591e2c4b706 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -239,6 +239,8 @@ public: bool addLegalizeMachineIR() override; bool addRegBankSelect() override; bool addGlobalInstructionSelect() override; + + std::unique_ptr getCSEConfig() const override; }; } // end anonymous namespace @@ -247,6 +249,10 @@ TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { return new MipsPassConfig(*this, PM); } +std::unique_ptr MipsPassConfig::getCSEConfig() const { + return getStandardCSEConfigForOpt(TM->getOptLevel()); +} + void MipsPassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); addPass(createAtomicExpandPass()); diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index d0006650cf8..73fb57a1f19 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -377,6 +377,8 @@ public: void addPreEmitPass() override; void addPreEmitPass2() override; void addPreSched2() override; + + std::unique_ptr getCSEConfig() const override; }; class X86ExecutionDomainFix : public ExecutionDomainFix { @@ -520,3 +522,7 @@ void X86PassConfig::addPreEmitPass2() { if (!TT.isOSDarwin() && !TT.isOSWindows()) addPass(createCFIInstrInserter()); } + +std::unique_ptr X86PassConfig::getCSEConfig() const { + return getStandardCSEConfigForOpt(TM->getOptLevel()); +} diff --git a/unittests/CodeGen/GlobalISel/CSETest.cpp b/unittests/CodeGen/GlobalISel/CSETest.cpp index 02627cae164..f2f755b23a0 100644 --- a/unittests/CodeGen/GlobalISel/CSETest.cpp +++ b/unittests/CodeGen/GlobalISel/CSETest.cpp @@ -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()); + CSEInfo.setCSEConfig(make_unique()); CSEInfo.analyze(*MF); B.setCSEInfo(&CSEInfo); CSEMIRBuilder CSEB(B.getState());