1; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs -show-mc-encoding < %s | FileCheck -enable-var-scope -check-prefixes=GCN,GFX9 %s 2; RUN: llc -march=amdgcn -mcpu=fiji -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,CIVI,VI %s 3; RUN: llc -march=amdgcn -mcpu=hawaii -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefixes=GCN,CIVI,CI %s 4 5; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_f16lo: 6; GFX9: v_mad_mix_f32 v0, v0, v1, v2 ; encoding: [0x00,0x40,0xa0,0xd3,0x00,0x03,0x0a,0x1c] 7; VI: v_mac_f32 8; CI: v_mad_f32 9define float @v_mad_mix_f32_f16lo_f16lo_f16lo(half %src0, half %src1, half %src2) #0 { 10 %src0.ext = fpext half %src0 to float 11 %src1.ext = fpext half %src1 to float 12 %src2.ext = fpext half %src2 to float 13 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.ext) 14 ret float %result 15} 16 17; GCN-LABEL: {{^}}v_mad_mix_f32_f16hi_f16hi_f16hi_int: 18; GFX9: v_mad_mix_f32 v0, v0, v1, v2 op_sel:[1,1,1] ; encoding 19; CIVI: v_mac_f32 20define float @v_mad_mix_f32_f16hi_f16hi_f16hi_int(i32 %src0, i32 %src1, i32 %src2) #0 { 21 %src0.hi = lshr i32 %src0, 16 22 %src1.hi = lshr i32 %src1, 16 23 %src2.hi = lshr i32 %src2, 16 24 %src0.i16 = trunc i32 %src0.hi to i16 25 %src1.i16 = trunc i32 %src1.hi to i16 26 %src2.i16 = trunc i32 %src2.hi to i16 27 %src0.fp16 = bitcast i16 %src0.i16 to half 28 %src1.fp16 = bitcast i16 %src1.i16 to half 29 %src2.fp16 = bitcast i16 %src2.i16 to half 30 %src0.ext = fpext half %src0.fp16 to float 31 %src1.ext = fpext half %src1.fp16 to float 32 %src2.ext = fpext half %src2.fp16 to float 33 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.ext) 34 ret float %result 35} 36 37; GCN-LABEL: {{^}}v_mad_mix_f32_f16hi_f16hi_f16hi_elt: 38; GFX9: v_mad_mix_f32 v0, v0, v1, v2 op_sel:[1,1,1] ; encoding 39; VI: v_mac_f32 40; CI: v_mad_f32 41define float @v_mad_mix_f32_f16hi_f16hi_f16hi_elt(<2 x half> %src0, <2 x half> %src1, <2 x half> %src2) #0 { 42 %src0.hi = extractelement <2 x half> %src0, i32 1 43 %src1.hi = extractelement <2 x half> %src1, i32 1 44 %src2.hi = extractelement <2 x half> %src2, i32 1 45 %src0.ext = fpext half %src0.hi to float 46 %src1.ext = fpext half %src1.hi to float 47 %src2.ext = fpext half %src2.hi to float 48 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.ext) 49 ret float %result 50} 51 52; GCN-LABEL: {{^}}v_mad_mix_v2f32: 53; GFX9: v_mov_b32_e32 v3, v1 54; GFX9-NEXT: v_mad_mix_f32 v1, v0, v3, v2 op_sel:[1,1,1] 55; GFX9-NEXT: v_mad_mix_f32 v0, v0, v3, v2 56 57; CIVI: v_mac_f32 58define <2 x float> @v_mad_mix_v2f32(<2 x half> %src0, <2 x half> %src1, <2 x half> %src2) #0 { 59 %src0.ext = fpext <2 x half> %src0 to <2 x float> 60 %src1.ext = fpext <2 x half> %src1 to <2 x float> 61 %src2.ext = fpext <2 x half> %src2 to <2 x float> 62 %result = tail call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %src0.ext, <2 x float> %src1.ext, <2 x float> %src2.ext) 63 ret <2 x float> %result 64} 65 66; GCN-LABEL: {{^}}v_mad_mix_v2f32_shuffle: 67; GCN: s_waitcnt 68; GFX9-NEXT: v_mov_b32_e32 v3, v1 69; GFX9-NEXT: v_mad_mix_f32 v1, v0, v3, v2 op_sel:[0,1,1] 70; GFX9-NEXT: v_mad_mix_f32 v0, v0, v3, v2 op_sel:[1,0,1] 71; GFX9-NEXT: s_setpc_b64 72 73; CIVI: v_mac_f32 74define <2 x float> @v_mad_mix_v2f32_shuffle(<2 x half> %src0, <2 x half> %src1, <2 x half> %src2) #0 { 75 %src0.shuf = shufflevector <2 x half> %src0, <2 x half> undef, <2 x i32> <i32 1, i32 0> 76 %src1.shuf = shufflevector <2 x half> %src1, <2 x half> undef, <2 x i32> <i32 0, i32 1> 77 %src2.shuf = shufflevector <2 x half> %src2, <2 x half> undef, <2 x i32> <i32 1, i32 1> 78 %src0.ext = fpext <2 x half> %src0.shuf to <2 x float> 79 %src1.ext = fpext <2 x half> %src1.shuf to <2 x float> 80 %src2.ext = fpext <2 x half> %src2.shuf to <2 x float> 81 %result = tail call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %src0.ext, <2 x float> %src1.ext, <2 x float> %src2.ext) 82 ret <2 x float> %result 83} 84 85; GCN-LABEL: {{^}}v_mad_mix_f32_negf16lo_f16lo_f16lo: 86; GFX9: s_waitcnt 87; GFX9-NEXT: v_mad_mix_f32 v0, -v0, v1, v2 ; encoding 88; GFX9-NEXT: s_setpc_b64 89 90; CIVI: v_mad_f32 91define float @v_mad_mix_f32_negf16lo_f16lo_f16lo(half %src0, half %src1, half %src2) #0 { 92 %src0.ext = fpext half %src0 to float 93 %src1.ext = fpext half %src1 to float 94 %src2.ext = fpext half %src2 to float 95 %src0.ext.neg = fsub float -0.0, %src0.ext 96 %result = tail call float @llvm.fmuladd.f32(float %src0.ext.neg, float %src1.ext, float %src2.ext) 97 ret float %result 98} 99 100; GCN-LABEL: {{^}}v_mad_mix_f32_absf16lo_f16lo_f16lo: 101; GFX9: v_mad_mix_f32 v0, |v0|, v1, v2 102 103; CIVI: v_mad_f32 104define float @v_mad_mix_f32_absf16lo_f16lo_f16lo(half %src0, half %src1, half %src2) #0 { 105 %src0.ext = fpext half %src0 to float 106 %src1.ext = fpext half %src1 to float 107 %src2.ext = fpext half %src2 to float 108 %src0.ext.abs = call float @llvm.fabs.f32(float %src0.ext) 109 %result = tail call float @llvm.fmuladd.f32(float %src0.ext.abs, float %src1.ext, float %src2.ext) 110 ret float %result 111} 112 113; GCN-LABEL: {{^}}v_mad_mix_f32_negabsf16lo_f16lo_f16lo: 114; GFX9: s_waitcnt 115; GFX9-NEXT: v_mad_mix_f32 v0, -|v0|, v1, v2 116; GFX9-NEXT: s_setpc_b64 117 118; CIVI: v_mad_f32 119define float @v_mad_mix_f32_negabsf16lo_f16lo_f16lo(half %src0, half %src1, half %src2) #0 { 120 %src0.ext = fpext half %src0 to float 121 %src1.ext = fpext half %src1 to float 122 %src2.ext = fpext half %src2 to float 123 %src0.ext.abs = call float @llvm.fabs.f32(float %src0.ext) 124 %src0.ext.neg.abs = fsub float -0.0, %src0.ext.abs 125 %result = tail call float @llvm.fmuladd.f32(float %src0.ext.neg.abs, float %src1.ext, float %src2.ext) 126 ret float %result 127} 128 129; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_f32: 130; GCN: s_waitcnt 131; GFX9-NEXT: v_mad_mix_f32 v0, v0, v1, v2 op_sel_hi:[1,1,0] ; encoding 132; GFX9-NEXT: s_setpc_b64 133 134; CIVI: v_mad_f32 135define float @v_mad_mix_f32_f16lo_f16lo_f32(half %src0, half %src1, float %src2) #0 { 136 %src0.ext = fpext half %src0 to float 137 %src1.ext = fpext half %src1 to float 138 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2) 139 ret float %result 140} 141 142; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_negf32: 143; GCN: s_waitcnt 144; GFX9-NEXT: v_mad_mix_f32 v0, v0, v1, -v2 op_sel_hi:[1,1,0] ; encoding 145; GFX9-NEXT: s_setpc_b64 146 147; CIVI: v_mad_f32 148define float @v_mad_mix_f32_f16lo_f16lo_negf32(half %src0, half %src1, float %src2) #0 { 149 %src0.ext = fpext half %src0 to float 150 %src1.ext = fpext half %src1 to float 151 %src2.neg = fsub float -0.0, %src2 152 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.neg) 153 ret float %result 154} 155 156; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_absf32: 157; GCN: s_waitcnt 158; GFX9-NEXT: v_mad_mix_f32 v0, v0, v1, |v2| op_sel_hi:[1,1,0] ; encoding 159; GFX9-NEXT: s_setpc_b64 160 161; CIVI: v_mad_f32 162define float @v_mad_mix_f32_f16lo_f16lo_absf32(half %src0, half %src1, float %src2) #0 { 163 %src0.ext = fpext half %src0 to float 164 %src1.ext = fpext half %src1 to float 165 %src2.abs = call float @llvm.fabs.f32(float %src2) 166 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.abs) 167 ret float %result 168} 169 170; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_negabsf32: 171; GCN: s_waitcnt 172; GFX9-NEXT: v_mad_mix_f32 v0, v0, v1, -|v2| op_sel_hi:[1,1,0] ; encoding 173; GFX9-NEXT: s_setpc_b64 174 175; CIVI: v_mad_f32 176define float @v_mad_mix_f32_f16lo_f16lo_negabsf32(half %src0, half %src1, float %src2) #0 { 177 %src0.ext = fpext half %src0 to float 178 %src1.ext = fpext half %src1 to float 179 %src2.abs = call float @llvm.fabs.f32(float %src2) 180 %src2.neg.abs = fsub float -0.0, %src2.abs 181 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.neg.abs) 182 ret float %result 183} 184 185; TODO: Fold inline immediates. Need to be careful because it is an 186; f16 inline immediate that may be converted to f32, not an actual f32 187; inline immediate. 188 189; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_f32imm1: 190; GCN: s_waitcnt 191; GFX9: v_mov_b32_e32 v2, 1.0 192; GFX9-NEXT: v_mad_mix_f32 v0, v0, v1, v2 op_sel_hi:[1,1,0] ; encoding 193 194; CIVI: v_mad_f32 v0, v0, v1, 1.0 195; GCN-NEXT: s_setpc_b64 196define float @v_mad_mix_f32_f16lo_f16lo_f32imm1(half %src0, half %src1) #0 { 197 %src0.ext = fpext half %src0 to float 198 %src1.ext = fpext half %src1 to float 199 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float 1.0) 200 ret float %result 201} 202 203; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_f32imminv2pi: 204; GCN: s_waitcnt 205; GFX9: v_mov_b32_e32 v2, 0.15915494 206; GFX9: v_mad_mix_f32 v0, v0, v1, v2 op_sel_hi:[1,1,0] ; encoding 207; VI: v_mad_f32 v0, v0, v1, 0.15915494 208define float @v_mad_mix_f32_f16lo_f16lo_f32imminv2pi(half %src0, half %src1) #0 { 209 %src0.ext = fpext half %src0 to float 210 %src1.ext = fpext half %src1 to float 211 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float 0x3FC45F3060000000) 212 ret float %result 213} 214 215; Attempt to break inline immediate folding. If the operand is 216; interpreted as f32, the inline immediate is really the f16 inline 217; imm value converted to f32. 218; fpext f16 1/2pi = 0x3e230000 219; f32 1/2pi = 0x3e22f983 220; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_cvtf16imminv2pi: 221; GFX9: v_mov_b32_e32 v2, 0x3e230000 222; GFX9: v_mad_mix_f32 v0, v0, v1, v2 op_sel_hi:[1,1,0] ; encoding 223 224; CIVI: v_madak_f32 v0, v0, v1, 0x3e230000 225define float @v_mad_mix_f32_f16lo_f16lo_cvtf16imminv2pi(half %src0, half %src1) #0 { 226 %src0.ext = fpext half %src0 to float 227 %src1.ext = fpext half %src1 to float 228 %src2 = fpext half 0xH3118 to float 229 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2) 230 ret float %result 231} 232 233; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_cvtf16imm63: 234; GFX9: v_mov_b32_e32 v2, 0x367c0000 235; GFX9: v_mad_mix_f32 v0, v0, v1, v2 op_sel_hi:[1,1,0] ; encoding 236 237; CIVI: v_madak_f32 v0, v0, v1, 0x367c0000 238define float @v_mad_mix_f32_f16lo_f16lo_cvtf16imm63(half %src0, half %src1) #0 { 239 %src0.ext = fpext half %src0 to float 240 %src1.ext = fpext half %src1 to float 241 %src2 = fpext half 0xH003F to float 242 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2) 243 ret float %result 244} 245 246; GCN-LABEL: {{^}}v_mad_mix_v2f32_f32imm1: 247; GFX9: v_mov_b32_e32 v2, v1 248; GFX9: v_mov_b32_e32 v3, 1.0 249; GFX9: v_mad_mix_f32 v1, v0, v2, v3 op_sel:[1,1,0] op_sel_hi:[1,1,0] ; encoding 250; GFX9: v_mad_mix_f32 v0, v0, v2, v3 op_sel_hi:[1,1,0] ; encoding 251define <2 x float> @v_mad_mix_v2f32_f32imm1(<2 x half> %src0, <2 x half> %src1) #0 { 252 %src0.ext = fpext <2 x half> %src0 to <2 x float> 253 %src1.ext = fpext <2 x half> %src1 to <2 x float> 254 %result = tail call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %src0.ext, <2 x float> %src1.ext, <2 x float> <float 1.0, float 1.0>) 255 ret <2 x float> %result 256} 257 258; GCN-LABEL: {{^}}v_mad_mix_v2f32_cvtf16imminv2pi: 259; GFX9: v_mov_b32_e32 v2, v1 260; GFX9: v_mov_b32_e32 v3, 0x3e230000 261; GFX9: v_mad_mix_f32 v1, v0, v2, v3 op_sel:[1,1,0] op_sel_hi:[1,1,0] ; encoding 262; GFX9: v_mad_mix_f32 v0, v0, v2, v3 op_sel_hi:[1,1,0] ; encoding 263define <2 x float> @v_mad_mix_v2f32_cvtf16imminv2pi(<2 x half> %src0, <2 x half> %src1) #0 { 264 %src0.ext = fpext <2 x half> %src0 to <2 x float> 265 %src1.ext = fpext <2 x half> %src1 to <2 x float> 266 %src2 = fpext <2 x half> <half 0xH3118, half 0xH3118> to <2 x float> 267 %result = tail call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %src0.ext, <2 x float> %src1.ext, <2 x float> %src2) 268 ret <2 x float> %result 269} 270 271; GCN-LABEL: {{^}}v_mad_mix_v2f32_f32imminv2pi: 272; GFX9: v_mov_b32_e32 v2, v1 273; GFX9: v_mov_b32_e32 v3, 0.15915494 274; GFX9: v_mad_mix_f32 v1, v0, v2, v3 op_sel:[1,1,0] op_sel_hi:[1,1,0] ; encoding 275; GFX9: v_mad_mix_f32 v0, v0, v2, v3 op_sel_hi:[1,1,0] ; encoding 276define <2 x float> @v_mad_mix_v2f32_f32imminv2pi(<2 x half> %src0, <2 x half> %src1) #0 { 277 %src0.ext = fpext <2 x half> %src0 to <2 x float> 278 %src1.ext = fpext <2 x half> %src1 to <2 x float> 279 %src2 = fpext <2 x half> <half 0xH3118, half 0xH3118> to <2 x float> 280 %result = tail call <2 x float> @llvm.fmuladd.v2f32(<2 x float> %src0.ext, <2 x float> %src1.ext, <2 x float> <float 0x3FC45F3060000000, float 0x3FC45F3060000000>) 281 ret <2 x float> %result 282} 283 284; GCN-LABEL: {{^}}v_mad_mix_clamp_f32_f16hi_f16hi_f16hi_elt: 285; GFX9: v_mad_mix_f32 v0, v0, v1, v2 op_sel:[1,1,1] clamp ; encoding 286; VI: v_mac_f32_e64 v{{[0-9]}}, v{{[0-9]}}, v{{[0-9]}} clamp{{$}} 287; CI: v_mad_f32 v{{[0-9]}}, v{{[0-9]}}, v{{[0-9]}}, v{{[0-9]}} clamp{{$}} 288define float @v_mad_mix_clamp_f32_f16hi_f16hi_f16hi_elt(<2 x half> %src0, <2 x half> %src1, <2 x half> %src2) #0 { 289 %src0.hi = extractelement <2 x half> %src0, i32 1 290 %src1.hi = extractelement <2 x half> %src1, i32 1 291 %src2.hi = extractelement <2 x half> %src2, i32 1 292 %src0.ext = fpext half %src0.hi to float 293 %src1.ext = fpext half %src1.hi to float 294 %src2.ext = fpext half %src2.hi to float 295 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.ext) 296 %max = call float @llvm.maxnum.f32(float %result, float 0.0) 297 %clamp = call float @llvm.minnum.f32(float %max, float 1.0) 298 ret float %clamp 299} 300 301; GCN-LABEL: no_mix_simple: 302; GCN: s_waitcnt 303; GCN-NEXT: v_mad_f32 v0, v0, v1, v2 304; GCN-NEXT: s_setpc_b64 305define float @no_mix_simple(float %src0, float %src1, float %src2) #0 { 306 %result = call float @llvm.fmuladd.f32(float %src0, float %src1, float %src2) 307 ret float %result 308} 309 310; GCN-LABEL: no_mix_simple_fabs: 311; GCN: s_waitcnt 312; GCN-NEXT: v_mad_f32 v0, |v0|, v1, v2 313; GCN-NEXT: s_setpc_b64 314define float @no_mix_simple_fabs(float %src0, float %src1, float %src2) #0 { 315 %src0.fabs = call float @llvm.fabs.f32(float %src0) 316 %result = call float @llvm.fmuladd.f32(float %src0.fabs, float %src1, float %src2) 317 ret float %result 318} 319 320; FIXME: Should abe able to select in thits case 321; All sources are converted from f16, so it doesn't matter 322; v_mad_mix_f32 flushes. 323 324; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_f16lo_f32_denormals: 325; GFX9: v_cvt_f32_f16 326; GFX9: v_cvt_f32_f16 327; GFX9: v_cvt_f32_f16 328; GFX9: v_fma_f32 329define float @v_mad_mix_f32_f16lo_f16lo_f16lo_f32_denormals(half %src0, half %src1, half %src2) #1 { 330 %src0.ext = fpext half %src0 to float 331 %src1.ext = fpext half %src1 to float 332 %src2.ext = fpext half %src2 to float 333 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.ext) 334 ret float %result 335} 336 337; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_f32_denormals: 338; GFX9: v_cvt_f32_f16 339; GFX9: v_cvt_f32_f16 340; GFX9: v_fma_f32 341define float @v_mad_mix_f32_f16lo_f16lo_f32_denormals(half %src0, half %src1, float %src2) #1 { 342 %src0.ext = fpext half %src0 to float 343 %src1.ext = fpext half %src1 to float 344 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2) 345 ret float %result 346} 347 348; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_f16lo_f32_denormals_fmulfadd: 349; GFX9: v_cvt_f32_f16 350; GFX9: v_cvt_f32_f16 351; GFX9: v_cvt_f32_f16 352; GFX9: v_mul_f32 353; GFX9: v_add_f32 354define float @v_mad_mix_f32_f16lo_f16lo_f16lo_f32_denormals_fmulfadd(half %src0, half %src1, half %src2) #1 { 355 %src0.ext = fpext half %src0 to float 356 %src1.ext = fpext half %src1 to float 357 %src2.ext = fpext half %src2 to float 358 %mul = fmul float %src0.ext, %src1.ext 359 %result = fadd float %mul, %src2.ext 360 ret float %result 361} 362 363; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_f32_denormals_fmulfadd: 364; GFX9: v_cvt_f32_f16 365; GFX9: v_cvt_f32_f16 366; GFX9: v_mul_f32 367; GFX9: v_add_f32 368define float @v_mad_mix_f32_f16lo_f16lo_f32_denormals_fmulfadd(half %src0, half %src1, float %src2) #1 { 369 %src0.ext = fpext half %src0 to float 370 %src1.ext = fpext half %src1 to float 371 %mul = fmul float %src0.ext, %src1.ext 372 %result = fadd float %mul, %src2 373 ret float %result 374} 375 376; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_f16lo_f32_flush_fmulfadd: 377; GCN: s_waitcnt 378; GFX9-NEXT: v_mad_mix_f32 v0, v0, v1, v2 ; encoding 379; GFX9-NEXT: s_setpc_b64 380define float @v_mad_mix_f32_f16lo_f16lo_f16lo_f32_flush_fmulfadd(half %src0, half %src1, half %src2) #0 { 381 %src0.ext = fpext half %src0 to float 382 %src1.ext = fpext half %src1 to float 383 %src2.ext = fpext half %src2 to float 384 %mul = fmul float %src0.ext, %src1.ext 385 %result = fadd float %mul, %src2.ext 386 ret float %result 387} 388 389; GCN-LABEL: {{^}}v_mad_mix_f32_f16lo_f16lo_f32_flush_fmulfadd: 390; GCN: s_waitcnt 391; GFX9-NEXT: v_mad_mix_f32 v0, v0, v1, v2 op_sel_hi:[1,1,0] ; encoding 392; GFX9-NEXT: s_setpc_b64 393define float @v_mad_mix_f32_f16lo_f16lo_f32_flush_fmulfadd(half %src0, half %src1, float %src2) #0 { 394 %src0.ext = fpext half %src0 to float 395 %src1.ext = fpext half %src1 to float 396 %mul = fmul float %src0.ext, %src1.ext 397 %result = fadd float %mul, %src2 398 ret float %result 399} 400 401; GCN-LABEL: {{^}}v_mad_mix_f32_negprecvtf16lo_f16lo_f16lo: 402; GFX9: s_waitcnt 403; GFX9-NEXT: v_mad_mix_f32 v0, -v0, v1, v2 ; encoding 404; GFX9-NEXT: s_setpc_b64 405 406; CIVI: v_mad_f32 407define float @v_mad_mix_f32_negprecvtf16lo_f16lo_f16lo(i32 %src0.arg, half %src1, half %src2) #0 { 408 %src0.arg.bc = bitcast i32 %src0.arg to <2 x half> 409 %src0 = extractelement <2 x half> %src0.arg.bc, i32 0 410 %src0.neg = fsub half -0.0, %src0 411 %src0.ext = fpext half %src0.neg to float 412 %src1.ext = fpext half %src1 to float 413 %src2.ext = fpext half %src2 to float 414; %src0.ext.neg = fsub float -0.0, %src0.ext 415 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.ext) 416 ret float %result 417} 418 419; Make sure we don't fold pre-cvt fneg if we already have a fabs 420; GCN-LABEL: {{^}}v_mad_mix_f32_precvtnegf16hi_abs_f16lo_f16lo: 421; GFX9: s_waitcnt 422define float @v_mad_mix_f32_precvtnegf16hi_abs_f16lo_f16lo(i32 %src0.arg, half %src1, half %src2) #0 { 423 %src0.arg.bc = bitcast i32 %src0.arg to <2 x half> 424 %src0 = extractelement <2 x half> %src0.arg.bc, i32 1 425 %src0.neg = fsub half -0.0, %src0 426 %src0.ext = fpext half %src0.neg to float 427 %src0.ext.abs = call float @llvm.fabs.f32(float %src0.ext) 428 %src1.ext = fpext half %src1 to float 429 %src2.ext = fpext half %src2 to float 430 %result = tail call float @llvm.fmuladd.f32(float %src0.ext.abs, float %src1.ext, float %src2.ext) 431 ret float %result 432} 433 434; GCN-LABEL: {{^}}v_mad_mix_f32_precvtabsf16hi_f16lo_f16lo: 435; GFX9: s_waitcnt 436; GFX9-NEXT: v_mad_mix_f32 v0, |v0|, v1, v2 op_sel:[1,0,0] 437; GFX9-NEXT: s_setpc_b64 438define float @v_mad_mix_f32_precvtabsf16hi_f16lo_f16lo(i32 %src0.arg, half %src1, half %src2) #0 { 439 %src0.arg.bc = bitcast i32 %src0.arg to <2 x half> 440 %src0 = extractelement <2 x half> %src0.arg.bc, i32 1 441 %src0.abs = call half @llvm.fabs.f16(half %src0) 442 %src0.ext = fpext half %src0.abs to float 443 %src1.ext = fpext half %src1 to float 444 %src2.ext = fpext half %src2 to float 445 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.ext) 446 ret float %result 447} 448 449; GCN-LABEL: {{^}}v_mad_mix_f32_preextractfneg_f16hi_f16lo_f16lo: 450; GFX9: s_waitcnt 451; GFX9-NEXT: v_mad_mix_f32 v0, -v0, v1, v2 op_sel:[1,0,0] 452; GFX9-NEXT: s_setpc_b64 453define float @v_mad_mix_f32_preextractfneg_f16hi_f16lo_f16lo(i32 %src0.arg, half %src1, half %src2) #0 { 454 %src0.arg.bc = bitcast i32 %src0.arg to <2 x half> 455 %fneg = fsub <2 x half> <half -0.0, half -0.0>, %src0.arg.bc 456 %src0 = extractelement <2 x half> %fneg, i32 1 457 %src0.ext = fpext half %src0 to float 458 %src1.ext = fpext half %src1 to float 459 %src2.ext = fpext half %src2 to float 460 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.ext) 461 ret float %result 462} 463 464; FIXME: Should be able to fold 465; GCN-LABEL: {{^}}v_mad_mix_f32_preextractfabs_f16hi_f16lo_f16lo: 466; GFX9: s_waitcnt 467; GFX9-NEXT: v_and_b32_e32 v0, 0x7fff0000, v0 468; GFX9-NEXT: v_mad_mix_f32 v0, v0, v1, v2 op_sel:[1,0,0] 469; GFX9-NEXT: s_setpc_b64 470define float @v_mad_mix_f32_preextractfabs_f16hi_f16lo_f16lo(i32 %src0.arg, half %src1, half %src2) #0 { 471 %src0.arg.bc = bitcast i32 %src0.arg to <2 x half> 472 %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %src0.arg.bc) 473 %src0 = extractelement <2 x half> %fabs, i32 1 474 %src0.ext = fpext half %src0 to float 475 %src1.ext = fpext half %src1 to float 476 %src2.ext = fpext half %src2 to float 477 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.ext) 478 ret float %result 479} 480 481; FIXME: Should be able to fold 482; GCN-LABEL: {{^}}v_mad_mix_f32_preextractfabsfneg_f16hi_f16lo_f16lo: 483; GFX9: s_waitcnt 484; GFX9-NEXT: v_and_b32_e32 v0, 0x7fff0000, v0 485; GFX9-NEXT: v_mad_mix_f32 v0, -v0, v1, v2 op_sel:[1,0,0] 486; GFX9-NEXT: s_setpc_b64 487define float @v_mad_mix_f32_preextractfabsfneg_f16hi_f16lo_f16lo(i32 %src0.arg, half %src1, half %src2) #0 { 488 %src0.arg.bc = bitcast i32 %src0.arg to <2 x half> 489 %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %src0.arg.bc) 490 %fneg.fabs = fsub <2 x half> <half -0.0, half -0.0>, %fabs 491 %src0 = extractelement <2 x half> %fneg.fabs, i32 1 492 %src0.ext = fpext half %src0 to float 493 %src1.ext = fpext half %src1 to float 494 %src2.ext = fpext half %src2 to float 495 %result = tail call float @llvm.fmuladd.f32(float %src0.ext, float %src1.ext, float %src2.ext) 496 ret float %result 497} 498 499declare half @llvm.fabs.f16(half) #2 500declare <2 x half> @llvm.fabs.v2f16(<2 x half>) #2 501declare float @llvm.fabs.f32(float) #2 502declare float @llvm.minnum.f32(float, float) #2 503declare float @llvm.maxnum.f32(float, float) #2 504declare float @llvm.fmuladd.f32(float, float, float) #2 505declare <2 x float> @llvm.fmuladd.v2f32(<2 x float>, <2 x float>, <2 x float>) #2 506 507attributes #0 = { nounwind "target-features"="-fp32-denormals" } 508attributes #1 = { nounwind "target-features"="+fp32-denormals" } 509attributes #2 = { nounwind readnone speculatable } 510