1// RUN: mlir-opt -test-spirv-module-combiner -split-input-file -verify-diagnostics %s | FileCheck %s 2 3// Deduplicate 2 global variables with the same descriptor set and binding. 4 5// CHECK: module { 6// CHECK-NEXT: spv.module Logical GLSL450 { 7// CHECK-NEXT: spv.GlobalVariable @foo 8 9// CHECK-NEXT: spv.func @use_foo 10// CHECK-NEXT: spv.mlir.addressof @foo 11// CHECK-NEXT: spv.Load 12// CHECK-NEXT: spv.ReturnValue 13// CHECK-NEXT: } 14 15// CHECK-NEXT: spv.func @use_bar 16// CHECK-NEXT: spv.mlir.addressof @foo 17// CHECK-NEXT: spv.Load 18// CHECK-NEXT: spv.FAdd 19// CHECK-NEXT: spv.ReturnValue 20// CHECK-NEXT: } 21// CHECK-NEXT: } 22// CHECK-NEXT: } 23 24spv.module Logical GLSL450 { 25 spv.GlobalVariable @foo bind(1, 0) : !spv.ptr<f32, Input> 26 27 spv.func @use_foo() -> f32 "None" { 28 %0 = spv.mlir.addressof @foo : !spv.ptr<f32, Input> 29 %1 = spv.Load "Input" %0 : f32 30 spv.ReturnValue %1 : f32 31 } 32} 33 34spv.module Logical GLSL450 { 35 spv.GlobalVariable @bar bind(1, 0) : !spv.ptr<f32, Input> 36 37 spv.func @use_bar() -> f32 "None" { 38 %0 = spv.mlir.addressof @bar : !spv.ptr<f32, Input> 39 %1 = spv.Load "Input" %0 : f32 40 %2 = spv.FAdd %1, %1 : f32 41 spv.ReturnValue %2 : f32 42 } 43} 44 45// ----- 46 47// Deduplicate 2 global variables with the same descriptor set and binding but different types. 48 49// CHECK: module { 50// CHECK-NEXT: spv.module Logical GLSL450 { 51// CHECK-NEXT: spv.GlobalVariable @foo bind(1, 0) 52 53// CHECK-NEXT: spv.GlobalVariable @bar bind(1, 0) 54 55// CHECK-NEXT: spv.func @use_bar 56// CHECK-NEXT: spv.mlir.addressof @bar 57// CHECK-NEXT: spv.Load 58// CHECK-NEXT: spv.ReturnValue 59// CHECK-NEXT: } 60// CHECK-NEXT: } 61// CHECK-NEXT: } 62 63spv.module Logical GLSL450 { 64 spv.GlobalVariable @foo bind(1, 0) : !spv.ptr<i32, Input> 65} 66 67spv.module Logical GLSL450 { 68 spv.GlobalVariable @bar bind(1, 0) : !spv.ptr<f32, Input> 69 70 spv.func @use_bar() -> f32 "None" { 71 %0 = spv.mlir.addressof @bar : !spv.ptr<f32, Input> 72 %1 = spv.Load "Input" %0 : f32 73 spv.ReturnValue %1 : f32 74 } 75} 76 77// ----- 78 79// Deduplicate 2 global variables with the same built-in attribute. 80 81// CHECK: module { 82// CHECK-NEXT: spv.module Logical GLSL450 { 83// CHECK-NEXT: spv.GlobalVariable @foo built_in("GlobalInvocationId") 84// CHECK-NEXT: spv.func @use_bar 85// CHECK-NEXT: spv.mlir.addressof @foo 86// CHECK-NEXT: spv.Load 87// CHECK-NEXT: spv.ReturnValue 88// CHECK-NEXT: } 89// CHECK-NEXT: } 90// CHECK-NEXT: } 91 92spv.module Logical GLSL450 { 93 spv.GlobalVariable @foo built_in("GlobalInvocationId") : !spv.ptr<vector<3xi32>, Input> 94} 95 96spv.module Logical GLSL450 { 97 spv.GlobalVariable @bar built_in("GlobalInvocationId") : !spv.ptr<vector<3xi32>, Input> 98 99 spv.func @use_bar() -> vector<3xi32> "None" { 100 %0 = spv.mlir.addressof @bar : !spv.ptr<vector<3xi32>, Input> 101 %1 = spv.Load "Input" %0 : vector<3xi32> 102 spv.ReturnValue %1 : vector<3xi32> 103 } 104} 105 106// ----- 107 108// Deduplicate 2 spec constants with the same spec ID. 109 110// CHECK: module { 111// CHECK-NEXT: spv.module Logical GLSL450 { 112// CHECK-NEXT: spv.SpecConstant @foo spec_id(5) 113 114// CHECK-NEXT: spv.func @use_foo() 115// CHECK-NEXT: %0 = spv.mlir.referenceof @foo 116// CHECK-NEXT: spv.ReturnValue 117// CHECK-NEXT: } 118 119// CHECK-NEXT: spv.func @use_bar() 120// CHECK-NEXT: %0 = spv.mlir.referenceof @foo 121// CHECK-NEXT: spv.FAdd 122// CHECK-NEXT: spv.ReturnValue 123// CHECK-NEXT: } 124// CHECK-NEXT: } 125// CHECK-NEXT: } 126 127spv.module Logical GLSL450 { 128 spv.SpecConstant @foo spec_id(5) = 1. : f32 129 130 spv.func @use_foo() -> (f32) "None" { 131 %0 = spv.mlir.referenceof @foo : f32 132 spv.ReturnValue %0 : f32 133 } 134} 135 136spv.module Logical GLSL450 { 137 spv.SpecConstant @bar spec_id(5) = 1. : f32 138 139 spv.func @use_bar() -> (f32) "None" { 140 %0 = spv.mlir.referenceof @bar : f32 141 %1 = spv.FAdd %0, %0 : f32 142 spv.ReturnValue %1 : f32 143 } 144} 145 146// ----- 147 148// Don't deduplicate functions with similar ops but different operands. 149 150// CHECK: spv.module Logical GLSL450 { 151// CHECK-NEXT: spv.func @foo(%[[ARG0:.+]]: f32, %[[ARG1:.+]]: f32, %[[ARG2:.+]]: f32) 152// CHECK-NEXT: %[[ADD:.+]] = spv.FAdd %[[ARG0]], %[[ARG1]] : f32 153// CHECK-NEXT: %[[MUL:.+]] = spv.FMul %[[ADD]], %[[ARG2]] : f32 154// CHECK-NEXT: spv.ReturnValue %[[MUL]] : f32 155// CHECK-NEXT: } 156// CHECK-NEXT: spv.func @foo_1(%[[ARG0:.+]]: f32, %[[ARG1:.+]]: f32, %[[ARG2:.+]]: f32) 157// CHECK-NEXT: %[[ADD:.+]] = spv.FAdd %[[ARG0]], %[[ARG2]] : f32 158// CHECK-NEXT: %[[MUL:.+]] = spv.FMul %[[ADD]], %[[ARG1]] : f32 159// CHECK-NEXT: spv.ReturnValue %[[MUL]] : f32 160// CHECK-NEXT: } 161// CHECK-NEXT: } 162 163spv.module Logical GLSL450 { 164 spv.func @foo(%a: f32, %b: f32, %c: f32) -> f32 "None" { 165 %add = spv.FAdd %a, %b: f32 166 %mul = spv.FMul %add, %c: f32 167 spv.ReturnValue %mul: f32 168 } 169} 170 171spv.module Logical GLSL450 { 172 spv.func @foo(%a: f32, %b: f32, %c: f32) -> f32 "None" { 173 %add = spv.FAdd %a, %c: f32 174 %mul = spv.FMul %add, %b: f32 175 spv.ReturnValue %mul: f32 176 } 177} 178 179// ----- 180 181// TODO: re-enable this test once we have better function deduplication. 182 183// XXXXX: module { 184// XXXXX-NEXT: spv.module Logical GLSL450 { 185// XXXXX-NEXT: spv.SpecConstant @bar spec_id(5) 186 187// XXXXX-NEXT: spv.func @foo(%arg0: f32) 188// XXXXX-NEXT: spv.ReturnValue 189// XXXXX-NEXT: } 190 191// XXXXX-NEXT: spv.func @foo_different_body(%arg0: f32) 192// XXXXX-NEXT: spv.mlir.referenceof 193// XXXXX-NEXT: spv.ReturnValue 194// XXXXX-NEXT: } 195 196// XXXXX-NEXT: spv.func @baz(%arg0: i32) 197// XXXXX-NEXT: spv.ReturnValue 198// XXXXX-NEXT: } 199 200// XXXXX-NEXT: spv.func @baz_no_return(%arg0: i32) 201// XXXXX-NEXT: spv.Return 202// XXXXX-NEXT: } 203 204// XXXXX-NEXT: spv.func @baz_no_return_different_control 205// XXXXX-NEXT: spv.Return 206// XXXXX-NEXT: } 207 208// XXXXX-NEXT: spv.func @baz_no_return_another_control 209// XXXXX-NEXT: spv.Return 210// XXXXX-NEXT: } 211 212// XXXXX-NEXT: spv.func @kernel 213// XXXXX-NEXT: spv.Return 214// XXXXX-NEXT: } 215 216// XXXXX-NEXT: spv.func @kernel_different_attr 217// XXXXX-NEXT: spv.Return 218// XXXXX-NEXT: } 219// XXXXX-NEXT: } 220// XXXXX-NEXT: } 221 222module { 223spv.module Logical GLSL450 { 224 spv.SpecConstant @bar spec_id(5) = 1. : f32 225 226 spv.func @foo(%arg0: f32) -> (f32) "None" { 227 spv.ReturnValue %arg0 : f32 228 } 229 230 spv.func @foo_duplicate(%arg0: f32) -> (f32) "None" { 231 spv.ReturnValue %arg0 : f32 232 } 233 234 spv.func @foo_different_body(%arg0: f32) -> (f32) "None" { 235 %0 = spv.mlir.referenceof @bar : f32 236 spv.ReturnValue %arg0 : f32 237 } 238 239 spv.func @baz(%arg0: i32) -> (i32) "None" { 240 spv.ReturnValue %arg0 : i32 241 } 242 243 spv.func @baz_no_return(%arg0: i32) "None" { 244 spv.Return 245 } 246 247 spv.func @baz_no_return_duplicate(%arg0: i32) -> () "None" { 248 spv.Return 249 } 250 251 spv.func @baz_no_return_different_control(%arg0: i32) -> () "Inline" { 252 spv.Return 253 } 254 255 spv.func @baz_no_return_another_control(%arg0: i32) -> () "Inline|Pure" { 256 spv.Return 257 } 258 259 spv.func @kernel( 260 %arg0: f32, 261 %arg1: !spv.ptr<!spv.struct<(!spv.array<12 x f32>)>, CrossWorkgroup>) "None" 262 attributes {spv.entry_point_abi = #spv.entry_point_abi<local_size = dense<[32, 1, 1]> : vector<3xi32>>} { 263 spv.Return 264 } 265 266 spv.func @kernel_different_attr( 267 %arg0: f32, 268 %arg1: !spv.ptr<!spv.struct<(!spv.array<12 x f32>)>, CrossWorkgroup>) "None" 269 attributes {spv.entry_point_abi = #spv.entry_point_abi<local_size = dense<[64, 1, 1]> : vector<3xi32>>} { 270 spv.Return 271 } 272} 273} 274