Create constant initilizer from static constructor if possible. (#717)
* Create constant initilizer from static constructor if possible.
This commit is contained in:
Родитель
9cb2d14005
Коммит
a7cba6d180
|
@ -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];
|
||||
}
|
Загрузка…
Ссылка в новой задаче