This commit is contained in:
Xiang Li 2018-02-07 13:53:16 -08:00
Родитель 8beb970b51
Коммит c6915bcccd
6 изменённых файлов: 66 добавлений и 582 удалений

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

@ -193,6 +193,9 @@ public:
// Precise attribute.
static const char kDxilPreciseAttributeMDName[];
// NonUniform attribute.
static const char kDxilNonUniformAttributeMDName[];
// Validator version.
static const char kDxilValidatorVersionMDName[];
// Validator version uses the same constants for fields as kDxilVersion*
@ -381,6 +384,7 @@ public:
// Utility functions.
static bool IsKnownNamedMetaData(llvm::NamedMDNode &Node);
static void combineDxilMetadata(llvm::Instruction *K, const llvm::Instruction *J);
static llvm::ConstantAsMetadata *Int32ToConstMD(int32_t v, llvm::LLVMContext &Ctx);
llvm::ConstantAsMetadata *Int32ToConstMD(int32_t v);
static llvm::ConstantAsMetadata *Uint32ToConstMD(unsigned v, llvm::LLVMContext &Ctx);
@ -405,6 +409,8 @@ public:
void ConstMDTupleToUint32Vector(llvm::MDTuple *pTupleMD, std::vector<unsigned> &Vec);
static bool IsMarkedPrecise(const llvm::Instruction *inst);
static void MarkPrecise(llvm::Instruction *inst);
static bool IsMarkedNonUniform(const llvm::Instruction *inst);
static void MarkNonUniform(llvm::Instruction *inst);
private:
llvm::LLVMContext &m_Ctx;

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

@ -769,8 +769,7 @@ void DxilLowerCreateHandleForLib::TranslateDxilResourceUses(
Value *resIDArg = hlslOP->GetU32Const(res.GetID());
// resLowerBound will be added after allocation in DxilCondenseResources.
Value *resLowerBound = hlslOP->GetU32Const(res.GetLowerBound());
// TODO: Set Non-uniform resource bit based on whether index comes from
// IOP_NonUniformResourceIndex.
Value *isUniformRes = hlslOP->GetI1Const(0);
Value *GV = res.GetGlobalSymbol();
@ -851,16 +850,18 @@ void DxilLowerCreateHandleForLib::TranslateDxilResourceUses(
}
createHandleArgs[DXIL::OperandIndex::kCreateHandleResIndexOpIdx] = idx;
//if (!NonUniformSet.count(idx))
// createHandleArgs[DXIL::OperandIndex::kCreateHandleIsUniformOpIdx] =
// isUniformRes;
//else
// createHandleArgs[DXIL::OperandIndex::kCreateHandleIsUniformOpIdx] =
// hlslOP->GetI1Const(1);
createHandleArgs[DXIL::OperandIndex::kCreateHandleIsUniformOpIdx] =
isUniformRes;
Value *handle = nullptr;
if (GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(GEP)) {
IRBuilder<> Builder = IRBuilder<>(GEPInst);
if (DxilMDHelper::IsMarkedNonUniform(GEPInst)) {
// Mark nonUniform.
createHandleArgs[DXIL::OperandIndex::kCreateHandleIsUniformOpIdx] =
hlslOP->GetI1Const(1);
}
createHandleArgs[DXIL::OperandIndex::kCreateHandleResIndexOpIdx] =
Builder.CreateAdd(idx, resLowerBound);
handle = Builder.CreateCall(createHandle, createHandleArgs, handleName);

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

@ -270,6 +270,7 @@ public:
GenerateDxilCBufferHandles(NonUniformSet);
MarkUpdateCounter(UpdateCounterSet);
LowerHLCreateHandle();
MarkNonUniform(NonUniformSet);
// For module which not promote mem2reg.
// Remove local resource alloca/load/store/phi.
@ -314,14 +315,6 @@ public:
private:
void RemoveLocalDxilResourceAllocas(Function *F);
void MarkUpdateCounter(std::unordered_set<LoadInst *> &UpdateCounterSet);
void
TranslateDxilResourceUses(DxilResourceBase &res,
std::unordered_set<LoadInst *> &UpdateCounterSet,
std::unordered_set<Value *> &NonUniformSet);
void
GenerateDxilResourceHandles(std::unordered_set<LoadInst *> &UpdateCounterSet,
std::unordered_set<Value *> &NonUniformSet);
void AddCreateHandleForPhiNodeAndSelect(OP *hlslOP);
void TranslateParamDxilResourceHandles(Function *F, std::unordered_map<Instruction *, Value *> &handleMap);
void GenerateParamDxilResourceHandles(
std::unordered_map<Instruction *, Value *> &handleMap);
@ -334,8 +327,7 @@ private:
std::unordered_set<LoadInst *> &UpdateCounterSet,
std::unordered_set<Value *> &NonUniformSet);
void LowerHLCreateHandle();
// Change struct type to legacy layout for cbuf and struct buf.
void UpdateStructTypeForLegacyLayout();
void MarkNonUniform(std::unordered_set<Value *> &NonUniformSet);
// Translate precise attribute into HL function call.
void TranslatePreciseAttribute();
@ -395,6 +387,17 @@ void DxilGenerationPass::LowerHLCreateHandle() {
}
}
void DxilGenerationPass::MarkNonUniform(
std::unordered_set<Value *> &NonUniformSet) {
for (Value *V : NonUniformSet) {
for (User *U : V->users()) {
if (Instruction *I = dyn_cast<Instruction>(U)) {
DxilMDHelper::MarkNonUniform(I);
}
}
}
}
static Value *MergeImmResClass(Value *resClass) {
if (ConstantInt *Imm = dyn_cast<ConstantInt>(resClass)) {
return resClass;
@ -603,403 +606,6 @@ void DxilGenerationPass::MarkUpdateCounter(
}
}
void DxilGenerationPass::TranslateDxilResourceUses(
DxilResourceBase &res, std::unordered_set<LoadInst *> &UpdateCounterSet,
std::unordered_set<Value *> &NonUniformSet) {
OP *hlslOP = m_pHLModule->GetOP();
Function *createHandle = hlslOP->GetOpFunc(
OP::OpCode::CreateHandle, llvm::Type::getVoidTy(m_pHLModule->GetCtx()));
Value *opArg = hlslOP->GetU32Const((unsigned)OP::OpCode::CreateHandle);
bool isViewResource = res.GetClass() == DXIL::ResourceClass::SRV || res.GetClass() == DXIL::ResourceClass::UAV;
bool isROV = isViewResource && static_cast<DxilResource &>(res).IsROV();
std::string handleName = (res.GetGlobalName() + Twine("_") + Twine(res.GetResClassName())).str();
if (isViewResource)
handleName += (Twine("_") + Twine(res.GetResDimName())).str();
if (isROV)
handleName += "_ROV";
Value *resClassArg = hlslOP->GetU8Const(
static_cast<std::underlying_type<DxilResourceBase::Class>::type>(
res.GetClass()));
Value *resIDArg = hlslOP->GetU32Const(res.GetID());
// resLowerBound will be added after allocation in DxilCondenseResources.
Value *resLowerBound = hlslOP->GetU32Const(0);
// TODO: Set Non-uniform resource bit based on whether index comes from IOP_NonUniformResourceIndex.
Value *isUniformRes = hlslOP->GetI1Const(0);
Value *GV = res.GetGlobalSymbol();
Module *pM = m_pHLModule->GetModule();
// TODO: add debug info to create handle.
DIVariable *DIV = nullptr;
DILocation *DL = nullptr;
if (m_HasDbgInfo) {
DebugInfoFinder &Finder = m_pHLModule->GetOrCreateDebugInfoFinder();
DIV =
HLModule::FindGlobalVariableDebugInfo(cast<GlobalVariable>(GV), Finder);
if (DIV)
// TODO: how to get col?
DL =
DILocation::get(pM->getContext(), DIV->getLine(), 1, DIV->getScope());
}
bool isResArray = res.GetRangeSize() > 1;
std::unordered_map<Function *, Instruction *> handleMapOnFunction;
Value *createHandleArgs[] = {opArg, resClassArg, resIDArg, resLowerBound,
isUniformRes};
for (iplist<Function>::iterator F : pM->getFunctionList()) {
if (!F->isDeclaration()) {
if (!isResArray) {
IRBuilder<> Builder(F->getEntryBlock().getFirstInsertionPt());
if (m_HasDbgInfo) {
// TODO: set debug info.
//Builder.SetCurrentDebugLocation(DL);
}
handleMapOnFunction[F] = Builder.CreateCall(createHandle, createHandleArgs, handleName);
}
}
}
for (auto U = GV->user_begin(), E = GV->user_end(); U != E; ) {
User *user = *(U++);
// Skip unused user.
if (user->user_empty())
continue;
if (LoadInst *ldInst = dyn_cast<LoadInst>(user)) {
if (UpdateCounterSet.count(ldInst)) {
DxilResource *resource = llvm::dyn_cast<DxilResource>(&res);
DXASSERT_NOMSG(resource);
DXASSERT_NOMSG(resource->GetClass() == DXIL::ResourceClass::UAV);
resource->SetHasCounter(true);
}
Function *userF = ldInst->getParent()->getParent();
DXASSERT(handleMapOnFunction.count(userF), "must exist");
Value *handle = handleMapOnFunction[userF];
ReplaceResourceUserWithHandle(ldInst, handle);
} else {
DXASSERT(dyn_cast<GEPOperator>(user) != nullptr,
"else AddOpcodeParamForIntrinsic in CodeGen did not patch uses "
"to only have ld/st refer to temp object");
GEPOperator *GEP = cast<GEPOperator>(user);
Value *idx = nullptr;
if (GEP->getNumIndices() == 2) {
// one dim array of resource
idx = (GEP->idx_begin() + 1)->get();
} else {
gep_type_iterator GEPIt = gep_type_begin(GEP), E = gep_type_end(GEP);
// Must be instruction for multi dim array.
std::unique_ptr<IRBuilder<> > Builder;
if (GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(GEP)) {
Builder = std::make_unique<IRBuilder<> >(GEPInst);
} else {
Builder = std::make_unique<IRBuilder<> >(GV->getContext());
}
for (; GEPIt != E; ++GEPIt) {
if (GEPIt->isArrayTy()) {
unsigned arraySize = GEPIt->getArrayNumElements();
Value * tmpIdx = GEPIt.getOperand();
if (idx == nullptr)
idx = tmpIdx;
else {
idx = Builder->CreateMul(idx, Builder->getInt32(arraySize));
idx = Builder->CreateAdd(idx, tmpIdx);
}
}
}
}
createHandleArgs[DXIL::OperandIndex::kCreateHandleResIndexOpIdx] = idx;
if (!NonUniformSet.count(idx))
createHandleArgs[DXIL::OperandIndex::kCreateHandleIsUniformOpIdx] =
isUniformRes;
else
createHandleArgs[DXIL::OperandIndex::kCreateHandleIsUniformOpIdx] =
hlslOP->GetI1Const(1);
Value *handle = nullptr;
if (GetElementPtrInst *GEPInst = dyn_cast<GetElementPtrInst>(GEP)) {
IRBuilder<> Builder = IRBuilder<>(GEPInst);
handle = Builder.CreateCall(createHandle, createHandleArgs, handleName);
}
for (auto GEPU = GEP->user_begin(), GEPE = GEP->user_end(); GEPU != GEPE; ) {
// Must be load inst.
LoadInst *ldInst = cast<LoadInst>(*(GEPU++));
if (UpdateCounterSet.count(ldInst)) {
DxilResource *resource = dyn_cast<DxilResource>(&res);
DXASSERT_NOMSG(resource);
DXASSERT_NOMSG(resource->GetClass() == DXIL::ResourceClass::UAV);
resource->SetHasCounter(true);
}
if (handle) {
ReplaceResourceUserWithHandle(ldInst, handle);
}
else {
IRBuilder<> Builder = IRBuilder<>(ldInst);
Value *localHandle = Builder.CreateCall(createHandle, createHandleArgs, handleName);
ReplaceResourceUserWithHandle(ldInst, localHandle);
}
}
}
}
// Erase unused handle.
for (auto It : handleMapOnFunction) {
Instruction *I = It.second;
if (I->user_empty())
I->eraseFromParent();
}
}
void DxilGenerationPass::GenerateDxilResourceHandles(
std::unordered_set<LoadInst *> &UpdateCounterSet,
std::unordered_set<Value *> &NonUniformSet) {
// Create sampler handle first, may be used by SRV operations.
for (size_t i = 0; i < m_pHLModule->GetSamplers().size(); i++) {
DxilSampler &S = m_pHLModule->GetSampler(i);
TranslateDxilResourceUses(S, UpdateCounterSet, NonUniformSet);
}
for (size_t i = 0; i < m_pHLModule->GetSRVs().size(); i++) {
HLResource &SRV = m_pHLModule->GetSRV(i);
TranslateDxilResourceUses(SRV, UpdateCounterSet, NonUniformSet);
}
for (size_t i = 0; i < m_pHLModule->GetUAVs().size(); i++) {
HLResource &UAV = m_pHLModule->GetUAV(i);
TranslateDxilResourceUses(UAV, UpdateCounterSet, NonUniformSet);
}
}
static void
AddResourceToSet(Instruction *Res, std::unordered_set<Instruction *> &resSet) {
unsigned startOpIdx = 0;
// Skip Cond for Select.
if (isa<SelectInst>(Res))
startOpIdx = 1;
else if (!isa<PHINode>(Res))
// Only check phi and select here.
return;
// Already add.
if (resSet.count(Res))
return;
resSet.insert(Res);
// Scan operand to add resource node which only used by phi/select.
unsigned numOperands = Res->getNumOperands();
for (unsigned i = startOpIdx; i < numOperands; i++) {
Value *V = Res->getOperand(i);
if (Instruction *I = dyn_cast<Instruction>(V)) {
AddResourceToSet(I, resSet);
}
}
}
// Transform
//
// %g_texture_texture_2d1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false)
// %g_texture_texture_2d = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 2, i1 false)
// %13 = select i1 %cmp, %dx.types.Handle %g_texture_texture_2d1, %dx.types.Handle %g_texture_texture_2d
// Into
// %11 = select i1 %cmp, i32 0, i32 2
// %12 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 %11, i1 false)
//
static bool MergeHandleOpWithSameValue(Instruction *HandleOp,
unsigned startOpIdx,
unsigned numOperands) {
Value *op0 = nullptr;
for (unsigned i = startOpIdx; i < numOperands; i++) {
Value *op = HandleOp->getOperand(i);
if (i == startOpIdx) {
op0 = op;
} else {
if (op0 != op)
op0 = nullptr;
}
}
if (op0) {
HandleOp->replaceAllUsesWith(op0);
return true;
}
return false;
}
static void
UpdateHandleOperands(Instruction *Res,
std::unordered_map<Instruction *, CallInst *> &handleMap,
std::unordered_set<Instruction *> &nonUniformOps) {
unsigned numOperands = Res->getNumOperands();
unsigned startOpIdx = 0;
// Skip Cond for Select.
if (SelectInst *Sel = dyn_cast<SelectInst>(Res))
startOpIdx = 1;
CallInst *Handle = handleMap[Res];
Instruction *resClass = cast<Instruction>(
Handle->getArgOperand(DXIL::OperandIndex::kCreateHandleResClassOpIdx));
Instruction *resID = cast<Instruction>(
Handle->getArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx));
Instruction *resAddr = cast<Instruction>(
Handle->getArgOperand(DXIL::OperandIndex::kCreateHandleResIndexOpIdx));
for (unsigned i = startOpIdx; i < numOperands; i++) {
if (!isa<Instruction>(Res->getOperand(i))) {
EmitResMappingError(Res);
continue;
}
Instruction *ResOp = cast<Instruction>(Res->getOperand(i));
CallInst *HandleOp = dyn_cast<CallInst>(ResOp);
if (!HandleOp) {
if (handleMap.count(ResOp)) {
EmitResMappingError(Res);
continue;
}
HandleOp = handleMap[ResOp];
}
Value *resClassOp =
HandleOp->getArgOperand(DXIL::OperandIndex::kCreateHandleResClassOpIdx);
Value *resIDOp =
HandleOp->getArgOperand(DXIL::OperandIndex::kCreateHandleResIDOpIdx);
Value *resAddrOp =
HandleOp->getArgOperand(DXIL::OperandIndex::kCreateHandleResIndexOpIdx);
resClass->setOperand(i, resClassOp);
resID->setOperand(i, resIDOp);
resAddr->setOperand(i, resAddrOp);
}
if (!MergeHandleOpWithSameValue(resClass, startOpIdx, numOperands))
nonUniformOps.insert(resClass);
if (!MergeHandleOpWithSameValue(resID, startOpIdx, numOperands))
nonUniformOps.insert(resID);
MergeHandleOpWithSameValue(resAddr, startOpIdx, numOperands);
}
void DxilGenerationPass::AddCreateHandleForPhiNodeAndSelect(OP *hlslOP) {
Function *createHandle = hlslOP->GetOpFunc(
OP::OpCode::CreateHandle, llvm::Type::getVoidTy(hlslOP->GetCtx()));
std::unordered_set<PHINode *> objPhiList;
std::unordered_set<SelectInst *> objSelectList;
std::unordered_set<Instruction *> resSelectSet;
for (User *U : createHandle->users()) {
for (User *HandleU : U->users()) {
Instruction *I = cast<Instruction>(HandleU);
if (!isa<CallInst>(I))
AddResourceToSet(I, resSelectSet);
}
}
// Generate Handle inst for Res inst.
FunctionType *FT = createHandle->getFunctionType();
Value *opArg = hlslOP->GetU32Const((unsigned)OP::OpCode::CreateHandle);
Type *resClassTy =
FT->getParamType(DXIL::OperandIndex::kCreateHandleResClassOpIdx);
Type *resIDTy = FT->getParamType(DXIL::OperandIndex::kCreateHandleResIDOpIdx);
Type *resAddrTy =
FT->getParamType(DXIL::OperandIndex::kCreateHandleResIndexOpIdx);
Value *UndefResClass = UndefValue::get(resClassTy);
Value *UndefResID = UndefValue::get(resIDTy);
Value *UndefResAddr = UndefValue::get(resAddrTy);
// phi/select node resource is not uniform
Value *nonUniformRes = hlslOP->GetI1Const(1);
std::unordered_map<Instruction *, CallInst *> handleMap;
for (Instruction *Res : resSelectSet) {
unsigned numOperands = Res->getNumOperands();
IRBuilder<> Builder(Res);
unsigned startOpIdx = 0;
// Skip Cond for Select.
if (SelectInst *Sel = dyn_cast<SelectInst>(Res)) {
startOpIdx = 1;
Value *Cond = Sel->getCondition();
Value *resClassSel =
Builder.CreateSelect(Cond, UndefResClass, UndefResClass);
Value *resIDSel = Builder.CreateSelect(Cond, UndefResID, UndefResID);
Value *resAddrSel =
Builder.CreateSelect(Cond, UndefResAddr, UndefResAddr);
CallInst *HandleSel =
Builder.CreateCall(createHandle, {opArg, resClassSel, resIDSel,
resAddrSel, nonUniformRes});
handleMap[Res] = HandleSel;
Res->replaceAllUsesWith(HandleSel);
} else {
PHINode *Phi = cast<PHINode>(Res); // res class must be same.
PHINode *resClassPhi = Builder.CreatePHI(resClassTy, numOperands);
PHINode *resIDPhi = Builder.CreatePHI(resIDTy, numOperands);
PHINode *resAddrPhi = Builder.CreatePHI(resAddrTy, numOperands);
for (unsigned i = 0; i < numOperands; i++) {
BasicBlock *BB = Phi->getIncomingBlock(i);
resClassPhi->addIncoming(UndefResClass, BB);
resIDPhi->addIncoming(UndefResID, BB);
resAddrPhi->addIncoming(UndefResAddr, BB);
}
IRBuilder<> HandleBuilder(Phi->getParent()->getFirstNonPHI());
CallInst *HandlePhi =
HandleBuilder.CreateCall(createHandle, {opArg, resClassPhi, resIDPhi,
resAddrPhi, nonUniformRes});
handleMap[Res] = HandlePhi;
Res->replaceAllUsesWith(HandlePhi);
}
}
// Update operand for Handle phi/select.
// If ResClass or ResID is phi/select, save to nonUniformOps.
std::unordered_set<Instruction *> nonUniformOps;
for (Instruction *Res : resSelectSet) {
UpdateHandleOperands(Res, handleMap, nonUniformOps);
}
bool bIsLib = m_pHLModule->GetShaderModel()->IsLib();
// ResClass and ResID must be uniform.
// Try to merge res class, res id into imm.
while (1) {
bool bUpdated = false;
for (auto It = nonUniformOps.begin(); It != nonUniformOps.end();) {
Instruction *I = *(It++);
unsigned numOperands = I->getNumOperands();
unsigned startOpIdx = 0;
// Skip Cond for Select.
if (SelectInst *Sel = dyn_cast<SelectInst>(I))
startOpIdx = 1;
if (MergeHandleOpWithSameValue(I, startOpIdx, numOperands)) {
nonUniformOps.erase(I);
bUpdated = true;
}
}
if (!bUpdated) {
if (!nonUniformOps.empty() && !bIsLib) {
for (Instruction *I : nonUniformOps) {
// Non uniform res class or res id.
EmitResMappingError(I);
}
return;
}
break;
}
}
// Remove useless select/phi.
for (Instruction *Res : resSelectSet) {
Res->eraseFromParent();
}
}
void DxilGenerationPass::GenerateDxilCBufferHandles(
std::unordered_set<Value *> &NonUniformSet) {
// For CBuffer, handle are mapped to HLCreateHandle.
@ -1194,171 +800,6 @@ ModulePass *llvm::createDxilGenerationPass(bool NotOptimized, hlsl::HLSLExtensio
INITIALIZE_PASS(DxilGenerationPass, "dxilgen", "HLSL DXIL Generation", false, false)
///////////////////////////////////////////////////////////////////////////////
namespace {
StructType *UpdateStructTypeForLegacyLayout(StructType *ST, bool IsCBuf,
DxilTypeSystem &TypeSys, Module &M);
Type *UpdateFieldTypeForLegacyLayout(Type *Ty, bool IsCBuf, DxilFieldAnnotation &annotation,
DxilTypeSystem &TypeSys, Module &M) {
DXASSERT(!Ty->isPointerTy(), "struct field should not be a pointer");
if (Ty->isArrayTy()) {
Type *EltTy = Ty->getArrayElementType();
Type *UpdatedTy = UpdateFieldTypeForLegacyLayout(EltTy, IsCBuf, annotation, TypeSys, M);
if (EltTy == UpdatedTy)
return Ty;
else
return ArrayType::get(UpdatedTy, Ty->getArrayNumElements());
} else if (HLMatrixLower::IsMatrixType(Ty)) {
DXASSERT(annotation.HasMatrixAnnotation(), "must a matrix");
unsigned rows, cols;
Type *EltTy = HLMatrixLower::GetMatrixInfo(Ty, cols, rows);
// Get cols and rows from annotation.
const DxilMatrixAnnotation &matrix = annotation.GetMatrixAnnotation();
if (matrix.Orientation == MatrixOrientation::RowMajor) {
rows = matrix.Rows;
cols = matrix.Cols;
} else {
DXASSERT(matrix.Orientation == MatrixOrientation::ColumnMajor, "");
cols = matrix.Rows;
rows = matrix.Cols;
}
// CBuffer matrix must 4 * 4 bytes align.
if (IsCBuf)
cols = 4;
EltTy = UpdateFieldTypeForLegacyLayout(EltTy, IsCBuf, annotation, TypeSys, M);
Type *rowTy = VectorType::get(EltTy, cols);
return ArrayType::get(rowTy, rows);
} else if (StructType *ST = dyn_cast<StructType>(Ty)) {
return UpdateStructTypeForLegacyLayout(ST, IsCBuf, TypeSys, M);
} else if (Ty->isVectorTy()) {
Type *EltTy = Ty->getVectorElementType();
Type *UpdatedTy = UpdateFieldTypeForLegacyLayout(EltTy, IsCBuf, annotation, TypeSys, M);
if (EltTy == UpdatedTy)
return Ty;
else
return VectorType::get(UpdatedTy, Ty->getVectorNumElements());
} else {
Type *i32Ty = Type::getInt32Ty(Ty->getContext());
// Basic types.
if (Ty->isHalfTy()) {
return Type::getFloatTy(Ty->getContext());
} else if (IntegerType *ITy = dyn_cast<IntegerType>(Ty)) {
if (ITy->getBitWidth() < 32)
return i32Ty;
else
return Ty;
} else
return Ty;
}
}
StructType *UpdateStructTypeForLegacyLayout(StructType *ST, bool IsCBuf,
DxilTypeSystem &TypeSys, Module &M) {
bool bUpdated = false;
unsigned fieldsCount = ST->getNumElements();
std::vector<Type *> fieldTypes(fieldsCount);
DxilStructAnnotation *SA = TypeSys.GetStructAnnotation(ST);
DXASSERT(SA, "must have annotation for struct type");
for (unsigned i = 0; i < fieldsCount; i++) {
Type *EltTy = ST->getElementType(i);
Type *UpdatedTy =
UpdateFieldTypeForLegacyLayout(EltTy, IsCBuf, SA->GetFieldAnnotation(i), TypeSys, M);
fieldTypes[i] = UpdatedTy;
if (EltTy != UpdatedTy)
bUpdated = true;
}
if (!bUpdated) {
return ST;
} else {
std::string legacyName = "dx.alignment.legacy." + ST->getName().str();
if (StructType *legacyST = M.getTypeByName(legacyName))
return legacyST;
StructType *NewST = StructType::create(ST->getContext(), fieldTypes, legacyName);
DxilStructAnnotation *NewSA = TypeSys.AddStructAnnotation(NewST);
// Clone annotation.
*NewSA = *SA;
return NewST;
}
}
void UpdateStructTypeForLegacyLayout(DxilResourceBase &Res, DxilTypeSystem &TypeSys, Module &M) {
GlobalVariable *GV = cast<GlobalVariable>(Res.GetGlobalSymbol());
Type *Ty = GV->getType()->getPointerElementType();
bool IsResourceArray = Res.GetRangeSize() != 1;
if (IsResourceArray) {
// Support Array of struct buffer.
if (Ty->isArrayTy())
Ty = Ty->getArrayElementType();
}
StructType *ST = cast<StructType>(Ty);
if (ST->isOpaque()) {
DXASSERT(Res.GetClass() == DxilResourceBase::Class::CBuffer,
"Only cbuffer can have opaque struct.");
return;
}
Type *UpdatedST = UpdateStructTypeForLegacyLayout(ST, IsResourceArray, TypeSys, M);
if (ST != UpdatedST) {
Type *Ty = GV->getType()->getPointerElementType();
if (IsResourceArray) {
// Support Array of struct buffer.
if (Ty->isArrayTy()) {
UpdatedST = ArrayType::get(UpdatedST, Ty->getArrayNumElements());
}
}
GlobalVariable *NewGV = cast<GlobalVariable>(M.getOrInsertGlobal(GV->getName().str() + "_legacy", UpdatedST));
Res.SetGlobalSymbol(NewGV);
// Delete old GV.
for (auto UserIt = GV->user_begin(); UserIt != GV->user_end(); ) {
Value *User = *(UserIt++);
if (Instruction *I = dyn_cast<Instruction>(User)) {
if (!User->user_empty())
I->replaceAllUsesWith(UndefValue::get(I->getType()));
I->eraseFromParent();
} else {
ConstantExpr *CE = cast<ConstantExpr>(User);
if (!CE->user_empty())
CE->replaceAllUsesWith(UndefValue::get(CE->getType()));
}
}
GV->removeDeadConstantUsers();
GV->eraseFromParent();
}
}
void UpdateStructTypeForLegacyLayoutOnHLM(HLModule &HLM) {
DxilTypeSystem &TypeSys = HLM.GetTypeSystem();
Module &M = *HLM.GetModule();
for (auto &CBuf : HLM.GetCBuffers()) {
UpdateStructTypeForLegacyLayout(*CBuf.get(), TypeSys, M);
}
for (auto &UAV : HLM.GetUAVs()) {
if (UAV->GetKind() == DxilResourceBase::Kind::StructuredBuffer)
UpdateStructTypeForLegacyLayout(*UAV.get(), TypeSys, M);
}
for (auto &SRV : HLM.GetSRVs()) {
if (SRV->GetKind() == DxilResourceBase::Kind::StructuredBuffer)
UpdateStructTypeForLegacyLayout(*SRV.get(), TypeSys, M);
}
}
}
void DxilGenerationPass::UpdateStructTypeForLegacyLayout() {
UpdateStructTypeForLegacyLayoutOnHLM(*m_pHLModule);
}
///////////////////////////////////////////////////////////////////////////////

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

@ -48,6 +48,7 @@ const char DxilMDHelper::kDxilTypeSystemMDName[] = "dx.type
const char DxilMDHelper::kDxilTypeSystemHelperVariablePrefix[] = "dx.typevar.";
const char DxilMDHelper::kDxilControlFlowHintMDName[] = "dx.controlflow.hints";
const char DxilMDHelper::kDxilPreciseAttributeMDName[] = "dx.precise";
const char DxilMDHelper::kDxilNonUniformAttributeMDName[] = "dx.nonuniform";
const char DxilMDHelper::kHLDxilResourceAttributeMDName[] = "dx.hl.resource.attribute";
const char DxilMDHelper::kDxilValidatorVersionMDName[] = "dx.valver";
@ -1539,6 +1540,14 @@ bool DxilMDHelper::IsKnownNamedMetaData(llvm::NamedMDNode &Node) {
return false;
}
void DxilMDHelper::combineDxilMetadata(llvm::Instruction *K,
const llvm::Instruction *J) {
if (IsMarkedNonUniform(J))
MarkNonUniform(K);
if (IsMarkedPrecise(J))
MarkPrecise(K);
}
ConstantAsMetadata *DxilMDHelper::Int32ToConstMD(int32_t v, LLVMContext &Ctx) {
return ConstantAsMetadata::get(Constant::getIntegerValue(IntegerType::get(Ctx, 32), APInt(32, v)));
}
@ -1673,4 +1682,22 @@ void DxilMDHelper::MarkPrecise(Instruction *I) {
I->setMetadata(DxilMDHelper::kDxilPreciseAttributeMDName, preciseNode);
}
bool DxilMDHelper::IsMarkedNonUniform(const Instruction *inst) {
int32_t val = 0;
if (MDNode *precise = inst->getMetadata(kDxilNonUniformAttributeMDName)) {
assert(precise->getNumOperands() == 1);
val = ConstMDToInt32(precise->getOperand(0));
}
return val;
}
void DxilMDHelper::MarkNonUniform(Instruction *I) {
LLVMContext &Ctx = I->getContext();
MDNode *preciseNode = MDNode::get(
Ctx,
{ ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Ctx), 1)) });
I->setMetadata(DxilMDHelper::kDxilNonUniformAttributeMDName, preciseNode);
}
} // namespace hlsl

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

@ -358,6 +358,7 @@ struct ValidationContext {
unsigned domainLocSize;
const unsigned kDxilControlFlowHintMDKind;
const unsigned kDxilPreciseMDKind;
const unsigned kDxilNonUniformMDKind;
const unsigned kLLVMLoopMDKind;
bool m_bCoverageIn, m_bInnerCoverageIn;
unsigned m_DxilMajor, m_DxilMinor;
@ -371,10 +372,11 @@ struct ValidationContext {
DxilMDHelper::kDxilControlFlowHintMDName)),
kDxilPreciseMDKind(llvmModule.getContext().getMDKindID(
DxilMDHelper::kDxilPreciseAttributeMDName)),
kDxilNonUniformMDKind(llvmModule.getContext().getMDKindID(
DxilMDHelper::kDxilNonUniformAttributeMDName)),
kLLVMLoopMDKind(llvmModule.getContext().getMDKindID("llvm.loop")),
DiagPrinter(DiagPrn), LastRuleEmit((ValidationRule)-1),
m_bCoverageIn(false), m_bInnerCoverageIn(false),
hasViewID(false) {
m_bCoverageIn(false), m_bInnerCoverageIn(false), hasViewID(false) {
DxilMod.GetDxilVersion(m_DxilMajor, m_DxilMinor);
for (unsigned i = 0; i < DXIL::kNumOutputStreams; i++) {
hasOutputPosition[i] = false;
@ -2373,6 +2375,7 @@ static void ValidateInstructionMetadata(Instruction *I,
}
} else if (MD.first == ValCtx.kDxilPreciseMDKind) {
// Validated in IsPrecise.
} else if (MD.first == ValCtx.kDxilNonUniformMDKind) {
} else if (MD.first == ValCtx.kLLVMLoopMDKind) {
ValidateLoopMetadata(MD.second, ValCtx);
} else if (MD.first == LLVMContext::MD_tbaa) {

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

@ -44,6 +44,8 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "dxc/HLSL/DxilMetadataHelper.h" // HLSL Change - combine dxil metadata.
using namespace llvm;
#define DEBUG_TYPE "local"
@ -1323,6 +1325,10 @@ void llvm::combineMetadata(Instruction *K, const Instruction *J, ArrayRef<unsign
break;
}
}
// HLSL Change Begin - combine dxil metadata.
hlsl::DxilMDHelper::combineDxilMetadata(K, J);
// HLSL Change End.
}
unsigned llvm::replaceDominatedUsesWith(Value *From, Value *To,