Move `AttributeMask` out of `llvm/IR/Attributes.h` to a new file `llvm/IR/AttributeMask.h`. After doing this we can remove the `#include <bitset>` and `#include <set>` directives from `Attributes.h`. Since there are many headers including `Attributes.h`, but not needing the definition of `AttributeMask`, this causes unnecessary bloating of the translation units and slows down compilation. This commit adds in the include directive for `llvm/IR/AttributeMask.h` to the handful of source files that need to see the definition. This reduces the total number of preprocessing tokens across the LLVM source files in lib from (roughly) 1,917,509,187 to 1,902,982,273 - a reduction of ~0.76%. This should result in a small improvement in compilation time. Differential Revision: https://reviews.llvm.org/D153728
193 lines
7.3 KiB
C++
193 lines
7.3 KiB
C++
//===- DXILPrepare.cpp - Prepare LLVM Module for DXIL encoding ------------===//
|
|
//
|
|
// 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 pases and utilities to convert a modern LLVM
|
|
/// module into a module compatible with the LLVM 3.7-based DirectX Intermediate
|
|
/// Language (DXIL).
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "DirectX.h"
|
|
#include "DirectXIRPasses/PointerTypeAnalysis.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/IR/AttributeMask.h"
|
|
#include "llvm/IR/IRBuilder.h"
|
|
#include "llvm/IR/Instruction.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/InitializePasses.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
#define DEBUG_TYPE "dxil-prepare"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::dxil;
|
|
|
|
namespace {
|
|
|
|
constexpr bool isValidForDXIL(Attribute::AttrKind Attr) {
|
|
return is_contained({Attribute::Alignment,
|
|
Attribute::AlwaysInline,
|
|
Attribute::Builtin,
|
|
Attribute::ByVal,
|
|
Attribute::InAlloca,
|
|
Attribute::Cold,
|
|
Attribute::Convergent,
|
|
Attribute::InlineHint,
|
|
Attribute::InReg,
|
|
Attribute::JumpTable,
|
|
Attribute::MinSize,
|
|
Attribute::Naked,
|
|
Attribute::Nest,
|
|
Attribute::NoAlias,
|
|
Attribute::NoBuiltin,
|
|
Attribute::NoCapture,
|
|
Attribute::NoDuplicate,
|
|
Attribute::NoImplicitFloat,
|
|
Attribute::NoInline,
|
|
Attribute::NonLazyBind,
|
|
Attribute::NonNull,
|
|
Attribute::Dereferenceable,
|
|
Attribute::DereferenceableOrNull,
|
|
Attribute::Memory,
|
|
Attribute::NoRedZone,
|
|
Attribute::NoReturn,
|
|
Attribute::NoUnwind,
|
|
Attribute::OptimizeForSize,
|
|
Attribute::OptimizeNone,
|
|
Attribute::ReadNone,
|
|
Attribute::ReadOnly,
|
|
Attribute::Returned,
|
|
Attribute::ReturnsTwice,
|
|
Attribute::SExt,
|
|
Attribute::StackAlignment,
|
|
Attribute::StackProtect,
|
|
Attribute::StackProtectReq,
|
|
Attribute::StackProtectStrong,
|
|
Attribute::SafeStack,
|
|
Attribute::StructRet,
|
|
Attribute::SanitizeAddress,
|
|
Attribute::SanitizeThread,
|
|
Attribute::SanitizeMemory,
|
|
Attribute::UWTable,
|
|
Attribute::ZExt},
|
|
Attr);
|
|
}
|
|
|
|
class DXILPrepareModule : public ModulePass {
|
|
|
|
static Value *maybeGenerateBitcast(IRBuilder<> &Builder,
|
|
PointerTypeMap &PointerTypes,
|
|
Instruction &Inst, Value *Operand,
|
|
Type *Ty) {
|
|
// Omit bitcasts if the incoming value matches the instruction type.
|
|
auto It = PointerTypes.find(Operand);
|
|
if (It != PointerTypes.end())
|
|
if (cast<TypedPointerType>(It->second)->getElementType() == Ty)
|
|
return nullptr;
|
|
// Insert bitcasts where we are removing the instruction.
|
|
Builder.SetInsertPoint(&Inst);
|
|
// This code only gets hit in opaque-pointer mode, so the type of the
|
|
// pointer doesn't matter.
|
|
PointerType *PtrTy = cast<PointerType>(Operand->getType());
|
|
return Builder.Insert(
|
|
CastInst::Create(Instruction::BitCast, Operand,
|
|
Builder.getInt8PtrTy(PtrTy->getAddressSpace())));
|
|
}
|
|
|
|
public:
|
|
bool runOnModule(Module &M) override {
|
|
PointerTypeMap PointerTypes = PointerTypeAnalysis::run(M);
|
|
AttributeMask AttrMask;
|
|
for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
|
|
I = Attribute::AttrKind(I + 1)) {
|
|
if (!isValidForDXIL(I))
|
|
AttrMask.addAttribute(I);
|
|
}
|
|
for (auto &F : M.functions()) {
|
|
F.removeFnAttrs(AttrMask);
|
|
F.removeRetAttrs(AttrMask);
|
|
for (size_t Idx = 0, End = F.arg_size(); Idx < End; ++Idx)
|
|
F.removeParamAttrs(Idx, AttrMask);
|
|
|
|
for (auto &BB : F) {
|
|
IRBuilder<> Builder(&BB);
|
|
for (auto &I : make_early_inc_range(BB)) {
|
|
if (I.getOpcode() == Instruction::FNeg) {
|
|
Builder.SetInsertPoint(&I);
|
|
Value *In = I.getOperand(0);
|
|
Value *Zero = ConstantFP::get(In->getType(), -0.0);
|
|
I.replaceAllUsesWith(Builder.CreateFSub(Zero, In));
|
|
I.eraseFromParent();
|
|
continue;
|
|
}
|
|
// Only insert bitcasts if the IR is using opaque pointers.
|
|
if (M.getContext().supportsTypedPointers())
|
|
continue;
|
|
|
|
// Emtting NoOp bitcast instructions allows the ValueEnumerator to be
|
|
// unmodified as it reserves instruction IDs during contruction.
|
|
if (auto LI = dyn_cast<LoadInst>(&I)) {
|
|
if (Value *NoOpBitcast = maybeGenerateBitcast(
|
|
Builder, PointerTypes, I, LI->getPointerOperand(),
|
|
LI->getType())) {
|
|
LI->replaceAllUsesWith(
|
|
Builder.CreateLoad(LI->getType(), NoOpBitcast));
|
|
LI->eraseFromParent();
|
|
}
|
|
continue;
|
|
}
|
|
if (auto SI = dyn_cast<StoreInst>(&I)) {
|
|
if (Value *NoOpBitcast = maybeGenerateBitcast(
|
|
Builder, PointerTypes, I, SI->getPointerOperand(),
|
|
SI->getValueOperand()->getType())) {
|
|
|
|
SI->replaceAllUsesWith(
|
|
Builder.CreateStore(SI->getValueOperand(), NoOpBitcast));
|
|
SI->eraseFromParent();
|
|
}
|
|
continue;
|
|
}
|
|
if (auto GEP = dyn_cast<GetElementPtrInst>(&I)) {
|
|
if (Value *NoOpBitcast = maybeGenerateBitcast(
|
|
Builder, PointerTypes, I, GEP->getPointerOperand(),
|
|
GEP->getResultElementType()))
|
|
GEP->setOperand(0, NoOpBitcast);
|
|
continue;
|
|
}
|
|
if (auto *CB = dyn_cast<CallBase>(&I)) {
|
|
CB->removeFnAttrs(AttrMask);
|
|
CB->removeRetAttrs(AttrMask);
|
|
for (size_t Idx = 0, End = CB->arg_size(); Idx < End; ++Idx)
|
|
CB->removeParamAttrs(Idx, AttrMask);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
DXILPrepareModule() : ModulePass(ID) {}
|
|
|
|
static char ID; // Pass identification.
|
|
};
|
|
char DXILPrepareModule::ID = 0;
|
|
|
|
} // end anonymous namespace
|
|
|
|
INITIALIZE_PASS_BEGIN(DXILPrepareModule, DEBUG_TYPE, "DXIL Prepare Module",
|
|
false, false)
|
|
INITIALIZE_PASS_END(DXILPrepareModule, DEBUG_TYPE, "DXIL Prepare Module", false,
|
|
false)
|
|
|
|
ModulePass *llvm::createDXILPrepareModulePass() {
|
|
return new DXILPrepareModule();
|
|
}
|