1; RUN: llc -march=amdgcn -mcpu=gfx901 -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefix=GFX9 -check-prefix=GCN %s 2; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -verify-machineinstrs < %s | FileCheck -check-prefix=VI -check-prefix=CIVI -check-prefix=GCN %s 3; RUN: llc -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %s | FileCheck -check-prefix=CI -check-prefix=CIVI -check-prefix=GCN %s 4 5; GCN-LABEL: {{^}}s_abs_v2i16: 6; GFX9: s_load_dword [[VAL:s[0-9]+]] 7; GFX9: v_pk_sub_i16 [[SUB:v[0-9]+]], 0, [[VAL]] 8; GFX9: v_pk_max_i16 [[MAX:v[0-9]+]], [[VAL]], [[SUB]] 9; GFX9: v_pk_add_u16 [[ADD:v[0-9]+]], [[MAX]], 2 10 11; CIVI: v_sub_i32_e32 12; CIVI-DAG: v_sub_i32_e32 13; CIVI: v_bfe_i32 14; CIVI-DAG: v_bfe_i32 15; CIVI-DAG: v_add_i32_e32 16; CIVI-DAG: v_lshlrev_b32_e32 v{{[0-9]+}}, 16 17; CIVI: v_add_i32_e32 18; CIVI: v_and_b32_e32 v{{[0-9]+}}, 0xffff, 19; CIVI: v_or_b32_e32 20define void @s_abs_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16> %val) #0 { 21 %neg = sub <2 x i16> zeroinitializer, %val 22 %cond = icmp sgt <2 x i16> %val, %neg 23 %res = select <2 x i1> %cond, <2 x i16> %val, <2 x i16> %neg 24 %res2 = add <2 x i16> %res, <i16 2, i16 2> 25 store <2 x i16> %res2, <2 x i16> addrspace(1)* %out, align 4 26 ret void 27} 28 29; GCN-LABEL: {{^}}v_abs_v2i16: 30; GFX9: flat_load_dword [[VAL:v[0-9]+]] 31; GFX9: v_pk_sub_i16 [[SUB:v[0-9]+]], 0, [[VAL]] 32; GFX9: v_pk_max_i16 [[MAX:v[0-9]+]], [[VAL]], [[SUB]] 33; GFX9: v_pk_add_u16 [[ADD:v[0-9]+]], [[MAX]], 2 34 35; VI: v_lshrrev_b32_e32 v{{[0-9]+}}, 16, 36; VI: v_sub_u16_e32 v{{[0-9]+}}, 0, v{{[0-9]+}} 37; VI: v_sub_u16_e32 v{{[0-9]+}}, 0, v{{[0-9]+}} 38; VI: v_max_i16_e32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} 39; VI: v_max_i16_e32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} 40; VI: v_add_u16_e32 v{{[0-9]+}}, 2, v{{[0-9]+}} 41; VI: v_add_u16_e32 v{{[0-9]+}}, 2, v{{[0-9]+}} 42; VI-NOT: v_and_b32 43; VI: v_or_b32_e32 44define void @v_abs_v2i16(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %src) #0 { 45 %tid = call i32 @llvm.amdgcn.workitem.id.x() 46 %gep.in = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %src, i32 %tid 47 %gep.out = getelementptr inbounds <2 x i16>, <2 x i16> addrspace(1)* %out, i32 %tid 48 %val = load <2 x i16>, <2 x i16> addrspace(1)* %gep.in, align 4 49 %neg = sub <2 x i16> zeroinitializer, %val 50 %cond = icmp sgt <2 x i16> %val, %neg 51 %res = select <2 x i1> %cond, <2 x i16> %val, <2 x i16> %neg 52 %res2 = add <2 x i16> %res, <i16 2, i16 2> 53 store <2 x i16> %res2, <2 x i16> addrspace(1)* %gep.out, align 4 54 ret void 55} 56 57; GCN-LABEL: {{^}}s_abs_v2i16_2: 58; GFX9: s_load_dword [[VAL:s[0-9]+]] 59; GFX9: v_pk_sub_i16 [[SUB:v[0-9]+]], 0, [[VAL]] 60; GFX9: v_pk_max_i16 [[MAX:v[0-9]+]], [[VAL]], [[SUB]] 61; GFX9: v_pk_add_u16 [[ADD:v[0-9]+]], [[MAX]], 2 62define void @s_abs_v2i16_2(<2 x i16> addrspace(1)* %out, <2 x i16> %val) #0 { 63 %z0 = insertelement <2 x i16> undef, i16 0, i16 0 64 %z1 = insertelement <2 x i16> %z0, i16 0, i16 1 65 %t0 = insertelement <2 x i16> undef, i16 2, i16 0 66 %t1 = insertelement <2 x i16> %t0, i16 2, i16 1 67 %neg = sub <2 x i16> %z1, %val 68 %cond = icmp sgt <2 x i16> %val, %neg 69 %res = select <2 x i1> %cond, <2 x i16> %val, <2 x i16> %neg 70 %res2 = add <2 x i16> %res, %t1 71 store <2 x i16> %res2, <2 x i16> addrspace(1)* %out, align 4 72 ret void 73} 74 75; GCN-LABEL: {{^}}v_abs_v2i16_2: 76; GFX9: buffer_load_dword [[VAL:v[0-9]+]] 77; GFX9: v_pk_sub_i16 [[SUB:v[0-9]+]], 0, [[VAL]] 78; GFX9: v_pk_max_i16 [[MAX:v[0-9]+]], [[VAL]], [[SUB]] 79; GFX9: v_pk_add_u16 [[ADD:v[0-9]+]], [[MAX]], 2 80define void @v_abs_v2i16_2(<2 x i16> addrspace(1)* %out, <2 x i16> addrspace(1)* %src) #0 { 81 %z0 = insertelement <2 x i16> undef, i16 0, i16 0 82 %z1 = insertelement <2 x i16> %z0, i16 0, i16 1 83 %t0 = insertelement <2 x i16> undef, i16 2, i16 0 84 %t1 = insertelement <2 x i16> %t0, i16 2, i16 1 85 %val = load <2 x i16>, <2 x i16> addrspace(1)* %src, align 4 86 %neg = sub <2 x i16> %z1, %val 87 %cond = icmp sgt <2 x i16> %val, %neg 88 %res = select <2 x i1> %cond, <2 x i16> %val, <2 x i16> %neg 89 %res2 = add <2 x i16> %res, %t1 90 store <2 x i16> %res2, <2 x i16> addrspace(1)* %out, align 4 91 ret void 92} 93 94; GCN-LABEL: {{^}}s_abs_v4i16: 95; GFX9: s_load_dword [[VAL0:s[0-9]+]] 96; GFX9: s_load_dword [[VAL1:s[0-9]+]] 97; GFX9-DAG: v_pk_sub_i16 [[SUB0:v[0-9]+]], 0, [[VAL0]] 98; GFX9-DAG: v_pk_max_i16 [[MAX0:v[0-9]+]], [[VAL0]], [[SUB0]] 99; GFX9-DAG: v_pk_add_u16 [[ADD0:v[0-9]+]], [[MAX0]], 2 100 101; GFX9-DAG: v_pk_sub_i16 [[SUB1:v[0-9]+]], 0, [[VAL1]] 102; GFX9-DAG: v_pk_max_i16 [[MAX1:v[0-9]+]], [[VAL1]], [[SUB1]] 103; GFX9-DAG: v_pk_add_u16 [[ADD1:v[0-9]+]], [[MAX1]], 2 104define void @s_abs_v4i16(<4 x i16> addrspace(1)* %out, <4 x i16> %val) #0 { 105 %z0 = insertelement <4 x i16> undef, i16 0, i16 0 106 %z1 = insertelement <4 x i16> %z0, i16 0, i16 1 107 %z2 = insertelement <4 x i16> %z1, i16 0, i16 2 108 %z3 = insertelement <4 x i16> %z2, i16 0, i16 3 109 %t0 = insertelement <4 x i16> undef, i16 2, i16 0 110 %t1 = insertelement <4 x i16> %t0, i16 2, i16 1 111 %t2 = insertelement <4 x i16> %t1, i16 2, i16 2 112 %t3 = insertelement <4 x i16> %t2, i16 2, i16 3 113 %neg = sub <4 x i16> %z3, %val 114 %cond = icmp sgt <4 x i16> %val, %neg 115 %res = select <4 x i1> %cond, <4 x i16> %val, <4 x i16> %neg 116 %res2 = add <4 x i16> %res, %t3 117 store <4 x i16> %res2, <4 x i16> addrspace(1)* %out, align 4 118 ret void 119} 120 121; GCN-LABEL: {{^}}v_abs_v4i16: 122; GFX9: buffer_load_dwordx2 v{{\[}}[[VAL0:[0-9]+]]:[[VAL1:[0-9]+]]{{\]}} 123 124; GFX9-DAG: v_pk_sub_i16 [[SUB0:v[0-9]+]], 0, v[[VAL0]] 125; GFX9-DAG: v_pk_max_i16 [[MAX0:v[0-9]+]], v[[VAL0]], [[SUB0]] 126; GFX9-DAG: v_pk_add_u16 [[ADD0:v[0-9]+]], [[MAX0]], 2 127 128; GFX9-DAG: v_pk_sub_i16 [[SUB1:v[0-9]+]], 0, v[[VAL1]] 129; GFX9-DAG: v_pk_max_i16 [[MAX1:v[0-9]+]], v[[VAL1]], [[SUB1]] 130; GFX9-DAG: v_pk_add_u16 [[ADD1:v[0-9]+]], [[MAX1]], 2 131define void @v_abs_v4i16(<4 x i16> addrspace(1)* %out, <4 x i16> addrspace(1)* %src) #0 { 132 %z0 = insertelement <4 x i16> undef, i16 0, i16 0 133 %z1 = insertelement <4 x i16> %z0, i16 0, i16 1 134 %z2 = insertelement <4 x i16> %z1, i16 0, i16 2 135 %z3 = insertelement <4 x i16> %z2, i16 0, i16 3 136 %t0 = insertelement <4 x i16> undef, i16 2, i16 0 137 %t1 = insertelement <4 x i16> %t0, i16 2, i16 1 138 %t2 = insertelement <4 x i16> %t1, i16 2, i16 2 139 %t3 = insertelement <4 x i16> %t2, i16 2, i16 3 140 %val = load <4 x i16>, <4 x i16> addrspace(1)* %src, align 4 141 %neg = sub <4 x i16> %z3, %val 142 %cond = icmp sgt <4 x i16> %val, %neg 143 %res = select <4 x i1> %cond, <4 x i16> %val, <4 x i16> %neg 144 %res2 = add <4 x i16> %res, %t3 145 store <4 x i16> %res2, <4 x i16> addrspace(1)* %out, align 4 146 ret void 147} 148 149; GCN-LABEL: {{^}}s_min_max_v2i16: 150define void @s_min_max_v2i16(<2 x i16> addrspace(1)* %out0, <2 x i16> addrspace(1)* %out1, <2 x i16> %val0, <2 x i16> %val1) #0 { 151 %cond0 = icmp sgt <2 x i16> %val0, %val1 152 %sel0 = select <2 x i1> %cond0, <2 x i16> %val0, <2 x i16> %val1 153 %sel1 = select <2 x i1> %cond0, <2 x i16> %val1, <2 x i16> %val0 154 155 store volatile <2 x i16> %sel0, <2 x i16> addrspace(1)* %out0, align 4 156 store volatile <2 x i16> %sel1, <2 x i16> addrspace(1)* %out1, align 4 157 ret void 158} 159 160; GCN-LABEL: {{^}}v_min_max_v2i16: 161define void @v_min_max_v2i16(<2 x i16> addrspace(1)* %out0, <2 x i16> addrspace(1)* %out1, <2 x i16> addrspace(1)* %ptr0, <2 x i16> addrspace(1)* %ptr1) #0 { 162 %val0 = load volatile <2 x i16>, <2 x i16> addrspace(1)* %ptr0 163 %val1 = load volatile <2 x i16>, <2 x i16> addrspace(1)* %ptr1 164 165 %cond0 = icmp sgt <2 x i16> %val0, %val1 166 %sel0 = select <2 x i1> %cond0, <2 x i16> %val0, <2 x i16> %val1 167 %sel1 = select <2 x i1> %cond0, <2 x i16> %val1, <2 x i16> %val0 168 169 store volatile <2 x i16> %sel0, <2 x i16> addrspace(1)* %out0, align 4 170 store volatile <2 x i16> %sel1, <2 x i16> addrspace(1)* %out1, align 4 171 ret void 172} 173 174; GCN-LABEL: {{^}}s_min_max_v4i32: 175define void @s_min_max_v4i32(<4 x i16> addrspace(1)* %out0, <4 x i16> addrspace(1)* %out1, <4 x i16> %val0, <4 x i16> %val1) #0 { 176 %cond0 = icmp sgt <4 x i16> %val0, %val1 177 %sel0 = select <4 x i1> %cond0, <4 x i16> %val0, <4 x i16> %val1 178 %sel1 = select <4 x i1> %cond0, <4 x i16> %val1, <4 x i16> %val0 179 180 store volatile <4 x i16> %sel0, <4 x i16> addrspace(1)* %out0, align 4 181 store volatile <4 x i16> %sel1, <4 x i16> addrspace(1)* %out1, align 4 182 ret void 183} 184 185; GCN-LABEL: {{^}}v_min_max_v2i16_user: 186define void @v_min_max_v2i16_user(<2 x i16> addrspace(1)* %out0, <2 x i16> addrspace(1)* %out1, <2 x i16> addrspace(1)* %ptr0, <2 x i16> addrspace(1)* %ptr1) #0 { 187 %val0 = load volatile <2 x i16>, <2 x i16> addrspace(1)* %ptr0 188 %val1 = load volatile <2 x i16>, <2 x i16> addrspace(1)* %ptr1 189 190 %cond0 = icmp sgt <2 x i16> %val0, %val1 191 %sel0 = select <2 x i1> %cond0, <2 x i16> %val0, <2 x i16> %val1 192 %sel1 = select <2 x i1> %cond0, <2 x i16> %val1, <2 x i16> %val0 193 194 store volatile <2 x i16> %sel0, <2 x i16> addrspace(1)* %out0, align 4 195 store volatile <2 x i16> %sel1, <2 x i16> addrspace(1)* %out1, align 4 196 store volatile <2 x i1> %cond0, <2 x i1> addrspace(1)* undef 197 ret void 198} 199 200; GCN-LABEL: {{^}}u_min_max_v2i16: 201; GFX9: v_pk_max_u16 v{{[0-9]+}}, v{{[0-9]+}}, s{{[0-9]+}} 202; GFX9: v_pk_min_u16 v{{[0-9]+}}, s{{[0-9]+}}, v{{[0-9]+}} 203define void @u_min_max_v2i16(<2 x i16> addrspace(1)* %out0, <2 x i16> addrspace(1)* %out1, <2 x i16> %val0, <2 x i16> %val1) nounwind { 204 %cond0 = icmp ugt <2 x i16> %val0, %val1 205 %sel0 = select <2 x i1> %cond0, <2 x i16> %val0, <2 x i16> %val1 206 %sel1 = select <2 x i1> %cond0, <2 x i16> %val1, <2 x i16> %val0 207 208 store volatile <2 x i16> %sel0, <2 x i16> addrspace(1)* %out0, align 4 209 store volatile <2 x i16> %sel1, <2 x i16> addrspace(1)* %out1, align 4 210 ret void 211} 212 213declare i32 @llvm.amdgcn.workitem.id.x() #1 214 215attributes #0 = { nounwind } 216attributes #1 = { nounwind readnone } 217