Skip to content

Commit d340726

Browse files
authored
opt: Fix invalid vector constant folding size (KhronosGroup#6798)
Use the actual vector component count instead of hardcoding 4 components when folding self-division of vectors in GetConstantUniformValue and FoldFMix. Fixes KhronosGroup#6794
1 parent 7058842 commit d340726

2 files changed

Lines changed: 242 additions & 3 deletions

File tree

source/opt/const_folding_rules.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,8 +1110,9 @@ const analysis::Constant* GetConstantUniformValue(
11101110
if (!uniform_inst) return nullptr;
11111111

11121112
uint32_t uniform_id = uniform_inst->result_id();
1113+
uint32_t count = type->AsVector()->element_count();
11131114
uniform =
1114-
const_mgr->GetConstant(type, std::vector<uint32_t>(4, uniform_id));
1115+
const_mgr->GetConstant(type, std::vector<uint32_t>(count, uniform_id));
11151116
}
11161117

11171118
return uniform;
@@ -1558,8 +1559,9 @@ ConstantFoldingRule FoldFMix() {
15581559
Instruction* one_inst = const_mgr->GetDefiningInstruction(one);
15591560
if (one_inst == nullptr) return nullptr;
15601561
uint32_t one_id = one_inst->result_id();
1561-
one =
1562-
const_mgr->GetConstant(result_type, std::vector<uint32_t>(4, one_id));
1562+
uint32_t count = result_type->AsVector()->element_count();
1563+
one = const_mgr->GetConstant(result_type,
1564+
std::vector<uint32_t>(count, one_id));
15631565
}
15641566

15651567
const analysis::Constant* temp1 = FoldFPBinaryOp(

test/opt/fold_test.cpp

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,6 +1896,31 @@ ::testing::Values(
18961896
"OpReturn\n" +
18971897
"OpFunctionEnd",
18981898
2, {1.6f,1.5f}),
1899+
// Test case 0a: FMix v3float
1900+
InstructionFoldingCase<std::vector<float>>(
1901+
Header() + "%v3float = OpTypeVector %float 3\n" +
1902+
"%float_0p1 = OpConstant %float 0.1\n" +
1903+
"%v3float_2_3_4 = OpConstantComposite %v3float %float_2 %float_3 %float_4\n" +
1904+
"%v3float_0_0_0 = OpConstantComposite %v3float %float_0 %float_0 %float_0\n" +
1905+
"%v3float_0p2_0p5_0p1 = OpConstantComposite %v3float %float_0p2 %float_0p5 %float_0p1\n" +
1906+
"%main = OpFunction %void None %void_func\n" +
1907+
"%main_lab = OpLabel\n" +
1908+
"%2 = OpExtInst %v3float %1 FMix %v3float_2_3_4 %v3float_0_0_0 %v3float_0p2_0p5_0p1\n" +
1909+
"OpReturn\n" +
1910+
"OpFunctionEnd",
1911+
2, {1.6f,1.5f,3.6f}),
1912+
// Test case 0b: FMix v8float
1913+
InstructionFoldingCase<std::vector<float>>(
1914+
Header() + "%v8float = OpTypeVector %float 8\n" +
1915+
"%v8float_ones = OpConstantComposite %v8float %float_1 %float_1 %float_1 %float_1 %float_1 %float_1 %float_1 %float_1\n" +
1916+
"%v8float_zeros = OpConstantComposite %v8float %float_0 %float_0 %float_0 %float_0 %float_0 %float_0 %float_0 %float_0\n" +
1917+
"%v8float_a = OpConstantComposite %v8float %float_0p5 %float_0p5 %float_0p5 %float_0p5 %float_0p5 %float_0p5 %float_0p5 %float_0p5\n" +
1918+
"%main = OpFunction %void None %void_func\n" +
1919+
"%main_lab = OpLabel\n" +
1920+
"%2 = OpExtInst %v8float %1 FMix %v8float_ones %v8float_zeros %v8float_a\n" +
1921+
"OpReturn\n" +
1922+
"OpFunctionEnd",
1923+
2, {0.5f,0.5f,0.5f,0.5f,0.5f,0.5f,0.5f,0.5f}),
18991924
// Test case 1: bit-cast unsigned int vector {0x3f800000, 0xbf800000} to
19001925
// float vector
19011926
InstructionFoldingCase<std::vector<float>>(
@@ -1988,6 +2013,218 @@ ::testing::Values(
19882013
));
19892014
// clang-format on
19902015

2016+
INSTANTIATE_TEST_SUITE_P(
2017+
RedundantDivVectorFloatTest, FloatVectorInstructionFoldingTest,
2018+
::testing::Values(
2019+
// Test case 0: FDiv v2float self-division x / x
2020+
InstructionFoldingCase<std::vector<float>>(
2021+
Header() + "%main = OpFunction %void None %void_func\n" +
2022+
"%main_lab = OpLabel\n" +
2023+
"%n = OpVariable %_ptr_v2float Function\n" +
2024+
"%3 = OpLoad %v2float %n\n" + "%2 = OpFDiv %v2float %3 %3\n" +
2025+
"OpReturn\n" + "OpFunctionEnd",
2026+
2, {1.0f, 1.0f}),
2027+
// Test case 1: FDiv v2float -x / x
2028+
InstructionFoldingCase<std::vector<float>>(
2029+
Header() + "%main = OpFunction %void None %void_func\n" +
2030+
"%main_lab = OpLabel\n" +
2031+
"%n = OpVariable %_ptr_v2float Function\n" +
2032+
"%3 = OpLoad %v2float %n\n" + "%4 = OpFNegate %v2float %3\n" +
2033+
"%2 = OpFDiv %v2float %4 %3\n" + "OpReturn\n" + "OpFunctionEnd",
2034+
2, {-1.0f, -1.0f}),
2035+
// Test case 2: FDiv v2float x / -x
2036+
InstructionFoldingCase<std::vector<float>>(
2037+
Header() + "%main = OpFunction %void None %void_func\n" +
2038+
"%main_lab = OpLabel\n" +
2039+
"%n = OpVariable %_ptr_v2float Function\n" +
2040+
"%3 = OpLoad %v2float %n\n" + "%4 = OpFNegate %v2float %3\n" +
2041+
"%2 = OpFDiv %v2float %3 %4\n" + "OpReturn\n" + "OpFunctionEnd",
2042+
2, {-1.0f, -1.0f}),
2043+
// Test case 3: FDiv v3float self-division
2044+
InstructionFoldingCase<std::vector<float>>(
2045+
Header() + "%v3float = OpTypeVector %float 3\n" +
2046+
"%_ptr_v3float = OpTypePointer Function %v3float\n" +
2047+
"%main = OpFunction %void None %void_func\n" +
2048+
"%main_lab = OpLabel\n" +
2049+
"%n = OpVariable %_ptr_v3float Function\n" +
2050+
"%3 = OpLoad %v3float %n\n" + "%2 = OpFDiv %v3float %3 %3\n" +
2051+
"OpReturn\n" + "OpFunctionEnd",
2052+
2, {1.0f, 1.0f, 1.0f}),
2053+
// Test case 4: FDiv v4float self-division
2054+
InstructionFoldingCase<std::vector<float>>(
2055+
Header() + "%main = OpFunction %void None %void_func\n" +
2056+
"%main_lab = OpLabel\n" +
2057+
"%n = OpVariable %_ptr_v4float Function\n" +
2058+
"%3 = OpLoad %v4float %n\n" + "%2 = OpFDiv %v4float %3 %3\n" +
2059+
"OpReturn\n" + "OpFunctionEnd",
2060+
2, {1.0f, 1.0f, 1.0f, 1.0f}),
2061+
// Test case 5: FDiv v8float self-division
2062+
InstructionFoldingCase<std::vector<float>>(
2063+
Header() + "%v8float = OpTypeVector %float 8\n" +
2064+
"%_ptr_v8float = OpTypePointer Function %v8float\n" +
2065+
"%main = OpFunction %void None %void_func\n" +
2066+
"%main_lab = OpLabel\n" +
2067+
"%n = OpVariable %_ptr_v8float Function\n" +
2068+
"%3 = OpLoad %v8float %n\n" + "%2 = OpFDiv %v8float %3 %3\n" +
2069+
"OpReturn\n" + "OpFunctionEnd",
2070+
2, {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}),
2071+
// Test case 6: FDiv v16float self-division
2072+
InstructionFoldingCase<std::vector<float>>(
2073+
Header() + "%v16float = OpTypeVector %float 16\n" +
2074+
"%_ptr_v16float = OpTypePointer Function %v16float\n" +
2075+
"%main = OpFunction %void None %void_func\n" +
2076+
"%main_lab = OpLabel\n" +
2077+
"%n = OpVariable %_ptr_v16float Function\n" +
2078+
"%3 = OpLoad %v16float %n\n" + "%2 = OpFDiv %v16float %3 %3\n" +
2079+
"OpReturn\n" + "OpFunctionEnd",
2080+
2,
2081+
{1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
2082+
1.0f, 1.0f, 1.0f, 1.0f, 1.0f})));
2083+
2084+
INSTANTIATE_TEST_SUITE_P(
2085+
RedundantDivVectorDoubleTest, DoubleVectorInstructionFoldingTest,
2086+
::testing::Values(
2087+
// Test case 0: FDiv v2double self-division x / x
2088+
InstructionFoldingCase<std::vector<double>>(
2089+
Header() + "%main = OpFunction %void None %void_func\n" +
2090+
"%main_lab = OpLabel\n" +
2091+
"%n = OpVariable %_ptr_v2double Function\n" +
2092+
"%3 = OpLoad %v2double %n\n" + "%2 = OpFDiv %v2double %3 %3\n" +
2093+
"OpReturn\n" + "OpFunctionEnd",
2094+
2, {1.0, 1.0})));
2095+
2096+
INSTANTIATE_TEST_SUITE_P(
2097+
RedundantDivVectorIntTest, IntVectorInstructionFoldingTest,
2098+
::testing::Values(
2099+
// Test case 0: SDiv v2int self-division x / x
2100+
InstructionFoldingCase<std::vector<int32_t>>(
2101+
Header() + "%main = OpFunction %void None %void_func\n" +
2102+
"%main_lab = OpLabel\n" +
2103+
"%n = OpVariable %_ptr_v2int Function\n" +
2104+
"%3 = OpLoad %v2int %n\n" + "%2 = OpSDiv %v2int %3 %3\n" +
2105+
"OpReturn\n" + "OpFunctionEnd",
2106+
2, {1, 1}),
2107+
// Test case 1: SDiv v2int -x / x
2108+
InstructionFoldingCase<std::vector<int32_t>>(
2109+
Header() + "%main = OpFunction %void None %void_func\n" +
2110+
"%main_lab = OpLabel\n" +
2111+
"%n = OpVariable %_ptr_v2int Function\n" +
2112+
"%3 = OpLoad %v2int %n\n" + "%4 = OpSNegate %v2int %3\n" +
2113+
"%2 = OpSDiv %v2int %4 %3\n" + "OpReturn\n" + "OpFunctionEnd",
2114+
2, {-1, -1})));
2115+
2116+
INSTANTIATE_TEST_SUITE_P(
2117+
RedundantDivVectorUIntTest, UIntVectorInstructionFoldingTest,
2118+
::testing::Values(
2119+
// Test case 0: UDiv v2uint self-division x / x
2120+
InstructionFoldingCase<std::vector<uint32_t>>(
2121+
Header() + "%_ptr_v2uint = OpTypePointer Function %v2uint\n" +
2122+
"%main = OpFunction %void None %void_func\n" +
2123+
"%main_lab = OpLabel\n" +
2124+
"%n = OpVariable %_ptr_v2uint Function\n" +
2125+
"%3 = OpLoad %v2uint %n\n" + "%2 = OpUDiv %v2uint %3 %3\n" +
2126+
"OpReturn\n" + "OpFunctionEnd",
2127+
2, {1, 1})));
2128+
2129+
INSTANTIATE_TEST_SUITE_P(
2130+
ChallengerStressTest, FloatVectorInstructionFoldingTest,
2131+
::testing::Values(
2132+
// Challenger Test case 0: FMix v3float
2133+
InstructionFoldingCase<std::vector<float>>(
2134+
Header() + "%v3float = OpTypeVector %float 3\n" +
2135+
"%v3float_2_3_4 = OpConstantComposite %v3float %float_2 "
2136+
"%float_3 %float_4\n" +
2137+
"%v3float_0_0_0 = OpConstantComposite %v3float %float_0 "
2138+
"%float_0 %float_0\n" +
2139+
"%v3float_0p2_0p5_0p5 = OpConstantComposite %v3float "
2140+
"%float_0p2 %float_0p5 %float_0p5\n" +
2141+
"%main = OpFunction %void None %void_func\n" +
2142+
"%main_lab = OpLabel\n" +
2143+
"%2 = OpExtInst %v3float %1 FMix %v3float_2_3_4 %v3float_0_0_0 "
2144+
"%v3float_0p2_0p5_0p5\n" +
2145+
"OpReturn\n" + "OpFunctionEnd",
2146+
2, {1.6f, 1.5f, 2.0f}),
2147+
// Challenger Test case 1: FMix v4float with different components
2148+
InstructionFoldingCase<std::vector<float>>(
2149+
Header() +
2150+
"%v4float_2_3_4_5 = OpConstantComposite %v4float %float_2 "
2151+
"%float_3 %float_4 %float_0\n" +
2152+
"%v4float_0p2_0p5_0p5_0p1 = OpConstantComposite %v4float "
2153+
"%float_0p2 %float_0p5 %float_0p5 %float_0p2\n" +
2154+
"%main = OpFunction %void None %void_func\n" +
2155+
"%main_lab = OpLabel\n" +
2156+
"%2 = OpExtInst %v4float %1 FMix %v4float_2_3_4_5 "
2157+
"%v4float_0_0_0_0 %v4float_0p2_0p5_0p5_0p1\n" +
2158+
"OpReturn\n" + "OpFunctionEnd",
2159+
2, {1.6f, 1.5f, 2.0f, 0.0f})));
2160+
2161+
INSTANTIATE_TEST_SUITE_P(
2162+
ChallengerStressTestInt, IntVectorInstructionFoldingTest,
2163+
::testing::Values(
2164+
// Challenger Test case 0: SDiv v3int self-division x / x
2165+
InstructionFoldingCase<std::vector<int32_t>>(
2166+
Header() + "%v3int = OpTypeVector %int 3\n" +
2167+
"%_ptr_v3int = OpTypePointer Function %v3int\n" +
2168+
"%main = OpFunction %void None %void_func\n" +
2169+
"%main_lab = OpLabel\n" +
2170+
"%n = OpVariable %_ptr_v3int Function\n" +
2171+
"%3 = OpLoad %v3int %n\n" + "%2 = OpSDiv %v3int %3 %3\n" +
2172+
"OpReturn\n" + "OpFunctionEnd",
2173+
2, {1, 1, 1}),
2174+
// Challenger Test case 1: SDiv v4int self-division x / x
2175+
InstructionFoldingCase<std::vector<int32_t>>(
2176+
Header() + "%main = OpFunction %void None %void_func\n" +
2177+
"%main_lab = OpLabel\n" +
2178+
"%n = OpVariable %_ptr_v4int Function\n" +
2179+
"%3 = OpLoad %v4int %n\n" + "%2 = OpSDiv %v4int %3 %3\n" +
2180+
"OpReturn\n" + "OpFunctionEnd",
2181+
2, {1, 1, 1, 1})));
2182+
2183+
INSTANTIATE_TEST_SUITE_P(
2184+
ChallengerStressTestUInt, UIntVectorInstructionFoldingTest,
2185+
::testing::Values(
2186+
// Challenger Test case 0: UDiv v3uint self-division x / x
2187+
InstructionFoldingCase<std::vector<uint32_t>>(
2188+
Header() + "%v3uint = OpTypeVector %uint 3\n" +
2189+
"%_ptr_v3uint = OpTypePointer Function %v3uint\n" +
2190+
"%main = OpFunction %void None %void_func\n" +
2191+
"%main_lab = OpLabel\n" +
2192+
"%n = OpVariable %_ptr_v3uint Function\n" +
2193+
"%3 = OpLoad %v3uint %n\n" + "%2 = OpUDiv %v3uint %3 %3\n" +
2194+
"OpReturn\n" + "OpFunctionEnd",
2195+
2, {1, 1, 1}),
2196+
// Challenger Test case 1: UDiv v4uint self-division x / x
2197+
InstructionFoldingCase<std::vector<uint32_t>>(
2198+
Header() + "%_ptr_v4uint = OpTypePointer Function %v4uint\n" +
2199+
"%main = OpFunction %void None %void_func\n" +
2200+
"%main_lab = OpLabel\n" +
2201+
"%n = OpVariable %_ptr_v4uint Function\n" +
2202+
"%3 = OpLoad %v4uint %n\n" + "%2 = OpUDiv %v4uint %3 %3\n" +
2203+
"OpReturn\n" + "OpFunctionEnd",
2204+
2, {1, 1, 1, 1})));
2205+
2206+
INSTANTIATE_TEST_SUITE_P(
2207+
ChallengerStressTestDouble, DoubleVectorInstructionFoldingTest,
2208+
::testing::Values(
2209+
// Challenger Test case 0: FDiv v3double self-division x / x
2210+
InstructionFoldingCase<std::vector<double>>(
2211+
Header() + "%v3double = OpTypeVector %double 3\n" +
2212+
"%_ptr_v3double = OpTypePointer Function %v3double\n" +
2213+
"%main = OpFunction %void None %void_func\n" +
2214+
"%main_lab = OpLabel\n" +
2215+
"%n = OpVariable %_ptr_v3double Function\n" +
2216+
"%3 = OpLoad %v3double %n\n" + "%2 = OpFDiv %v3double %3 %3\n" +
2217+
"OpReturn\n" + "OpFunctionEnd",
2218+
2, {1.0, 1.0, 1.0}),
2219+
// Challenger Test case 1: FDiv v4double self-division x / x
2220+
InstructionFoldingCase<std::vector<double>>(
2221+
Header() + "%main = OpFunction %void None %void_func\n" +
2222+
"%main_lab = OpLabel\n" +
2223+
"%n = OpVariable %_ptr_v4double Function\n" +
2224+
"%3 = OpLoad %v4double %n\n" + "%2 = OpFDiv %v4double %3 %3\n" +
2225+
"OpReturn\n" + "OpFunctionEnd",
2226+
2, {1.0, 1.0, 1.0, 1.0})));
2227+
19912228
using FloatMatrixInstructionFoldingTest = ::testing::TestWithParam<
19922229
InstructionFoldingCase<std::vector<std::vector<float>>>>;
19932230

0 commit comments

Comments
 (0)