1; RUN: llc -march=amdgcn -mcpu=gfx801 -verify-machineinstrs -denormal-fp-math-f32=preserve-sign < %s | FileCheck -enable-var-scope -check-prefixes=GCN,VI,VI-FLUSH,GCN-FLUSH,GCN-NOEXCEPT %s 2; RUN: llc -march=amdgcn -mcpu=gfx801 -verify-machineinstrs -mattr=+fp-exceptions -denormal-fp-math-f32=preserve-sign < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GCN-EXCEPT,VI,VI-FLUSH,GCN-FLUSH %s 3; RUN: llc -march=amdgcn -mcpu=gfx801 -verify-machineinstrs -denormal-fp-math-f32=ieee < %s | FileCheck -enable-var-scope -check-prefixes=GCN,VI,VI-DENORM,GCN-DENORM,GCN-NOEXCEPT %s 4; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs -denormal-fp-math-f32=ieee < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GFX9,GFX9-DENORM,GCN-DENORM,GCN-NOEXCEPT %s 5; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs -denormal-fp-math-f32=preserve-sign < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GFX9,GFX9-FLUSH,GCN-FLUSH,GCN-NOEXCEPT %s 6 7; GCN-LABEL: {{^}}test_no_fold_canonicalize_loaded_value_f32: 8; GCN-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, v{{[0-9]+}} 9; GFX9-DENORM: v_max_f32_e32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} 10define amdgpu_kernel void @test_no_fold_canonicalize_loaded_value_f32(float addrspace(1)* %arg) { 11 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 12 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 13 %v = load float, float addrspace(1)* %gep, align 4 14 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 15 store float %canonicalized, float addrspace(1)* %gep, align 4 16 ret void 17} 18 19; GCN-LABEL: {{^}}test_fold_canonicalize_fmul_value_f32: 20; GCN: v_mul_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}} 21; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 22; GCN-NOT: 1.0 23define amdgpu_kernel void @test_fold_canonicalize_fmul_value_f32(float addrspace(1)* %arg) { 24 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 25 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 26 %load = load float, float addrspace(1)* %gep, align 4 27 %v = fmul float %load, 15.0 28 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 29 store float %canonicalized, float addrspace(1)* %gep, align 4 30 ret void 31} 32 33; GCN-LABEL: {{^}}test_fold_canonicalize_fmul_legacy_value_f32: 34; GCN: v_mul_legacy_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}} 35; GCN-NOT: v_mul 36; GCN-NOT: v_max 37; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 38define amdgpu_kernel void @test_fold_canonicalize_fmul_legacy_value_f32(float addrspace(1)* %arg) { 39 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 40 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 41 %load = load float, float addrspace(1)* %gep, align 4 42 %v = call float @llvm.amdgcn.fmul.legacy(float %load, float 15.0) 43 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 44 store float %canonicalized, float addrspace(1)* %gep, align 4 45 ret void 46} 47 48; GCN-LABEL: {{^}}test_fold_canonicalize_sub_value_f32: 49; GCN: v_sub_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}} 50; GCN-NOT: v_mul 51; GCN-NOT: v_max 52; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 53define amdgpu_kernel void @test_fold_canonicalize_sub_value_f32(float addrspace(1)* %arg) { 54 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 55 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 56 %load = load float, float addrspace(1)* %gep, align 4 57 %v = fsub float 15.0, %load 58 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 59 store float %canonicalized, float addrspace(1)* %gep, align 4 60 ret void 61} 62 63; GCN-LABEL: {{^}}test_fold_canonicalize_add_value_f32: 64; GCN: v_add_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}} 65; GCN-NOT: v_mul 66; GCN-NOT: v_max 67; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 68define amdgpu_kernel void @test_fold_canonicalize_add_value_f32(float addrspace(1)* %arg) { 69 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 70 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 71 %load = load float, float addrspace(1)* %gep, align 4 72 %v = fadd float %load, 15.0 73 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 74 store float %canonicalized, float addrspace(1)* %gep, align 4 75 ret void 76} 77 78; GCN-LABEL: {{^}}test_fold_canonicalize_sqrt_value_f32: 79; GCN: v_sqrt_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}} 80; GCN-NOT: v_mul 81; GCN-NOT: v_max 82; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 83define amdgpu_kernel void @test_fold_canonicalize_sqrt_value_f32(float addrspace(1)* %arg) { 84 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 85 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 86 %load = load float, float addrspace(1)* %gep, align 4 87 %v = call float @llvm.sqrt.f32(float %load) 88 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 89 store float %canonicalized, float addrspace(1)* %gep, align 4 90 ret void 91} 92 93; GCN-LABEL: test_fold_canonicalize_fceil_value_f32: 94; GCN: v_ceil_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}} 95; GCN-NOT: v_mul 96; GCN-NOT: v_max 97; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 98define amdgpu_kernel void @test_fold_canonicalize_fceil_value_f32(float addrspace(1)* %arg) { 99 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 100 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 101 %load = load float, float addrspace(1)* %gep, align 4 102 %v = call float @llvm.ceil.f32(float %load) 103 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 104 store float %canonicalized, float addrspace(1)* %gep, align 4 105 ret void 106} 107 108; GCN-LABEL: test_fold_canonicalize_floor_value_f32: 109; GCN: v_floor_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}} 110; GCN-NOT: v_mul 111; GCN-NOT: v_max 112; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 113define amdgpu_kernel void @test_fold_canonicalize_floor_value_f32(float addrspace(1)* %arg) { 114 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 115 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 116 %load = load float, float addrspace(1)* %gep, align 4 117 %v = call float @llvm.floor.f32(float %load) 118 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 119 store float %canonicalized, float addrspace(1)* %gep, align 4 120 ret void 121} 122 123; GCN-LABEL: test_fold_canonicalize_fma_value_f32: 124; GCN: s_mov_b32 [[SREG:s[0-9]+]], 0x41700000 125; GCN: v_fma_f32 [[V:v[0-9]+]], v{{[0-9]+}}, [[SREG]], [[SREG]] 126; GCN-NOT: v_mul 127; GCN-NOT: v_max 128; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 129define amdgpu_kernel void @test_fold_canonicalize_fma_value_f32(float addrspace(1)* %arg) { 130 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 131 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 132 %load = load float, float addrspace(1)* %gep, align 4 133 %v = call float @llvm.fma.f32(float %load, float 15.0, float 15.0) 134 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 135 store float %canonicalized, float addrspace(1)* %gep, align 4 136 ret void 137} 138 139; GCN-LABEL: test_fold_canonicalize_fmad_ftz_value_f32: 140; GCN: v_mov_b32_e32 [[V:v[0-9]+]], 0x41700000 141; GCN: v_mac_f32_e32 [[V]], v{{[0-9]+}}, v{{[0-9]+$}} 142; GCN-NOT: v_mul 143; GCN-NOT: v_max 144; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 145define amdgpu_kernel void @test_fold_canonicalize_fmad_ftz_value_f32(float addrspace(1)* %arg) { 146 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 147 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 148 %load = load float, float addrspace(1)* %gep, align 4 149 %v = call float @llvm.amdgcn.fmad.ftz.f32(float %load, float 15.0, float 15.0) 150 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 151 store float %canonicalized, float addrspace(1)* %gep, align 4 152 ret void 153} 154 155; GCN-LABEL: test_fold_canonicalize_fmuladd_value_f32: 156; GCN-FLUSH: v_mac_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}}, v{{[0-9]+}} 157; GCN-DENORM: s_mov_b32 [[SREG:s[0-9]+]], 0x41700000 158; GCN-DENORM: v_fma_f32 [[V:v[0-9]+]], v{{[0-9]+}}, [[SREG]], [[SREG]] 159; GCN-NOT: v_mul 160; GCN-NOT: v_max 161; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 162; GCN-NOT: 1.0 163define amdgpu_kernel void @test_fold_canonicalize_fmuladd_value_f32(float addrspace(1)* %arg) { 164 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 165 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 166 %load = load float, float addrspace(1)* %gep, align 4 167 %v = call float @llvm.fmuladd.f32(float %load, float 15.0, float 15.0) 168 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 169 store float %canonicalized, float addrspace(1)* %gep, align 4 170 ret void 171} 172 173; GCN-LABEL: test_fold_canonicalize_canonicalize_value_f32: 174; GCN: {{flat|global}}_load_dword [[LOAD:v[0-9]+]], 175; GCN-FLUSH: v_mul_f32_e32 [[V:v[0-9]+]], 1.0, [[LOAD]] 176; GCN-DENORM: v_max_f32_e32 [[V:v[0-9]+]], [[LOAD]], [[LOAD]] 177; GCN-NOT: v_mul 178; GCN-NOT: v_max 179; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 180define amdgpu_kernel void @test_fold_canonicalize_canonicalize_value_f32(float addrspace(1)* %arg) { 181 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 182 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 183 %load = load float, float addrspace(1)* %gep, align 4 184 %v = call float @llvm.canonicalize.f32(float %load) 185 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 186 store float %canonicalized, float addrspace(1)* %gep, align 4 187 ret void 188} 189 190; GCN-LABEL: test_fold_canonicalize_fpextend_value_f64_f32: 191; GCN: v_cvt_f64_f32_e32 [[V:v\[[0-9]+:[0-9]+\]]], v{{[0-9]+}} 192; GCN-NOT: v_mul 193; GCN-NOT: v_max 194; GCN: {{flat|global}}_store_dwordx2 v[{{[0-9:]+}}], [[V]] 195define amdgpu_kernel void @test_fold_canonicalize_fpextend_value_f64_f32(float addrspace(1)* %arg, double addrspace(1)* %out) { 196 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 197 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 198 %load = load float, float addrspace(1)* %gep, align 4 199 %v = fpext float %load to double 200 %canonicalized = tail call double @llvm.canonicalize.f64(double %v) 201 %gep2 = getelementptr inbounds double, double addrspace(1)* %out, i32 %id 202 store double %canonicalized, double addrspace(1)* %gep2, align 8 203 ret void 204} 205 206; GCN-LABEL: test_fold_canonicalize_fpextend_value_f32_f16: 207; GCN: v_cvt_f32_f16_e32 [[V:v[0-9]+]], v{{[0-9]+}} 208; GCN-NOT: v_mul 209; GCN-NOT: v_max 210; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 211define amdgpu_kernel void @test_fold_canonicalize_fpextend_value_f32_f16(half addrspace(1)* %arg, float addrspace(1)* %out) { 212 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 213 %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id 214 %load = load half, half addrspace(1)* %gep, align 2 215 %v = fpext half %load to float 216 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 217 %gep2 = getelementptr inbounds float, float addrspace(1)* %out, i32 %id 218 store float %canonicalized, float addrspace(1)* %gep2, align 4 219 ret void 220} 221 222; GCN-LABEL: test_fold_canonicalize_fpextend_value_f32_f16_flushf16: 223; GCN: v_cvt_f32_f16_e32 [[V:v[0-9]+]], v{{[0-9]+}} 224; GCN-NOT: v_mul 225; GCN-NOT: v_max 226; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 227define amdgpu_kernel void @test_fold_canonicalize_fpextend_value_f32_f16_flushf16(half addrspace(1)* %arg, float addrspace(1)* %out) #2 { 228 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 229 %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id 230 %load = load half, half addrspace(1)* %gep, align 2 231 %v = fpext half %load to float 232 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 233 %gep2 = getelementptr inbounds float, float addrspace(1)* %out, i32 %id 234 store float %canonicalized, float addrspace(1)* %gep2, align 4 235 ret void 236} 237 238; GCN-LABEL: test_fold_canonicalize_fpround_value_f32_f64: 239; GCN: v_cvt_f32_f64_e32 [[V:v[0-9]+]], v[{{[0-9:]+}}] 240; GCN-NOT: v_mul 241; GCN-NOT: v_max 242; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 243define amdgpu_kernel void @test_fold_canonicalize_fpround_value_f32_f64(double addrspace(1)* %arg, float addrspace(1)* %out) { 244 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 245 %gep = getelementptr inbounds double, double addrspace(1)* %arg, i32 %id 246 %load = load double, double addrspace(1)* %gep, align 8 247 %v = fptrunc double %load to float 248 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 249 %gep2 = getelementptr inbounds float, float addrspace(1)* %out, i32 %id 250 store float %canonicalized, float addrspace(1)* %gep2, align 4 251 ret void 252} 253 254; GCN-LABEL: test_fold_canonicalize_fpround_value_f16_f32: 255; GCN: v_cvt_f16_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}} 256; GCN-NOT: v_max 257; GCN-NOT: v_mul 258; GCN: {{flat|global}}_store_short v[{{[0-9:]+}}], [[V]] 259define amdgpu_kernel void @test_fold_canonicalize_fpround_value_f16_f32(float addrspace(1)* %arg, half addrspace(1)* %out) { 260 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 261 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 262 %load = load float, float addrspace(1)* %gep, align 4 263 %v = fptrunc float %load to half 264 %canonicalized = tail call half @llvm.canonicalize.f16(half %v) 265 %gep2 = getelementptr inbounds half, half addrspace(1)* %out, i32 %id 266 store half %canonicalized, half addrspace(1)* %gep2, align 2 267 ret void 268} 269 270; GCN-LABEL: test_fold_canonicalize_fpround_value_f16_f32_flushf16: 271; GCN: v_cvt_f16_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}} 272; GCN-NOT: v_max 273; GCN-NOT: v_mul 274; GCN: {{flat|global}}_store_short v[{{[0-9:]+}}], [[V]] 275define amdgpu_kernel void @test_fold_canonicalize_fpround_value_f16_f32_flushf16(float addrspace(1)* %arg, half addrspace(1)* %out) #2 { 276 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 277 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 278 %load = load float, float addrspace(1)* %gep, align 4 279 %v = fptrunc float %load to half 280 %canonicalized = tail call half @llvm.canonicalize.f16(half %v) 281 %gep2 = getelementptr inbounds half, half addrspace(1)* %out, i32 %id 282 store half %canonicalized, half addrspace(1)* %gep2, align 2 283 ret void 284} 285 286; GCN-LABEL: test_fold_canonicalize_fpround_value_v2f16_v2f32: 287; GCN-DAG: v_cvt_f16_f32_e32 [[V0:v[0-9]+]], v{{[0-9]+}} 288; VI-DAG: v_cvt_f16_f32_sdwa [[V1:v[0-9]+]], v{{[0-9]+}} 289; VI: v_or_b32_e32 [[V:v[0-9]+]], [[V0]], [[V1]] 290; GFX9: v_cvt_f16_f32_e32 [[V1:v[0-9]+]], v{{[0-9]+}} 291; GFX9: v_and_b32_e32 [[V0_16:v[0-9]+]], 0xffff, [[V0]] 292; GFX9: v_lshl_or_b32 [[V:v[0-9]+]], [[V1]], 16, [[V0_16]] 293; GCN-NOT: v_mul 294; GCN-NOT: v_max 295; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 296define amdgpu_kernel void @test_fold_canonicalize_fpround_value_v2f16_v2f32(<2 x float> addrspace(1)* %arg, <2 x half> addrspace(1)* %out) { 297 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 298 %gep = getelementptr inbounds <2 x float>, <2 x float> addrspace(1)* %arg, i32 %id 299 %load = load <2 x float>, <2 x float> addrspace(1)* %gep, align 8 300 %v = fptrunc <2 x float> %load to <2 x half> 301 %canonicalized = tail call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %v) 302 %gep2 = getelementptr inbounds <2 x half>, <2 x half> addrspace(1)* %out, i32 %id 303 store <2 x half> %canonicalized, <2 x half> addrspace(1)* %gep2, align 4 304 ret void 305} 306 307; GCN-LABEL: test_no_fold_canonicalize_fneg_value_f32: 308; GCN-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, -1.0, v{{[0-9]+}} 309; GCN-DENORM: v_max_f32_e64 v{{[0-9]+}}, -v{{[0-9]+}}, -v{{[0-9]+}} 310define amdgpu_kernel void @test_no_fold_canonicalize_fneg_value_f32(float addrspace(1)* %arg) { 311 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 312 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 313 %load = load float, float addrspace(1)* %gep, align 4 314 %v = fsub float -0.0, %load 315 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 316 store float %canonicalized, float addrspace(1)* %gep, align 4 317 ret void 318} 319 320; GCN-LABEL: test_fold_canonicalize_fneg_value_f32: 321; GCN: v_xor_b32_e32 [[V:v[0-9]+]], 0x80000000, v{{[0-9]+}} 322; GCN-NOT: v_mul 323; GCN-NOT: v_max 324; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 325define amdgpu_kernel void @test_fold_canonicalize_fneg_value_f32(float addrspace(1)* %arg) { 326 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 327 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 328 %load = load float, float addrspace(1)* %gep, align 4 329 %v0 = fadd float %load, 0.0 330 %v = fsub float -0.0, %v0 331 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 332 store float %canonicalized, float addrspace(1)* %gep, align 4 333 ret void 334} 335 336; GCN-LABEL: test_no_fold_canonicalize_fabs_value_f32: 337; GCN-FLUSH: v_mul_f32_e64 v{{[0-9]+}}, 1.0, |v{{[0-9]+}}| 338; GCN-DENORM: v_max_f32_e64 v{{[0-9]+}}, |v{{[0-9]+}}|, |v{{[0-9]+}}| 339define amdgpu_kernel void @test_no_fold_canonicalize_fabs_value_f32(float addrspace(1)* %arg) { 340 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 341 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 342 %load = load float, float addrspace(1)* %gep, align 4 343 %v = tail call float @llvm.fabs.f32(float %load) 344 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 345 store float %canonicalized, float addrspace(1)* %gep, align 4 346 ret void 347} 348 349; GCN-LABEL: test_no_fold_canonicalize_fcopysign_value_f32: 350; GCN-FLUSH: v_mul_f32_e64 v{{[0-9]+}}, 1.0, |v{{[0-9]+}}| 351; GCN-DENORM: v_max_f32_e64 v{{[0-9]+}}, |v{{[0-9]+}}|, |v{{[0-9]+}}| 352; GCN-NOT: v_mul_ 353; GCN-NOT: v_max_ 354define amdgpu_kernel void @test_no_fold_canonicalize_fcopysign_value_f32(float addrspace(1)* %arg, float %sign) { 355 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 356 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 357 %load = load float, float addrspace(1)* %gep, align 4 358 %canon.load = tail call float @llvm.canonicalize.f32(float %load) 359 %copysign = call float @llvm.copysign.f32(float %canon.load, float %sign) 360 %v = tail call float @llvm.fabs.f32(float %load) 361 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 362 store float %canonicalized, float addrspace(1)* %gep, align 4 363 ret void 364} 365 366; GCN-LABEL: test_fold_canonicalize_fabs_value_f32: 367; GCN: v_and_b32_e32 [[V:v[0-9]+]], 0x7fffffff, v{{[0-9]+}} 368; GCN-NOT: v_mul 369; GCN-NOT: v_max 370; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 371define amdgpu_kernel void @test_fold_canonicalize_fabs_value_f32(float addrspace(1)* %arg) { 372 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 373 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 374 %load = load float, float addrspace(1)* %gep, align 4 375 %v0 = fadd float %load, 0.0 376 %v = tail call float @llvm.fabs.f32(float %v0) 377 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 378 store float %canonicalized, float addrspace(1)* %gep, align 4 379 ret void 380} 381 382; GCN-LABEL: test_fold_canonicalize_sin_value_f32: 383; GCN: v_sin_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}} 384; GCN-NOT: v_mul 385; GCN-NOT: v_max 386; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 387define amdgpu_kernel void @test_fold_canonicalize_sin_value_f32(float addrspace(1)* %arg) { 388 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 389 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 390 %load = load float, float addrspace(1)* %gep, align 4 391 %v = tail call float @llvm.sin.f32(float %load) 392 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 393 store float %canonicalized, float addrspace(1)* %gep, align 4 394 ret void 395} 396 397; GCN-LABEL: test_fold_canonicalize_cos_value_f32: 398; GCN: v_cos_f32_e32 [[V:v[0-9]+]], v{{[0-9]+}} 399; GCN-NOT: v_mul 400; GCN-NOT: v_max 401; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 402define amdgpu_kernel void @test_fold_canonicalize_cos_value_f32(float addrspace(1)* %arg) { 403 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 404 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 405 %load = load float, float addrspace(1)* %gep, align 4 406 %v = tail call float @llvm.cos.f32(float %load) 407 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 408 store float %canonicalized, float addrspace(1)* %gep, align 4 409 ret void 410} 411 412; GCN-LABEL: test_fold_canonicalize_sin_value_f16: 413; GCN: v_sin_f16_e32 [[V0:v[0-9]+]], v{{[0-9]+}} 414; GCN-NOT: v_mul 415; GCN-NOT: v_max 416; GCN: {{flat|global}}_store_short v[{{[0-9:]+}}], [[V0]] 417define amdgpu_kernel void @test_fold_canonicalize_sin_value_f16(half addrspace(1)* %arg) { 418 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 419 %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id 420 %load = load half, half addrspace(1)* %gep, align 2 421 %v = tail call half @llvm.sin.f16(half %load) 422 %canonicalized = tail call half @llvm.canonicalize.f16(half %v) 423 store half %canonicalized, half addrspace(1)* %gep, align 2 424 ret void 425} 426 427; GCN-LABEL: test_fold_canonicalize_cos_value_f16: 428; GCN: v_cos_f16_e32 [[V0:v[0-9]+]], v{{[0-9]+}} 429; GCN-NOT: v_mul 430; GCN-NOT: v_max 431; GCN: {{flat|global}}_store_short v[{{[0-9:]+}}], [[V0]] 432define amdgpu_kernel void @test_fold_canonicalize_cos_value_f16(half addrspace(1)* %arg) { 433 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 434 %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id 435 %load = load half, half addrspace(1)* %gep, align 2 436 %v = tail call half @llvm.cos.f16(half %load) 437 %canonicalized = tail call half @llvm.canonicalize.f16(half %v) 438 store half %canonicalized, half addrspace(1)* %gep, align 2 439 ret void 440} 441 442; GCN-LABEL: test_fold_canonicalize_qNaN_value_f32: 443; GCN: v_mov_b32_e32 [[V:v[0-9]+]], 0x7fc00000 444; GCN-NOT: v_mul 445; GCN-NOT: v_max 446; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 447define amdgpu_kernel void @test_fold_canonicalize_qNaN_value_f32(float addrspace(1)* %arg) { 448 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 449 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 450 %canonicalized = tail call float @llvm.canonicalize.f32(float 0x7FF8000000000000) 451 store float %canonicalized, float addrspace(1)* %gep, align 4 452 ret void 453} 454 455; GCN-LABEL: test_fold_canonicalize_minnum_value_from_load_f32_ieee_mode: 456; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]] 457; GCN-FLUSH: v_mul_f32_e32 [[QUIET:v[0-9]+]], 1.0, [[VAL]] 458; GCN-DENORM: v_max_f32_e32 [[QUIET:v[0-9]+]], [[VAL]], [[VAL]] 459; GCN: v_min_f32_e32 [[V:v[0-9]+]], 0, [[QUIET]] 460 461; GCN-NOT: v_max 462; GCN-NOT: v_mul 463 464; GFX9: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 465define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_ieee_mode(float addrspace(1)* %arg) { 466 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 467 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 468 %load = load float, float addrspace(1)* %gep, align 4 469 %v = tail call float @llvm.minnum.f32(float %load, float 0.0) 470 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 471 store float %canonicalized, float addrspace(1)* %gep, align 4 472 ret void 473} 474 475; GCN-LABEL: test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode: 476; VI-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, v{{[0-9]+}} 477; GCN-DENORM-NOT: v_max 478; GCN-DENORM-NOT: v_mul 479 480; GCN: v_min_f32_e32 v{{[0-9]+}}, 0, v{{[0-9]+}} 481; GCN-DENORM-NOT: v_max 482; GCN-DENORM-NOT: v_mul 483 484; GFX9: {{flat|global}}_store_dword v[{{[0-9:]+}}] 485define amdgpu_kernel void @test_fold_canonicalize_minnum_value_from_load_f32_nnan_ieee_mode(float addrspace(1)* %arg) #1 { 486 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 487 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 488 %load = load float, float addrspace(1)* %gep, align 4 489 %v = tail call float @llvm.minnum.f32(float %load, float 0.0) 490 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 491 store float %canonicalized, float addrspace(1)* %gep, align 4 492 ret void 493} 494 495; GCN-LABEL: test_fold_canonicalize_minnum_value_f32: 496; GCN: v_min_f32_e32 [[V:v[0-9]+]], 0, v{{[0-9]+}} 497; GCN-NOT: v_mul 498; GCN-NOT: v_max 499; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 500define amdgpu_kernel void @test_fold_canonicalize_minnum_value_f32(float addrspace(1)* %arg) { 501 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 502 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 503 %load = load float, float addrspace(1)* %gep, align 4 504 %v0 = fadd float %load, 0.0 505 %v = tail call float @llvm.minnum.f32(float %v0, float 0.0) 506 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 507 store float %canonicalized, float addrspace(1)* %gep, align 4 508 ret void 509} 510 511; FIXME: Should there be more checks here? minnum with NaN operand is simplified away. 512 513; GCN-LABEL: test_fold_canonicalize_sNaN_value_f32: 514; GCN: {{flat|global}}_load_dword [[LOAD:v[0-9]+]] 515; GCN-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, [[LOAD]] 516; GCN-DENORM: v_max_f32_e32 v{{[0-9]+}}, [[LOAD]], [[LOAD]] 517define amdgpu_kernel void @test_fold_canonicalize_sNaN_value_f32(float addrspace(1)* %arg) { 518 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 519 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 520 %load = load float, float addrspace(1)* %gep, align 4 521 %v = tail call float @llvm.minnum.f32(float %load, float bitcast (i32 2139095041 to float)) 522 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 523 store float %canonicalized, float addrspace(1)* %gep, align 4 524 ret void 525} 526 527; GCN-LABEL: test_fold_canonicalize_denorm_value_f32: 528; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]] 529 530; GFX9-DENORM: v_max_f32_e32 [[QUIET:v[0-9]+]], [[VAL]], [[VAL]] 531; GFX9-DENORM: v_min_f32_e32 [[RESULT:v[0-9]+]], 0x7fffff, [[QUIET]] 532 533; GFX9-FLUSH: v_mul_f32_e32 [[QUIET:v[0-9]+]], 1.0, [[VAL]] 534; GFX9-FLUSH: v_min_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET]] 535 536 537; VI-FLUSH: v_mul_f32_e32 [[QUIET_V0:v[0-9]+]], 1.0, [[VAL]] 538; VI-FLUSH: v_min_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET_V0]] 539 540; VI-DENORM: v_min_f32_e32 [[RESULT:v[0-9]+]], 0x7fffff, [[VAL]] 541 542; GCN-NOT: v_mul 543; GCN-NOT: v_max 544; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[RESULT]] 545define amdgpu_kernel void @test_fold_canonicalize_denorm_value_f32(float addrspace(1)* %arg) { 546 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 547 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 548 %load = load float, float addrspace(1)* %gep, align 4 549 %v = tail call float @llvm.minnum.f32(float %load, float bitcast (i32 8388607 to float)) 550 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 551 store float %canonicalized, float addrspace(1)* %gep, align 4 552 ret void 553} 554 555; GCN-LABEL: test_fold_canonicalize_maxnum_value_from_load_f32_ieee_mode: 556; GCN: {{flat|global}}_load_dword [[VAL:v[0-9]+]] 557 558; GFX9: v_max_f32_e32 [[RESULT:v[0-9]+]], 0, [[VAL]] 559 560; VI-FLUSH: v_mul_f32_e32 [[QUIET:v[0-9]+]], 1.0, [[VAL]] 561; VI-FLUSH: v_max_f32_e32 [[RESULT:v[0-9]+]], 0, [[QUIET]] 562 563; VI-DENORM: v_max_f32_e32 [[RESULT:v[0-9]+]], 0, [[VAL]] 564 565; GCN-NOT: v_mul 566; GCN-NOT: v_max 567; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[RESULT]] 568define amdgpu_kernel void @test_fold_canonicalize_maxnum_value_from_load_f32_ieee_mode(float addrspace(1)* %arg) { 569 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 570 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 571 %load = load float, float addrspace(1)* %gep, align 4 572 %v = tail call float @llvm.maxnum.f32(float %load, float 0.0) 573 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 574 store float %canonicalized, float addrspace(1)* %gep, align 4 575 ret void 576} 577 578; GCN-LABEL: test_fold_canonicalize_maxnum_value_f32: 579; GCN: v_max_f32_e32 [[V:v[0-9]+]], 0, v{{[0-9]+}} 580; GCN-NOT: v_max 581; GCN-NOT: v_mul 582; GCN: {{flat|global}}_store_dword v[{{[0-9:]+}}], [[V]] 583define amdgpu_kernel void @test_fold_canonicalize_maxnum_value_f32(float addrspace(1)* %arg) { 584 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 585 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 586 %load = load float, float addrspace(1)* %gep, align 4 587 %v0 = fadd float %load, 0.0 588 %v = tail call float @llvm.maxnum.f32(float %v0, float 0.0) 589 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 590 store float %canonicalized, float addrspace(1)* %gep, align 4 591 ret void 592} 593 594; GCN-LABEL: test_fold_canonicalize_maxnum_value_f64: 595; GCN: v_max_f64 [[V:v\[[0-9]+:[0-9]+\]]], v[{{[0-9:]+}}], 0 596; GCN-NOT: v_mul 597; GCN-NOT: v_max 598; GCN: {{flat|global}}_store_dwordx2 v[{{[0-9:]+}}], [[V]] 599define amdgpu_kernel void @test_fold_canonicalize_maxnum_value_f64(double addrspace(1)* %arg) { 600 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 601 %gep = getelementptr inbounds double, double addrspace(1)* %arg, i32 %id 602 %load = load double, double addrspace(1)* %gep, align 8 603 %v0 = fadd double %load, 0.0 604 %v = tail call double @llvm.maxnum.f64(double %v0, double 0.0) 605 %canonicalized = tail call double @llvm.canonicalize.f64(double %v) 606 store double %canonicalized, double addrspace(1)* %gep, align 8 607 ret void 608} 609 610; GCN-LABEL: test_fold_canonicalize_fmul_value_f32_no_ieee: 611; GCN: v_mul_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}} 612; GCN-NOT: v_mul 613; GCN-NOT: v_max 614; GCN-NEXT: ; return 615define amdgpu_ps float @test_fold_canonicalize_fmul_value_f32_no_ieee(float %arg) { 616entry: 617 %v = fmul float %arg, 15.0 618 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 619 ret float %canonicalized 620} 621 622; GCN-LABEL: test_fold_canonicalize_fmul_nnan_value_f32_no_ieee: 623; GCN: v_mul_f32_e32 [[V:v[0-9]+]], 0x41700000, v{{[0-9]+}} 624; GCN-NOT: v_mul 625; GCN-NOT: v_max 626; GCN-NEXT: ; return 627define amdgpu_ps float @test_fold_canonicalize_fmul_nnan_value_f32_no_ieee(float %arg) { 628entry: 629 %v = fmul nnan float %arg, 15.0 630 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 631 ret float %canonicalized 632} 633 634; GCN-LABEL: {{^}}test_fold_canonicalize_fdiv_value_f32_no_ieee: 635; GCN: v_div_fixup_f32 636; GCN-NOT: v_max 637; GCN-NOT: v_mul 638; GCN: ; return 639define amdgpu_ps float @test_fold_canonicalize_fdiv_value_f32_no_ieee(float %arg0) { 640entry: 641 %v = fdiv float 15.0, %arg0 642 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 643 ret float %canonicalized 644} 645 646; GCN-LABEL: {{^}}test_fold_canonicalize_load_nnan_value_f32 647; GFX9-DENORM: global_load_dword [[V:v[0-9]+]], 648; GFX9-DENORM: global_store_dword v[{{[0-9:]+}}], [[V]] 649; GFX9-DENORM-NOT: 1.0 650; GCN-FLUSH: v_mul_f32_e32 v{{[0-9]+}}, 1.0, v{{[0-9]+}} 651define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f32(float addrspace(1)* %arg, float addrspace(1)* %out) #1 { 652 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 653 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 654 %v = load float, float addrspace(1)* %gep, align 4 655 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 656 %gep2 = getelementptr inbounds float, float addrspace(1)* %out, i32 %id 657 store float %canonicalized, float addrspace(1)* %gep2, align 4 658 ret void 659} 660 661; GCN-LABEL: {{^}}test_fold_canonicalize_load_nnan_value_f64 662; GCN: {{flat|global}}_load_dwordx2 [[V:v\[[0-9:]+\]]], 663; GCN: {{flat|global}}_store_dwordx2 v[{{[0-9:]+}}], [[V]] 664; GCN-NOT: v_mul_ 665; GCN-NOT: v_max_ 666define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f64(double addrspace(1)* %arg, double addrspace(1)* %out) #1 { 667 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 668 %gep = getelementptr inbounds double, double addrspace(1)* %arg, i32 %id 669 %v = load double, double addrspace(1)* %gep, align 8 670 %canonicalized = tail call double @llvm.canonicalize.f64(double %v) 671 %gep2 = getelementptr inbounds double, double addrspace(1)* %out, i32 %id 672 store double %canonicalized, double addrspace(1)* %gep2, align 8 673 ret void 674} 675 676; GCN-LABEL: {{^}}test_fold_canonicalize_load_nnan_value_f16 677; GCN: {{flat|global}}_load_ushort [[V:v[0-9]+]], 678; GCN-NOT: v_mul 679; GCN-NOT: v_max 680; GCN: {{flat|global}}_store_short v{{\[[0-9]+:[0-9]+\]}}, [[V]] 681define amdgpu_kernel void @test_fold_canonicalize_load_nnan_value_f16(half addrspace(1)* %arg, half addrspace(1)* %out) #1 { 682 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 683 %gep = getelementptr inbounds half, half addrspace(1)* %arg, i32 %id 684 %v = load half, half addrspace(1)* %gep, align 2 685 %canonicalized = tail call half @llvm.canonicalize.f16(half %v) 686 %gep2 = getelementptr inbounds half, half addrspace(1)* %out, i32 %id 687 store half %canonicalized, half addrspace(1)* %gep2, align 2 688 ret void 689} 690 691; GCN-LABEL: {{^}}test_fold_canonicalize_select_value_f32: 692; GCN: v_add_f32 693; GCN: v_add_f32 694; GCN: v_cndmask_b32 695; GCN-NOT: v_mul_ 696; GCN-NOT: v_max_ 697define amdgpu_kernel void @test_fold_canonicalize_select_value_f32(float addrspace(1)* %arg) { 698 %id = tail call i32 @llvm.amdgcn.workitem.id.x() 699 %gep = getelementptr inbounds float, float addrspace(1)* %arg, i32 %id 700 %load0 = load volatile float, float addrspace(1)* %gep, align 4 701 %load1 = load volatile float, float addrspace(1)* %gep, align 4 702 %load2 = load volatile i32, i32 addrspace(1)* undef, align 4 703 %v0 = fadd float %load0, 15.0 704 %v1 = fadd float %load1, 32.0 705 %cond = icmp eq i32 %load2, 0 706 %select = select i1 %cond, float %v0, float %v1 707 %canonicalized = tail call float @llvm.canonicalize.f32(float %select) 708 store float %canonicalized, float addrspace(1)* %gep, align 4 709 ret void 710} 711 712; Need to quiet the nan with a separate instruction since it will be 713; passed through the minnum. 714; FIXME: canonicalize doens't work correctly without ieee_mode 715 716; GCN-LABEL: {{^}}test_fold_canonicalize_minnum_value_no_ieee_mode: 717; GFX9-NOT: v0 718; GFX9-NOT: v1 719; GFX9: v_min_f32_e32 v0, v0, v1 720; GFX9-NEXT: ; return to shader 721 722; VI-FLUSH: v_min_f32_e32 v0, v0, v1 723; VI-FLUSH-NEXT: v_mul_f32_e32 v0, 1.0, v0 724; VI-FLUSH-NEXT: ; return 725 726; VI-DENORM-NOT: v0 727; VI-DENORM: v_min_f32_e32 v0, v0, v1 728; VI-DENORM-NEXT: ; return 729define amdgpu_ps float @test_fold_canonicalize_minnum_value_no_ieee_mode(float %arg0, float %arg1) { 730 %v = tail call float @llvm.minnum.f32(float %arg0, float %arg1) 731 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 732 ret float %canonicalized 733} 734 735; GCN-LABEL: {{^}}test_fold_canonicalize_minnum_value_ieee_mode: 736; GFX9: v_min_f32_e32 v0, v0, v1 737; GFX9-NEXT: s_setpc_b64 738 739; VI-FLUSH-DAG: v_mul_f32_e32 v0, 1.0, v0 740; VI-FLUSH-DAG: v_mul_f32_e32 v1, 1.0, v1 741; VI-FLUSH: v_min_f32_e32 v0, v0, v1 742 743; VI-DENORM-DAG: v_max_f32_e32 v0, v0, v0 744; VI-DENORM-DAG: v_max_f32_e32 v1, v1, v1 745; VI-DENORM: v_min_f32_e32 v0, v0, v1 746 747; VI-NEXT: s_setpc_b64 748define float @test_fold_canonicalize_minnum_value_ieee_mode(float %arg0, float %arg1) { 749 %v = tail call float @llvm.minnum.f32(float %arg0, float %arg1) 750 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 751 ret float %canonicalized 752} 753 754; Canonicalizing flush necessary pre-gfx9 755; GCN-LABEL: {{^}}test_fold_canonicalize_minnum_value_no_ieee_mode_nnan: 756; GCN: v_min_f32_e32 v0, v0, v1 757; VI-FLUSH-NEXT: v_mul_f32_e32 v0, 1.0, v0 758; GCN-NEXT: ; return 759define amdgpu_ps float @test_fold_canonicalize_minnum_value_no_ieee_mode_nnan(float %arg0, float %arg1) #1 { 760 %v = tail call float @llvm.minnum.f32(float %arg0, float %arg1) 761 %canonicalized = tail call float @llvm.canonicalize.f32(float %v) 762 ret float %canonicalized 763} 764 765; GCN-LABEL: {{^}}v_test_canonicalize_build_vector_v2f16: 766; GFX9-DAG: v_add_f16_e32 767; GFX9-DAG: v_mul_f16_e32 768; GFX9-NOT: v_max 769; GFX9-NOT: v_pk_max 770define <2 x half> @v_test_canonicalize_build_vector_v2f16(<2 x half> %vec) { 771 %lo = extractelement <2 x half> %vec, i32 0 772 %hi = extractelement <2 x half> %vec, i32 1 773 %lo.op = fadd half %lo, 1.0 774 %hi.op = fmul half %lo, 4.0 775 %ins0 = insertelement <2 x half> undef, half %lo.op, i32 0 776 %ins1 = insertelement <2 x half> %ins0, half %hi.op, i32 1 777 %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins1) 778 ret <2 x half> %canonicalized 779} 780 781; GCN-LABEL: {{^}}v_test_canonicalize_build_vector_noncanon1_v2f16: 782; GFX9: v_add_f16_e32 783; GFX9: v_pk_max 784define <2 x half> @v_test_canonicalize_build_vector_noncanon1_v2f16(<2 x half> %vec) { 785 %lo = extractelement <2 x half> %vec, i32 0 786 %lo.op = fadd half %lo, 1.0 787 %ins = insertelement <2 x half> %vec, half %lo.op, i32 0 788 %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins) 789 ret <2 x half> %canonicalized 790} 791 792; GCN-LABEL: {{^}}v_test_canonicalize_build_vector_noncanon0_v2f16: 793; GFX9: v_add_f16_sdwa 794; GFX9: v_pk_max 795define <2 x half> @v_test_canonicalize_build_vector_noncanon0_v2f16(<2 x half> %vec) { 796 %hi = extractelement <2 x half> %vec, i32 1 797 %hi.op = fadd half %hi, 1.0 798 %ins = insertelement <2 x half> %vec, half %hi.op, i32 1 799 %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins) 800 ret <2 x half> %canonicalized 801} 802 803; GCN-LABEL: {{^}}v_test_canonicalize_extract_element_v2f16: 804; GFX9: s_waitcnt 805; GFX9-NEXT: v_mul_f16_e32 v0, 4.0, v0 806; GFX9-NEXT: s_setpc_b64 807define half @v_test_canonicalize_extract_element_v2f16(<2 x half> %vec) { 808 %vec.op = fmul <2 x half> %vec, <half 4.0, half 4.0> 809 %elt = extractelement <2 x half> %vec.op, i32 0 810 %canonicalized = call half @llvm.canonicalize.f16(half %elt) 811 ret half %canonicalized 812} 813 814; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_v2f16: 815; GFX9: v_mul_f16_e32 816; GFX9: v_pk_mul_f16 817; GFX9-NOT: v_max 818; GFX9-NOT: v_pk_max 819define <2 x half> @v_test_canonicalize_insertelement_v2f16(<2 x half> %vec, half %val, i32 %idx) { 820 %vec.op = fmul <2 x half> %vec, <half 4.0, half 4.0> 821 %ins.op = fmul half %val, 8.0 822 %ins = insertelement <2 x half> %vec.op, half %ins.op, i32 %idx 823 %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins) 824 ret <2 x half> %canonicalized 825} 826 827; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_noncanon_vec_v2f16: 828; GFX9: v_mul_f16 829; GFX9: v_pk_max_f16 v0, v0, v0 830; GFX9-NEXT: s_setpc_b64 831define <2 x half> @v_test_canonicalize_insertelement_noncanon_vec_v2f16(<2 x half> %vec, half %val, i32 %idx) { 832 %ins.op = fmul half %val, 8.0 833 %ins = insertelement <2 x half> %vec, half %ins.op, i32 %idx 834 %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins) 835 ret <2 x half> %canonicalized 836} 837 838; GCN-LABEL: {{^}}v_test_canonicalize_insertelement_noncanon_insval_v2f16: 839; GFX9: v_pk_mul_f16 840; GFX9: v_pk_max_f16 v0, v0, v0 841; GFX9-NEXT: s_setpc_b64 842define <2 x half> @v_test_canonicalize_insertelement_noncanon_insval_v2f16(<2 x half> %vec, half %val, i32 %idx) { 843 %vec.op = fmul <2 x half> %vec, <half 4.0, half 4.0> 844 %ins = insertelement <2 x half> %vec.op, half %val, i32 %idx 845 %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %ins) 846 ret <2 x half> %canonicalized 847} 848 849; GCN-LABEL: {{^}}v_test_canonicalize_cvt_pkrtz: 850; GCN: s_waitcnt 851; GCN-NEXT: v_cvt_pkrtz_f16_f32 v0, v0, v1 852; GCN-NEXT: s_setpc_b64 853define <2 x half> @v_test_canonicalize_cvt_pkrtz(float %a, float %b) { 854 %cvt = call <2 x half> @llvm.amdgcn.cvt.pkrtz(float %a, float %b) 855 %canonicalized = call <2 x half> @llvm.canonicalize.v2f16(<2 x half> %cvt) 856 ret <2 x half> %canonicalized 857} 858 859; GCN-LABEL: {{^}}v_test_canonicalize_cubeid: 860; GCN: s_waitcnt 861; GCN-NEXT: v_cubeid_f32 v0, v0, v1, v2 862; GCN-NEXT: s_setpc_b64 863define float @v_test_canonicalize_cubeid(float %a, float %b, float %c) { 864 %cvt = call float @llvm.amdgcn.cubeid(float %a, float %b, float %c) 865 %canonicalized = call float @llvm.canonicalize.f32(float %cvt) 866 ret float %canonicalized 867} 868 869; GCN-LABEL: {{^}}v_test_canonicalize_frexp_mant: 870; GCN: s_waitcnt 871; GCN-NEXT: v_frexp_mant_f32_e32 v0, v0 872; GCN-NEXT: s_setpc_b64 873define float @v_test_canonicalize_frexp_mant(float %a) { 874 %cvt = call float @llvm.amdgcn.frexp.mant.f32(float %a) 875 %canonicalized = call float @llvm.canonicalize.f32(float %cvt) 876 ret float %canonicalized 877} 878 879; Avoid failing the test on FreeBSD11.0 which will match the GCN-NOT: 1.0 880; in the .amd_amdgpu_isa "amdgcn-unknown-freebsd11.0--gfx802" directive 881; GCN: .amd_amdgpu_isa 882 883declare float @llvm.canonicalize.f32(float) #0 884declare float @llvm.copysign.f32(float, float) #0 885declare float @llvm.amdgcn.fmul.legacy(float, float) #0 886declare float @llvm.amdgcn.fmad.ftz.f32(float, float, float) #0 887declare double @llvm.canonicalize.f64(double) #0 888declare half @llvm.canonicalize.f16(half) #0 889declare <2 x half> @llvm.canonicalize.v2f16(<2 x half>) #0 890declare i32 @llvm.amdgcn.workitem.id.x() #0 891declare float @llvm.sqrt.f32(float) #0 892declare float @llvm.ceil.f32(float) #0 893declare float @llvm.floor.f32(float) #0 894declare float @llvm.fma.f32(float, float, float) #0 895declare float @llvm.fmuladd.f32(float, float, float) #0 896declare float @llvm.fabs.f32(float) #0 897declare float @llvm.sin.f32(float) #0 898declare float @llvm.cos.f32(float) #0 899declare half @llvm.sin.f16(half) #0 900declare half @llvm.cos.f16(half) #0 901declare float @llvm.minnum.f32(float, float) #0 902declare float @llvm.maxnum.f32(float, float) #0 903declare double @llvm.maxnum.f64(double, double) #0 904declare <2 x half> @llvm.amdgcn.cvt.pkrtz(float, float) #0 905declare float @llvm.amdgcn.cubeid(float, float, float) #0 906declare float @llvm.amdgcn.frexp.mant.f32(float) #0 907 908attributes #0 = { nounwind readnone } 909attributes #1 = { "no-nans-fp-math"="true" } 910attributes #2 = { "denormal-fp-math"="preserve-sign,preserve-sign" "denormal-fp-math-f32"="ieee,ieee" } 911