reduce_load_size_test.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. // Copyright (c) 2018 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <string>
  15. #include "test/opt/pass_fixture.h"
  16. #include "test/opt/pass_utils.h"
  17. namespace spvtools {
  18. namespace opt {
  19. namespace {
  20. using ReduceLoadSizeTest = PassTest<::testing::Test>;
  21. TEST_F(ReduceLoadSizeTest, cbuffer_load_extract) {
  22. // Originally from the following HLSL:
  23. // struct S {
  24. // uint f;
  25. // };
  26. //
  27. //
  28. // cbuffer gBuffer { uint a[32]; };
  29. //
  30. // RWStructuredBuffer<S> gRWSBuffer;
  31. //
  32. // uint foo(uint p[32]) {
  33. // return p[1];
  34. // }
  35. //
  36. // [numthreads(1,1,1)]
  37. // void main() {
  38. // gRWSBuffer[0].f = foo(a);
  39. // }
  40. const std::string test =
  41. R"(
  42. OpCapability Shader
  43. OpMemoryModel Logical GLSL450
  44. OpEntryPoint GLCompute %main "main"
  45. OpExecutionMode %main LocalSize 1 1 1
  46. OpSource HLSL 600
  47. OpName %type_gBuffer "type.gBuffer"
  48. OpMemberName %type_gBuffer 0 "a"
  49. OpName %gBuffer "gBuffer"
  50. OpName %S "S"
  51. OpMemberName %S 0 "f"
  52. OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
  53. OpName %gRWSBuffer "gRWSBuffer"
  54. OpName %main "main"
  55. OpDecorate %_arr_uint_uint_32 ArrayStride 16
  56. OpMemberDecorate %type_gBuffer 0 Offset 0
  57. OpDecorate %type_gBuffer Block
  58. OpMemberDecorate %S 0 Offset 0
  59. OpDecorate %_runtimearr_S ArrayStride 4
  60. OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
  61. OpDecorate %type_RWStructuredBuffer_S BufferBlock
  62. OpDecorate %gBuffer DescriptorSet 0
  63. OpDecorate %gBuffer Binding 0
  64. OpDecorate %gRWSBuffer DescriptorSet 0
  65. OpDecorate %gRWSBuffer Binding 1
  66. %uint = OpTypeInt 32 0
  67. %uint_32 = OpConstant %uint 32
  68. %_arr_uint_uint_32 = OpTypeArray %uint %uint_32
  69. %type_gBuffer = OpTypeStruct %_arr_uint_uint_32
  70. %_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer
  71. %S = OpTypeStruct %uint
  72. %_runtimearr_S = OpTypeRuntimeArray %S
  73. %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
  74. %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
  75. %int = OpTypeInt 32 1
  76. %void = OpTypeVoid
  77. %15 = OpTypeFunction %void
  78. %int_0 = OpConstant %int 0
  79. %_ptr_Uniform__arr_uint_uint_32 = OpTypePointer Uniform %_arr_uint_uint_32
  80. %uint_0 = OpConstant %uint 0
  81. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  82. %gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform
  83. %gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
  84. %main = OpFunction %void None %15
  85. %20 = OpLabel
  86. ; CHECK: [[ac1:%\w+]] = OpAccessChain {{%\w+}} %gBuffer %int_0
  87. ; CHECK: [[ac2:%\w+]] = OpAccessChain {{%\w+}} [[ac1]] %uint_1
  88. ; CHECK: [[ld:%\w+]] = OpLoad {{%\w+}} [[ac2]]
  89. ; CHECK: OpStore {{%\w+}} [[ld]]
  90. %21 = OpAccessChain %_ptr_Uniform__arr_uint_uint_32 %gBuffer %int_0
  91. %22 = OpLoad %_arr_uint_uint_32 %21 ; Load of 32-element array.
  92. %23 = OpCompositeExtract %uint %22 1
  93. %24 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0
  94. OpStore %24 %23
  95. OpReturn
  96. OpFunctionEnd
  97. )";
  98. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  99. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  100. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  101. SinglePassRunAndMatch<ReduceLoadSize>(test, false);
  102. }
  103. TEST_F(ReduceLoadSizeTest, cbuffer_load_extract_vector) {
  104. // Originally from the following HLSL:
  105. // struct S {
  106. // uint f;
  107. // };
  108. //
  109. //
  110. // cbuffer gBuffer { uint4 a; };
  111. //
  112. // RWStructuredBuffer<S> gRWSBuffer;
  113. //
  114. // uint foo(uint p[32]) {
  115. // return p[1];
  116. // }
  117. //
  118. // [numthreads(1,1,1)]
  119. // void main() {
  120. // gRWSBuffer[0].f = foo(a);
  121. // }
  122. const std::string test =
  123. R"(OpCapability Shader
  124. OpMemoryModel Logical GLSL450
  125. OpEntryPoint GLCompute %main "main"
  126. OpExecutionMode %main LocalSize 1 1 1
  127. OpSource HLSL 600
  128. OpName %type_gBuffer "type.gBuffer"
  129. OpMemberName %type_gBuffer 0 "a"
  130. OpName %gBuffer "gBuffer"
  131. OpName %S "S"
  132. OpMemberName %S 0 "f"
  133. OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
  134. OpName %gRWSBuffer "gRWSBuffer"
  135. OpName %main "main"
  136. OpMemberDecorate %type_gBuffer 0 Offset 0
  137. OpDecorate %type_gBuffer Block
  138. OpMemberDecorate %S 0 Offset 0
  139. OpDecorate %_runtimearr_S ArrayStride 4
  140. OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
  141. OpDecorate %type_RWStructuredBuffer_S BufferBlock
  142. OpDecorate %gBuffer DescriptorSet 0
  143. OpDecorate %gBuffer Binding 0
  144. OpDecorate %gRWSBuffer DescriptorSet 0
  145. OpDecorate %gRWSBuffer Binding 1
  146. %uint = OpTypeInt 32 0
  147. %uint_32 = OpConstant %uint 32
  148. %v4uint = OpTypeVector %uint 4
  149. %type_gBuffer = OpTypeStruct %v4uint
  150. %_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer
  151. %S = OpTypeStruct %uint
  152. %_runtimearr_S = OpTypeRuntimeArray %S
  153. %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
  154. %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
  155. %int = OpTypeInt 32 1
  156. %void = OpTypeVoid
  157. %15 = OpTypeFunction %void
  158. %int_0 = OpConstant %int 0
  159. %_ptr_Uniform_v4uint = OpTypePointer Uniform %v4uint
  160. %uint_0 = OpConstant %uint 0
  161. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  162. %gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform
  163. %gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
  164. %main = OpFunction %void None %15
  165. %20 = OpLabel
  166. %21 = OpAccessChain %_ptr_Uniform_v4uint %gBuffer %int_0
  167. %22 = OpLoad %v4uint %21
  168. %23 = OpCompositeExtract %uint %22 1
  169. %24 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0
  170. OpStore %24 %23
  171. OpReturn
  172. OpFunctionEnd
  173. )";
  174. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  175. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  176. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  177. SinglePassRunAndCheck<ReduceLoadSize>(test, test, true, false);
  178. }
  179. TEST_F(ReduceLoadSizeTest, cbuffer_load_5_extract) {
  180. // All of the elements of the value loaded are used, so we should not
  181. // change the load.
  182. const std::string test =
  183. R"(OpCapability Shader
  184. OpMemoryModel Logical GLSL450
  185. OpEntryPoint GLCompute %main "main"
  186. OpExecutionMode %main LocalSize 1 1 1
  187. OpSource HLSL 600
  188. OpName %type_gBuffer "type.gBuffer"
  189. OpMemberName %type_gBuffer 0 "a"
  190. OpName %gBuffer "gBuffer"
  191. OpName %S "S"
  192. OpMemberName %S 0 "f"
  193. OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
  194. OpName %gRWSBuffer "gRWSBuffer"
  195. OpName %main "main"
  196. OpDecorate %_arr_uint_uint_5 ArrayStride 16
  197. OpMemberDecorate %type_gBuffer 0 Offset 0
  198. OpDecorate %type_gBuffer Block
  199. OpMemberDecorate %S 0 Offset 0
  200. OpDecorate %_runtimearr_S ArrayStride 4
  201. OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
  202. OpDecorate %type_RWStructuredBuffer_S BufferBlock
  203. OpDecorate %gBuffer DescriptorSet 0
  204. OpDecorate %gBuffer Binding 0
  205. OpDecorate %gRWSBuffer DescriptorSet 0
  206. OpDecorate %gRWSBuffer Binding 1
  207. %uint = OpTypeInt 32 0
  208. %uint_5 = OpConstant %uint 5
  209. %_arr_uint_uint_5 = OpTypeArray %uint %uint_5
  210. %type_gBuffer = OpTypeStruct %_arr_uint_uint_5
  211. %_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer
  212. %S = OpTypeStruct %uint
  213. %_runtimearr_S = OpTypeRuntimeArray %S
  214. %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
  215. %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
  216. %int = OpTypeInt 32 1
  217. %void = OpTypeVoid
  218. %15 = OpTypeFunction %void
  219. %int_0 = OpConstant %int 0
  220. %_ptr_Uniform__arr_uint_uint_5 = OpTypePointer Uniform %_arr_uint_uint_5
  221. %uint_0 = OpConstant %uint 0
  222. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  223. %gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform
  224. %gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
  225. %main = OpFunction %void None %15
  226. %20 = OpLabel
  227. %21 = OpAccessChain %_ptr_Uniform__arr_uint_uint_5 %gBuffer %int_0
  228. %22 = OpLoad %_arr_uint_uint_5 %21
  229. %23 = OpCompositeExtract %uint %22 0
  230. %24 = OpCompositeExtract %uint %22 1
  231. %25 = OpCompositeExtract %uint %22 2
  232. %26 = OpCompositeExtract %uint %22 3
  233. %27 = OpCompositeExtract %uint %22 4
  234. %28 = OpIAdd %uint %23 %24
  235. %29 = OpIAdd %uint %28 %25
  236. %30 = OpIAdd %uint %29 %26
  237. %31 = OpIAdd %uint %20 %27
  238. %32 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0
  239. OpStore %32 %31
  240. OpReturn
  241. OpFunctionEnd
  242. )";
  243. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  244. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  245. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  246. SinglePassRunAndCheck<ReduceLoadSize>(test, test, true, false);
  247. }
  248. TEST_F(ReduceLoadSizeTest, cbuffer_load_fully_used) {
  249. // The result of the load (%22) is used in an instruction that uses the whole
  250. // load and has only 1 in operand. This trigger issue #1559.
  251. const std::string test =
  252. R"(OpCapability Shader
  253. OpMemoryModel Logical GLSL450
  254. OpEntryPoint GLCompute %main "main"
  255. OpExecutionMode %main LocalSize 1 1 1
  256. OpSource HLSL 600
  257. OpName %type_gBuffer "type.gBuffer"
  258. OpMemberName %type_gBuffer 0 "a"
  259. OpName %gBuffer "gBuffer"
  260. OpName %S "S"
  261. OpMemberName %S 0 "f"
  262. OpName %type_RWStructuredBuffer_S "type.RWStructuredBuffer.S"
  263. OpName %gRWSBuffer "gRWSBuffer"
  264. OpName %main "main"
  265. OpMemberDecorate %type_gBuffer 0 Offset 0
  266. OpDecorate %type_gBuffer Block
  267. OpMemberDecorate %S 0 Offset 0
  268. OpDecorate %_runtimearr_S ArrayStride 4
  269. OpMemberDecorate %type_RWStructuredBuffer_S 0 Offset 0
  270. OpDecorate %type_RWStructuredBuffer_S BufferBlock
  271. OpDecorate %gBuffer DescriptorSet 0
  272. OpDecorate %gBuffer Binding 0
  273. OpDecorate %gRWSBuffer DescriptorSet 0
  274. OpDecorate %gRWSBuffer Binding 1
  275. %uint = OpTypeInt 32 0
  276. %uint_32 = OpConstant %uint 32
  277. %v4uint = OpTypeVector %uint 4
  278. %float = OpTypeFloat 32
  279. %v4float = OpTypeVector %float 4
  280. %type_gBuffer = OpTypeStruct %v4uint
  281. %_ptr_Uniform_type_gBuffer = OpTypePointer Uniform %type_gBuffer
  282. %S = OpTypeStruct %uint
  283. %_runtimearr_S = OpTypeRuntimeArray %S
  284. %type_RWStructuredBuffer_S = OpTypeStruct %_runtimearr_S
  285. %_ptr_Uniform_type_RWStructuredBuffer_S = OpTypePointer Uniform %type_RWStructuredBuffer_S
  286. %int = OpTypeInt 32 1
  287. %void = OpTypeVoid
  288. %15 = OpTypeFunction %void
  289. %int_0 = OpConstant %int 0
  290. %_ptr_Uniform_v4uint = OpTypePointer Uniform %v4uint
  291. %uint_0 = OpConstant %uint 0
  292. %_ptr_Uniform_uint = OpTypePointer Uniform %uint
  293. %gBuffer = OpVariable %_ptr_Uniform_type_gBuffer Uniform
  294. %gRWSBuffer = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_S Uniform
  295. %main = OpFunction %void None %15
  296. %20 = OpLabel
  297. %21 = OpAccessChain %_ptr_Uniform_v4uint %gBuffer %int_0
  298. %22 = OpLoad %v4uint %21
  299. %23 = OpCompositeExtract %uint %22 1
  300. %24 = OpConvertUToF %v4float %22
  301. %25 = OpAccessChain %_ptr_Uniform_uint %gRWSBuffer %int_0 %uint_0 %int_0
  302. OpStore %25 %23
  303. OpReturn
  304. OpFunctionEnd
  305. )";
  306. SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  307. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
  308. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES);
  309. SinglePassRunAndCheck<ReduceLoadSize>(test, test, true, false);
  310. }
  311. TEST_F(ReduceLoadSizeTest, extract_with_no_index) {
  312. const std::string test =
  313. R"(
  314. OpCapability ImageGatherExtended
  315. OpExtension ""
  316. OpMemoryModel Logical GLSL450
  317. OpEntryPoint Fragment %4 "P�Ma'" %12 %17
  318. OpExecutionMode %4 OriginUpperLeft
  319. %void = OpTypeVoid
  320. %3 = OpTypeFunction %void
  321. %float = OpTypeFloat 32
  322. %_struct_7 = OpTypeStruct %float %float
  323. %_ptr_Input__struct_7 = OpTypePointer Input %_struct_7
  324. %_ptr_Output__struct_7 = OpTypePointer Output %_struct_7
  325. %12 = OpVariable %_ptr_Input__struct_7 Input
  326. %17 = OpVariable %_ptr_Output__struct_7 Output
  327. %4 = OpFunction %void DontInline|Pure|Const %3
  328. %245 = OpLabel
  329. %13 = OpLoad %_struct_7 %12
  330. %33 = OpCompositeExtract %_struct_7 %13
  331. OpReturn
  332. OpFunctionEnd
  333. )";
  334. auto result = SinglePassRunAndDisassemble<ReduceLoadSize>(test, true, true);
  335. EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result));
  336. }
  337. } // namespace
  338. } // namespace opt
  339. } // namespace spvtools