mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-26 13:20:05 +00:00
parent
3b7aebca45
commit
8496780f57
@ -627,28 +627,45 @@ bool IdIsAvailableBeforeInstruction(opt::IRContext* context,
|
||||
assert(context->get_instr_block(instruction) &&
|
||||
"|instruction| must be in a basic block");
|
||||
|
||||
auto defining_instruction = context->get_def_use_mgr()->GetDef(id);
|
||||
auto enclosing_function = context->get_instr_block(instruction)->GetParent();
|
||||
auto id_definition = context->get_def_use_mgr()->GetDef(id);
|
||||
auto function_enclosing_instruction =
|
||||
context->get_instr_block(instruction)->GetParent();
|
||||
// If the id a function parameter, it needs to be associated with the
|
||||
// function containing the instruction.
|
||||
if (defining_instruction->opcode() == SpvOpFunctionParameter) {
|
||||
return InstructionIsFunctionParameter(defining_instruction,
|
||||
enclosing_function);
|
||||
if (id_definition->opcode() == SpvOpFunctionParameter) {
|
||||
return InstructionIsFunctionParameter(id_definition,
|
||||
function_enclosing_instruction);
|
||||
}
|
||||
if (!context->get_instr_block(id)) {
|
||||
// The id is at global scope.
|
||||
return true;
|
||||
}
|
||||
if (defining_instruction == instruction) {
|
||||
if (id_definition == instruction) {
|
||||
// The instruction is not available right before its own definition.
|
||||
return false;
|
||||
}
|
||||
const auto* dominator_analysis =
|
||||
context->GetDominatorAnalysis(enclosing_function);
|
||||
return dominator_analysis->IsReachable(
|
||||
context->get_instr_block(instruction)) &&
|
||||
dominator_analysis->IsReachable(context->get_instr_block(id)) &&
|
||||
dominator_analysis->Dominates(defining_instruction, instruction);
|
||||
context->GetDominatorAnalysis(function_enclosing_instruction);
|
||||
if (dominator_analysis->IsReachable(context->get_instr_block(instruction)) &&
|
||||
dominator_analysis->IsReachable(context->get_instr_block(id)) &&
|
||||
dominator_analysis->Dominates(id_definition, instruction)) {
|
||||
// The id's definition dominates the instruction, and both the definition
|
||||
// and the instruction are in reachable blocks, thus the id is available at
|
||||
// the instruction.
|
||||
return true;
|
||||
}
|
||||
if (id_definition->opcode() == SpvOpVariable &&
|
||||
function_enclosing_instruction ==
|
||||
context->get_instr_block(id)->GetParent()) {
|
||||
assert(!dominator_analysis->IsReachable(
|
||||
context->get_instr_block(instruction)) &&
|
||||
"If the instruction were in a reachable block we should already "
|
||||
"have returned true.");
|
||||
// The id is a variable and it is in the same function as |instruction|.
|
||||
// This is OK despite |instruction| being unreachable.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InstructionIsFunctionParameter(opt::Instruction* instruction,
|
||||
|
@ -82,6 +82,7 @@ TEST(TransformationAddCopyMemoryTest, BasicTest) {
|
||||
OpSelectionMerge %29 None
|
||||
OpBranchConditional %27 %28 %31
|
||||
%28 = OpLabel
|
||||
%89 = OpCopyObject %18 %19
|
||||
OpBranch %29
|
||||
%31 = OpLabel
|
||||
OpBranch %29
|
||||
@ -151,86 +152,86 @@ TEST(TransformationAddCopyMemoryTest, BasicTest) {
|
||||
SpvStorageClassPrivate, 20)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Instruction descriptor is invalid (id 89 is undefined).
|
||||
// Instruction descriptor is invalid (id 90 is undefined).
|
||||
ASSERT_FALSE(TransformationAddCopyMemory(
|
||||
MakeInstructionDescriptor(89, SpvOpVariable, 0), 89, 19,
|
||||
MakeInstructionDescriptor(90, SpvOpVariable, 0), 90, 19,
|
||||
SpvStorageClassPrivate, 20)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Cannot insert OpCopyMemory before OpPhi.
|
||||
ASSERT_FALSE(
|
||||
TransformationAddCopyMemory(MakeInstructionDescriptor(75, SpvOpPhi, 0),
|
||||
89, 19, SpvStorageClassPrivate, 20)
|
||||
90, 19, SpvStorageClassPrivate, 20)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Source instruction is invalid.
|
||||
ASSERT_FALSE(TransformationAddCopyMemory(
|
||||
MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 89, 76,
|
||||
MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 76,
|
||||
SpvStorageClassPrivate, 0)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Source instruction's type doesn't exist.
|
||||
ASSERT_FALSE(TransformationAddCopyMemory(
|
||||
MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 89, 5,
|
||||
MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 5,
|
||||
SpvStorageClassPrivate, 0)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Source instruction's type is invalid.
|
||||
ASSERT_FALSE(
|
||||
TransformationAddCopyMemory(MakeInstructionDescriptor(41, SpvOpLoad, 0),
|
||||
89, 40, SpvStorageClassPrivate, 0)
|
||||
90, 40, SpvStorageClassPrivate, 0)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Source instruction is OpUndef.
|
||||
ASSERT_FALSE(
|
||||
TransformationAddCopyMemory(MakeInstructionDescriptor(41, SpvOpLoad, 0),
|
||||
89, 87, SpvStorageClassPrivate, 0)
|
||||
90, 87, SpvStorageClassPrivate, 0)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Source instruction is OpConstantNull.
|
||||
ASSERT_FALSE(
|
||||
TransformationAddCopyMemory(MakeInstructionDescriptor(41, SpvOpLoad, 0),
|
||||
89, 88, SpvStorageClassPrivate, 0)
|
||||
90, 88, SpvStorageClassPrivate, 0)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Storage class is invalid.
|
||||
ASSERT_FALSE(TransformationAddCopyMemory(
|
||||
MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 89, 19,
|
||||
MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
|
||||
SpvStorageClassWorkgroup, 20)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Initializer is 0.
|
||||
ASSERT_FALSE(TransformationAddCopyMemory(
|
||||
MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 89, 19,
|
||||
MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
|
||||
SpvStorageClassPrivate, 0)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Initializer has wrong type.
|
||||
ASSERT_FALSE(TransformationAddCopyMemory(
|
||||
MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 89, 19,
|
||||
MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
|
||||
SpvStorageClassPrivate, 25)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Source and target instructions are in different functions.
|
||||
ASSERT_FALSE(
|
||||
TransformationAddCopyMemory(MakeInstructionDescriptor(13, SpvOpLoad, 0),
|
||||
89, 19, SpvStorageClassPrivate, 20)
|
||||
90, 19, SpvStorageClassPrivate, 20)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Source instruction doesn't dominate the target instruction.
|
||||
ASSERT_FALSE(TransformationAddCopyMemory(
|
||||
MakeInstructionDescriptor(77, SpvOpLogicalEqual, 0), 89, 19,
|
||||
MakeInstructionDescriptor(77, SpvOpLogicalEqual, 0), 90, 89,
|
||||
SpvStorageClassPrivate, 20)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Source and target instructions are the same.
|
||||
ASSERT_FALSE(TransformationAddCopyMemory(
|
||||
MakeInstructionDescriptor(19, SpvOpVariable, 0), 89, 19,
|
||||
MakeInstructionDescriptor(19, SpvOpVariable, 0), 90, 19,
|
||||
SpvStorageClassPrivate, 20)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Correct transformations.
|
||||
uint32_t fresh_id = 89;
|
||||
uint32_t fresh_id = 90;
|
||||
auto descriptor = MakeInstructionDescriptor(27, SpvOpFunctionCall, 0);
|
||||
std::vector<uint32_t> source_ids = {19, 23, 26, 30, 35, 39, 68, 86};
|
||||
std::vector<uint32_t> initializers = {20, 24, 25, 25, 36, 84, 85, 20};
|
||||
@ -294,16 +295,16 @@ TEST(TransformationAddCopyMemoryTest, BasicTest) {
|
||||
%86 = OpVariable %79 Private %20
|
||||
%87 = OpUndef %79
|
||||
%88 = OpConstantNull %79
|
||||
%89 = OpVariable %79 Private %20
|
||||
%91 = OpVariable %78 Private %25
|
||||
%93 = OpVariable %81 Private %36
|
||||
%95 = OpVariable %83 Private %85
|
||||
%90 = OpVariable %79 Private %20
|
||||
%92 = OpVariable %78 Private %25
|
||||
%94 = OpVariable %81 Private %36
|
||||
%96 = OpVariable %83 Private %85
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
%96 = OpVariable %18 Function %20
|
||||
%94 = OpVariable %38 Function %84
|
||||
%92 = OpVariable %7 Function %25
|
||||
%90 = OpVariable %22 Function %24
|
||||
%97 = OpVariable %18 Function %20
|
||||
%95 = OpVariable %38 Function %84
|
||||
%93 = OpVariable %7 Function %25
|
||||
%91 = OpVariable %22 Function %24
|
||||
%19 = OpVariable %18 Function
|
||||
%23 = OpVariable %22 Function
|
||||
%26 = OpVariable %7 Function
|
||||
@ -314,18 +315,19 @@ TEST(TransformationAddCopyMemoryTest, BasicTest) {
|
||||
OpStore %19 %20
|
||||
OpStore %23 %24
|
||||
OpStore %26 %25
|
||||
OpCopyMemory %89 %19
|
||||
OpCopyMemory %90 %23
|
||||
OpCopyMemory %91 %26
|
||||
OpCopyMemory %92 %30
|
||||
OpCopyMemory %93 %35
|
||||
OpCopyMemory %94 %39
|
||||
OpCopyMemory %95 %68
|
||||
OpCopyMemory %96 %86
|
||||
OpCopyMemory %90 %19
|
||||
OpCopyMemory %91 %23
|
||||
OpCopyMemory %92 %26
|
||||
OpCopyMemory %93 %30
|
||||
OpCopyMemory %94 %35
|
||||
OpCopyMemory %95 %39
|
||||
OpCopyMemory %96 %68
|
||||
OpCopyMemory %97 %86
|
||||
%27 = OpFunctionCall %6 %10 %26
|
||||
OpSelectionMerge %29 None
|
||||
OpBranchConditional %27 %28 %31
|
||||
%28 = OpLabel
|
||||
%89 = OpCopyObject %18 %19
|
||||
OpBranch %29
|
||||
%31 = OpLabel
|
||||
OpBranch %29
|
||||
|
@ -280,10 +280,6 @@ TEST(TransformationMutatePointerTest, HandlesUnreachableBlocks) {
|
||||
|
||||
const auto insert_before = MakeInstructionDescriptor(10, SpvOpReturn, 0);
|
||||
|
||||
// Local variable doesn't dominate an unreachable block.
|
||||
ASSERT_FALSE(TransformationMutatePointer(9, 50, insert_before)
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Can mutate a global variable in an unreachable block.
|
||||
TransformationMutatePointer transformation(12, 50, insert_before);
|
||||
ASSERT_TRUE(
|
||||
|
Loading…
Reference in New Issue
Block a user