mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-25 01:01:04 +00:00
Handle undef literal value in vector shuffle
Fixes #1731 * Updated folding rules related to vector shuffle to account for the undef literal value: * FoldVectorShuffleFeedingShuffle * FoldVectorShuffleFeedingExtract * FoldVectorShuffleWithConstants * These rules would commit memory violations due to treating the undef literal value as an accessible composite component
This commit is contained in:
parent
effafedcee
commit
b49f76fd62
@ -95,9 +95,13 @@ ConstantFoldingRule FoldVectorShuffleWithConstants() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> ids;
|
std::vector<uint32_t> ids;
|
||||||
|
const uint32_t undef_literal_value = 0xffffffff;
|
||||||
for (uint32_t i = 2; i < inst->NumInOperands(); ++i) {
|
for (uint32_t i = 2; i < inst->NumInOperands(); ++i) {
|
||||||
uint32_t index = inst->GetSingleWordInOperand(i);
|
uint32_t index = inst->GetSingleWordInOperand(i);
|
||||||
if (index < c1_components.size()) {
|
if (index == undef_literal_value) {
|
||||||
|
// Don't fold shuffle with undef literal value.
|
||||||
|
return nullptr;
|
||||||
|
} else if (index < c1_components.size()) {
|
||||||
Instruction* member_inst =
|
Instruction* member_inst =
|
||||||
const_mgr->GetDefiningInstruction(c1_components[index]);
|
const_mgr->GetDefiningInstruction(c1_components[index]);
|
||||||
ids.push_back(member_inst->result_id());
|
ids.push_back(member_inst->result_id());
|
||||||
|
@ -1502,6 +1502,14 @@ FoldingRule VectorShuffleFeedingExtract() {
|
|||||||
uint32_t new_index =
|
uint32_t new_index =
|
||||||
cinst->GetSingleWordInOperand(2 + inst->GetSingleWordInOperand(1));
|
cinst->GetSingleWordInOperand(2 + inst->GetSingleWordInOperand(1));
|
||||||
|
|
||||||
|
// Extracting an undefined value so fold this extract into an undef.
|
||||||
|
const uint32_t undef_literal_value = 0xffffffff;
|
||||||
|
if (new_index == undef_literal_value) {
|
||||||
|
inst->SetOpcode(SpvOpUndef);
|
||||||
|
inst->SetInOperands({});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the id of the of the vector the elemtent comes from, and update the
|
// Get the id of the of the vector the elemtent comes from, and update the
|
||||||
// index if needed.
|
// index if needed.
|
||||||
uint32_t new_vector = 0;
|
uint32_t new_vector = 0;
|
||||||
@ -2035,10 +2043,13 @@ FoldingRule VectorShuffleFeedingShuffle() {
|
|||||||
std::vector<Operand> new_operands;
|
std::vector<Operand> new_operands;
|
||||||
new_operands.resize(
|
new_operands.resize(
|
||||||
2, {SPV_OPERAND_TYPE_ID, {0}}); // Place holders for vector operands.
|
2, {SPV_OPERAND_TYPE_ID, {0}}); // Place holders for vector operands.
|
||||||
|
const uint32_t undef_literal = 0xffffffff;
|
||||||
for (uint32_t op = 2; op < inst->NumInOperands(); ++op) {
|
for (uint32_t op = 2; op < inst->NumInOperands(); ++op) {
|
||||||
uint32_t component_index = inst->GetSingleWordInOperand(op);
|
uint32_t component_index = inst->GetSingleWordInOperand(op);
|
||||||
|
|
||||||
if (feeder_is_op0 == (component_index < op0_length)) {
|
// Do not interpret the undefined value literal as coming from operand 1.
|
||||||
|
if (component_index != undef_literal &&
|
||||||
|
feeder_is_op0 == (component_index < op0_length)) {
|
||||||
// This component comes from the feeding_shuffle_inst. Update
|
// This component comes from the feeding_shuffle_inst. Update
|
||||||
// |component_index| to be the index into the operand of the feeder.
|
// |component_index| to be the index into the operand of the feeder.
|
||||||
|
|
||||||
|
@ -452,11 +452,12 @@ TEST_P(IntVectorInstructionFoldingTest, Case) {
|
|||||||
// Fold the instruction to test.
|
// Fold the instruction to test.
|
||||||
analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
|
analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
|
||||||
Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
|
Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
|
||||||
|
SpvOp original_opcode = inst->opcode();
|
||||||
bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
|
bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
|
||||||
|
|
||||||
// Make sure the instruction folded as expected.
|
// Make sure the instruction folded as expected.
|
||||||
EXPECT_TRUE(succeeded);
|
EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode);
|
||||||
if (inst != nullptr) {
|
if (succeeded && inst != nullptr) {
|
||||||
EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
|
EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
|
||||||
inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
|
inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
|
||||||
std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
|
std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
|
||||||
@ -496,7 +497,25 @@ INSTANTIATE_TEST_CASE_P(TestCase, IntVectorInstructionFoldingTest,
|
|||||||
"%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" +
|
"%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" +
|
||||||
"OpReturn\n" +
|
"OpReturn\n" +
|
||||||
"OpFunctionEnd",
|
"OpFunctionEnd",
|
||||||
2, {0,3})
|
2, {0,3}),
|
||||||
|
InstructionFoldingCase<std::vector<uint32_t>>(
|
||||||
|
Header() + "%main = OpFunction %void None %void_func\n" +
|
||||||
|
"%main_lab = OpLabel\n" +
|
||||||
|
"%n = OpVariable %_ptr_int Function\n" +
|
||||||
|
"%load = OpLoad %int %n\n" +
|
||||||
|
"%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 4294967295 3\n" +
|
||||||
|
"OpReturn\n" +
|
||||||
|
"OpFunctionEnd",
|
||||||
|
2, {0,0}),
|
||||||
|
InstructionFoldingCase<std::vector<uint32_t>>(
|
||||||
|
Header() + "%main = OpFunction %void None %void_func\n" +
|
||||||
|
"%main_lab = OpLabel\n" +
|
||||||
|
"%n = OpVariable %_ptr_int Function\n" +
|
||||||
|
"%load = OpLoad %int %n\n" +
|
||||||
|
"%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 4294967295 \n" +
|
||||||
|
"OpReturn\n" +
|
||||||
|
"OpFunctionEnd",
|
||||||
|
2, {0,0})
|
||||||
));
|
));
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@ -5512,7 +5531,22 @@ INSTANTIATE_TEST_CASE_P(CompositeExtractMatchingTest, MatchingInstructionFolding
|
|||||||
"%5 = OpCompositeExtract %double %4 3\n" +
|
"%5 = OpCompositeExtract %double %4 3\n" +
|
||||||
"OpReturn\n" +
|
"OpReturn\n" +
|
||||||
"OpFunctionEnd",
|
"OpFunctionEnd",
|
||||||
5, false)
|
5, false),
|
||||||
|
// Test case 7: Extracting the undefined literal value from a vector
|
||||||
|
// shuffle.
|
||||||
|
InstructionFoldingCase<bool>(
|
||||||
|
Header() +
|
||||||
|
"; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
|
||||||
|
"; CHECK: %4 = OpUndef [[int]]\n" +
|
||||||
|
"%main = OpFunction %void None %void_func\n" +
|
||||||
|
"%main_lab = OpLabel\n" +
|
||||||
|
"%n = OpVariable %_ptr_v4int Function\n" +
|
||||||
|
"%2 = OpLoad %v4int %n\n" +
|
||||||
|
"%3 = OpVectorShuffle %v2int %2 %2 2 4294967295\n" +
|
||||||
|
"%4 = OpCompositeExtract %int %3 1\n" +
|
||||||
|
"OpReturn\n" +
|
||||||
|
"OpFunctionEnd",
|
||||||
|
4, true)
|
||||||
));
|
));
|
||||||
|
|
||||||
INSTANTIATE_TEST_CASE_P(DotProductMatchingTest, MatchingInstructionFoldingTest,
|
INSTANTIATE_TEST_CASE_P(DotProductMatchingTest, MatchingInstructionFoldingTest,
|
||||||
@ -5898,6 +5932,27 @@ INSTANTIATE_TEST_CASE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoResu
|
|||||||
"%9 = OpVectorShuffle %v4double %7 %8 2 0 1 3\n" +
|
"%9 = OpVectorShuffle %v4double %7 %8 2 0 1 3\n" +
|
||||||
"OpReturn\n" +
|
"OpReturn\n" +
|
||||||
"OpFunctionEnd",
|
"OpFunctionEnd",
|
||||||
|
9, true),
|
||||||
|
// Test case 13: Shuffle with undef literal.
|
||||||
|
InstructionFoldingCase<bool>(
|
||||||
|
Header() +
|
||||||
|
"; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
|
||||||
|
"; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
|
||||||
|
"; CHECK: OpVectorShuffle\n" +
|
||||||
|
"; CHECK: OpVectorShuffle {{%\\w+}} %7 {{%\\w+}} 2 0 1 4294967295\n" +
|
||||||
|
"; CHECK: OpReturn\n" +
|
||||||
|
"%main = OpFunction %void None %void_func\n" +
|
||||||
|
"%main_lab = OpLabel\n" +
|
||||||
|
"%2 = OpVariable %_ptr_v4double Function\n" +
|
||||||
|
"%3 = OpVariable %_ptr_v4double Function\n" +
|
||||||
|
"%4 = OpVariable %_ptr_v4double Function\n" +
|
||||||
|
"%5 = OpLoad %v4double %2\n" +
|
||||||
|
"%6 = OpLoad %v4double %3\n" +
|
||||||
|
"%7 = OpLoad %v4double %4\n" +
|
||||||
|
"%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
|
||||||
|
"%9 = OpVectorShuffle %v4double %7 %8 2 0 1 4294967295\n" +
|
||||||
|
"OpReturn\n" +
|
||||||
|
"OpFunctionEnd",
|
||||||
9, true)
|
9, true)
|
||||||
));
|
));
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user