Skip to content

Commit 06430aa

Browse files
committed
Gate O1experimental fast path on risky composite types
1 parent 4dd86f9 commit 06430aa

2 files changed

Lines changed: 94 additions & 1 deletion

File tree

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include "clang/SPIRV/String.h"
3030
#include "clang/Sema/Sema.h"
3131
#include "llvm/ADT/APInt.h"
32+
#include "llvm/ADT/SmallPtrSet.h"
33+
#include "llvm/ADT/SmallVector.h"
3234
#include "llvm/ADT/SetVector.h"
3335
#include "llvm/ADT/StringExtras.h"
3436
#include "llvm/Support/Casting.h"
@@ -596,6 +598,7 @@ SpirvEmitter::SpirvEmitter(CompilerInstance &ci)
596598
needsLegalizationLoopUnroll(false),
597599
needsLegalizationSsaRewrite(false),
598600
sawExplicitUnrollHint(false),
601+
experimentalFastCompileRequiresDefaultPath(false),
599602
beforeHlslLegalization(false), mainSourceFile(nullptr) {
600603

601604
// Get ShaderModel from command line hlsl profile option.
@@ -1570,6 +1573,84 @@ bool SpirvEmitter::handleNodePayloadArrayType(const ParmVarDecl *decl,
15701573
}
15711574
}
15721575

1576+
void SpirvEmitter::noteExperimentalFastCompileRisk(
1577+
QualType type, bool hasAliasedPointerAttr) {
1578+
if (!spirvOptions.o1ExperimentalFastCompile || type.isNull())
1579+
return;
1580+
1581+
auto hasRiskyDecorations = [](const Decl *decl) {
1582+
if (!decl || !decl->hasAttrs())
1583+
return false;
1584+
1585+
if (decl->hasAttr<VKAliasedPointerAttr>())
1586+
return true;
1587+
1588+
for (const auto *attr : decl->getAttrs()) {
1589+
if (const auto *decorateAttr = dyn_cast<VKDecorateExtAttr>(attr)) {
1590+
const auto decoration =
1591+
static_cast<spv::Decoration>(decorateAttr->getDecorate());
1592+
if (decoration == spv::Decoration::AliasedPointer ||
1593+
decoration == spv::Decoration::RestrictPointer) {
1594+
return true;
1595+
}
1596+
}
1597+
}
1598+
return false;
1599+
};
1600+
1601+
llvm::SmallVector<QualType, 8> worklist;
1602+
llvm::SmallPtrSet<const Type *, 16> visitedTypes;
1603+
worklist.push_back(type);
1604+
1605+
while (!worklist.empty()) {
1606+
QualType currentType = worklist.pop_back_val();
1607+
if (currentType.isNull())
1608+
continue;
1609+
1610+
Optional<bool> isRowMajor = llvm::None;
1611+
currentType = desugarType(currentType, &isRowMajor);
1612+
1613+
const Type *typePtr = currentType.getTypePtrOrNull();
1614+
if (!typePtr || !visitedTypes.insert(typePtr).second)
1615+
continue;
1616+
1617+
if (hasAliasedPointerAttr || hlsl::IsVKBufferPointerType(currentType) ||
1618+
isOpaqueArrayType(currentType) || isOpaqueStructType(currentType) ||
1619+
isBindlessOpaqueArray(currentType)) {
1620+
experimentalFastCompileRequiresDefaultPath = true;
1621+
return;
1622+
}
1623+
1624+
if (const auto *arrayType = currentType->getAsArrayTypeUnsafe()) {
1625+
worklist.push_back(arrayType->getElementType());
1626+
continue;
1627+
}
1628+
1629+
const auto *recordType = currentType->getAs<RecordType>();
1630+
if (!recordType)
1631+
continue;
1632+
1633+
const RecordDecl *recordDecl = recordType->getDecl();
1634+
if (hasRiskyDecorations(recordDecl)) {
1635+
experimentalFastCompileRequiresDefaultPath = true;
1636+
return;
1637+
}
1638+
1639+
if (const auto *cxxRecordDecl = dyn_cast<CXXRecordDecl>(recordDecl)) {
1640+
for (const auto &base : cxxRecordDecl->bases())
1641+
worklist.push_back(base.getType());
1642+
}
1643+
1644+
for (const FieldDecl *fieldDecl : recordDecl->fields()) {
1645+
if (hasRiskyDecorations(fieldDecl)) {
1646+
experimentalFastCompileRequiresDefaultPath = true;
1647+
return;
1648+
}
1649+
worklist.push_back(fieldDecl->getType());
1650+
}
1651+
}
1652+
}
1653+
15731654
void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) {
15741655
// Forward declaration of a function inside another.
15751656
if (!decl->isThisDeclarationADefinition()) {
@@ -1578,6 +1659,8 @@ void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) {
15781659
return;
15791660
}
15801661

1662+
noteExperimentalFastCompileRisk(decl->getReturnType());
1663+
15811664
// A RAII class for maintaining the current function under traversal.
15821665
class FnEnvRAII {
15831666
public:
@@ -1682,6 +1765,7 @@ void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) {
16821765
// For non-static member function, the first parameter should be the
16831766
// object on which we are invoking this method.
16841767
QualType valueType = memberFn->getThisType(astContext)->getPointeeType();
1768+
noteExperimentalFastCompileRisk(valueType);
16851769

16861770
// Remember the parameter for the 'this' object so later we can handle
16871771
// CXXThisExpr correctly.
@@ -1716,6 +1800,8 @@ void SpirvEmitter::doFunctionDecl(const FunctionDecl *decl) {
17161800
for (uint32_t i = 0; i < decl->getNumParams(); ++i) {
17171801
const ParmVarDecl *paramDecl = decl->getParamDecl(i);
17181802
QualType paramType = paramDecl->getType();
1803+
noteExperimentalFastCompileRisk(paramType,
1804+
paramDecl->hasAttr<VKAliasedPointerAttr>());
17191805
auto *param =
17201806
declIdMapper.createFnParam(paramDecl, i + 1 + isNonStaticMemberFn);
17211807
if (isEntry) {
@@ -2038,6 +2124,8 @@ void SpirvEmitter::doVarDecl(const VarDecl *decl) {
20382124

20392125
const auto loc = decl->getLocation();
20402126
const auto range = decl->getSourceRange();
2127+
noteExperimentalFastCompileRisk(decl->getType(),
2128+
decl->hasAttr<VKAliasedPointerAttr>());
20412129

20422130
if (isExtResultIdType(decl->getType())) {
20432131
declIdMapper.createResultId(decl);
@@ -16670,7 +16758,9 @@ bool SpirvEmitter::spirvToolsOptimize(std::vector<uint32_t> *mod,
1667016758

1667116759
bool SpirvEmitter::useSpirvFastCompileProfile() const {
1667216760
return spirvOptions.o1ExperimentalFastCompile &&
16673-
spirvOptions.optConfig.empty();
16761+
spirvOptions.optConfig.empty() &&
16762+
!experimentalFastCompileRequiresDefaultPath &&
16763+
!declIdMapper.requiresFlatteningCompositeResources();
1667416764
}
1667516765

1667616766
bool SpirvEmitter::spirvToolsLegalize(std::vector<uint32_t> *mod,

tools/clang/lib/SPIRV/SpirvEmitter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,8 @@ class SpirvEmitter : public ASTConsumer {
13401340
/// Returns true on success and false otherwise.
13411341
bool spirvToolsOptimize(std::vector<uint32_t> *mod, std::string *messages);
13421342
bool useSpirvFastCompileProfile() const;
1343+
void noteExperimentalFastCompileRisk(QualType type,
1344+
bool hasAliasedPointerAttr = false);
13431345

13441346
// \brief Runs the pass represented by the given pass token on the module.
13451347
// Returns true if the pass was successfully run. Any messages from the
@@ -1582,6 +1584,7 @@ class SpirvEmitter : public ASTConsumer {
15821584
bool needsLegalizationLoopUnroll;
15831585
bool needsLegalizationSsaRewrite;
15841586
bool sawExplicitUnrollHint;
1587+
bool experimentalFastCompileRequiresDefaultPath;
15851588

15861589
/// Whether the translated SPIR-V binary passes --before-hlsl-legalization
15871590
/// option to spirv-val because of illegal function parameter scope.

0 commit comments

Comments
 (0)