summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/loop_descriptor.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/3rdparty/spirv-tools/source/opt/loop_descriptor.cpp')
-rw-r--r--3rdparty/bgfx/3rdparty/spirv-tools/source/opt/loop_descriptor.cpp82
1 files changed, 51 insertions, 31 deletions
diff --git a/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/loop_descriptor.cpp b/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/loop_descriptor.cpp
index efc56bdba68..13982d1819c 100644
--- a/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/loop_descriptor.cpp
+++ b/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/loop_descriptor.cpp
@@ -191,14 +191,13 @@ bool Loop::GetInductionInitValue(const Instruction* induction,
if (!constant) return false;
if (value) {
- const analysis::Integer* type =
- constant->AsIntConstant()->type()->AsInteger();
-
- if (type->IsSigned()) {
- *value = constant->AsIntConstant()->GetS32BitValue();
- } else {
- *value = constant->AsIntConstant()->GetU32BitValue();
+ const analysis::Integer* type = constant->type()->AsInteger();
+ if (!type) {
+ return false;
}
+
+ *value = type->IsSigned() ? constant->GetSignExtendedValue()
+ : constant->GetZeroExtendedValue();
}
return true;
@@ -485,16 +484,34 @@ void Loop::ComputeLoopStructuredOrder(
if (include_pre_header && GetPreHeaderBlock())
ordered_loop_blocks->push_back(loop_preheader_);
- cfg.ForEachBlockInReversePostOrder(
- loop_header_, [ordered_loop_blocks, this](BasicBlock* bb) {
- if (IsInsideLoop(bb)) ordered_loop_blocks->push_back(bb);
- });
+
+ bool is_shader =
+ context_->get_feature_mgr()->HasCapability(SpvCapabilityShader);
+ if (!is_shader) {
+ cfg.ForEachBlockInReversePostOrder(
+ loop_header_, [ordered_loop_blocks, this](BasicBlock* bb) {
+ if (IsInsideLoop(bb)) ordered_loop_blocks->push_back(bb);
+ });
+ } else {
+ // If this is a shader, it is possible that there are unreachable merge and
+ // continue blocks that must be copied to retain the structured order.
+ // The structured order will include these.
+ std::list<BasicBlock*> order;
+ cfg.ComputeStructuredOrder(loop_header_->GetParent(), loop_header_,
+ loop_merge_, &order);
+ for (BasicBlock* bb : order) {
+ if (bb == GetMergeBlock()) {
+ break;
+ }
+ ordered_loop_blocks->push_back(bb);
+ }
+ }
if (include_merge && GetMergeBlock())
ordered_loop_blocks->push_back(loop_merge_);
}
LoopDescriptor::LoopDescriptor(IRContext* context, const Function* f)
- : loops_(), dummy_top_loop_(nullptr) {
+ : loops_(), placeholder_top_loop_(nullptr) {
PopulateList(context, f);
}
@@ -575,7 +592,7 @@ void LoopDescriptor::PopulateList(IRContext* context, const Function* f) {
}
}
for (Loop* loop : loops_) {
- if (!loop->HasParent()) dummy_top_loop_.nested_loops_.push_back(loop);
+ if (!loop->HasParent()) placeholder_top_loop_.nested_loops_.push_back(loop);
}
}
@@ -665,22 +682,19 @@ bool Loop::FindNumberOfIterations(const Instruction* induction,
if (!upper_bound) return false;
// Must be integer because of the opcode on the condition.
- int64_t condition_value = 0;
+ const analysis::Integer* type = upper_bound->type()->AsInteger();
- const analysis::Integer* type =
- upper_bound->AsIntConstant()->type()->AsInteger();
-
- if (type->width() > 32) {
+ if (!type || type->width() > 64) {
return false;
}
- if (type->IsSigned()) {
- condition_value = upper_bound->AsIntConstant()->GetS32BitValue();
- } else {
- condition_value = upper_bound->AsIntConstant()->GetU32BitValue();
- }
+ int64_t condition_value = type->IsSigned()
+ ? upper_bound->GetSignExtendedValue()
+ : upper_bound->GetZeroExtendedValue();
// Find the instruction which is stepping through the loop.
+ //
+ // GetInductionStepOperation returns nullptr if |step_inst| is OpConstantNull.
Instruction* step_inst = GetInductionStepOperation(induction);
if (!step_inst) return false;
@@ -706,7 +720,7 @@ bool Loop::FindNumberOfIterations(const Instruction* induction,
step_value = -step_value;
}
- // Find the inital value of the loop and make sure it is a constant integer.
+ // Find the initial value of the loop and make sure it is a constant integer.
int64_t init_value = 0;
if (!GetInductionInitValue(induction, &init_value)) return false;
@@ -738,9 +752,13 @@ bool Loop::FindNumberOfIterations(const Instruction* induction,
// We retrieve the number of iterations using the following formula, diff /
// |step_value| where diff is calculated differently according to the
// |condition| and uses the |condition_value| and |init_value|. If diff /
-// |step_value| is NOT cleanly divisable then we add one to the sum.
+// |step_value| is NOT cleanly divisible then we add one to the sum.
int64_t Loop::GetIterations(SpvOp condition, int64_t condition_value,
int64_t init_value, int64_t step_value) const {
+ if (step_value == 0) {
+ return 0;
+ }
+
int64_t diff = 0;
switch (condition) {
@@ -782,7 +800,7 @@ int64_t Loop::GetIterations(SpvOp condition, int64_t condition_value,
// If the condition is not met to begin with the loop will never iterate.
if (!(init_value >= condition_value)) return 0;
- // We subract one to make it the same as SpvOpGreaterThan as it is
+ // We subtract one to make it the same as SpvOpGreaterThan as it is
// functionally equivalent.
diff = init_value - (condition_value - 1);
@@ -914,6 +932,7 @@ bool LoopDescriptor::CreatePreHeaderBlocksIfMissing() {
for (auto& loop : *this) {
if (!loop.GetPreHeaderBlock()) {
modified = true;
+ // TODO(1841): Handle failure to create pre-header.
loop.GetOrCreatePreHeaderBlock();
}
}
@@ -936,22 +955,23 @@ void LoopDescriptor::PostModificationCleanup() {
for (Loop* loop : loops_to_remove_) {
loops_.erase(std::find(loops_.begin(), loops_.end(), loop));
+ delete loop;
}
for (auto& pair : loops_to_add_) {
Loop* parent = pair.first;
- Loop* loop = pair.second;
+ std::unique_ptr<Loop> loop = std::move(pair.second);
if (parent) {
loop->SetParent(nullptr);
- parent->AddNestedLoop(loop);
+ parent->AddNestedLoop(loop.get());
for (uint32_t block_id : loop->GetBlocks()) {
parent->AddBasicBlock(block_id);
}
}
- loops_.emplace_back(loop);
+ loops_.emplace_back(loop.release());
}
loops_to_add_.clear();
@@ -967,7 +987,7 @@ void LoopDescriptor::ClearLoops() {
// Adds a new loop nest to the descriptor set.
Loop* LoopDescriptor::AddLoopNest(std::unique_ptr<Loop> new_loop) {
Loop* loop = new_loop.release();
- if (!loop->HasParent()) dummy_top_loop_.nested_loops_.push_back(loop);
+ if (!loop->HasParent()) placeholder_top_loop_.nested_loops_.push_back(loop);
// Iterate from inner to outer most loop, adding basic block to loop mapping
// as we go.
for (Loop& current_loop :
@@ -981,7 +1001,7 @@ Loop* LoopDescriptor::AddLoopNest(std::unique_ptr<Loop> new_loop) {
}
void LoopDescriptor::RemoveLoop(Loop* loop) {
- Loop* parent = loop->GetParent() ? loop->GetParent() : &dummy_top_loop_;
+ Loop* parent = loop->GetParent() ? loop->GetParent() : &placeholder_top_loop_;
parent->nested_loops_.erase(std::find(parent->nested_loops_.begin(),
parent->nested_loops_.end(), loop));
std::for_each(