From a7cba6d18020d00d11e4b930454eaa451816a60e Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Tue, 17 Oct 2017 18:17:00 -0700 Subject: [PATCH] Create constant initilizer from static constructor if possible. (#717) * Create constant initilizer from static constructor if possible. --- tools/clang/lib/CodeGen/CGHLSLMS.cpp | 121 +++++++++++++----- .../shader-compat-suite/static_imm.hlsl | 22 ++++ 2 files changed, 114 insertions(+), 29 deletions(-) create mode 100644 tools/clang/test/CodeGenHLSL/shader-compat-suite/static_imm.hlsl diff --git a/tools/clang/lib/CodeGen/CGHLSLMS.cpp b/tools/clang/lib/CodeGen/CGHLSLMS.cpp index 6f0da7615..5199764d7 100644 --- a/tools/clang/lib/CodeGen/CGHLSLMS.cpp +++ b/tools/clang/lib/CodeGen/CGHLSLMS.cpp @@ -31,6 +31,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/IR/InstIterator.h" #include #include #include @@ -4016,6 +4017,96 @@ static void ReplaceConstStaticGlobals( } } +bool BuildImmInit(Function *Ctor) { + GlobalVariable *GV = nullptr; + SmallVector ImmList; + bool allConst = true; + for (inst_iterator I = inst_begin(Ctor), E = inst_end(Ctor); I != E; ++I) { + if (StoreInst *SI = dyn_cast(&(*I))) { + Value *V = SI->getValueOperand(); + if (!isa(V) || V->getType()->isPointerTy()) { + allConst = false; + break; + } + ImmList.emplace_back(cast(V)); + Value *Ptr = SI->getPointerOperand(); + if (GEPOperator *GepOp = dyn_cast(Ptr)) { + Ptr = GepOp->getPointerOperand(); + if (GlobalVariable *pGV = dyn_cast(Ptr)) { + if (GV == nullptr) + GV = pGV; + else + DXASSERT(GV == pGV, "else pointer mismatch"); + } + } + } else { + if (!isa(*I)) { + allConst = false; + break; + } + } + } + if (!allConst) + return false; + if (!GV) + return false; + + llvm::Type *Ty = GV->getType()->getElementType(); + llvm::ArrayType *AT = dyn_cast(Ty); + // TODO: support other types. + if (!AT) + return false; + if (ImmList.size() != AT->getNumElements()) + return false; + Constant *Init = llvm::ConstantArray::get(AT, ImmList); + GV->setInitializer(Init); + return true; +} + +void ProcessCtorFunctions(llvm::Module &M, StringRef globalName, + Instruction *InsertPt) { + // add global call to entry func + GlobalVariable *GV = M.getGlobalVariable(globalName); + if (GV) { + if (ConstantArray *CA = dyn_cast(GV->getInitializer())) { + + IRBuilder<> Builder(InsertPt); + for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; + ++i) { + if (isa(*i)) + continue; + ConstantStruct *CS = cast(*i); + if (isa(CS->getOperand(1))) + continue; + + // Must have a function or null ptr. + if (!isa(CS->getOperand(1))) + continue; + Function *Ctor = cast(CS->getOperand(1)); + DXASSERT(Ctor->getReturnType()->isVoidTy() && Ctor->arg_size() == 0, + "function type must be void (void)"); + + for (inst_iterator I = inst_begin(Ctor), E = inst_end(Ctor); I != E; + ++I) { + if (CallInst *CI = dyn_cast(&(*I))) { + Function *F = CI->getCalledFunction(); + // Try to build imm initilizer. + // If not work, add global call to entry func. + if (BuildImmInit(F) == false) { + Builder.CreateCall(F); + } + } else { + DXASSERT(isa(&(*I)), + "else invalid Global constructor function"); + } + } + } + // remove the GV + GV->eraseFromParent(); + } + } +} + void CGMSHLSLRuntime::FinishCodeGen() { // Library don't have entry. if (!m_bIsLib) { @@ -4068,36 +4159,8 @@ void CGMSHLSLRuntime::FinishCodeGen() { ConstructCBuffer(m_pHLModule, CBufferType, m_ConstVarAnnotationMap); if (!m_bIsLib) { - // add global call to entry func - auto AddGlobalCall = [&](StringRef globalName, Instruction *InsertPt) { - GlobalVariable *GV = TheModule.getGlobalVariable(globalName); - if (GV) { - if (ConstantArray *CA = dyn_cast(GV->getInitializer())) { - - IRBuilder<> Builder(InsertPt); - for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; - ++i) { - if (isa(*i)) - continue; - ConstantStruct *CS = cast(*i); - if (isa(CS->getOperand(1))) - continue; - - // Must have a function or null ptr. - if (!isa(CS->getOperand(1))) - continue; - Function *Ctor = cast(CS->getOperand(1)); - assert(Ctor->getReturnType()->isVoidTy() && Ctor->arg_size() == 0 && - "function type must be void (void)"); - Builder.CreateCall(Ctor); - } - // remove the GV - GV->eraseFromParent(); - } - } - }; // need this for "llvm.global_dtors"? - AddGlobalCall("llvm.global_ctors", + ProcessCtorFunctions(TheModule ,"llvm.global_ctors", EntryFunc->getEntryBlock().getFirstInsertionPt()); } // translate opcode into parameter for intrinsic functions diff --git a/tools/clang/test/CodeGenHLSL/shader-compat-suite/static_imm.hlsl b/tools/clang/test/CodeGenHLSL/shader-compat-suite/static_imm.hlsl new file mode 100644 index 000000000..9a1d4b274 --- /dev/null +++ b/tools/clang/test/CodeGenHLSL/shader-compat-suite/static_imm.hlsl @@ -0,0 +1,22 @@ +// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s + +// Make sure create constant for static array. +// CHECK: constant [3 x float] [float 0.000000e+00, float 0x3FF1B22D20000000, float -2.800000e+01] +// CHECK: constant [3 x float] [float 0x3FF4A3D700000000, float 0x4046666660000000, float 0x3FB99999A0000000] + +static const float2 t[ 3 ]= + { + + + float2(0, 3.0f) * 0.43f, + + float2(1.58f, 64) * 0.7f, + + float2(-28, 0.1f) + }; + +uint i; + +float2 main() : SV_Target { + return t[i]; +} \ No newline at end of file