1; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=kaveri -verify-machineinstrs < %s | FileCheck -check-prefix=CI -check-prefix=GCN -check-prefix=CIVI %s 2; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=VI -check-prefix=GFX89 -check-prefix=GCN -check-prefix=CIVI %s 3; RUN: llc -mtriple=amdgcn--amdhsa -mcpu=gfx901 -verify-machineinstrs < %s | FileCheck -check-prefix=GFX89 -check-prefix=GFX9 -check-prefix=GCN %s 4 5; GCN-LABEL: {{^}}fneg_fabs_fadd_f16: 6; CI: v_cvt_f32_f16_e32 7; CI: v_cvt_f32_f16_e64 [[CVT_ABS_X:v[0-9]+]], |v{{[0-9]+}}| 8; CI: v_subrev_f32_e32 v{{[0-9]+}}, [[CVT_ABS_X]], v{{[0-9]+}} 9 10; GFX89-NOT: _and 11; GFX89: v_sub_f16_e64 {{v[0-9]+}}, {{v[0-9]+}}, |{{v[0-9]+}}| 12define void @fneg_fabs_fadd_f16(half addrspace(1)* %out, half %x, half %y) { 13 %fabs = call half @llvm.fabs.f16(half %x) 14 %fsub = fsub half -0.0, %fabs 15 %fadd = fadd half %y, %fsub 16 store half %fadd, half addrspace(1)* %out, align 2 17 ret void 18} 19 20; GCN-LABEL: {{^}}fneg_fabs_fmul_f16: 21; CI-DAG: v_cvt_f32_f16_e32 22; CI-DAG: v_cvt_f32_f16_e64 [[CVT_NEG_ABS_X:v[0-9]+]], -|{{v[0-9]+}}| 23; CI: v_mul_f32_e32 {{v[0-9]+}}, [[CVT_NEG_ABS_X]], {{v[0-9]+}} 24; CI: v_cvt_f16_f32_e32 25 26; GFX89-NOT: _and 27; GFX89: v_mul_f16_e64 [[MUL:v[0-9]+]], {{v[0-9]+}}, -|{{v[0-9]+}}| 28; GFX89-NOT: [[MUL]] 29; GFX89: flat_store_short v{{\[[0-9]+:[0-9]+\]}}, [[MUL]] 30define void @fneg_fabs_fmul_f16(half addrspace(1)* %out, half %x, half %y) { 31 %fabs = call half @llvm.fabs.f16(half %x) 32 %fsub = fsub half -0.0, %fabs 33 %fmul = fmul half %y, %fsub 34 store half %fmul, half addrspace(1)* %out, align 2 35 ret void 36} 37 38; DAGCombiner will transform: 39; (fabs (f16 bitcast (i16 a))) => (f16 bitcast (and (i16 a), 0x7FFFFFFF)) 40; unless isFabsFree returns true 41 42; GCN-LABEL: {{^}}fneg_fabs_free_f16: 43; GCN: v_or_b32_e32 v{{[0-9]+}}, 0x8000, v{{[0-9]+}} 44define void @fneg_fabs_free_f16(half addrspace(1)* %out, i16 %in) { 45 %bc = bitcast i16 %in to half 46 %fabs = call half @llvm.fabs.f16(half %bc) 47 %fsub = fsub half -0.0, %fabs 48 store half %fsub, half addrspace(1)* %out 49 ret void 50} 51 52; GCN-LABEL: {{^}}fneg_fabs_f16: 53; GCN: v_or_b32_e32 v{{[0-9]+}}, 0x8000, v{{[0-9]+}} 54define void @fneg_fabs_f16(half addrspace(1)* %out, half %in) { 55 %fabs = call half @llvm.fabs.f16(half %in) 56 %fsub = fsub half -0.0, %fabs 57 store half %fsub, half addrspace(1)* %out, align 2 58 ret void 59} 60 61; GCN-LABEL: {{^}}v_fneg_fabs_f16: 62; GCN: v_or_b32_e32 v{{[0-9]+}}, 0x8000, v{{[0-9]+}} 63define void @v_fneg_fabs_f16(half addrspace(1)* %out, half addrspace(1)* %in) { 64 %val = load half, half addrspace(1)* %in, align 2 65 %fabs = call half @llvm.fabs.f16(half %val) 66 %fsub = fsub half -0.0, %fabs 67 store half %fsub, half addrspace(1)* %out, align 2 68 ret void 69} 70 71; FIXME: single bit op 72; GCN-LABEL: {{^}}s_fneg_fabs_v2f16: 73; CIVI: s_mov_b32 [[MASK:s[0-9]+]], 0x8000{{$}} 74; CIVI: v_or_b32_e32 v{{[0-9]+}}, [[MASK]], 75; CIVI: v_or_b32_e32 v{{[0-9]+}}, [[MASK]], 76; CIVI: flat_store_dword 77 78; GFX9: s_or_b32 s{{[0-9]+}}, 0x80008000, s{{[0-9]+}} 79define void @s_fneg_fabs_v2f16(<2 x half> addrspace(1)* %out, <2 x half> %in) { 80 %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %in) 81 %fneg.fabs = fsub <2 x half> <half -0.0, half -0.0>, %fabs 82 store <2 x half> %fneg.fabs, <2 x half> addrspace(1)* %out 83 ret void 84} 85 86; GCN-LABEL: {{^}}fneg_fabs_v4f16: 87; CIVI: s_mov_b32 [[MASK:s[0-9]+]], 0x8000{{$}} 88; CIVI: v_or_b32_e32 v{{[0-9]+}}, [[MASK]], 89; CIVI: v_or_b32_e32 v{{[0-9]+}}, [[MASK]], 90; CIVI: v_or_b32_e32 v{{[0-9]+}}, [[MASK]], 91; CIVI: v_or_b32_e32 v{{[0-9]+}}, [[MASK]], 92 93; GFX9: s_mov_b32 [[MASK:s[0-9]+]], 0x80008000 94; GFX9: s_or_b32 s{{[0-9]+}}, [[MASK]], s{{[0-9]+}} 95; GFX9: s_or_b32 s{{[0-9]+}}, [[MASK]], s{{[0-9]+}} 96 97; GCN: flat_store_dwordx2 98define void @fneg_fabs_v4f16(<4 x half> addrspace(1)* %out, <4 x half> %in) { 99 %fabs = call <4 x half> @llvm.fabs.v4f16(<4 x half> %in) 100 %fsub = fsub <4 x half> <half -0.0, half -0.0, half -0.0, half -0.0>, %fabs 101 store <4 x half> %fsub, <4 x half> addrspace(1)* %out 102 ret void 103} 104 105; GCN-LABEL: {{^}}fold_user_fneg_fabs_v2f16: 106; CI: v_cvt_f32_f16_e64 v{{[0-9]+}}, -|v{{[0-9]+}}| 107; CI: v_cvt_f32_f16_e64 v{{[0-9]+}}, -|v{{[0-9]+}}| 108; CI: v_mul_f32_e32 v{{[0-9]+}}, 4.0, v{{[0-9]+}} 109; CI: v_mul_f32_e32 v{{[0-9]+}}, 4.0, v{{[0-9]+}} 110 111; VI: v_mul_f16_e64 v{{[0-9]+}}, -|v{{[0-9]+}}|, 4.0 112; VI: v_mul_f16_e64 v{{[0-9]+}}, -|v{{[0-9]+}}|, 4.0 113 114; GFX9: s_and_b32 [[ABS:s[0-9]+]], s{{[0-9]+}}, 0x7fff7fff 115; GFX9: v_pk_mul_f16 v{{[0-9]+}}, [[ABS]], 4.0 neg_lo:[1,0] neg_hi:[1,0] 116define void @fold_user_fneg_fabs_v2f16(<2 x half> addrspace(1)* %out, <2 x half> %in) #0 { 117 %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %in) 118 %fneg.fabs = fsub <2 x half> <half -0.0, half -0.0>, %fabs 119 %mul = fmul <2 x half> %fneg.fabs, <half 4.0, half 4.0> 120 store <2 x half> %mul, <2 x half> addrspace(1)* %out 121 ret void 122} 123 124; GCN-LABEL: {{^}}s_fneg_multi_use_fabs_v2f16: 125; GFX9: s_and_b32 [[ABS:s[0-9]+]], s{{[0-9]+}}, 0x7fff7fff 126; GFX9: v_mov_b32_e32 [[VABS:v[0-9]+]], [[ABS]] 127; GFX9: v_xor_b32_e32 [[NEG:v[0-9]+]], 0x80008000, [[VABS]] 128define void @s_fneg_multi_use_fabs_v2f16(<2 x half> addrspace(1)* %out0, <2 x half> addrspace(1)* %out1, <2 x half> %in) { 129 %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %in) 130 %fneg = fsub <2 x half> <half -0.0, half -0.0>, %fabs 131 store <2 x half> %fabs, <2 x half> addrspace(1)* %out0 132 store <2 x half> %fneg, <2 x half> addrspace(1)* %out1 133 ret void 134} 135 136; GCN-LABEL: {{^}}s_fneg_multi_use_fabs_foldable_neg_v2f16: 137; GFX9: s_and_b32 [[ABS:s[0-9]+]], s{{[0-9]+}}, 0x7fff7fff 138; GFX9: v_pk_mul_f16 v{{[0-9]+}}, [[ABS]], 4.0 neg_lo:[1,0] neg_hi:[1,0] 139define void @s_fneg_multi_use_fabs_foldable_neg_v2f16(<2 x half> addrspace(1)* %out0, <2 x half> addrspace(1)* %out1, <2 x half> %in) { 140 %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %in) 141 %fneg = fsub <2 x half> <half -0.0, half -0.0>, %fabs 142 %mul = fmul <2 x half> %fneg, <half 4.0, half 4.0> 143 store <2 x half> %fabs, <2 x half> addrspace(1)* %out0 144 store <2 x half> %mul, <2 x half> addrspace(1)* %out1 145 ret void 146} 147 148declare half @llvm.fabs.f16(half) #1 149declare <2 x half> @llvm.fabs.v2f16(<2 x half>) #1 150declare <4 x half> @llvm.fabs.v4f16(<4 x half>) #1 151 152attributes #0 = { nounwind } 153attributes #1 = { nounwind readnone } 154