llvm-project/llvm/lib/Target/DirectX/DirectXTargetMachine.cpp
Farzon Lotfi 544562ebc2
[DirectX] Remove lifetime intrinsics and run Dead Store Elimination (#152636)
fixes #151764

This fix has two parts first we track all lifetime intrinsics and if
they are users of an alloca of a target extention like dx.RawBuffer then
we eliminate those memory intrinsics when we visit the alloca.

We do step one to allow us to use the Dead Store Elimination Pass. This
removes the alloca and simplifies the use of the target extention back
to using just the global. That keeps things in a form the
DXILBitcodeWriter is expecting.

Obviously to pull this off we needed to bring back the legacy pass
manager plumbing for the DSE pass and hook it up into the DirectX
backend.

The net impact of this change is that DML shader pass rate went from
89.72% (4268 successful compilations) to 90.98% (4328 successful
compilations).
2025-08-12 12:42:08 -04:00

211 lines
7.8 KiB
C++

//===- DirectXTargetMachine.cpp - DirectX Target Implementation -*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains DirectX target initializer.
///
//===----------------------------------------------------------------------===//
#include "DirectXTargetMachine.h"
#include "DXILCBufferAccess.h"
#include "DXILDataScalarization.h"
#include "DXILFlattenArrays.h"
#include "DXILForwardHandleAccesses.h"
#include "DXILIntrinsicExpansion.h"
#include "DXILLegalizePass.h"
#include "DXILOpLowering.h"
#include "DXILPostOptimizationValidation.h"
#include "DXILPrettyPrinter.h"
#include "DXILResourceAccess.h"
#include "DXILResourceImplicitBinding.h"
#include "DXILRootSignature.h"
#include "DXILShaderFlags.h"
#include "DXILTranslateMetadata.h"
#include "DXILWriter/DXILWriterPass.h"
#include "DirectX.h"
#include "DirectXSubtarget.h"
#include "DirectXTargetTransformInfo.h"
#include "TargetInfo/DirectXTargetInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/MCSectionDXContainer.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/Scalarizer.h"
#include <optional>
using namespace llvm;
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeDirectXTarget() {
RegisterTargetMachine<DirectXTargetMachine> X(getTheDirectXTarget());
auto *PR = PassRegistry::getPassRegistry();
initializeDXILIntrinsicExpansionLegacyPass(*PR);
initializeDXILDataScalarizationLegacyPass(*PR);
initializeDXILFlattenArraysLegacyPass(*PR);
initializeScalarizerLegacyPassPass(*PR);
initializeDXILLegalizeLegacyPass(*PR);
initializeDXILPrepareModulePass(*PR);
initializeEmbedDXILPassPass(*PR);
initializeWriteDXILPassPass(*PR);
initializeDXContainerGlobalsPass(*PR);
initializeDXILOpLoweringLegacyPass(*PR);
initializeDXILResourceAccessLegacyPass(*PR);
initializeDXILResourceImplicitBindingLegacyPass(*PR);
initializeDXILTranslateMetadataLegacyPass(*PR);
initializeDXILPostOptimizationValidationLegacyPass(*PR);
initializeShaderFlagsAnalysisWrapperPass(*PR);
initializeRootSignatureAnalysisWrapperPass(*PR);
initializeDXILFinalizeLinkageLegacyPass(*PR);
initializeDXILPrettyPrinterLegacyPass(*PR);
initializeDXILForwardHandleAccessesLegacyPass(*PR);
initializeDSELegacyPassPass(*PR);
initializeDXILCBufferAccessLegacyPass(*PR);
}
class DXILTargetObjectFile : public TargetLoweringObjectFile {
public:
DXILTargetObjectFile() = default;
MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
const TargetMachine &TM) const override {
return getContext().getDXContainerSection(GO->getSection(), Kind);
}
protected:
MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
const TargetMachine &TM) const override {
llvm_unreachable("Not supported!");
}
};
class DirectXPassConfig : public TargetPassConfig {
public:
DirectXPassConfig(DirectXTargetMachine &TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
DirectXTargetMachine &getDirectXTargetMachine() const {
return getTM<DirectXTargetMachine>();
}
FunctionPass *createTargetRegisterAllocator(bool) override { return nullptr; }
void addCodeGenPrepare() override {
addPass(createDXILFinalizeLinkageLegacyPass());
addPass(createDXILResourceAccessLegacyPass());
addPass(createDXILIntrinsicExpansionLegacyPass());
addPass(createDXILCBufferAccessLegacyPass());
addPass(createDXILDataScalarizationLegacyPass());
ScalarizerPassOptions DxilScalarOptions;
DxilScalarOptions.ScalarizeLoadStore = true;
addPass(createScalarizerPass(DxilScalarOptions));
addPass(createDXILFlattenArraysLegacyPass());
addPass(createDXILForwardHandleAccessesLegacyPass());
addPass(createDeadStoreEliminationPass());
addPass(createDXILLegalizeLegacyPass());
addPass(createDXILResourceImplicitBindingLegacyPass());
addPass(createDXILTranslateMetadataLegacyPass());
addPass(createDXILPostOptimizationValidationLegacyPass());
addPass(createDXILOpLoweringLegacyPass());
addPass(createDXILPrepareModulePass());
}
};
DirectXTargetMachine::DirectXTargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
std::optional<Reloc::Model> RM,
std::optional<CodeModel::Model> CM,
CodeGenOptLevel OL, bool JIT)
: CodeGenTargetMachineImpl(
T,
"e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-"
"f32:32-f64:64-n8:16:32:64",
TT, CPU, FS, Options, Reloc::Static, CodeModel::Small, OL),
TLOF(std::make_unique<DXILTargetObjectFile>()),
Subtarget(std::make_unique<DirectXSubtarget>(TT, CPU, FS, *this)) {
initAsmInfo();
}
DirectXTargetMachine::~DirectXTargetMachine() {}
void DirectXTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) {
#define GET_PASS_REGISTRY "DirectXPassRegistry.def"
#include "llvm/Passes/TargetPassRegistry.inc"
}
bool DirectXTargetMachine::addPassesToEmitFile(
PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *DwoOut,
CodeGenFileType FileType, bool DisableVerify,
MachineModuleInfoWrapperPass *MMIWP) {
TargetPassConfig *PassConfig = createPassConfig(PM);
PassConfig->addCodeGenPrepare();
switch (FileType) {
case CodeGenFileType::AssemblyFile:
PM.add(createDXILPrettyPrinterLegacyPass(Out));
PM.add(createPrintModulePass(Out, "", true));
break;
case CodeGenFileType::ObjectFile:
if (TargetPassConfig::willCompleteCodeGenPipeline()) {
PM.add(createDXILEmbedderPass());
// We embed the other DXContainer globals after embedding DXIL so that the
// globals don't pollute the DXIL.
PM.add(createDXContainerGlobalsPass());
if (!MMIWP)
MMIWP = new MachineModuleInfoWrapperPass(this);
PM.add(MMIWP);
if (addAsmPrinter(PM, Out, DwoOut, FileType,
MMIWP->getMMI().getContext()))
return true;
} else
PM.add(createDXILWriterPass(Out));
break;
case CodeGenFileType::Null:
break;
}
return false;
}
bool DirectXTargetMachine::addPassesToEmitMC(PassManagerBase &PM,
MCContext *&Ctx,
raw_pwrite_stream &Out,
bool DisableVerify) {
return true;
}
TargetPassConfig *DirectXTargetMachine::createPassConfig(PassManagerBase &PM) {
return new DirectXPassConfig(*this, PM);
}
const DirectXSubtarget *
DirectXTargetMachine::getSubtargetImpl(const Function &) const {
return Subtarget.get();
}
TargetTransformInfo
DirectXTargetMachine::getTargetTransformInfo(const Function &F) const {
return TargetTransformInfo(std::make_unique<DirectXTTIImpl>(this, F));
}
DirectXTargetLowering::DirectXTargetLowering(const DirectXTargetMachine &TM,
const DirectXSubtarget &STI)
: TargetLowering(TM) {
addRegisterClass(MVT::i32, &dxil::DXILClassRegClass);
computeRegisterProperties(STI.getRegisterInfo());
}