mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-24 16:51:06 +00:00
Update MARK-V to version 1.01
Includes: - Multi-sequence move-to-front - Coding by id descriptor - Statistical coding of non-id words - Joint coding of opcode and num_operands Removed explicit form Huffman codec constructor - The standard use case for it is to be constructed from initializer list. Using serialization for Huffman codecs
This commit is contained in:
parent
40e9c60ffe
commit
b36acbec0e
@ -12,7 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
add_library(SPIRV-Tools-comp markv_codec.cpp)
|
||||
add_library(SPIRV-Tools-comp markv_codec.cpp markv_autogen.cpp)
|
||||
|
||||
spvtools_default_compile_options(SPIRV-Tools-comp)
|
||||
target_include_directories(SPIRV-Tools-comp
|
||||
|
57
source/comp/markv_autogen.cpp
Normal file
57
source/comp/markv_autogen.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// 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 "markv_autogen.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "spirv/1.2/spirv.h"
|
||||
|
||||
using spvutils::HuffmanCodec;
|
||||
|
||||
namespace {
|
||||
|
||||
// Signals that the value is not in the coding scheme and a fallback method
|
||||
// needs to be used.
|
||||
const uint64_t kMarkvNoneOfTheAbove = GetMarkvNonOfTheAbove();
|
||||
|
||||
inline uint32_t CombineOpcodeAndNumOperands(uint32_t opcode,
|
||||
uint32_t num_operands) {
|
||||
return opcode | (num_operands << 16);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// The following file contains autogenerated statistical coding rules.
|
||||
// Generated by running spirv-stats on representative corpus of shaders with
|
||||
// flags:
|
||||
// --codegen_opcode_and_num_operands_hist
|
||||
// --codegen_opcode_and_num_operands_markov_huffman_codecs
|
||||
// --codegen_literal_string_huffman_codecs
|
||||
// --codegen_non_id_word_huffman_codecs
|
||||
// --codegen_id_descriptor_huffman_codecs
|
||||
//
|
||||
// Example:
|
||||
// find <SHADER_CORPUS_DIR> -type f -print0 | xargs -0 -s 2000000
|
||||
// ~/SPIRV-Tools/build/tools/spirv-stats -v
|
||||
// --codegen_opcode_and_num_operands_hist
|
||||
// --codegen_opcode_and_num_operands_markov_huffman_codecs
|
||||
// --codegen_literal_string_huffman_codecs --codegen_non_id_word_huffman_codecs
|
||||
// --codegen_id_descriptor_huffman_codecs -o
|
||||
// ~/SPIRV-Tools/source/comp/markv_autogen.inc
|
||||
#include "markv_autogen.inc"
|
45
source/comp/markv_autogen.h
Normal file
45
source/comp/markv_autogen.h
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef LIBSPIRV_COMP_MARKV_AUTOGEN_H_
|
||||
#define LIBSPIRV_COMP_MARKV_AUTOGEN_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
|
||||
#include "util/huffman_codec.h"
|
||||
|
||||
inline uint64_t GetMarkvNonOfTheAbove() {
|
||||
// Magic number.
|
||||
return 1111111111111111111;
|
||||
}
|
||||
|
||||
std::map<uint64_t, uint32_t> GetOpcodeAndNumOperandsHist();
|
||||
|
||||
std::map<uint32_t, std::unique_ptr<spvutils::HuffmanCodec<uint64_t>>>
|
||||
GetOpcodeAndNumOperandsMarkovHuffmanCodecs();
|
||||
|
||||
std::map<uint32_t, std::unique_ptr<spvutils::HuffmanCodec<std::string>>>
|
||||
GetLiteralStringHuffmanCodecs();
|
||||
|
||||
std::map<std::pair<uint32_t, uint32_t>,
|
||||
std::unique_ptr<spvutils::HuffmanCodec<uint64_t>>>
|
||||
GetNonIdWordHuffmanCodecs();
|
||||
|
||||
std::map<std::pair<uint32_t, uint32_t>,
|
||||
std::unique_ptr<spvutils::HuffmanCodec<uint64_t>>>
|
||||
GetIdDescriptorHuffmanCodecs();
|
||||
|
||||
#endif // LIBSPIRV_COMP_MARKV_AUTOGEN_H_
|
3920
source/comp/markv_autogen.inc
Normal file
3920
source/comp/markv_autogen.inc
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -328,3 +328,61 @@ bool spvIsIdType(spv_operand_type_t type) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
|
||||
SpvOp opcode) {
|
||||
std::function<bool(unsigned index)> out;
|
||||
switch (opcode) {
|
||||
case SpvOpExecutionMode:
|
||||
case SpvOpEntryPoint:
|
||||
case SpvOpName:
|
||||
case SpvOpMemberName:
|
||||
case SpvOpSelectionMerge:
|
||||
case SpvOpDecorate:
|
||||
case SpvOpMemberDecorate:
|
||||
case SpvOpTypeStruct:
|
||||
case SpvOpBranch:
|
||||
case SpvOpLoopMerge:
|
||||
out = [](unsigned) { return true; };
|
||||
break;
|
||||
case SpvOpGroupDecorate:
|
||||
case SpvOpGroupMemberDecorate:
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch:
|
||||
out = [](unsigned index) { return index != 0; };
|
||||
break;
|
||||
|
||||
case SpvOpFunctionCall:
|
||||
// The Function parameter.
|
||||
out = [](unsigned index) { return index == 2; };
|
||||
break;
|
||||
|
||||
case SpvOpPhi:
|
||||
out = [](unsigned index) { return index > 1; };
|
||||
break;
|
||||
|
||||
case SpvOpEnqueueKernel:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 8; };
|
||||
break;
|
||||
|
||||
case SpvOpGetKernelNDrangeSubGroupCount:
|
||||
case SpvOpGetKernelNDrangeMaxSubGroupSize:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 3; };
|
||||
break;
|
||||
|
||||
case SpvOpGetKernelWorkGroupSize:
|
||||
case SpvOpGetKernelPreferredWorkGroupSizeMultiple:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 2; };
|
||||
break;
|
||||
case SpvOpTypeForwardPointer:
|
||||
out = [](unsigned index) { return index == 0; };
|
||||
break;
|
||||
default:
|
||||
out = [](unsigned) { return false; };
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define LIBSPIRV_OPERAND_H_
|
||||
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "table.h"
|
||||
@ -124,4 +125,11 @@ spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
|
||||
// Is the operand an ID?
|
||||
bool spvIsIdType(spv_operand_type_t type);
|
||||
|
||||
// Takes the opcode of an instruction and returns
|
||||
// a function object that will return true if the index
|
||||
// of the operand can be forward declared. This function will
|
||||
// used in the SSA validation stage of the pipeline
|
||||
std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
|
||||
SpvOp opcode);
|
||||
|
||||
#endif // LIBSPIRV_OPERAND_H_
|
||||
|
@ -210,7 +210,7 @@ class HuffmanCodec {
|
||||
|
||||
// Encodes |val| and stores its Huffman code in the lower |num_bits| of
|
||||
// |bits|. Returns false of |val| is not in the Huffman table.
|
||||
bool Encode(const Val& val, uint64_t* bits, size_t* num_bits) {
|
||||
bool Encode(const Val& val, uint64_t* bits, size_t* num_bits) const {
|
||||
auto it = encoding_table_.find(val);
|
||||
if (it == encoding_table_.end())
|
||||
return false;
|
||||
@ -225,7 +225,8 @@ class HuffmanCodec {
|
||||
// |read_bit| has type bool func(bool* bit). When called, the next bit is
|
||||
// stored in |bit|. |read_bit| returns false if the stream terminates
|
||||
// prematurely.
|
||||
bool DecodeFromStream(const std::function<bool(bool*)>& read_bit, Val* val) {
|
||||
bool DecodeFromStream(
|
||||
const std::function<bool(bool*)>& read_bit, Val* val) const {
|
||||
uint32_t node = root_;
|
||||
while (true) {
|
||||
assert(node);
|
||||
|
@ -325,7 +325,7 @@ class MultiMoveToFront {
|
||||
public:
|
||||
// Inserts |value| to sequence with handle |mtf|.
|
||||
// Returns false if |mtf| already has |value|.
|
||||
bool Insert(uint32_t mtf, const Val& value) {
|
||||
bool Insert(uint64_t mtf, const Val& value) {
|
||||
if (GetMtf(mtf).Insert(value)) {
|
||||
val_to_mtfs_[value].insert(mtf);
|
||||
return true;
|
||||
@ -335,7 +335,7 @@ class MultiMoveToFront {
|
||||
|
||||
// Removes |value| from sequence with handle |mtf|.
|
||||
// Returns false if |mtf| doesn't have |value|.
|
||||
bool Remove(uint32_t mtf, const Val& value) {
|
||||
bool Remove(uint64_t mtf, const Val& value) {
|
||||
if (GetMtf(mtf).Remove(value)) {
|
||||
val_to_mtfs_[value].erase(mtf);
|
||||
return true;
|
||||
@ -351,7 +351,7 @@ class MultiMoveToFront {
|
||||
return;
|
||||
|
||||
auto& mtfs_containing_value = it->second;
|
||||
for (uint32_t mtf : mtfs_containing_value) {
|
||||
for (uint64_t mtf : mtfs_containing_value) {
|
||||
GetMtf(mtf).Remove(value);
|
||||
}
|
||||
|
||||
@ -360,18 +360,18 @@ class MultiMoveToFront {
|
||||
|
||||
// Computes rank of |value| in sequence |mtf|.
|
||||
// Returns false if |mtf| doesn't have |value|.
|
||||
bool RankFromValue(uint32_t mtf, const Val& value, uint32_t* rank) {
|
||||
bool RankFromValue(uint64_t mtf, const Val& value, uint32_t* rank) {
|
||||
return GetMtf(mtf).RankFromValue(value, rank);
|
||||
}
|
||||
|
||||
// Finds |value| with |rank| in sequence |mtf|.
|
||||
// Returns false if |rank| is out of bounds.
|
||||
bool ValueFromRank(uint32_t mtf, uint32_t rank, Val* value) {
|
||||
bool ValueFromRank(uint64_t mtf, uint32_t rank, Val* value) {
|
||||
return GetMtf(mtf).ValueFromRank(rank, value);
|
||||
}
|
||||
|
||||
// Returns size of |mtf| sequence.
|
||||
uint32_t GetSize(uint32_t mtf) {
|
||||
uint32_t GetSize(uint64_t mtf) {
|
||||
return GetMtf(mtf).GetSize();
|
||||
}
|
||||
|
||||
@ -382,20 +382,20 @@ class MultiMoveToFront {
|
||||
return;
|
||||
|
||||
const auto& mtfs_containing_value = it->second;
|
||||
for (uint32_t mtf : mtfs_containing_value) {
|
||||
for (uint64_t mtf : mtfs_containing_value) {
|
||||
GetMtf(mtf).Promote(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Inserts |value| in sequence |mtf| or promotes if it's already there.
|
||||
void InsertOrPromote(uint32_t mtf, const Val& value) {
|
||||
void InsertOrPromote(uint64_t mtf, const Val& value) {
|
||||
if (!Insert(mtf, value)) {
|
||||
GetMtf(mtf).Promote(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns if |mtf| sequence has |value|.
|
||||
bool HasValue(uint32_t mtf, const Val& value) {
|
||||
bool HasValue(uint64_t mtf, const Val& value) {
|
||||
return GetMtf(mtf).HasValue(value);
|
||||
}
|
||||
|
||||
@ -403,7 +403,7 @@ class MultiMoveToFront {
|
||||
// Returns actual MoveToFront object corresponding to |handle|.
|
||||
// As multiple operations are often performed consecutively for the same
|
||||
// sequence, the last returned value is cached.
|
||||
MoveToFront<Val>& GetMtf(uint32_t handle) {
|
||||
MoveToFront<Val>& GetMtf(uint64_t handle) {
|
||||
if (!cached_mtf_ || cached_handle_ != handle) {
|
||||
cached_handle_ = handle;
|
||||
cached_mtf_ = &mtfs_[handle];
|
||||
@ -413,13 +413,13 @@ class MultiMoveToFront {
|
||||
}
|
||||
|
||||
// Container holding MoveToFront objects. Map key is sequence handle.
|
||||
std::map<uint32_t, MoveToFront<Val>> mtfs_;
|
||||
std::map<uint64_t, MoveToFront<Val>> mtfs_;
|
||||
|
||||
// Container mapping value to sequences which contain that value.
|
||||
std::unordered_map<Val, std::set<uint32_t>> val_to_mtfs_;
|
||||
std::unordered_map<Val, std::set<uint64_t>> val_to_mtfs_;
|
||||
|
||||
// Cache for the last accessed sequence.
|
||||
uint32_t cached_handle_ = 0;
|
||||
uint64_t cached_handle_ = 0;
|
||||
MoveToFront<Val>* cached_mtf_ = nullptr;
|
||||
};
|
||||
|
||||
@ -471,7 +471,15 @@ bool MoveToFront<Val>::RankFromValue(const Val& value, uint32_t* rank) {
|
||||
}
|
||||
|
||||
const uint32_t old_size = GetSize();
|
||||
(void)old_size;
|
||||
if (old_size == 1) {
|
||||
if (ValueOf(root_) == value) {
|
||||
*rank = 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const auto it = value_to_node_.find(value);
|
||||
if (it == value_to_node_.end()) {
|
||||
return false;
|
||||
@ -524,7 +532,9 @@ bool MoveToFront<Val>::Promote(const Val& value) {
|
||||
}
|
||||
|
||||
const uint32_t old_size = GetSize();
|
||||
(void)old_size;
|
||||
if (old_size == 1)
|
||||
return ValueOf(root_) == value;
|
||||
|
||||
const auto it = value_to_node_.find(value);
|
||||
if (it == value_to_node_.end()) {
|
||||
return false;
|
||||
@ -561,6 +571,11 @@ bool MoveToFront<Val>::ValueFromRank(uint32_t rank, Val* value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (old_size == 1) {
|
||||
*value = ValueOf(root_);
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool update_timestamp = (rank != 1);
|
||||
|
||||
uint32_t node = root_;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "instruction.h"
|
||||
#include "message.h"
|
||||
#include "opcode.h"
|
||||
#include "operand.h"
|
||||
#include "spirv_validator_options.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "val/function.h"
|
||||
@ -3056,66 +3057,6 @@ bool idUsage::isValid(const spv_instruction_t* inst) {
|
||||
#undef TODO
|
||||
#undef CASE
|
||||
}
|
||||
// This function takes the opcode of an instruction and returns
|
||||
// a function object that will return true if the index
|
||||
// of the operand can be forwarad declared. This function will
|
||||
// used in the SSA validation stage of the pipeline
|
||||
function<bool(unsigned)> getCanBeForwardDeclaredFunction(SpvOp opcode) {
|
||||
function<bool(unsigned index)> out;
|
||||
switch (opcode) {
|
||||
case SpvOpExecutionMode:
|
||||
case SpvOpEntryPoint:
|
||||
case SpvOpName:
|
||||
case SpvOpMemberName:
|
||||
case SpvOpSelectionMerge:
|
||||
case SpvOpDecorate:
|
||||
case SpvOpMemberDecorate:
|
||||
case SpvOpTypeStruct:
|
||||
case SpvOpBranch:
|
||||
case SpvOpLoopMerge:
|
||||
out = [](unsigned) { return true; };
|
||||
break;
|
||||
case SpvOpGroupDecorate:
|
||||
case SpvOpGroupMemberDecorate:
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch:
|
||||
out = [](unsigned index) { return index != 0; };
|
||||
break;
|
||||
|
||||
case SpvOpFunctionCall:
|
||||
// The Function parameter.
|
||||
out = [](unsigned index) { return index == 2; };
|
||||
break;
|
||||
|
||||
case SpvOpPhi:
|
||||
out = [](unsigned index) { return index > 1; };
|
||||
break;
|
||||
|
||||
case SpvOpEnqueueKernel:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 8; };
|
||||
break;
|
||||
|
||||
case SpvOpGetKernelNDrangeSubGroupCount:
|
||||
case SpvOpGetKernelNDrangeMaxSubGroupSize:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 3; };
|
||||
break;
|
||||
|
||||
case SpvOpGetKernelWorkGroupSize:
|
||||
case SpvOpGetKernelPreferredWorkGroupSizeMultiple:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 2; };
|
||||
break;
|
||||
case SpvOpTypeForwardPointer:
|
||||
out = [](unsigned index) { return index == 0; };
|
||||
break;
|
||||
default:
|
||||
out = [](unsigned) { return false; };
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
namespace libspirv {
|
||||
@ -3214,7 +3155,7 @@ spv_result_t CheckIdDefinitionDominateUse(const ValidationState_t& _) {
|
||||
spv_result_t IdPass(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
auto can_have_forward_declared_ids =
|
||||
getCanBeForwardDeclaredFunction(static_cast<SpvOp>(inst->opcode));
|
||||
spvOperandCanBeForwardDeclaredFunction(static_cast<SpvOp>(inst->opcode));
|
||||
|
||||
// Keep track of a result id defined by this instruction. 0 means it
|
||||
// does not define an id.
|
||||
|
@ -165,6 +165,92 @@ void TestEncodeDecode(const std::string& original_text) {
|
||||
spvMarkvBinaryDestroy(markv_binary);
|
||||
}
|
||||
|
||||
void TestEncodeDecodeShaderMainBody(const std::string& body) {
|
||||
const std::string prefix =
|
||||
R"(
|
||||
OpCapability Shader
|
||||
OpCapability Int64
|
||||
OpCapability Float64
|
||||
%ext_inst = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main"
|
||||
%void = OpTypeVoid
|
||||
%func = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
%f32 = OpTypeFloat 32
|
||||
%u32 = OpTypeInt 32 0
|
||||
%s32 = OpTypeInt 32 1
|
||||
%f64 = OpTypeFloat 64
|
||||
%u64 = OpTypeInt 64 0
|
||||
%s64 = OpTypeInt 64 1
|
||||
%boolvec2 = OpTypeVector %bool 2
|
||||
%s32vec2 = OpTypeVector %s32 2
|
||||
%u32vec2 = OpTypeVector %u32 2
|
||||
%f32vec2 = OpTypeVector %f32 2
|
||||
%f64vec2 = OpTypeVector %f64 2
|
||||
%boolvec3 = OpTypeVector %bool 3
|
||||
%u32vec3 = OpTypeVector %u32 3
|
||||
%s32vec3 = OpTypeVector %s32 3
|
||||
%f32vec3 = OpTypeVector %f32 3
|
||||
%f64vec3 = OpTypeVector %f64 3
|
||||
%boolvec4 = OpTypeVector %bool 4
|
||||
%u32vec4 = OpTypeVector %u32 4
|
||||
%s32vec4 = OpTypeVector %s32 4
|
||||
%f32vec4 = OpTypeVector %f32 4
|
||||
%f64vec4 = OpTypeVector %f64 4
|
||||
|
||||
%f32_0 = OpConstant %f32 0
|
||||
%f32_1 = OpConstant %f32 1
|
||||
%f32_2 = OpConstant %f32 2
|
||||
%f32_3 = OpConstant %f32 3
|
||||
%f32_4 = OpConstant %f32 4
|
||||
%f32_pi = OpConstant %f32 3.14159
|
||||
|
||||
%s32_0 = OpConstant %s32 0
|
||||
%s32_1 = OpConstant %s32 1
|
||||
%s32_2 = OpConstant %s32 2
|
||||
%s32_3 = OpConstant %s32 3
|
||||
%s32_4 = OpConstant %s32 4
|
||||
%s32_m1 = OpConstant %s32 -1
|
||||
|
||||
%u32_0 = OpConstant %u32 0
|
||||
%u32_1 = OpConstant %u32 1
|
||||
%u32_2 = OpConstant %u32 2
|
||||
%u32_3 = OpConstant %u32 3
|
||||
%u32_4 = OpConstant %u32 4
|
||||
|
||||
%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
|
||||
%u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
|
||||
%u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
|
||||
%u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
|
||||
%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
|
||||
%u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
|
||||
|
||||
%s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1
|
||||
%s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2
|
||||
%s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2
|
||||
%s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3
|
||||
%s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3
|
||||
%s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4
|
||||
|
||||
%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
|
||||
%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
|
||||
%f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
|
||||
%f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
|
||||
%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
|
||||
%f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
|
||||
|
||||
%main = OpFunction %void None %func
|
||||
%main_entry = OpLabel)";
|
||||
|
||||
const std::string suffix =
|
||||
R"(
|
||||
OpReturn
|
||||
OpFunctionEnd)";
|
||||
|
||||
TestEncodeDecode(prefix + body + suffix);
|
||||
}
|
||||
|
||||
TEST(Markv, U32Literal) {
|
||||
TestEncodeDecode(R"(
|
||||
OpCapability Shader
|
||||
@ -322,6 +408,39 @@ OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, WithMultipleFunctions) {
|
||||
TestEncodeDecode(R"(
|
||||
OpCapability Addresses
|
||||
OpCapability Kernel
|
||||
OpCapability GenericPointer
|
||||
OpCapability Linkage
|
||||
OpMemoryModel Physical32 OpenCL
|
||||
%f32 = OpTypeFloat 32
|
||||
%one = OpConstant %f32 1
|
||||
%void = OpTypeVoid
|
||||
%void_func = OpTypeFunction %void
|
||||
%f32_func = OpTypeFunction %f32 %f32
|
||||
%sqr_plus_one = OpFunction %f32 None %f32_func
|
||||
%x = OpFunctionParameter %f32
|
||||
%100 = OpLabel
|
||||
%x2 = OpFMul %f32 %x %x
|
||||
%x2p1 = OpFunctionCall %f32 %plus_one %x2
|
||||
OpReturnValue %x2p1
|
||||
OpFunctionEnd
|
||||
%plus_one = OpFunction %f32 None %f32_func
|
||||
%y = OpFunctionParameter %f32
|
||||
%200 = OpLabel
|
||||
%yp1 = OpFAdd %f32 %y %one
|
||||
OpReturnValue %yp1
|
||||
OpFunctionEnd
|
||||
%main = OpFunction %void None %void_func
|
||||
%entry_main = OpLabel
|
||||
%1p1 = OpFunctionCall %f32 %sqr_plus_one %one
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, ForwardDeclaredId) {
|
||||
TestEncodeDecode(R"(
|
||||
OpCapability Addresses
|
||||
@ -430,4 +549,304 @@ OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, F32Mul) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%val1 = OpFMul %f32 %f32_0 %f32_1
|
||||
%val2 = OpFMul %f32 %f32_2 %f32_0
|
||||
%val3 = OpFMul %f32 %f32_pi %f32_2
|
||||
%val4 = OpFMul %f32 %f32_1 %f32_1
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, U32Mul) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%val1 = OpIMul %u32 %u32_0 %u32_1
|
||||
%val2 = OpIMul %u32 %u32_2 %u32_0
|
||||
%val3 = OpIMul %u32 %u32_3 %u32_2
|
||||
%val4 = OpIMul %u32 %u32_1 %u32_1
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, S32Mul) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%val1 = OpIMul %s32 %s32_0 %s32_1
|
||||
%val2 = OpIMul %s32 %s32_2 %s32_0
|
||||
%val3 = OpIMul %s32 %s32_m1 %s32_2
|
||||
%val4 = OpIMul %s32 %s32_1 %s32_1
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, F32Add) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%val1 = OpFAdd %f32 %f32_0 %f32_1
|
||||
%val2 = OpFAdd %f32 %f32_2 %f32_0
|
||||
%val3 = OpFAdd %f32 %f32_pi %f32_2
|
||||
%val4 = OpFAdd %f32 %f32_1 %f32_1
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, U32Add) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%val1 = OpIAdd %u32 %u32_0 %u32_1
|
||||
%val2 = OpIAdd %u32 %u32_2 %u32_0
|
||||
%val3 = OpIAdd %u32 %u32_3 %u32_2
|
||||
%val4 = OpIAdd %u32 %u32_1 %u32_1
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, S32Add) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%val1 = OpIAdd %s32 %s32_0 %s32_1
|
||||
%val2 = OpIAdd %s32 %s32_2 %s32_0
|
||||
%val3 = OpIAdd %s32 %s32_m1 %s32_2
|
||||
%val4 = OpIAdd %s32 %s32_1 %s32_1
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, F32Dot) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%dot2_1 = OpDot %f32 %f32vec2_01 %f32vec2_12
|
||||
%dot2_2 = OpDot %f32 %f32vec2_01 %f32vec2_01
|
||||
%dot2_3 = OpDot %f32 %f32vec2_12 %f32vec2_12
|
||||
%dot3_1 = OpDot %f32 %f32vec3_012 %f32vec3_123
|
||||
%dot3_2 = OpDot %f32 %f32vec3_012 %f32vec3_012
|
||||
%dot3_3 = OpDot %f32 %f32vec3_123 %f32vec3_123
|
||||
%dot4_1 = OpDot %f32 %f32vec4_0123 %f32vec4_1234
|
||||
%dot4_2 = OpDot %f32 %f32vec4_0123 %f32vec4_0123
|
||||
%dot4_3 = OpDot %f32 %f32vec4_1234 %f32vec4_1234
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, F32VectorCompositeConstruct) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%cc1 = OpCompositeConstruct %f32vec4 %f32vec2_01 %f32vec2_12
|
||||
%cc2 = OpCompositeConstruct %f32vec3 %f32vec2_01 %f32_2
|
||||
%cc3 = OpCompositeConstruct %f32vec2 %f32_1 %f32_2
|
||||
%cc4 = OpCompositeConstruct %f32vec4 %f32_1 %f32_2 %cc3
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, U32VectorCompositeConstruct) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%cc1 = OpCompositeConstruct %u32vec4 %u32vec2_01 %u32vec2_12
|
||||
%cc2 = OpCompositeConstruct %u32vec3 %u32vec2_01 %u32_2
|
||||
%cc3 = OpCompositeConstruct %u32vec2 %u32_1 %u32_2
|
||||
%cc4 = OpCompositeConstruct %u32vec4 %u32_1 %u32_2 %cc3
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, S32VectorCompositeConstruct) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%cc1 = OpCompositeConstruct %u32vec4 %u32vec2_01 %u32vec2_12
|
||||
%cc2 = OpCompositeConstruct %u32vec3 %u32vec2_01 %u32_2
|
||||
%cc3 = OpCompositeConstruct %u32vec2 %u32_1 %u32_2
|
||||
%cc4 = OpCompositeConstruct %u32vec4 %u32_1 %u32_2 %cc3
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, F32VectorCompositeExtract) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%f32vec4_3210 = OpCompositeConstruct %f32vec4 %f32_3 %f32_2 %f32_1 %f32_0
|
||||
%f32vec3_013 = OpCompositeExtract %f32vec3 %f32vec4_0123 0 1 3
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, F32VectorComparison) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%f32vec4_3210 = OpCompositeConstruct %f32vec4 %f32_3 %f32_2 %f32_1 %f32_0
|
||||
%c1 = OpFOrdEqual %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
%c2 = OpFUnordEqual %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
%c3 = OpFOrdNotEqual %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
%c4 = OpFUnordNotEqual %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
%c5 = OpFOrdLessThan %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
%c6 = OpFUnordLessThan %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
%c7 = OpFOrdGreaterThan %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
%c8 = OpFUnordGreaterThan %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
%c9 = OpFOrdLessThanEqual %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
%c10 = OpFUnordLessThanEqual %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
%c11 = OpFOrdGreaterThanEqual %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
%c12 = OpFUnordGreaterThanEqual %boolvec4 %f32vec4_0123 %f32vec4_3210
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, VectorShuffle) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%f32vec4_3210 = OpCompositeConstruct %f32vec4 %f32_3 %f32_2 %f32_1 %f32_0
|
||||
%sh1 = OpVectorShuffle %f32vec2 %f32vec4_0123 %f32vec4_3210 3 6
|
||||
%sh2 = OpVectorShuffle %f32vec3 %f32vec2_01 %f32vec4_3210 0 3 4
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, VectorTimesScalar) {
|
||||
TestEncodeDecodeShaderMainBody(R"(
|
||||
%f32vec4_3210 = OpCompositeConstruct %f32vec4 %f32_3 %f32_2 %f32_1 %f32_0
|
||||
%res1 = OpVectorTimesScalar %f32vec4 %f32vec4_0123 %f32_2
|
||||
%res2 = OpVectorTimesScalar %f32vec4 %f32vec4_3210 %f32_2
|
||||
%res3 = OpVectorTimesScalar %u32vec3 %u32vec3_012 %u32_2
|
||||
%res4 = OpVectorTimesScalar %s32vec2 %s32vec2_01 %s32_2
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, SpirvSpecSample) {
|
||||
TestEncodeDecode(R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main" %31 %33 %42 %57
|
||||
OpExecutionMode %4 OriginLowerLeft
|
||||
|
||||
; Debug information
|
||||
OpSource GLSL 450
|
||||
OpName %4 "main"
|
||||
OpName %9 "scale"
|
||||
OpName %17 "S"
|
||||
OpMemberName %17 0 "b"
|
||||
OpMemberName %17 1 "v"
|
||||
OpMemberName %17 2 "i"
|
||||
OpName %18 "blockName"
|
||||
OpMemberName %18 0 "s"
|
||||
OpMemberName %18 1 "cond"
|
||||
OpName %20 ""
|
||||
OpName %31 "color"
|
||||
OpName %33 "color1"
|
||||
OpName %42 "color2"
|
||||
OpName %48 "i"
|
||||
OpName %57 "multiplier"
|
||||
|
||||
; Annotations (non-debug)
|
||||
OpDecorate %15 ArrayStride 16
|
||||
OpMemberDecorate %17 0 Offset 0
|
||||
OpMemberDecorate %17 1 Offset 16
|
||||
OpMemberDecorate %17 2 Offset 96
|
||||
OpMemberDecorate %18 0 Offset 0
|
||||
OpMemberDecorate %18 1 Offset 112
|
||||
OpDecorate %18 Block
|
||||
OpDecorate %20 DescriptorSet 0
|
||||
OpDecorate %42 NoPerspective
|
||||
|
||||
; All types, variables, and constants
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2 ; void ()
|
||||
%6 = OpTypeFloat 32 ; 32-bit float
|
||||
%7 = OpTypeVector %6 4 ; vec4
|
||||
%8 = OpTypePointer Function %7 ; function-local vec4*
|
||||
%10 = OpConstant %6 1
|
||||
%11 = OpConstant %6 2
|
||||
%12 = OpConstantComposite %7 %10 %10 %11 %10 ; vec4(1.0, 1.0, 2.0, 1.0)
|
||||
%13 = OpTypeInt 32 0 ; 32-bit int, sign-less
|
||||
%14 = OpConstant %13 5
|
||||
%15 = OpTypeArray %7 %14
|
||||
%16 = OpTypeInt 32 1
|
||||
%17 = OpTypeStruct %13 %15 %16
|
||||
%18 = OpTypeStruct %17 %13
|
||||
%19 = OpTypePointer Uniform %18
|
||||
%20 = OpVariable %19 Uniform
|
||||
%21 = OpConstant %16 1
|
||||
%22 = OpTypePointer Uniform %13
|
||||
%25 = OpTypeBool
|
||||
%26 = OpConstant %13 0
|
||||
%30 = OpTypePointer Output %7
|
||||
%31 = OpVariable %30 Output
|
||||
%32 = OpTypePointer Input %7
|
||||
%33 = OpVariable %32 Input
|
||||
%35 = OpConstant %16 0
|
||||
%36 = OpConstant %16 2
|
||||
%37 = OpTypePointer Uniform %7
|
||||
%42 = OpVariable %32 Input
|
||||
%47 = OpTypePointer Function %16
|
||||
%55 = OpConstant %16 4
|
||||
%57 = OpVariable %32 Input
|
||||
|
||||
; All functions
|
||||
%4 = OpFunction %2 None %3 ; main()
|
||||
%5 = OpLabel
|
||||
%9 = OpVariable %8 Function
|
||||
%48 = OpVariable %47 Function
|
||||
OpStore %9 %12
|
||||
%23 = OpAccessChain %22 %20 %21 ; location of cond
|
||||
%24 = OpLoad %13 %23 ; load 32-bit int from cond
|
||||
%27 = OpINotEqual %25 %24 %26 ; convert to bool
|
||||
OpSelectionMerge %29 None ; structured if
|
||||
OpBranchConditional %27 %28 %41 ; if cond
|
||||
%28 = OpLabel ; then
|
||||
%34 = OpLoad %7 %33
|
||||
%38 = OpAccessChain %37 %20 %35 %21 %36 ; s.v[2]
|
||||
%39 = OpLoad %7 %38
|
||||
%40 = OpFAdd %7 %34 %39
|
||||
OpStore %31 %40
|
||||
OpBranch %29
|
||||
%41 = OpLabel ; else
|
||||
%43 = OpLoad %7 %42
|
||||
%44 = OpExtInst %7 %1 Sqrt %43 ; extended instruction sqrt
|
||||
%45 = OpLoad %7 %9
|
||||
%46 = OpFMul %7 %44 %45
|
||||
OpStore %31 %46
|
||||
OpBranch %29
|
||||
%29 = OpLabel ; endif
|
||||
OpStore %48 %35
|
||||
OpBranch %49
|
||||
%49 = OpLabel
|
||||
OpLoopMerge %51 %52 None ; structured loop
|
||||
OpBranch %53
|
||||
%53 = OpLabel
|
||||
%54 = OpLoad %16 %48
|
||||
%56 = OpSLessThan %25 %54 %55 ; i < 4 ?
|
||||
OpBranchConditional %56 %50 %51 ; body or break
|
||||
%50 = OpLabel ; body
|
||||
%58 = OpLoad %7 %57
|
||||
%59 = OpLoad %7 %31
|
||||
%60 = OpFMul %7 %59 %58
|
||||
OpStore %31 %60
|
||||
OpBranch %52
|
||||
%52 = OpLabel ; continue target
|
||||
%61 = OpLoad %16 %48
|
||||
%62 = OpIAdd %16 %61 %21 ; ++i
|
||||
OpStore %48 %62
|
||||
OpBranch %49 ; loop back
|
||||
%51 = OpLabel ; loop merge point
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(Markv, SampleFromDeadBranchEliminationTest) {
|
||||
TestEncodeDecode(R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %gl_FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 140
|
||||
OpName %main "main"
|
||||
OpName %gl_FragColor "gl_FragColor"
|
||||
%void = OpTypeVoid
|
||||
%5 = OpTypeFunction %void
|
||||
%bool = OpTypeBool
|
||||
%true = OpConstantTrue %bool
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%float_0 = OpConstant %float 0
|
||||
%12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
|
||||
%float_1 = OpConstant %float 1
|
||||
%14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%gl_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%main = OpFunction %void None %5
|
||||
%17 = OpLabel
|
||||
OpSelectionMerge %18 None
|
||||
OpBranchConditional %true %19 %20
|
||||
%19 = OpLabel
|
||||
OpBranch %18
|
||||
%20 = OpLabel
|
||||
OpBranch %18
|
||||
%18 = OpLabel
|
||||
%21 = OpPhi %v4float %12 %19 %14 %20
|
||||
OpStore %gl_FragColor %21
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -23,14 +23,26 @@
|
||||
|
||||
#include "spirv/1.2/spirv.h"
|
||||
#include "source/enum_string_mapping.h"
|
||||
#include "source/comp/markv_autogen.h"
|
||||
#include "source/opcode.h"
|
||||
#include "source/operand.h"
|
||||
#include "source/spirv_constant.h"
|
||||
#include "source/util/huffman_codec.h"
|
||||
|
||||
using libspirv::SpirvStats;
|
||||
using spvutils::HuffmanCodec;
|
||||
|
||||
namespace {
|
||||
|
||||
// Signals that the value is not in the coding scheme and a fallback method
|
||||
// needs to be used.
|
||||
const uint64_t kMarkvNoneOfTheAbove = GetMarkvNonOfTheAbove();
|
||||
|
||||
inline uint32_t CombineOpcodeAndNumOperands(uint32_t opcode,
|
||||
uint32_t num_operands) {
|
||||
return opcode | (num_operands << 16);
|
||||
}
|
||||
|
||||
// Returns all SPIR-V v1.2 opcodes.
|
||||
std::vector<uint32_t> GetAllOpcodes() {
|
||||
return std::vector<uint32_t>({
|
||||
@ -599,23 +611,30 @@ void StatsAnalyzer::WriteCodegenOpcodeAndNumOperandsHist(std::ostream& out) {
|
||||
total += kv.second;
|
||||
}
|
||||
|
||||
uint32_t left_out = 0;
|
||||
|
||||
for (const auto& kv : stats_.opcode_and_num_operands_hist) {
|
||||
const uint32_t count = kv.second;
|
||||
const double kFrequentEnoughToAnalyze = 0.001;
|
||||
if (double(count) / double(total) < kFrequentEnoughToAnalyze) continue;
|
||||
const uint32_t opcode_and_num_operands = kv.first;
|
||||
const uint32_t opcode = opcode_and_num_operands & 0xFFFF;
|
||||
const uint32_t num_operands = opcode_and_num_operands >> 16;
|
||||
|
||||
if (opcode == SpvOpTypeStruct)
|
||||
if (opcode == SpvOpTypeStruct ||
|
||||
double(count) / double(total) < kFrequentEnoughToAnalyze) {
|
||||
left_out += count;
|
||||
continue;
|
||||
}
|
||||
|
||||
out << " { CombineOpcodeAndNumOperands(SpvOp"
|
||||
<< spvOpcodeString(SpvOp(opcode))
|
||||
<< ", " << num_operands << "), " << count << " },\n";
|
||||
}
|
||||
|
||||
out << " { kMarkvNoneOfTheAbove, " << 1 + int(total * 0.05) << " },\n";
|
||||
// Heuristic.
|
||||
const uint32_t none_of_the_above =
|
||||
std::max(1, int(left_out + total * 0.01));
|
||||
out << " { kMarkvNoneOfTheAbove, " << none_of_the_above << " },\n";
|
||||
out << " });\n}\n";
|
||||
}
|
||||
|
||||
@ -628,7 +647,7 @@ void StatsAnalyzer::WriteCodegenOpcodeAndNumOperandsMarkovHuffmanCodecs(
|
||||
|
||||
for (const auto& kv : stats_.opcode_and_num_operands_markov_hist) {
|
||||
const uint32_t prev_opcode = kv.first;
|
||||
const double kFrequentEnoughToAnalyze = 0.001;
|
||||
const double kFrequentEnoughToAnalyze = 0.01;
|
||||
if (opcode_freq_[prev_opcode] < kFrequentEnoughToAnalyze) continue;
|
||||
|
||||
const std::unordered_map<uint32_t, uint32_t>& hist = kv.second;
|
||||
@ -638,10 +657,9 @@ void StatsAnalyzer::WriteCodegenOpcodeAndNumOperandsMarkovHuffmanCodecs(
|
||||
total += pair.second;
|
||||
}
|
||||
|
||||
out << " {\n";
|
||||
out << " std::unique_ptr<HuffmanCodec<uint64_t>> "
|
||||
<< "codec(new HuffmanCodec<uint64_t>({\n";
|
||||
uint32_t left_out = 0;
|
||||
|
||||
std::map<uint64_t, uint32_t> processed_hist;
|
||||
for (const auto& pair : hist) {
|
||||
const uint32_t opcode_and_num_operands = pair.first;
|
||||
const uint32_t opcode = opcode_and_num_operands & 0xFFFF;
|
||||
@ -654,17 +672,25 @@ void StatsAnalyzer::WriteCodegenOpcodeAndNumOperandsMarkovHuffmanCodecs(
|
||||
const double posterior_freq = double(count) / double(total);
|
||||
|
||||
if (opcode_freq_[opcode] < kFrequentEnoughToAnalyze &&
|
||||
posterior_freq < kFrequentEnoughToAnalyze) continue;
|
||||
|
||||
total += count;
|
||||
out << " { CombineOpcodeAndNumOperands(SpvOp"
|
||||
<< spvOpcodeString(SpvOp(opcode))
|
||||
<< ", " << num_operands << "), " << count << " },\n";
|
||||
posterior_freq < kFrequentEnoughToAnalyze) {
|
||||
left_out += count;
|
||||
continue;
|
||||
}
|
||||
processed_hist.emplace(CombineOpcodeAndNumOperands(opcode, num_operands),
|
||||
count);
|
||||
}
|
||||
|
||||
out << " { kMarkvNoneOfTheAbove, " << 1 + int(total * 0.05) << " },\n";
|
||||
// Heuristic.
|
||||
processed_hist.emplace(kMarkvNoneOfTheAbove,
|
||||
std::max(1, int(left_out + total * 0.01)));
|
||||
|
||||
out << " }));\n" << std::endl;
|
||||
HuffmanCodec<uint64_t> codec(processed_hist);
|
||||
|
||||
out << " {\n";
|
||||
out << " std::unique_ptr<HuffmanCodec<uint64_t>> "
|
||||
<< "codec(new HuffmanCodec<uint64_t>";
|
||||
out << codec.SerializeToText(4);
|
||||
out << ");\n" << std::endl;
|
||||
out << " codecs.emplace(SpvOp" << GetOpcodeString(prev_opcode)
|
||||
<< ", std::move(codec));\n";
|
||||
out << " }\n\n";
|
||||
@ -695,22 +721,31 @@ void StatsAnalyzer::WriteCodegenLiteralStringHuffmanCodecs(std::ostream& out) {
|
||||
total += pair.second;
|
||||
}
|
||||
|
||||
out << " {\n";
|
||||
out << " std::unique_ptr<HuffmanCodec<std::string>> "
|
||||
<< "codec(new HuffmanCodec<std::string>({\n";
|
||||
uint32_t left_out = 0;
|
||||
|
||||
std::map<std::string, uint32_t> processed_hist;
|
||||
for (const auto& pair : hist) {
|
||||
const uint32_t count = pair.second;
|
||||
const double freq = double(count) / double(total);
|
||||
const double kStringFrequentEnoughToAnalyze = 0.001;
|
||||
if (freq < kStringFrequentEnoughToAnalyze) continue;
|
||||
out << " { std::string(\"" << pair.first << "\"), " << count
|
||||
<< " },\n";
|
||||
if (freq < kStringFrequentEnoughToAnalyze) {
|
||||
left_out += count;
|
||||
continue;
|
||||
}
|
||||
processed_hist.emplace(pair.first, count);
|
||||
}
|
||||
|
||||
out << " { std::string(\"kMarkvNoneOfTheAbove\"), "
|
||||
<< 1 + int(total * 0.05) << " },\n";
|
||||
// Heuristic.
|
||||
processed_hist.emplace("kMarkvNoneOfTheAbove",
|
||||
std::max(1, int(left_out + total * 0.01)));
|
||||
|
||||
out << " }));\n" << std::endl;
|
||||
HuffmanCodec<std::string> codec(processed_hist);
|
||||
|
||||
out << " {\n";
|
||||
out << " std::unique_ptr<HuffmanCodec<std::string>> "
|
||||
<< "codec(new HuffmanCodec<std::string>";
|
||||
out << codec.SerializeToText(4);
|
||||
out << ");\n" << std::endl;
|
||||
out << " codecs.emplace(SpvOp" << spvOpcodeString(SpvOp(opcode))
|
||||
<< ", std::move(codec));\n";
|
||||
out << " }\n\n";
|
||||
@ -741,21 +776,32 @@ void StatsAnalyzer::WriteCodegenNonIdWordHuffmanCodecs(std::ostream& out) {
|
||||
total += pair.second;
|
||||
}
|
||||
|
||||
out << " {\n";
|
||||
out << " std::unique_ptr<HuffmanCodec<uint64_t>> "
|
||||
<< "codec(new HuffmanCodec<uint64_t>({\n";
|
||||
uint32_t left_out = 0;
|
||||
|
||||
std::map<uint64_t, uint32_t> processed_hist;
|
||||
for (const auto& pair : hist) {
|
||||
const uint32_t word = pair.first;
|
||||
const uint32_t count = pair.second;
|
||||
const double freq = double(count) / double(total);
|
||||
const double kWordFrequentEnoughToAnalyze = 0.001;
|
||||
if (freq < kWordFrequentEnoughToAnalyze) continue;
|
||||
out << " { " << word << ", " << count << " },\n";
|
||||
const double kWordFrequentEnoughToAnalyze = 0.01;
|
||||
if (freq < kWordFrequentEnoughToAnalyze) {
|
||||
left_out += count;
|
||||
continue;
|
||||
}
|
||||
processed_hist.emplace(word, count);
|
||||
}
|
||||
|
||||
out << " { kMarkvNoneOfTheAbove, " << 1 + int(total * 0.05) << " },\n";
|
||||
// Heuristic.
|
||||
processed_hist.emplace(kMarkvNoneOfTheAbove,
|
||||
std::max(1, int(left_out + total * 0.01)));
|
||||
|
||||
out << " }));\n" << std::endl;
|
||||
HuffmanCodec<uint64_t> codec(processed_hist);
|
||||
|
||||
out << " {\n";
|
||||
out << " std::unique_ptr<HuffmanCodec<uint64_t>> "
|
||||
<< "codec(new HuffmanCodec<uint64_t>";
|
||||
out << codec.SerializeToText(4);
|
||||
out << ");\n" << std::endl;
|
||||
out << " codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOp"
|
||||
<< spvOpcodeString(SpvOp(opcode))
|
||||
<< ", " << index << "), std::move(codec));\n";
|
||||
@ -778,31 +824,43 @@ void StatsAnalyzer::WriteCodegenIdDescriptorHuffmanCodecs(
|
||||
const uint32_t opcode = opcode_and_index.first;
|
||||
const uint32_t index = opcode_and_index.second;
|
||||
|
||||
const double kOpcodeFrequentEnoughToAnalyze = 0.001;
|
||||
const double kOpcodeFrequentEnoughToAnalyze = 0.01;
|
||||
if (opcode_freq_[opcode] < kOpcodeFrequentEnoughToAnalyze) continue;
|
||||
|
||||
const std::map<uint32_t, uint32_t>& hist = kv.second;
|
||||
|
||||
|
||||
uint32_t total = 0;
|
||||
for (const auto& pair : hist) {
|
||||
total += pair.second;
|
||||
}
|
||||
|
||||
out << " {\n";
|
||||
out << " std::unique_ptr<HuffmanCodec<uint64_t>> "
|
||||
<< "codec(new HuffmanCodec<uint64_t>({\n";
|
||||
uint32_t left_out = 0;
|
||||
|
||||
std::map<uint64_t, uint32_t> processed_hist;
|
||||
for (const auto& pair : hist) {
|
||||
const uint32_t descriptor = pair.first;
|
||||
const uint32_t count = pair.second;
|
||||
const double freq = double(count) / double(total);
|
||||
const double kDescriptorFrequentEnoughToAnalyze = 0.005;
|
||||
if (freq < kDescriptorFrequentEnoughToAnalyze) continue;
|
||||
out << " { " << descriptor << ", " << count << " },\n";
|
||||
const double kDescriptorFrequentEnoughToAnalyze = 0.01;
|
||||
if (freq < kDescriptorFrequentEnoughToAnalyze) {
|
||||
left_out += count;
|
||||
continue;
|
||||
}
|
||||
processed_hist.emplace(descriptor, count);
|
||||
}
|
||||
|
||||
out << " { kMarkvNoneOfTheAbove, " << 1 + int(total * 0.05) << " },\n";
|
||||
// Heuristic.
|
||||
processed_hist.emplace(kMarkvNoneOfTheAbove,
|
||||
std::max(1, int(left_out + total * 0.01)));
|
||||
|
||||
out << " }));\n" << std::endl;
|
||||
HuffmanCodec<uint64_t> codec(processed_hist);
|
||||
|
||||
out << " {\n";
|
||||
out << " std::unique_ptr<HuffmanCodec<uint64_t>> "
|
||||
<< "codec(new HuffmanCodec<uint64_t>";
|
||||
out << codec.SerializeToText(4);
|
||||
out << ");\n" << std::endl;
|
||||
out << " codecs.emplace(std::pair<uint32_t, uint32_t>(SpvOp"
|
||||
<< spvOpcodeString(SpvOp(opcode))
|
||||
<< ", " << index << "), std::move(codec));\n";
|
||||
|
Loading…
Reference in New Issue
Block a user