mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-27 05:40:06 +00:00
Avoid checking def-use dominance for OpPhi value operands
The def-use dominance checker doesn't have enough info to know that a particular use is in an OpPhi, so skip tracking those uses for now. Add a TODO to do a proper OpPhi variable-argument check in the future. Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/286
This commit is contained in:
parent
64ff3c6dc1
commit
1408aea260
@ -2420,6 +2420,9 @@ spv_result_t CheckIdDefinitionDominateUse(const ValidationState_t& _) {
|
||||
// NOTE: Ids defined outside of functions must appear before they are used
|
||||
// This check is being performed in the IdPass function
|
||||
}
|
||||
// TODO(dneto): We don't track check of IDs by phi nodes. We should check
|
||||
// that for each (variable, predecessor) pair in an OpPhi, that the variable
|
||||
// is defined in a block that dominates that predecessor block.
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
@ -2450,7 +2453,17 @@ spv_result_t IdPass(ValidationState_t& _,
|
||||
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
|
||||
case SPV_OPERAND_TYPE_SCOPE_ID:
|
||||
if (_.IsDefinedId(*operand_ptr)) {
|
||||
_.RegisterUseId(*operand_ptr);
|
||||
if (inst->opcode == SpvOpPhi && i > 1) {
|
||||
// For now, ignore uses of IDs as arguments to OpPhi, since
|
||||
// the job of an OpPhi is to allow a block to use an ID from a
|
||||
// block that doesn't dominate the use.
|
||||
// We only track usage by a particular block, rather than
|
||||
// which instruction and operand number is using the value, so
|
||||
// we have to just bluntly avod tracking the use here.
|
||||
// Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/286
|
||||
} else {
|
||||
_.RegisterUseId(*operand_ptr);
|
||||
}
|
||||
ret = SPV_SUCCESS;
|
||||
} else if (can_have_forward_declared_ids(i)) {
|
||||
ret = _.ForwardDeclareId(*operand_ptr);
|
||||
|
@ -545,6 +545,7 @@ const string kBasicTypes = R"(
|
||||
%zero = OpConstant %intt 0
|
||||
%one = OpConstant %intt 1
|
||||
%ten = OpConstant %intt 10
|
||||
%false = OpConstantFalse %boolt
|
||||
)";
|
||||
|
||||
const string kKernelTypesAndConstants = R"(
|
||||
@ -1172,6 +1173,34 @@ TEST_F(ValidateSSA, PhiUseDoesntDominateUseOfPhiOperandUsedBeforeDefinitionBad)
|
||||
MatchesRegex("ID .\\[inew\\] has not been defined"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateSSA, PhiUseMayComeFromNonDominatingBlockGood) {
|
||||
string str = kHeader
|
||||
+ "OpName %if_true \"if_true\"\n"
|
||||
+ "OpName %exit \"exit\"\n"
|
||||
+ "OpName %copy \"copy\"\n"
|
||||
+ kBasicTypes +
|
||||
R"(
|
||||
%func = OpFunction %voidt None %vfunct
|
||||
%entry = OpLabel
|
||||
OpBranchConditional %false %if_true %exit
|
||||
|
||||
%if_true = OpLabel
|
||||
%copy = OpCopyObject %boolt %false
|
||||
OpBranch %exit
|
||||
|
||||
; The use of %copy here is ok, even though it was defined
|
||||
; in a block that does not dominate %exit. That's the point
|
||||
; of an OpPhi.
|
||||
%exit = OpLabel
|
||||
%value = OpPhi %boolt %false %entry %copy %if_true
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
CompileSuccessfully(str);
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString();
|
||||
}
|
||||
|
||||
TEST_F(ValidateSSA, UseFunctionParameterFromOtherFunctionBad) {
|
||||
string str = kHeader +
|
||||
"OpName %first \"first\"\n"
|
||||
|
Loading…
Reference in New Issue
Block a user