1; RUN: llc -march=amdgcn -mcpu=tahiti -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=SI %s 2; RUN: llc -march=amdgcn -mcpu=fiji -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=VI %s 3 4; IEEE bit enabled for compute kernel, no shouldn't use. 5; GCN-LABEL: {{^}}v_omod_div2_f32_enable_ieee_signed_zeros: 6; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]] 7; GCN: v_add_f32_e32 [[ADD:v[0-9]+]], 1.0, [[A]]{{$}} 8; GCN: v_mul_f32_e32 v{{[0-9]+}}, 0.5, [[ADD]]{{$}} 9define amdgpu_kernel void @v_omod_div2_f32_enable_ieee_signed_zeros(float addrspace(1)* %out, float addrspace(1)* %aptr) #4 { 10 %tid = call i32 @llvm.amdgcn.workitem.id.x() 11 %gep0 = getelementptr float, float addrspace(1)* %aptr, i32 %tid 12 %out.gep = getelementptr float, float addrspace(1)* %out, i32 %tid 13 %a = load float, float addrspace(1)* %gep0 14 %add = fadd float %a, 1.0 15 %div2 = fmul float %add, 0.5 16 store float %div2, float addrspace(1)* %out.gep 17 ret void 18} 19 20; IEEE bit enabled for compute kernel, no shouldn't use even though nsz is allowed 21; GCN-LABEL: {{^}}v_omod_div2_f32_enable_ieee_nsz: 22; GCN: {{buffer|flat}}_load_dword [[A:v[0-9]+]] 23; GCN: v_add_f32_e32 [[ADD:v[0-9]+]], 1.0, [[A]]{{$}} 24; GCN: v_mul_f32_e32 v{{[0-9]+}}, 0.5, [[ADD]]{{$}} 25define amdgpu_kernel void @v_omod_div2_f32_enable_ieee_nsz(float addrspace(1)* %out, float addrspace(1)* %aptr) #0 { 26 %tid = call i32 @llvm.amdgcn.workitem.id.x() 27 %gep0 = getelementptr float, float addrspace(1)* %aptr, i32 %tid 28 %out.gep = getelementptr float, float addrspace(1)* %out, i32 %tid 29 %a = load float, float addrspace(1)* %gep0 30 %add = fadd float %a, 1.0 31 %div2 = fmul float %add, 0.5 32 store float %div2, float addrspace(1)* %out.gep 33 ret void 34} 35 36; Only allow without IEEE bit if signed zeros are significant. 37; GCN-LABEL: {{^}}v_omod_div2_f32_signed_zeros: 38; GCN: v_add_f32_e32 [[ADD:v[0-9]+]], 1.0, v0{{$}} 39; GCN: v_mul_f32_e32 v{{[0-9]+}}, 0.5, [[ADD]]{{$}} 40define amdgpu_ps void @v_omod_div2_f32_signed_zeros(float %a) #4 { 41 %add = fadd float %a, 1.0 42 %div2 = fmul float %add, 0.5 43 store float %div2, float addrspace(1)* undef 44 ret void 45} 46 47; GCN-LABEL: {{^}}v_omod_div2_f32: 48; GCN: v_add_f32_e64 v{{[0-9]+}}, v0, 1.0 div:2{{$}} 49define amdgpu_ps void @v_omod_div2_f32(float %a) #0 { 50 %add = fadd float %a, 1.0 51 %div2 = fmul float %add, 0.5 52 store float %div2, float addrspace(1)* undef 53 ret void 54} 55 56; GCN-LABEL: {{^}}v_omod_mul2_f32: 57; GCN: v_add_f32_e64 v{{[0-9]+}}, v0, 1.0 mul:2{{$}} 58define amdgpu_ps void @v_omod_mul2_f32(float %a) #0 { 59 %add = fadd float %a, 1.0 60 %div2 = fmul float %add, 2.0 61 store float %div2, float addrspace(1)* undef 62 ret void 63} 64 65; GCN-LABEL: {{^}}v_omod_mul4_f32: 66; GCN: v_add_f32_e64 v{{[0-9]+}}, v0, 1.0 mul:4{{$}} 67define amdgpu_ps void @v_omod_mul4_f32(float %a) #0 { 68 %add = fadd float %a, 1.0 69 %div2 = fmul float %add, 4.0 70 store float %div2, float addrspace(1)* undef 71 ret void 72} 73 74; GCN-LABEL: {{^}}v_omod_mul4_multi_use_f32: 75; GCN: v_add_f32_e32 [[ADD:v[0-9]+]], 1.0, v0{{$}} 76; GCN: v_mul_f32_e32 v{{[0-9]+}}, 4.0, [[ADD]]{{$}} 77define amdgpu_ps void @v_omod_mul4_multi_use_f32(float %a) #0 { 78 %add = fadd float %a, 1.0 79 %div2 = fmul float %add, 4.0 80 store float %div2, float addrspace(1)* undef 81 store volatile float %add, float addrspace(1)* undef 82 ret void 83} 84 85; GCN-LABEL: {{^}}v_omod_mul4_dbg_use_f32: 86; GCN: v_add_f32_e64 v{{[0-9]+}}, v0, 1.0 mul:4{{$}} 87define amdgpu_ps void @v_omod_mul4_dbg_use_f32(float %a) #0 { 88 %add = fadd float %a, 1.0 89 call void @llvm.dbg.value(metadata float %add, i64 0, metadata !4, metadata !9), !dbg !10 90 %div2 = fmul float %add, 4.0 91 store float %div2, float addrspace(1)* undef 92 ret void 93} 94 95; Clamp is applied after omod, folding both into instruction is OK. 96; GCN-LABEL: {{^}}v_clamp_omod_div2_f32: 97; GCN: v_add_f32_e64 v{{[0-9]+}}, v0, 1.0 clamp div:2{{$}} 98define amdgpu_ps void @v_clamp_omod_div2_f32(float %a) #0 { 99 %add = fadd float %a, 1.0 100 %div2 = fmul float %add, 0.5 101 102 %max = call float @llvm.maxnum.f32(float %div2, float 0.0) 103 %clamp = call float @llvm.minnum.f32(float %max, float 1.0) 104 store float %clamp, float addrspace(1)* undef 105 ret void 106} 107 108; Cannot fold omod into clamp 109; GCN-LABEL: {{^}}v_omod_div2_clamp_f32: 110; GCN: v_add_f32_e64 [[ADD:v[0-9]+]], v0, 1.0 clamp{{$}} 111; GCN: v_mul_f32_e32 v{{[0-9]+}}, 0.5, [[ADD]]{{$}} 112define amdgpu_ps void @v_omod_div2_clamp_f32(float %a) #0 { 113 %add = fadd float %a, 1.0 114 %max = call float @llvm.maxnum.f32(float %add, float 0.0) 115 %clamp = call float @llvm.minnum.f32(float %max, float 1.0) 116 %div2 = fmul float %clamp, 0.5 117 store float %div2, float addrspace(1)* undef 118 ret void 119} 120 121; GCN-LABEL: {{^}}v_omod_div2_abs_src_f32: 122; GCN: v_add_f32_e32 [[ADD:v[0-9]+]], 1.0, v0{{$}} 123; GCN: v_mul_f32_e64 v{{[0-9]+}}, |[[ADD]]|, 0.5{{$}} 124define amdgpu_ps void @v_omod_div2_abs_src_f32(float %a) #0 { 125 %add = fadd float %a, 1.0 126 %abs.add = call float @llvm.fabs.f32(float %add) 127 %div2 = fmul float %abs.add, 0.5 128 store float %div2, float addrspace(1)* undef 129 ret void 130} 131 132; GCN-LABEL: {{^}}v_omod_add_self_clamp_f32: 133; GCN: v_add_f32_e64 v{{[0-9]+}}, v0, v0 clamp{{$}} 134define amdgpu_ps void @v_omod_add_self_clamp_f32(float %a) #0 { 135 %add = fadd float %a, %a 136 %max = call float @llvm.maxnum.f32(float %add, float 0.0) 137 %clamp = call float @llvm.minnum.f32(float %max, float 1.0) 138 store float %clamp, float addrspace(1)* undef 139 ret void 140} 141 142; GCN-LABEL: {{^}}v_omod_add_clamp_self_f32: 143; GCN: v_max_f32_e64 [[CLAMP:v[0-9]+]], v0, v0 clamp{{$}} 144; GCN: v_add_f32_e32 v{{[0-9]+}}, [[CLAMP]], [[CLAMP]]{{$}} 145define amdgpu_ps void @v_omod_add_clamp_self_f32(float %a) #0 { 146 %max = call float @llvm.maxnum.f32(float %a, float 0.0) 147 %clamp = call float @llvm.minnum.f32(float %max, float 1.0) 148 %add = fadd float %clamp, %clamp 149 store float %add, float addrspace(1)* undef 150 ret void 151} 152 153; GCN-LABEL: {{^}}v_omod_add_abs_self_f32: 154; GCN: v_add_f32_e32 [[X:v[0-9]+]], 1.0, v0 155; GCN: v_add_f32_e64 v{{[0-9]+}}, |[[X]]|, |[[X]]|{{$}} 156define amdgpu_ps void @v_omod_add_abs_self_f32(float %a) #0 { 157 %x = fadd float %a, 1.0 158 %abs.x = call float @llvm.fabs.f32(float %x) 159 %add = fadd float %abs.x, %abs.x 160 store float %add, float addrspace(1)* undef 161 ret void 162} 163 164; GCN-LABEL: {{^}}v_omod_add_abs_x_x_f32: 165 166; GCN: v_add_f32_e32 [[X:v[0-9]+]], 1.0, v0 167; GCN: v_add_f32_e64 v{{[0-9]+}}, |[[X]]|, [[X]]{{$}} 168define amdgpu_ps void @v_omod_add_abs_x_x_f32(float %a) #0 { 169 %x = fadd float %a, 1.0 170 %abs.x = call float @llvm.fabs.f32(float %x) 171 %add = fadd float %abs.x, %x 172 store float %add, float addrspace(1)* undef 173 ret void 174} 175 176; GCN-LABEL: {{^}}v_omod_add_x_abs_x_f32: 177; GCN: v_add_f32_e32 [[X:v[0-9]+]], 1.0, v0 178; GCN: v_add_f32_e64 v{{[0-9]+}}, [[X]], |[[X]]|{{$}} 179define amdgpu_ps void @v_omod_add_x_abs_x_f32(float %a) #0 { 180 %x = fadd float %a, 1.0 181 %abs.x = call float @llvm.fabs.f32(float %x) 182 %add = fadd float %x, %abs.x 183 store float %add, float addrspace(1)* undef 184 ret void 185} 186 187; Don't fold omod into omod into another omod. 188; GCN-LABEL: {{^}}v_omod_div2_omod_div2_f32: 189; GCN: v_add_f32_e64 [[ADD:v[0-9]+]], v0, 1.0 div:2{{$}} 190; GCN: v_mul_f32_e32 v{{[0-9]+}}, 0.5, [[ADD]]{{$}} 191define amdgpu_ps void @v_omod_div2_omod_div2_f32(float %a) #0 { 192 %add = fadd float %a, 1.0 193 %div2.0 = fmul float %add, 0.5 194 %div2.1 = fmul float %div2.0, 0.5 195 store float %div2.1, float addrspace(1)* undef 196 ret void 197} 198 199; Don't fold omod if denorms enabled 200; GCN-LABEL: {{^}}v_omod_div2_f32_denormals: 201; GCN: v_add_f32_e32 [[ADD:v[0-9]+]], 1.0, v0{{$}} 202; GCN: v_mul_f32_e32 v{{[0-9]+}}, 0.5, [[ADD]]{{$}} 203define amdgpu_ps void @v_omod_div2_f32_denormals(float %a) #2 { 204 %add = fadd float %a, 1.0 205 %div2 = fmul float %add, 0.5 206 store float %div2, float addrspace(1)* undef 207 ret void 208} 209 210; Don't fold omod if denorms enabled for add form. 211; GCN-LABEL: {{^}}v_omod_mul2_f32_denormals: 212; GCN: v_add_f32_e32 [[ADD:v[0-9]+]], 1.0, v0{{$}} 213; GCN: v_add_f32_e32 v{{[0-9]+}}, [[ADD]], [[ADD]]{{$}} 214define amdgpu_ps void @v_omod_mul2_f32_denormals(float %a) #2 { 215 %add = fadd float %a, 1.0 216 %mul2 = fadd float %add, %add 217 store float %mul2, float addrspace(1)* undef 218 ret void 219} 220 221; Don't fold omod if denorms enabled 222; GCN-LABEL: {{^}}v_omod_div2_f16_denormals: 223; VI: v_add_f16_e32 [[ADD:v[0-9]+]], 1.0, v0{{$}} 224; VI: v_mul_f16_e32 v{{[0-9]+}}, 0.5, [[ADD]]{{$}} 225define amdgpu_ps void @v_omod_div2_f16_denormals(half %a) #0 { 226 %add = fadd half %a, 1.0 227 %div2 = fmul half %add, 0.5 228 store half %div2, half addrspace(1)* undef 229 ret void 230} 231 232; Don't fold omod if denorms enabled for add form. 233; GCN-LABEL: {{^}}v_omod_mul2_f16_denormals: 234; VI: v_add_f16_e32 [[ADD:v[0-9]+]], 1.0, v0{{$}} 235; VI: v_add_f16_e32 v{{[0-9]+}}, [[ADD]], [[ADD]]{{$}} 236define amdgpu_ps void @v_omod_mul2_f16_denormals(half %a) #0 { 237 %add = fadd half %a, 1.0 238 %mul2 = fadd half %add, %add 239 store half %mul2, half addrspace(1)* undef 240 ret void 241} 242 243; GCN-LABEL: {{^}}v_omod_div2_f16_no_denormals: 244; VI-NOT: v0 245; VI: v_add_f16_e64 [[ADD:v[0-9]+]], v0, 1.0 div:2{{$}} 246define amdgpu_ps void @v_omod_div2_f16_no_denormals(half %a) #3 { 247 %add = fadd half %a, 1.0 248 %div2 = fmul half %add, 0.5 249 store half %div2, half addrspace(1)* undef 250 ret void 251} 252 253; GCN-LABEL: {{^}}v_omod_mac_to_mad: 254; GCN: v_mad_f32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]}} mul:2{{$}} 255define amdgpu_ps void @v_omod_mac_to_mad(float %b, float %a) #0 { 256 %mul = fmul float %a, %a 257 %add = fadd float %mul, %b 258 %mad = fmul float %add, 2.0 259 %res = fmul float %mad, %b 260 store float %res, float addrspace(1)* undef 261 ret void 262} 263 264declare i32 @llvm.amdgcn.workitem.id.x() #1 265declare float @llvm.fabs.f32(float) #1 266declare float @llvm.floor.f32(float) #1 267declare float @llvm.minnum.f32(float, float) #1 268declare float @llvm.maxnum.f32(float, float) #1 269declare float @llvm.amdgcn.fmed3.f32(float, float, float) #1 270declare double @llvm.fabs.f64(double) #1 271declare double @llvm.minnum.f64(double, double) #1 272declare double @llvm.maxnum.f64(double, double) #1 273declare half @llvm.fabs.f16(half) #1 274declare half @llvm.minnum.f16(half, half) #1 275declare half @llvm.maxnum.f16(half, half) #1 276declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 277 278attributes #0 = { nounwind "denormal-fp-math-f32"="preserve-sign,preserve-sign" "no-signed-zeros-fp-math"="true" } 279attributes #1 = { nounwind readnone } 280attributes #2 = { nounwind "denormal-fp-math-f32"="ieee,ieee" "no-signed-zeros-fp-math"="true" } 281attributes #3 = { nounwind "denormal-fp-math"="preserve-sign,preserve-sign" "no-signed-zeros-fp-math"="true" } 282attributes #4 = { nounwind "no-signed-zeros-fp-math"="false" } 283 284!llvm.dbg.cu = !{!0} 285!llvm.module.flags = !{!2, !3} 286 287!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, isOptimized: true, runtimeVersion: 0, emissionKind: NoDebug) 288!1 = !DIFile(filename: "/tmp/foo.cl", directory: "/dev/null") 289!2 = !{i32 2, !"Dwarf Version", i32 4} 290!3 = !{i32 2, !"Debug Info Version", i32 3} 291!4 = !DILocalVariable(name: "add", arg: 1, scope: !5, file: !1, line: 1) 292!5 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0) 293!6 = !DISubroutineType(types: !7) 294!7 = !{null, !8} 295!8 = !DIBasicType(name: "float", size: 32, align: 32) 296!9 = !DIExpression() 297!10 = !DILocation(line: 1, column: 42, scope: !5) 298