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