1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx900 < %s | FileCheck -check-prefixes=GCN,GFX9 %s 3; RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=fiji < %s | FileCheck -check-prefixes=GCN,GFX8 %s 4; RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx1010 < %s | FileCheck -check-prefixes=GFX10 %s 5 6define half @v_constained_fma_f16_fpexcept_strict(half %x, half %y, half %z) #0 { 7; GCN-LABEL: v_constained_fma_f16_fpexcept_strict: 8; GCN: ; %bb.0: 9; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 10; GCN-NEXT: v_fma_f16 v0, v0, v1, v2 11; GCN-NEXT: s_setpc_b64 s[30:31] 12; 13; GFX10-LABEL: v_constained_fma_f16_fpexcept_strict: 14; GFX10: ; %bb.0: 15; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 16; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 17; GFX10-NEXT: v_fmac_f16_e32 v2, v0, v1 18; GFX10-NEXT: v_mov_b32_e32 v0, v2 19; GFX10-NEXT: s_setpc_b64 s[30:31] 20 %val = call half @llvm.experimental.constrained.fma.f16(half %x, half %y, half %z, metadata !"round.tonearest", metadata !"fpexcept.strict") 21 ret half %val 22} 23 24define <2 x half> @v_constained_fma_v2f16_fpexcept_strict(<2 x half> %x, <2 x half> %y, <2 x half> %z) #0 { 25; GFX9-LABEL: v_constained_fma_v2f16_fpexcept_strict: 26; GFX9: ; %bb.0: 27; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 28; GFX9-NEXT: v_pk_fma_f16 v0, v0, v1, v2 29; GFX9-NEXT: s_setpc_b64 s[30:31] 30; 31; GFX8-LABEL: v_constained_fma_v2f16_fpexcept_strict: 32; GFX8: ; %bb.0: 33; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 34; GFX8-NEXT: v_lshrrev_b32_e32 v5, 16, v0 35; GFX8-NEXT: v_lshrrev_b32_e32 v3, 16, v2 36; GFX8-NEXT: v_lshrrev_b32_e32 v4, 16, v1 37; GFX8-NEXT: v_fma_f16 v3, v5, v4, v3 38; GFX8-NEXT: v_lshlrev_b32_e32 v3, 16, v3 39; GFX8-NEXT: v_fma_f16 v0, v0, v1, v2 40; GFX8-NEXT: v_or_b32_sdwa v0, v0, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD 41; GFX8-NEXT: s_setpc_b64 s[30:31] 42; 43; GFX10-LABEL: v_constained_fma_v2f16_fpexcept_strict: 44; GFX10: ; %bb.0: 45; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 46; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 47; GFX10-NEXT: v_pk_fma_f16 v0, v0, v1, v2 48; GFX10-NEXT: s_setpc_b64 s[30:31] 49 %val = call <2 x half> @llvm.experimental.constrained.fma.v2f16(<2 x half> %x, <2 x half> %y, <2 x half> %z, metadata !"round.tonearest", metadata !"fpexcept.strict") 50 ret <2 x half> %val 51} 52 53define <3 x half> @v_constained_fma_v3f16_fpexcept_strict(<3 x half> %x, <3 x half> %y, <3 x half> %z) #0 { 54; GFX9-LABEL: v_constained_fma_v3f16_fpexcept_strict: 55; GFX9: ; %bb.0: 56; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 57; GFX9-NEXT: v_pk_fma_f16 v0, v0, v2, v4 58; GFX9-NEXT: v_fma_f16 v1, v1, v3, v5 59; GFX9-NEXT: s_setpc_b64 s[30:31] 60; 61; GFX8-LABEL: v_constained_fma_v3f16_fpexcept_strict: 62; GFX8: ; %bb.0: 63; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 64; GFX8-NEXT: v_lshrrev_b32_e32 v8, 16, v0 65; GFX8-NEXT: v_lshrrev_b32_e32 v6, 16, v4 66; GFX8-NEXT: v_lshrrev_b32_e32 v7, 16, v2 67; GFX8-NEXT: v_fma_f16 v6, v8, v7, v6 68; GFX8-NEXT: v_lshlrev_b32_e32 v6, 16, v6 69; GFX8-NEXT: v_fma_f16 v0, v0, v2, v4 70; GFX8-NEXT: v_or_b32_sdwa v0, v0, v6 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD 71; GFX8-NEXT: v_fma_f16 v1, v1, v3, v5 72; GFX8-NEXT: s_setpc_b64 s[30:31] 73; 74; GFX10-LABEL: v_constained_fma_v3f16_fpexcept_strict: 75; GFX10: ; %bb.0: 76; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 77; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 78; GFX10-NEXT: v_fmac_f16_e32 v5, v1, v3 79; GFX10-NEXT: v_pk_fma_f16 v0, v0, v2, v4 80; GFX10-NEXT: v_mov_b32_e32 v1, v5 81; GFX10-NEXT: s_setpc_b64 s[30:31] 82 %val = call <3 x half> @llvm.experimental.constrained.fma.v3f16(<3 x half> %x, <3 x half> %y, <3 x half> %z, metadata !"round.tonearest", metadata !"fpexcept.strict") 83 ret <3 x half> %val 84} 85 86define <4 x half> @v_constained_fma_v4f16_fpexcept_strict(<4 x half> %x, <4 x half> %y, <4 x half> %z) #0 { 87; GFX9-LABEL: v_constained_fma_v4f16_fpexcept_strict: 88; GFX9: ; %bb.0: 89; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 90; GFX9-NEXT: v_lshrrev_b32_e32 v8, 16, v1 91; GFX9-NEXT: v_lshrrev_b32_e32 v6, 16, v5 92; GFX9-NEXT: v_lshrrev_b32_e32 v7, 16, v3 93; GFX9-NEXT: v_fma_f16 v6, v8, v7, v6 94; GFX9-NEXT: v_lshrrev_b32_e32 v9, 16, v0 95; GFX9-NEXT: v_lshrrev_b32_e32 v7, 16, v4 96; GFX9-NEXT: v_lshrrev_b32_e32 v8, 16, v2 97; GFX9-NEXT: v_fma_f16 v0, v0, v2, v4 98; GFX9-NEXT: v_mov_b32_e32 v2, 0xffff 99; GFX9-NEXT: v_fma_f16 v1, v1, v3, v5 100; GFX9-NEXT: v_and_b32_e32 v1, v2, v1 101; GFX9-NEXT: v_fma_f16 v7, v9, v8, v7 102; GFX9-NEXT: v_and_b32_e32 v0, v2, v0 103; GFX9-NEXT: v_lshl_or_b32 v0, v7, 16, v0 104; GFX9-NEXT: v_lshl_or_b32 v1, v6, 16, v1 105; GFX9-NEXT: s_setpc_b64 s[30:31] 106; 107; GFX8-LABEL: v_constained_fma_v4f16_fpexcept_strict: 108; GFX8: ; %bb.0: 109; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 110; GFX8-NEXT: v_lshrrev_b32_e32 v8, 16, v1 111; GFX8-NEXT: v_lshrrev_b32_e32 v6, 16, v5 112; GFX8-NEXT: v_lshrrev_b32_e32 v7, 16, v3 113; GFX8-NEXT: v_fma_f16 v6, v8, v7, v6 114; GFX8-NEXT: v_lshrrev_b32_e32 v9, 16, v0 115; GFX8-NEXT: v_lshrrev_b32_e32 v7, 16, v4 116; GFX8-NEXT: v_lshrrev_b32_e32 v8, 16, v2 117; GFX8-NEXT: v_fma_f16 v7, v9, v8, v7 118; GFX8-NEXT: v_fma_f16 v0, v0, v2, v4 119; GFX8-NEXT: v_lshlrev_b32_e32 v2, 16, v7 120; GFX8-NEXT: v_or_b32_sdwa v0, v0, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD 121; GFX8-NEXT: v_fma_f16 v1, v1, v3, v5 122; GFX8-NEXT: v_lshlrev_b32_e32 v2, 16, v6 123; GFX8-NEXT: v_or_b32_sdwa v1, v1, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD 124; GFX8-NEXT: s_setpc_b64 s[30:31] 125; 126; GFX10-LABEL: v_constained_fma_v4f16_fpexcept_strict: 127; GFX10: ; %bb.0: 128; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 129; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 130; GFX10-NEXT: v_lshrrev_b32_e32 v6, 16, v5 131; GFX10-NEXT: v_lshrrev_b32_e32 v9, 16, v4 132; GFX10-NEXT: v_lshrrev_b32_e32 v7, 16, v3 133; GFX10-NEXT: v_lshrrev_b32_e32 v8, 16, v1 134; GFX10-NEXT: v_lshrrev_b32_e32 v10, 16, v2 135; GFX10-NEXT: v_lshrrev_b32_e32 v11, 16, v0 136; GFX10-NEXT: v_fmac_f16_e32 v4, v0, v2 137; GFX10-NEXT: v_mov_b32_e32 v0, 0xffff 138; GFX10-NEXT: v_fmac_f16_e32 v5, v1, v3 139; GFX10-NEXT: v_fmac_f16_e32 v6, v8, v7 140; GFX10-NEXT: v_fmac_f16_e32 v9, v11, v10 141; GFX10-NEXT: v_and_b32_e32 v1, v0, v4 142; GFX10-NEXT: v_and_b32_e32 v2, v0, v5 143; GFX10-NEXT: v_lshl_or_b32 v0, v9, 16, v1 144; GFX10-NEXT: v_lshl_or_b32 v1, v6, 16, v2 145; GFX10-NEXT: s_setpc_b64 s[30:31] 146 %val = call <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half> %x, <4 x half> %y, <4 x half> %z, metadata !"round.tonearest", metadata !"fpexcept.strict") 147 ret <4 x half> %val 148} 149 150define half @v_constained_fma_f16_fpexcept_strict_fneg(half %x, half %y, half %z) #0 { 151; GCN-LABEL: v_constained_fma_f16_fpexcept_strict_fneg: 152; GCN: ; %bb.0: 153; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 154; GCN-NEXT: v_fma_f16 v0, v0, v1, -v2 155; GCN-NEXT: s_setpc_b64 s[30:31] 156; 157; GFX10-LABEL: v_constained_fma_f16_fpexcept_strict_fneg: 158; GFX10: ; %bb.0: 159; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 160; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 161; GFX10-NEXT: v_fma_f16 v0, v0, v1, -v2 162; GFX10-NEXT: s_setpc_b64 s[30:31] 163 %neg.z = fneg half %z 164 %val = call half @llvm.experimental.constrained.fma.f16(half %x, half %y, half %neg.z, metadata !"round.tonearest", metadata !"fpexcept.strict") 165 ret half %val 166} 167 168define half @v_constained_fma_f16_fpexcept_strict_fneg_fneg(half %x, half %y, half %z) #0 { 169; GCN-LABEL: v_constained_fma_f16_fpexcept_strict_fneg_fneg: 170; GCN: ; %bb.0: 171; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 172; GCN-NEXT: v_fma_f16 v0, -v0, -v1, v2 173; GCN-NEXT: s_setpc_b64 s[30:31] 174; 175; GFX10-LABEL: v_constained_fma_f16_fpexcept_strict_fneg_fneg: 176; GFX10: ; %bb.0: 177; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 178; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 179; GFX10-NEXT: v_fmac_f16_e64 v2, -v0, -v1 180; GFX10-NEXT: v_mov_b32_e32 v0, v2 181; GFX10-NEXT: s_setpc_b64 s[30:31] 182 %neg.x = fneg half %x 183 %neg.y = fneg half %y 184 %val = call half @llvm.experimental.constrained.fma.f16(half %neg.x, half %neg.y, half %z, metadata !"round.tonearest", metadata !"fpexcept.strict") 185 ret half %val 186} 187 188define half @v_constained_fma_f16_fpexcept_strict_fabs_fabs(half %x, half %y, half %z) #0 { 189; GCN-LABEL: v_constained_fma_f16_fpexcept_strict_fabs_fabs: 190; GCN: ; %bb.0: 191; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 192; GCN-NEXT: v_fma_f16 v0, |v0|, |v1|, v2 193; GCN-NEXT: s_setpc_b64 s[30:31] 194; 195; GFX10-LABEL: v_constained_fma_f16_fpexcept_strict_fabs_fabs: 196; GFX10: ; %bb.0: 197; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 198; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 199; GFX10-NEXT: v_fmac_f16_e64 v2, |v0|, |v1| 200; GFX10-NEXT: v_mov_b32_e32 v0, v2 201; GFX10-NEXT: s_setpc_b64 s[30:31] 202 %neg.x = call half @llvm.fabs.f16(half %x) 203 %neg.y = call half @llvm.fabs.f16(half %y) 204 %val = call half @llvm.experimental.constrained.fma.f16(half %neg.x, half %neg.y, half %z, metadata !"round.tonearest", metadata !"fpexcept.strict") 205 ret half %val 206} 207 208define <2 x half> @v_constained_fma_v2f16_fpexcept_strict_fneg_fneg(<2 x half> %x, <2 x half> %y, <2 x half> %z) #0 { 209; GFX9-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg: 210; GFX9: ; %bb.0: 211; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 212; GFX9-NEXT: v_pk_fma_f16 v0, v0, v1, v2 neg_lo:[1,1,0] neg_hi:[1,1,0] 213; GFX9-NEXT: s_setpc_b64 s[30:31] 214; 215; GFX8-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg: 216; GFX8: ; %bb.0: 217; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 218; GFX8-NEXT: v_lshrrev_b32_e32 v5, 16, v0 219; GFX8-NEXT: v_lshrrev_b32_e32 v3, 16, v2 220; GFX8-NEXT: v_lshrrev_b32_e32 v4, 16, v1 221; GFX8-NEXT: v_fma_f16 v3, -v5, -v4, v3 222; GFX8-NEXT: v_lshlrev_b32_e32 v3, 16, v3 223; GFX8-NEXT: v_fma_f16 v0, -v0, -v1, v2 224; GFX8-NEXT: v_or_b32_sdwa v0, v0, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD 225; GFX8-NEXT: s_setpc_b64 s[30:31] 226; 227; GFX10-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg: 228; GFX10: ; %bb.0: 229; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 230; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 231; GFX10-NEXT: v_pk_fma_f16 v0, v0, v1, v2 neg_lo:[1,1,0] neg_hi:[1,1,0] 232; GFX10-NEXT: s_setpc_b64 s[30:31] 233 %neg.x = fneg <2 x half> %x 234 %neg.y = fneg <2 x half> %y 235 %val = call <2 x half> @llvm.experimental.constrained.fma.v2f16(<2 x half> %neg.x, <2 x half> %neg.y, <2 x half> %z, metadata !"round.tonearest", metadata !"fpexcept.strict") 236 ret <2 x half> %val 237} 238 239declare half @llvm.fabs.f16(half) #1 240declare half @llvm.experimental.constrained.fma.f16(half, half, half, metadata, metadata) #1 241declare <2 x half> @llvm.experimental.constrained.fma.v2f16(<2 x half>, <2 x half>, <2 x half>, metadata, metadata) #1 242declare <3 x half> @llvm.experimental.constrained.fma.v3f16(<3 x half>, <3 x half>, <3 x half>, metadata, metadata) #1 243declare <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half>, <4 x half>, <4 x half>, metadata, metadata) #1 244 245attributes #0 = { strictfp } 246attributes #1 = { inaccessiblememonly nounwind willreturn } 247