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_mov_b32_e32 v6, v5 79; GFX10-NEXT: v_pk_fma_f16 v0, v0, v2, v4 80; GFX10-NEXT: v_fmac_f16_e32 v6, v1, v3 81; GFX10-NEXT: v_mov_b32_e32 v1, v6 82; GFX10-NEXT: s_setpc_b64 s[30:31] 83 %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") 84 ret <3 x half> %val 85} 86 87define <4 x half> @v_constained_fma_v4f16_fpexcept_strict(<4 x half> %x, <4 x half> %y, <4 x half> %z) #0 { 88; GFX9-LABEL: v_constained_fma_v4f16_fpexcept_strict: 89; GFX9: ; %bb.0: 90; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 91; GFX9-NEXT: v_lshrrev_b32_e32 v8, 16, v1 92; GFX9-NEXT: v_lshrrev_b32_e32 v6, 16, v5 93; GFX9-NEXT: v_lshrrev_b32_e32 v7, 16, v3 94; GFX9-NEXT: v_fma_f16 v6, v8, v7, v6 95; GFX9-NEXT: v_lshrrev_b32_e32 v9, 16, v0 96; GFX9-NEXT: v_lshrrev_b32_e32 v7, 16, v4 97; GFX9-NEXT: v_lshrrev_b32_e32 v8, 16, v2 98; GFX9-NEXT: v_fma_f16 v0, v0, v2, v4 99; GFX9-NEXT: v_mov_b32_e32 v2, 0xffff 100; GFX9-NEXT: v_fma_f16 v1, v1, v3, v5 101; GFX9-NEXT: v_and_b32_e32 v1, v2, v1 102; GFX9-NEXT: v_fma_f16 v7, v9, v8, v7 103; GFX9-NEXT: v_and_b32_e32 v0, v2, v0 104; GFX9-NEXT: v_lshl_or_b32 v0, v7, 16, v0 105; GFX9-NEXT: v_lshl_or_b32 v1, v6, 16, v1 106; GFX9-NEXT: s_setpc_b64 s[30:31] 107; 108; GFX8-LABEL: v_constained_fma_v4f16_fpexcept_strict: 109; GFX8: ; %bb.0: 110; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 111; GFX8-NEXT: v_lshrrev_b32_e32 v8, 16, v1 112; GFX8-NEXT: v_lshrrev_b32_e32 v6, 16, v5 113; GFX8-NEXT: v_lshrrev_b32_e32 v7, 16, v3 114; GFX8-NEXT: v_fma_f16 v6, v8, v7, v6 115; GFX8-NEXT: v_lshrrev_b32_e32 v9, 16, v0 116; GFX8-NEXT: v_lshrrev_b32_e32 v7, 16, v4 117; GFX8-NEXT: v_lshrrev_b32_e32 v8, 16, v2 118; GFX8-NEXT: v_fma_f16 v7, v9, v8, v7 119; GFX8-NEXT: v_fma_f16 v0, v0, v2, v4 120; GFX8-NEXT: v_lshlrev_b32_e32 v2, 16, v7 121; GFX8-NEXT: v_or_b32_sdwa v0, v0, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD 122; GFX8-NEXT: v_fma_f16 v1, v1, v3, v5 123; GFX8-NEXT: v_lshlrev_b32_e32 v2, 16, v6 124; GFX8-NEXT: v_or_b32_sdwa v1, v1, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD 125; GFX8-NEXT: s_setpc_b64 s[30:31] 126; 127; GFX10-LABEL: v_constained_fma_v4f16_fpexcept_strict: 128; GFX10: ; %bb.0: 129; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 130; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 131; GFX10-NEXT: v_mov_b32_e32 v14, v5 132; GFX10-NEXT: v_mov_b32_e32 v15, v4 133; GFX10-NEXT: v_lshrrev_b32_e32 v7, 16, v3 134; GFX10-NEXT: v_lshrrev_b32_e32 v8, 16, v1 135; GFX10-NEXT: v_lshrrev_b32_e32 v10, 16, v2 136; GFX10-NEXT: v_lshrrev_b32_e32 v5, 16, v14 137; GFX10-NEXT: v_lshrrev_b32_e32 v4, 16, v15 138; GFX10-NEXT: v_lshrrev_b32_e32 v11, 16, v0 139; GFX10-NEXT: v_fmac_f16_e32 v15, v0, v2 140; GFX10-NEXT: v_mov_b32_e32 v0, 0xffff 141; GFX10-NEXT: v_fmac_f16_e32 v14, v1, v3 142; GFX10-NEXT: v_fmac_f16_e32 v5, v8, v7 143; GFX10-NEXT: v_fmac_f16_e32 v4, v11, v10 144; GFX10-NEXT: v_and_b32_e32 v1, v0, v15 145; GFX10-NEXT: v_and_b32_e32 v2, v0, v14 146; GFX10-NEXT: v_lshl_or_b32 v0, v4, 16, v1 147; GFX10-NEXT: v_lshl_or_b32 v1, v5, 16, v2 148; GFX10-NEXT: s_setpc_b64 s[30:31] 149 %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") 150 ret <4 x half> %val 151} 152 153define half @v_constained_fma_f16_fpexcept_strict_fneg(half %x, half %y, half %z) #0 { 154; GCN-LABEL: v_constained_fma_f16_fpexcept_strict_fneg: 155; GCN: ; %bb.0: 156; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 157; GCN-NEXT: v_fma_f16 v0, v0, v1, -v2 158; GCN-NEXT: s_setpc_b64 s[30:31] 159; 160; GFX10-LABEL: v_constained_fma_f16_fpexcept_strict_fneg: 161; GFX10: ; %bb.0: 162; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 163; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 164; GFX10-NEXT: v_fma_f16 v0, v0, v1, -v2 165; GFX10-NEXT: s_setpc_b64 s[30:31] 166 %neg.z = fneg half %z 167 %val = call half @llvm.experimental.constrained.fma.f16(half %x, half %y, half %neg.z, metadata !"round.tonearest", metadata !"fpexcept.strict") 168 ret half %val 169} 170 171define half @v_constained_fma_f16_fpexcept_strict_fneg_fneg(half %x, half %y, half %z) #0 { 172; GCN-LABEL: v_constained_fma_f16_fpexcept_strict_fneg_fneg: 173; GCN: ; %bb.0: 174; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 175; GCN-NEXT: v_fma_f16 v0, -v0, -v1, v2 176; GCN-NEXT: s_setpc_b64 s[30:31] 177; 178; GFX10-LABEL: v_constained_fma_f16_fpexcept_strict_fneg_fneg: 179; GFX10: ; %bb.0: 180; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 181; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 182; GFX10-NEXT: v_fmac_f16_e64 v2, -v0, -v1 183; GFX10-NEXT: v_mov_b32_e32 v0, v2 184; GFX10-NEXT: s_setpc_b64 s[30:31] 185 %neg.x = fneg half %x 186 %neg.y = fneg half %y 187 %val = call half @llvm.experimental.constrained.fma.f16(half %neg.x, half %neg.y, half %z, metadata !"round.tonearest", metadata !"fpexcept.strict") 188 ret half %val 189} 190 191define half @v_constained_fma_f16_fpexcept_strict_fabs_fabs(half %x, half %y, half %z) #0 { 192; GCN-LABEL: v_constained_fma_f16_fpexcept_strict_fabs_fabs: 193; GCN: ; %bb.0: 194; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 195; GCN-NEXT: v_fma_f16 v0, |v0|, |v1|, v2 196; GCN-NEXT: s_setpc_b64 s[30:31] 197; 198; GFX10-LABEL: v_constained_fma_f16_fpexcept_strict_fabs_fabs: 199; GFX10: ; %bb.0: 200; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 201; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 202; GFX10-NEXT: v_fmac_f16_e64 v2, |v0|, |v1| 203; GFX10-NEXT: v_mov_b32_e32 v0, v2 204; GFX10-NEXT: s_setpc_b64 s[30:31] 205 %neg.x = call half @llvm.fabs.f16(half %x) 206 %neg.y = call half @llvm.fabs.f16(half %y) 207 %val = call half @llvm.experimental.constrained.fma.f16(half %neg.x, half %neg.y, half %z, metadata !"round.tonearest", metadata !"fpexcept.strict") 208 ret half %val 209} 210 211define <2 x half> @v_constained_fma_v2f16_fpexcept_strict_fneg_fneg(<2 x half> %x, <2 x half> %y, <2 x half> %z) #0 { 212; GFX9-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg: 213; GFX9: ; %bb.0: 214; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 215; GFX9-NEXT: v_pk_fma_f16 v0, v0, v1, v2 neg_lo:[1,1,0] neg_hi:[1,1,0] 216; GFX9-NEXT: s_setpc_b64 s[30:31] 217; 218; GFX8-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg: 219; GFX8: ; %bb.0: 220; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 221; GFX8-NEXT: v_lshrrev_b32_e32 v5, 16, v0 222; GFX8-NEXT: v_lshrrev_b32_e32 v3, 16, v2 223; GFX8-NEXT: v_lshrrev_b32_e32 v4, 16, v1 224; GFX8-NEXT: v_fma_f16 v3, -v5, -v4, v3 225; GFX8-NEXT: v_lshlrev_b32_e32 v3, 16, v3 226; GFX8-NEXT: v_fma_f16 v0, -v0, -v1, v2 227; GFX8-NEXT: v_or_b32_sdwa v0, v0, v3 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:WORD_0 src1_sel:DWORD 228; GFX8-NEXT: s_setpc_b64 s[30:31] 229; 230; GFX10-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg: 231; GFX10: ; %bb.0: 232; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 233; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 234; GFX10-NEXT: v_pk_fma_f16 v0, v0, v1, v2 neg_lo:[1,1,0] neg_hi:[1,1,0] 235; GFX10-NEXT: s_setpc_b64 s[30:31] 236 %neg.x = fneg <2 x half> %x 237 %neg.y = fneg <2 x half> %y 238 %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") 239 ret <2 x half> %val 240} 241 242declare half @llvm.fabs.f16(half) #1 243declare half @llvm.experimental.constrained.fma.f16(half, half, half, metadata, metadata) #1 244declare <2 x half> @llvm.experimental.constrained.fma.v2f16(<2 x half>, <2 x half>, <2 x half>, metadata, metadata) #1 245declare <3 x half> @llvm.experimental.constrained.fma.v3f16(<3 x half>, <3 x half>, <3 x half>, metadata, metadata) #1 246declare <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half>, <4 x half>, <4 x half>, metadata, metadata) #1 247 248attributes #0 = { strictfp } 249attributes #1 = { inaccessiblememonly nounwind willreturn } 250