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 v3, 16, v2 35; GFX8-NEXT: v_lshrrev_b32_e32 v4, 16, v1 36; GFX8-NEXT: v_lshrrev_b32_e32 v5, 16, v0 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_e32 v0, v0, v3 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 v6, 16, v4 65; GFX8-NEXT: v_lshrrev_b32_e32 v7, 16, v2 66; GFX8-NEXT: v_lshrrev_b32_e32 v8, 16, v0 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_e32 v0, v0, v6 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 v6, 16, v5 91; GFX9-NEXT: v_lshrrev_b32_e32 v7, 16, v3 92; GFX9-NEXT: v_lshrrev_b32_e32 v8, 16, v1 93; GFX9-NEXT: v_fma_f16 v6, v8, v7, v6 94; GFX9-NEXT: v_lshrrev_b32_e32 v7, 16, v4 95; GFX9-NEXT: v_lshrrev_b32_e32 v8, 16, v2 96; GFX9-NEXT: v_lshrrev_b32_e32 v9, 16, v0 97; GFX9-NEXT: v_fma_f16 v1, v1, v3, v5 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 v7, v9, v8, v7 101; GFX9-NEXT: v_and_b32_e32 v0, v2, v0 102; GFX9-NEXT: v_and_b32_e32 v1, v2, v1 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 v6, 16, v5 111; GFX8-NEXT: v_lshrrev_b32_e32 v7, 16, v3 112; GFX8-NEXT: v_lshrrev_b32_e32 v8, 16, v1 113; GFX8-NEXT: v_fma_f16 v6, v8, v7, v6 114; GFX8-NEXT: v_lshrrev_b32_e32 v7, 16, v4 115; GFX8-NEXT: v_lshrrev_b32_e32 v8, 16, v2 116; GFX8-NEXT: v_lshrrev_b32_e32 v9, 16, v0 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_fma_f16 v1, v1, v3, v5 121; GFX8-NEXT: v_or_b32_e32 v0, v0, v2 122; GFX8-NEXT: v_lshlrev_b32_e32 v2, 16, v6 123; GFX8-NEXT: v_or_b32_e32 v1, v1, v2 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 v7, 16, v3 132; GFX10-NEXT: v_lshrrev_b32_e32 v8, 16, v1 133; GFX10-NEXT: v_lshrrev_b32_e32 v9, 16, v4 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_fma_f16 v0, -v0, -v1, v2 180; GFX10-NEXT: s_setpc_b64 s[30:31] 181 %neg.x = fneg half %x 182 %neg.y = fneg half %y 183 %val = call half @llvm.experimental.constrained.fma.f16(half %neg.x, half %neg.y, half %z, metadata !"round.tonearest", metadata !"fpexcept.strict") 184 ret half %val 185} 186 187define half @v_constained_fma_f16_fpexcept_strict_fabs_fabs(half %x, half %y, half %z) #0 { 188; GCN-LABEL: v_constained_fma_f16_fpexcept_strict_fabs_fabs: 189; GCN: ; %bb.0: 190; GCN-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 191; GCN-NEXT: v_fma_f16 v0, |v0|, |v1|, v2 192; GCN-NEXT: s_setpc_b64 s[30:31] 193; 194; GFX10-LABEL: v_constained_fma_f16_fpexcept_strict_fabs_fabs: 195; GFX10: ; %bb.0: 196; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 197; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 198; GFX10-NEXT: v_fma_f16 v0, |v0|, |v1|, v2 199; GFX10-NEXT: s_setpc_b64 s[30:31] 200 %neg.x = call half @llvm.fabs.f16(half %x) 201 %neg.y = call half @llvm.fabs.f16(half %y) 202 %val = call half @llvm.experimental.constrained.fma.f16(half %neg.x, half %neg.y, half %z, metadata !"round.tonearest", metadata !"fpexcept.strict") 203 ret half %val 204} 205 206define <2 x half> @v_constained_fma_v2f16_fpexcept_strict_fneg_fneg(<2 x half> %x, <2 x half> %y, <2 x half> %z) #0 { 207; GFX9-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg: 208; GFX9: ; %bb.0: 209; GFX9-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 210; GFX9-NEXT: v_pk_fma_f16 v0, v0, v1, v2 neg_lo:[1,1,0] neg_hi:[1,1,0] 211; GFX9-NEXT: s_setpc_b64 s[30:31] 212; 213; GFX8-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg: 214; GFX8: ; %bb.0: 215; GFX8-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 216; GFX8-NEXT: v_lshrrev_b32_e32 v3, 16, v2 217; GFX8-NEXT: v_lshrrev_b32_e32 v4, 16, v1 218; GFX8-NEXT: v_lshrrev_b32_e32 v5, 16, v0 219; GFX8-NEXT: v_fma_f16 v3, -v5, -v4, v3 220; GFX8-NEXT: v_lshlrev_b32_e32 v3, 16, v3 221; GFX8-NEXT: v_fma_f16 v0, -v0, -v1, v2 222; GFX8-NEXT: v_or_b32_e32 v0, v0, v3 223; GFX8-NEXT: s_setpc_b64 s[30:31] 224; 225; GFX10-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg: 226; GFX10: ; %bb.0: 227; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) 228; GFX10-NEXT: s_waitcnt_vscnt null, 0x0 229; GFX10-NEXT: v_pk_fma_f16 v0, v0, v1, v2 neg_lo:[1,1,0] neg_hi:[1,1,0] 230; GFX10-NEXT: s_setpc_b64 s[30:31] 231 %neg.x = fneg <2 x half> %x 232 %neg.y = fneg <2 x half> %y 233 %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") 234 ret <2 x half> %val 235} 236 237declare half @llvm.fabs.f16(half) #1 238declare half @llvm.experimental.constrained.fma.f16(half, half, half, metadata, metadata) #1 239declare <2 x half> @llvm.experimental.constrained.fma.v2f16(<2 x half>, <2 x half>, <2 x half>, metadata, metadata) #1 240declare <3 x half> @llvm.experimental.constrained.fma.v3f16(<3 x half>, <3 x half>, <3 x half>, metadata, metadata) #1 241declare <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half>, <4 x half>, <4 x half>, metadata, metadata) #1 242 243attributes #0 = { strictfp } 244attributes #1 = { inaccessiblememonly nounwind willreturn } 245