16599fdabSChris Bieneman //===- DXILPrepare.cpp - Prepare LLVM Module for DXIL encoding ------------===//
26599fdabSChris Bieneman //
36599fdabSChris Bieneman // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46599fdabSChris Bieneman // See https://llvm.org/LICENSE.txt for license information.
56599fdabSChris Bieneman // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66599fdabSChris Bieneman //
76599fdabSChris Bieneman //===----------------------------------------------------------------------===//
86599fdabSChris Bieneman ///
96599fdabSChris Bieneman /// \file This file contains pases and utilities to convert a modern LLVM
106599fdabSChris Bieneman /// module into a module compatible with the LLVM 3.7-based DirectX Intermediate
116599fdabSChris Bieneman /// Language (DXIL).
126599fdabSChris Bieneman //===----------------------------------------------------------------------===//
136599fdabSChris Bieneman
146599fdabSChris Bieneman #include "DirectX.h"
15f5d054cdSChris Bieneman #include "PointerTypeAnalysis.h"
166599fdabSChris Bieneman #include "llvm/ADT/STLExtras.h"
176599fdabSChris Bieneman #include "llvm/ADT/SmallVector.h"
186599fdabSChris Bieneman #include "llvm/CodeGen/Passes.h"
196599fdabSChris Bieneman #include "llvm/IR/IRBuilder.h"
206599fdabSChris Bieneman #include "llvm/IR/Instruction.h"
216599fdabSChris Bieneman #include "llvm/IR/Module.h"
226599fdabSChris Bieneman #include "llvm/InitializePasses.h"
236599fdabSChris Bieneman #include "llvm/Pass.h"
246599fdabSChris Bieneman #include "llvm/Support/Compiler.h"
256599fdabSChris Bieneman
266599fdabSChris Bieneman #define DEBUG_TYPE "dxil-prepare"
276599fdabSChris Bieneman
286599fdabSChris Bieneman using namespace llvm;
29f5d054cdSChris Bieneman using namespace llvm::dxil;
306599fdabSChris Bieneman
316599fdabSChris Bieneman namespace {
326599fdabSChris Bieneman
isValidForDXIL(Attribute::AttrKind Attr)336599fdabSChris Bieneman constexpr bool isValidForDXIL(Attribute::AttrKind Attr) {
346599fdabSChris Bieneman return is_contained({Attribute::Alignment,
356599fdabSChris Bieneman Attribute::AlwaysInline,
366599fdabSChris Bieneman Attribute::Builtin,
376599fdabSChris Bieneman Attribute::ByVal,
386599fdabSChris Bieneman Attribute::InAlloca,
396599fdabSChris Bieneman Attribute::Cold,
406599fdabSChris Bieneman Attribute::Convergent,
416599fdabSChris Bieneman Attribute::InlineHint,
426599fdabSChris Bieneman Attribute::InReg,
436599fdabSChris Bieneman Attribute::JumpTable,
446599fdabSChris Bieneman Attribute::MinSize,
456599fdabSChris Bieneman Attribute::Naked,
466599fdabSChris Bieneman Attribute::Nest,
476599fdabSChris Bieneman Attribute::NoAlias,
486599fdabSChris Bieneman Attribute::NoBuiltin,
496599fdabSChris Bieneman Attribute::NoCapture,
506599fdabSChris Bieneman Attribute::NoDuplicate,
516599fdabSChris Bieneman Attribute::NoImplicitFloat,
526599fdabSChris Bieneman Attribute::NoInline,
536599fdabSChris Bieneman Attribute::NonLazyBind,
546599fdabSChris Bieneman Attribute::NonNull,
556599fdabSChris Bieneman Attribute::Dereferenceable,
566599fdabSChris Bieneman Attribute::DereferenceableOrNull,
576599fdabSChris Bieneman Attribute::NoRedZone,
586599fdabSChris Bieneman Attribute::NoReturn,
596599fdabSChris Bieneman Attribute::NoUnwind,
606599fdabSChris Bieneman Attribute::OptimizeForSize,
616599fdabSChris Bieneman Attribute::OptimizeNone,
626599fdabSChris Bieneman Attribute::ReadNone,
636599fdabSChris Bieneman Attribute::ReadOnly,
646599fdabSChris Bieneman Attribute::ArgMemOnly,
656599fdabSChris Bieneman Attribute::Returned,
666599fdabSChris Bieneman Attribute::ReturnsTwice,
676599fdabSChris Bieneman Attribute::SExt,
686599fdabSChris Bieneman Attribute::StackAlignment,
696599fdabSChris Bieneman Attribute::StackProtect,
706599fdabSChris Bieneman Attribute::StackProtectReq,
716599fdabSChris Bieneman Attribute::StackProtectStrong,
726599fdabSChris Bieneman Attribute::SafeStack,
736599fdabSChris Bieneman Attribute::StructRet,
746599fdabSChris Bieneman Attribute::SanitizeAddress,
756599fdabSChris Bieneman Attribute::SanitizeThread,
766599fdabSChris Bieneman Attribute::SanitizeMemory,
776599fdabSChris Bieneman Attribute::UWTable,
786599fdabSChris Bieneman Attribute::ZExt},
796599fdabSChris Bieneman Attr);
806599fdabSChris Bieneman }
816599fdabSChris Bieneman
826599fdabSChris Bieneman class DXILPrepareModule : public ModulePass {
83f5d054cdSChris Bieneman
maybeGenerateBitcast(IRBuilder<> & Builder,PointerTypeMap & PointerTypes,Instruction & Inst,Value * Operand,Type * Ty)84f5d054cdSChris Bieneman static Value *maybeGenerateBitcast(IRBuilder<> &Builder,
85f5d054cdSChris Bieneman PointerTypeMap &PointerTypes,
86f5d054cdSChris Bieneman Instruction &Inst, Value *Operand,
87f5d054cdSChris Bieneman Type *Ty) {
88f5d054cdSChris Bieneman // Omit bitcasts if the incoming value matches the instruction type.
89f5d054cdSChris Bieneman auto It = PointerTypes.find(Operand);
90f5d054cdSChris Bieneman if (It != PointerTypes.end())
91f5d054cdSChris Bieneman if (cast<TypedPointerType>(It->second)->getElementType() == Ty)
92f5d054cdSChris Bieneman return nullptr;
93f5d054cdSChris Bieneman // Insert bitcasts where we are removing the instruction.
94f5d054cdSChris Bieneman Builder.SetInsertPoint(&Inst);
95f5d054cdSChris Bieneman // This code only gets hit in opaque-pointer mode, so the type of the
96f5d054cdSChris Bieneman // pointer doesn't matter.
9704d4130aSChris Bieneman PointerType *PtrTy = cast<PointerType>(Operand->getType());
9804d4130aSChris Bieneman return Builder.Insert(
9904d4130aSChris Bieneman CastInst::Create(Instruction::BitCast, Operand,
10004d4130aSChris Bieneman Builder.getInt8PtrTy(PtrTy->getAddressSpace())));
101f5d054cdSChris Bieneman }
102f5d054cdSChris Bieneman
1036599fdabSChris Bieneman public:
runOnModule(Module & M)1046599fdabSChris Bieneman bool runOnModule(Module &M) override {
105f5d054cdSChris Bieneman PointerTypeMap PointerTypes = PointerTypeAnalysis::run(M);
1066599fdabSChris Bieneman AttributeMask AttrMask;
1076599fdabSChris Bieneman for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
1086599fdabSChris Bieneman I = Attribute::AttrKind(I + 1)) {
1096599fdabSChris Bieneman if (!isValidForDXIL(I))
1106599fdabSChris Bieneman AttrMask.addAttribute(I);
1116599fdabSChris Bieneman }
1126599fdabSChris Bieneman for (auto &F : M.functions()) {
1136599fdabSChris Bieneman F.removeFnAttrs(AttrMask);
1146599fdabSChris Bieneman F.removeRetAttrs(AttrMask);
115f5d054cdSChris Bieneman for (size_t Idx = 0, End = F.arg_size(); Idx < End; ++Idx)
1166599fdabSChris Bieneman F.removeParamAttrs(Idx, AttrMask);
1176599fdabSChris Bieneman
1186599fdabSChris Bieneman for (auto &BB : F) {
1196599fdabSChris Bieneman IRBuilder<> Builder(&BB);
1206599fdabSChris Bieneman for (auto &I : make_early_inc_range(BB)) {
1216599fdabSChris Bieneman if (I.getOpcode() == Instruction::FNeg) {
1226599fdabSChris Bieneman Builder.SetInsertPoint(&I);
1236599fdabSChris Bieneman Value *In = I.getOperand(0);
1246599fdabSChris Bieneman Value *Zero = ConstantFP::get(In->getType(), -0.0);
1256599fdabSChris Bieneman I.replaceAllUsesWith(Builder.CreateFSub(Zero, In));
1266599fdabSChris Bieneman I.eraseFromParent();
127f5d054cdSChris Bieneman continue;
128f5d054cdSChris Bieneman }
129f5d054cdSChris Bieneman // Only insert bitcasts if the IR is using opaque pointers.
130*12ca031bSpython3kgae if (M.getContext().supportsTypedPointers())
131f5d054cdSChris Bieneman continue;
132f5d054cdSChris Bieneman
133f5d054cdSChris Bieneman // Emtting NoOp bitcast instructions allows the ValueEnumerator to be
134f5d054cdSChris Bieneman // unmodified as it reserves instruction IDs during contruction.
135f5d054cdSChris Bieneman if (auto LI = dyn_cast<LoadInst>(&I)) {
136f5d054cdSChris Bieneman if (Value *NoOpBitcast = maybeGenerateBitcast(
137f5d054cdSChris Bieneman Builder, PointerTypes, I, LI->getPointerOperand(),
138f5d054cdSChris Bieneman LI->getType())) {
139f5d054cdSChris Bieneman LI->replaceAllUsesWith(
140f5d054cdSChris Bieneman Builder.CreateLoad(LI->getType(), NoOpBitcast));
141f5d054cdSChris Bieneman LI->eraseFromParent();
142f5d054cdSChris Bieneman }
143f5d054cdSChris Bieneman continue;
144f5d054cdSChris Bieneman }
145f5d054cdSChris Bieneman if (auto SI = dyn_cast<StoreInst>(&I)) {
146f5d054cdSChris Bieneman if (Value *NoOpBitcast = maybeGenerateBitcast(
147f5d054cdSChris Bieneman Builder, PointerTypes, I, SI->getPointerOperand(),
148f5d054cdSChris Bieneman SI->getValueOperand()->getType())) {
149f5d054cdSChris Bieneman
150f5d054cdSChris Bieneman SI->replaceAllUsesWith(
151f5d054cdSChris Bieneman Builder.CreateStore(SI->getValueOperand(), NoOpBitcast));
152f5d054cdSChris Bieneman SI->eraseFromParent();
153f5d054cdSChris Bieneman }
154f5d054cdSChris Bieneman continue;
155f5d054cdSChris Bieneman }
156f5d054cdSChris Bieneman if (auto GEP = dyn_cast<GetElementPtrInst>(&I)) {
157f5d054cdSChris Bieneman if (Value *NoOpBitcast = maybeGenerateBitcast(
158f5d054cdSChris Bieneman Builder, PointerTypes, I, GEP->getPointerOperand(),
159f5d054cdSChris Bieneman GEP->getResultElementType()))
160f5d054cdSChris Bieneman GEP->setOperand(0, NoOpBitcast);
161f5d054cdSChris Bieneman continue;
1626599fdabSChris Bieneman }
1636599fdabSChris Bieneman }
1646599fdabSChris Bieneman }
1656599fdabSChris Bieneman }
1666599fdabSChris Bieneman return true;
1676599fdabSChris Bieneman }
1686599fdabSChris Bieneman
DXILPrepareModule()1696599fdabSChris Bieneman DXILPrepareModule() : ModulePass(ID) {}
1706599fdabSChris Bieneman
1716599fdabSChris Bieneman static char ID; // Pass identification.
1726599fdabSChris Bieneman };
1736599fdabSChris Bieneman char DXILPrepareModule::ID = 0;
1746599fdabSChris Bieneman
1756599fdabSChris Bieneman } // end anonymous namespace
1766599fdabSChris Bieneman
1776599fdabSChris Bieneman INITIALIZE_PASS_BEGIN(DXILPrepareModule, DEBUG_TYPE, "DXIL Prepare Module",
1786599fdabSChris Bieneman false, false)
1796599fdabSChris Bieneman INITIALIZE_PASS_END(DXILPrepareModule, DEBUG_TYPE, "DXIL Prepare Module", false,
1806599fdabSChris Bieneman false)
1816599fdabSChris Bieneman
createDXILPrepareModulePass()1826599fdabSChris Bieneman ModulePass *llvm::createDXILPrepareModulePass() {
1836599fdabSChris Bieneman return new DXILPrepareModule();
1846599fdabSChris Bieneman }
185