Create constant initilizer from static constructor if possible. (#717)

* Create constant initilizer from static constructor if possible.
This commit is contained in:
Xiang Li 2017-10-17 18:17:00 -07:00 коммит произвёл GitHub
Родитель 9cb2d14005
Коммит a7cba6d180
2 изменённых файлов: 114 добавлений и 29 удалений

Просмотреть файл

@ -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 <memory>
#include <unordered_map>
#include <unordered_set>
@ -4016,6 +4017,96 @@ static void ReplaceConstStaticGlobals(
}
}
bool BuildImmInit(Function *Ctor) {
GlobalVariable *GV = nullptr;
SmallVector<Constant *, 4> ImmList;
bool allConst = true;
for (inst_iterator I = inst_begin(Ctor), E = inst_end(Ctor); I != E; ++I) {
if (StoreInst *SI = dyn_cast<StoreInst>(&(*I))) {
Value *V = SI->getValueOperand();
if (!isa<Constant>(V) || V->getType()->isPointerTy()) {
allConst = false;
break;
}
ImmList.emplace_back(cast<Constant>(V));
Value *Ptr = SI->getPointerOperand();
if (GEPOperator *GepOp = dyn_cast<GEPOperator>(Ptr)) {
Ptr = GepOp->getPointerOperand();
if (GlobalVariable *pGV = dyn_cast<GlobalVariable>(Ptr)) {
if (GV == nullptr)
GV = pGV;
else
DXASSERT(GV == pGV, "else pointer mismatch");
}
}
} else {
if (!isa<ReturnInst>(*I)) {
allConst = false;
break;
}
}
}
if (!allConst)
return false;
if (!GV)
return false;
llvm::Type *Ty = GV->getType()->getElementType();
llvm::ArrayType *AT = dyn_cast<llvm::ArrayType>(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<ConstantArray>(GV->getInitializer())) {
IRBuilder<> Builder(InsertPt);
for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e;
++i) {
if (isa<ConstantAggregateZero>(*i))
continue;
ConstantStruct *CS = cast<ConstantStruct>(*i);
if (isa<ConstantPointerNull>(CS->getOperand(1)))
continue;
// Must have a function or null ptr.
if (!isa<Function>(CS->getOperand(1)))
continue;
Function *Ctor = cast<Function>(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<CallInst>(&(*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<ReturnInst>(&(*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<ConstantArray>(GV->getInitializer())) {
IRBuilder<> Builder(InsertPt);
for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e;
++i) {
if (isa<ConstantAggregateZero>(*i))
continue;
ConstantStruct *CS = cast<ConstantStruct>(*i);
if (isa<ConstantPointerNull>(CS->getOperand(1)))
continue;
// Must have a function or null ptr.
if (!isa<Function>(CS->getOperand(1)))
continue;
Function *Ctor = cast<Function>(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

Просмотреть файл

@ -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];
}