mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2025-01-11 09:00:06 +00:00
Update passes to handle function declarations (#4599)
Spirv-opt has not had to handle module with function declarations. This lead many passes to assume that every function has a body. This is not always true. This commit will modify a number of passes to handle function declarations. Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/4443
This commit is contained in:
parent
b2ba019bf6
commit
7c5b17d379
@ -291,6 +291,10 @@ bool CCPPass::ReplaceValues() {
|
||||
}
|
||||
|
||||
bool CCPPass::PropagateConstants(Function* fp) {
|
||||
if (fp->IsDeclaration()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mark function parameters as varying.
|
||||
fp->ForEachParam([this](const Instruction* inst) {
|
||||
values_[inst->result_id()] = kVaryingSSAId;
|
||||
|
@ -34,6 +34,10 @@ Pass::Status CombineAccessChains::Process() {
|
||||
}
|
||||
|
||||
bool CombineAccessChains::ProcessFunction(Function& function) {
|
||||
if (function.IsDeclaration()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool modified = false;
|
||||
|
||||
cfg()->ForEachBlockInReversePostOrder(
|
||||
|
@ -40,6 +40,10 @@ bool IsDebugDeclareOrValue(Instruction* di) {
|
||||
Pass::Status CopyPropagateArrays::Process() {
|
||||
bool modified = false;
|
||||
for (Function& function : *get_module()) {
|
||||
if (function.IsDeclaration()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BasicBlock* entry_bb = &*function.begin();
|
||||
|
||||
for (auto var_inst = entry_bb->begin(); var_inst->opcode() == SpvOpVariable;
|
||||
|
@ -420,6 +420,10 @@ bool DeadBranchElimPass::EraseDeadBlocks(
|
||||
}
|
||||
|
||||
bool DeadBranchElimPass::EliminateDeadBranches(Function* func) {
|
||||
if (func->IsDeclaration()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool modified = false;
|
||||
std::unordered_set<BasicBlock*> live_blocks;
|
||||
modified |= MarkLiveBlocks(func, &live_blocks);
|
||||
|
@ -177,6 +177,9 @@ class Function {
|
||||
// debuggers.
|
||||
void Dump() const;
|
||||
|
||||
// Returns true is a function declaration and not a function definition.
|
||||
bool IsDeclaration() { return begin() == end(); }
|
||||
|
||||
private:
|
||||
// The OpFunction instruction that begins the definition of this function.
|
||||
std::unique_ptr<Instruction> def_inst_;
|
||||
|
@ -1102,6 +1102,10 @@ void LoopUtils::Finalize() {
|
||||
Pass::Status LoopUnroller::Process() {
|
||||
bool changed = false;
|
||||
for (Function& f : *context()->module()) {
|
||||
if (f.IsDeclaration()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LoopDescriptor* LD = context()->GetLoopDescriptor(&f);
|
||||
for (Loop& loop : *LD) {
|
||||
LoopUtils loop_utils{context(), &loop};
|
||||
|
@ -24,6 +24,10 @@ Pass::Status RedundancyEliminationPass::Process() {
|
||||
ValueNumberTable vnTable(context());
|
||||
|
||||
for (auto& func : *get_module()) {
|
||||
if (func.IsDeclaration()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build the dominator tree for this function. It is how the code is
|
||||
// traversed.
|
||||
DominatorTree& dom_tree =
|
||||
|
@ -35,6 +35,10 @@ namespace opt {
|
||||
Pass::Status ScalarReplacementPass::Process() {
|
||||
Status status = Status::SuccessWithoutChange;
|
||||
for (auto& f : *get_module()) {
|
||||
if (f.IsDeclaration()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Status functionStatus = ProcessFunction(&f);
|
||||
if (functionStatus == Status::Failure)
|
||||
return functionStatus;
|
||||
|
@ -45,6 +45,10 @@ void SimplificationPass::AddNewOperands(
|
||||
}
|
||||
|
||||
bool SimplificationPass::SimplifyFunction(Function* function) {
|
||||
if (function->IsDeclaration()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool modified = false;
|
||||
// Phase 1: Traverse all instructions in dominance order.
|
||||
// The second phase will only be on the instructions whose inputs have changed
|
||||
|
@ -753,6 +753,9 @@ Pass::Status SSARewriter::RewriteFunctionIntoSSA(Function* fp) {
|
||||
Pass::Status SSARewritePass::Process() {
|
||||
Status status = Status::SuccessWithoutChange;
|
||||
for (auto& fn : *get_module()) {
|
||||
if (fn.IsDeclaration()) {
|
||||
continue;
|
||||
}
|
||||
status =
|
||||
CombineStatus(status, SSARewriter(this).RewriteFunctionIntoSSA(&fn));
|
||||
// Kill DebugDeclares for target variables.
|
||||
|
@ -1208,6 +1208,32 @@ TEST_F(CCPTest, CCPNoChangeFailureWithUnfoldableInstr) {
|
||||
auto result = SinglePassRunAndMatch<CCPPass>(text, true);
|
||||
EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
|
||||
}
|
||||
|
||||
TEST_F(CCPTest, FunctionDeclaration) {
|
||||
// Make sure the pass works with a function declaration that is called.
|
||||
const std::string text = R"(OpCapability Addresses
|
||||
OpCapability Linkage
|
||||
OpCapability Kernel
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
|
||||
OpExecutionMode %2 ContractionOff
|
||||
OpSource Unknown 0
|
||||
OpDecorate %3 LinkageAttributes "julia_error_7712" Import
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%3 = OpFunction %void None %5
|
||||
OpFunctionEnd
|
||||
%2 = OpFunction %void None %5
|
||||
%6 = OpLabel
|
||||
%7 = OpFunctionCall %void %3
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<CCPPass>(text, text, false);
|
||||
}
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
@ -768,6 +768,32 @@ OpFunctionEnd
|
||||
SinglePassRunAndMatch<CombineAccessChains>(text, true);
|
||||
}
|
||||
|
||||
TEST_F(CombineAccessChainsTest, FunctionDeclaration) {
|
||||
// Make sure the pass works with a function declaration that is called.
|
||||
const std::string text = R"(OpCapability Addresses
|
||||
OpCapability Linkage
|
||||
OpCapability Kernel
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
|
||||
OpExecutionMode %2 ContractionOff
|
||||
OpSource Unknown 0
|
||||
OpDecorate %3 LinkageAttributes "julia_error_7712" Import
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%3 = OpFunction %void None %5
|
||||
OpFunctionEnd
|
||||
%2 = OpFunction %void None %5
|
||||
%6 = OpLabel
|
||||
%7 = OpFunctionCall %void %3
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<CombineAccessChains>(text, text, false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
@ -1814,6 +1814,31 @@ OpFunctionEnd
|
||||
SinglePassRunAndMatch<CopyPropagateArrays>(before, false);
|
||||
}
|
||||
|
||||
TEST_F(CopyPropArrayPassTest, FunctionDeclaration) {
|
||||
// Make sure the pass works with a function declaration that is called.
|
||||
const std::string text = R"(OpCapability Addresses
|
||||
OpCapability Linkage
|
||||
OpCapability Kernel
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
|
||||
OpExecutionMode %2 ContractionOff
|
||||
OpSource Unknown 0
|
||||
OpDecorate %3 LinkageAttributes "julia_error_7712" Import
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%3 = OpFunction %void None %5
|
||||
OpFunctionEnd
|
||||
%2 = OpFunction %void None %5
|
||||
%6 = OpLabel
|
||||
%7 = OpFunctionCall %void %3
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<CopyPropagateArrays>(text, text, false);
|
||||
}
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
@ -3442,6 +3442,32 @@ TEST_F(DeadBranchElimTest, DontTransferDecorations) {
|
||||
SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
|
||||
}
|
||||
|
||||
TEST_F(DeadBranchElimTest, FunctionDeclaration) {
|
||||
// Make sure the pass works with a function declaration that is called.
|
||||
const std::string text = R"(OpCapability Addresses
|
||||
OpCapability Linkage
|
||||
OpCapability Kernel
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
|
||||
OpExecutionMode %2 ContractionOff
|
||||
OpSource Unknown 0
|
||||
OpDecorate %3 LinkageAttributes "julia_error_7712" Import
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%3 = OpFunction %void None %5
|
||||
OpFunctionEnd
|
||||
%2 = OpFunction %void None %5
|
||||
%6 = OpLabel
|
||||
%7 = OpFunctionCall %void %3
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<DeadBranchElimPass>(text, text, false);
|
||||
}
|
||||
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// More complex control flow
|
||||
|
@ -4225,6 +4225,32 @@ TEST_F(LocalSSAElimTest, PointerVariables) {
|
||||
SinglePassRunAndMatch<SSARewritePass>(text, true);
|
||||
}
|
||||
|
||||
TEST_F(LocalSSAElimTest, FunctionDeclaration) {
|
||||
// Make sure the pass works with a function declaration that is called.
|
||||
const std::string text = R"(OpCapability Addresses
|
||||
OpCapability Linkage
|
||||
OpCapability Kernel
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
|
||||
OpExecutionMode %2 ContractionOff
|
||||
OpSource Unknown 0
|
||||
OpDecorate %3 LinkageAttributes "julia_error_7712" Import
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%3 = OpFunction %void None %5
|
||||
OpFunctionEnd
|
||||
%2 = OpFunction %void None %5
|
||||
%6 = OpLabel
|
||||
%7 = OpFunctionCall %void %3
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<SSARewritePass>(text, text, false);
|
||||
}
|
||||
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// No optimization in the presence of
|
||||
|
@ -42,6 +42,10 @@ class PartialUnrollerTestPass : public Pass {
|
||||
Status Process() override {
|
||||
bool changed = false;
|
||||
for (Function& f : *context()->module()) {
|
||||
if (f.IsDeclaration()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LoopDescriptor& loop_descriptor = *context()->GetLoopDescriptor(&f);
|
||||
for (auto& loop : loop_descriptor) {
|
||||
LoopUtils loop_utils{context(), &loop};
|
||||
@ -1510,6 +1514,33 @@ OpFunctionEnd
|
||||
SinglePassRunAndCheck<PartialUnrollerTestPass<2>>(text, text, false);
|
||||
}
|
||||
|
||||
TEST_F(PassClassTest, FunctionDeclaration) {
|
||||
// Make sure the pass works with a function declaration that is called.
|
||||
const std::string text = R"(OpCapability Addresses
|
||||
OpCapability Linkage
|
||||
OpCapability Kernel
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
|
||||
OpExecutionMode %2 ContractionOff
|
||||
OpSource Unknown 0
|
||||
OpDecorate %3 LinkageAttributes "julia_error_7712" Import
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%3 = OpFunction %void None %5
|
||||
OpFunctionEnd
|
||||
%2 = OpFunction %void None %5
|
||||
%6 = OpLabel
|
||||
%7 = OpFunctionCall %void %3
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<LoopUnroller>(text, text, false);
|
||||
SinglePassRunAndCheck<PartialUnrollerTestPass<1>>(text, text, false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
@ -335,6 +335,32 @@ TEST_F(RedundancyEliminationTest, OpenCLDebugInfo100) {
|
||||
SinglePassRunAndMatch<RedundancyEliminationPass>(text, false);
|
||||
}
|
||||
|
||||
TEST_F(RedundancyEliminationTest, FunctionDeclaration) {
|
||||
// Make sure the pass works with a function declaration that is called.
|
||||
const std::string text = R"(OpCapability Addresses
|
||||
OpCapability Linkage
|
||||
OpCapability Kernel
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
|
||||
OpExecutionMode %2 ContractionOff
|
||||
OpSource Unknown 0
|
||||
OpDecorate %3 LinkageAttributes "julia_error_7712" Import
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%3 = OpFunction %void None %5
|
||||
OpFunctionEnd
|
||||
%2 = OpFunction %void None %5
|
||||
%6 = OpLabel
|
||||
%7 = OpFunctionCall %void %3
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<RedundancyEliminationPass>(text, text, false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
} // namespace spvtools
|
@ -2237,6 +2237,32 @@ OpFunctionEnd
|
||||
SinglePassRunAndMatch<ScalarReplacementPass>(text, false);
|
||||
}
|
||||
|
||||
TEST_F(ScalarReplacementTest, FunctionDeclaration) {
|
||||
// Make sure the pass works with a function declaration that is called.
|
||||
const std::string text = R"(OpCapability Addresses
|
||||
OpCapability Linkage
|
||||
OpCapability Kernel
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
|
||||
OpExecutionMode %2 ContractionOff
|
||||
OpSource Unknown 0
|
||||
OpDecorate %3 LinkageAttributes "julia_error_7712" Import
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%3 = OpFunction %void None %5
|
||||
OpFunctionEnd
|
||||
%2 = OpFunction %void None %5
|
||||
%6 = OpLabel
|
||||
%7 = OpFunctionCall %void %3
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<ScalarReplacementPass>(text, text, false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
@ -360,6 +360,31 @@ OpFunctionEnd
|
||||
SinglePassRunAndMatch<SimplificationPass>(spirv, true);
|
||||
}
|
||||
|
||||
TEST_F(SimplificationTest, FunctionDeclaration) {
|
||||
// Make sure the pass works with a function declaration that is called.
|
||||
const std::string text = R"(OpCapability Addresses
|
||||
OpCapability Linkage
|
||||
OpCapability Kernel
|
||||
OpCapability Int8
|
||||
%1 = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Physical64 OpenCL
|
||||
OpEntryPoint Kernel %2 "_Z23julia__1166_kernel_77094Bool"
|
||||
OpExecutionMode %2 ContractionOff
|
||||
OpSource Unknown 0
|
||||
OpDecorate %3 LinkageAttributes "julia_error_7712" Import
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%3 = OpFunction %void None %5
|
||||
OpFunctionEnd
|
||||
%2 = OpFunction %void None %5
|
||||
%6 = OpLabel
|
||||
%7 = OpFunctionCall %void %3
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<SimplificationPass>(text, text, false);
|
||||
}
|
||||
} // namespace
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
Loading…
Reference in New Issue
Block a user