mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-30 15:00:06 +00:00
c4dc046399
The sprir-v generated from HLSL code contain many copyies of very large arrays. Not only are these time consumming, but they also cause problems for drivers because they require too much space. To work around this, we will implement an array copy propagation. Note that we will not implement a complete array data flow analysis in order to implement this. We will be looking for very simple cases: 1) The source must never be stored to. 2) The target must be stored to exactly once. 3) The store to the target must be a store to the entire array, and be a copy of the entire source. 4) All loads of the target must be dominated by the store. The hard part is keeping all of the types correct. We do not want to have to do too large a search to update everything, which may not be possible, do we give up if we see any instruction that might be hard to update. Also in types.h, the element decorations are not stored in an std::map. This change was done so the hashing algorithm for a Struct is consistent. With the std::unordered_map, the traversal order was non-deterministic leading to the same type getting hashed to different values. See |Struct::GetExtraHashWords|. Contributes to #1416.
74 lines
1.8 KiB
C++
74 lines
1.8 KiB
C++
// Copyright (c) 2018 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "dominator_analysis.h"
|
|
|
|
#include <unordered_set>
|
|
|
|
#include "ir_context.h"
|
|
|
|
namespace spvtools {
|
|
namespace opt {
|
|
|
|
ir::BasicBlock* DominatorAnalysisBase::CommonDominator(
|
|
ir::BasicBlock* b1, ir::BasicBlock* b2) const {
|
|
if (!b1 || !b2) return nullptr;
|
|
|
|
std::unordered_set<ir::BasicBlock*> seen;
|
|
ir::BasicBlock* block = b1;
|
|
while (block && seen.insert(block).second) {
|
|
block = ImmediateDominator(block);
|
|
}
|
|
|
|
block = b2;
|
|
while (block && !seen.count(block)) {
|
|
block = ImmediateDominator(block);
|
|
}
|
|
|
|
return block;
|
|
}
|
|
|
|
bool DominatorAnalysisBase::Dominates(ir::Instruction* a,
|
|
ir::Instruction* b) const {
|
|
if (!a || !b) {
|
|
return false;
|
|
}
|
|
|
|
if (a == b) {
|
|
return true;
|
|
}
|
|
|
|
ir::BasicBlock* bb_a = a->context()->get_instr_block(a);
|
|
ir::BasicBlock* bb_b = b->context()->get_instr_block(b);
|
|
|
|
if (bb_a != bb_b) {
|
|
return tree_.Dominates(bb_a, bb_b);
|
|
}
|
|
|
|
for (ir::Instruction& inst : *bb_a) {
|
|
if (&inst == a) {
|
|
return true;
|
|
} else if (&inst == b) {
|
|
return false;
|
|
}
|
|
}
|
|
assert(false &&
|
|
"We did not find the load or store in the block they are "
|
|
"supposed to be in.");
|
|
return false;
|
|
}
|
|
|
|
} // namespace opt
|
|
} // namespace spvtools
|