1; XUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=SI %s 2; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-fp16-denormals -verify-machineinstrs < %s | FileCheck -check-prefix=GCN -check-prefix=VI %s 3 4; Make sure (fmul (fadd x, x), c) -> (fmul x, (fmul 2.0, c)) doesn't 5; make add an instruction if the fadd has more than one use. 6 7declare half @llvm.fabs.f16(half) #1 8declare float @llvm.fabs.f32(float) #1 9 10; GCN-LABEL: {{^}}multiple_fadd_use_test_f32: 11; SI: v_max_legacy_f32_e64 [[A16:v[0-9]+]], 12; SI: v_add_f32_e32 [[A17:v[0-9]+]], [[A16]], [[A16]] 13; SI: v_mul_f32_e32 [[A18:v[0-9]+]], [[A17]], [[A17]] 14; SI: v_mad_f32 [[A20:v[0-9]+]], -[[A18]], [[A17]], 1.0 15; SI: buffer_store_dword [[A20]] 16 17; VI: v_add_f32_e64 v{{[0-9]+}}, s{{[0-9]+}}, -1.0 18; VI: v_add_f32_e64 v{{[0-9]+}}, s{{[0-9]+}}, -1.0 19; VI: v_cmp_gt_f32_e64 vcc, |v{{[0-9]+}}|, |v{{[0-9]+}}| 20; VI: v_cndmask_b32_e32 21; VI: v_add_f32_e64 v{{[0-9]+}}, |v{{[0-9]+}}|, |v{{[0-9]+}}| 22; VI: v_mul_f32_e64 v{{[0-9]+}}, v{{[0-9]+}}, -v{{[0-9]+}} 23; VI: v_mad_f32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}}, 1.0 24define void @multiple_fadd_use_test_f32(float addrspace(1)* %out, float %x, float %y, float %z) #0 { 25 %a11 = fadd fast float %y, -1.0 26 %a12 = call float @llvm.fabs.f32(float %a11) 27 %a13 = fadd fast float %x, -1.0 28 %a14 = call float @llvm.fabs.f32(float %a13) 29 %a15 = fcmp ogt float %a12, %a14 30 %a16 = select i1 %a15, float %a12, float %a14 31 %a17 = fmul fast float %a16, 2.0 32 %a18 = fmul fast float %a17, %a17 33 %a19 = fmul fast float %a18, %a17 34 %a20 = fsub fast float 1.0, %a19 35 store float %a20, float addrspace(1)* %out 36 ret void 37} 38 39; GCN-LABEL: {{^}}multiple_use_fadd_fmac_f32: 40; GCN-DAG: v_add_f32_e64 [[MUL2:v[0-9]+]], [[X:s[0-9]+]], s{{[0-9]+}} 41; GCN-DAG: v_mac_f32_e64 [[MAD:v[0-9]+]], [[X]], 2.0 42; GCN-DAG: buffer_store_dword [[MUL2]] 43; GCN-DAG: buffer_store_dword [[MAD]] 44; GCN: s_endpgm 45define void @multiple_use_fadd_fmac_f32(float addrspace(1)* %out, float %x, float %y) #0 { 46 %out.gep.1 = getelementptr float, float addrspace(1)* %out, i32 1 47 %mul2 = fmul fast float %x, 2.0 48 %mad = fadd fast float %mul2, %y 49 store volatile float %mul2, float addrspace(1)* %out 50 store volatile float %mad, float addrspace(1)* %out.gep.1 51 ret void 52} 53 54; GCN-LABEL: {{^}}multiple_use_fadd_fmad_f32: 55; GCN-DAG: v_add_f32_e64 [[MUL2:v[0-9]+]], |[[X:s[0-9]+]]|, |s{{[0-9]+}}| 56; GCN-DAG: v_mad_f32 [[MAD:v[0-9]+]], |[[X]]|, 2.0, v{{[0-9]+}} 57; GCN-DAG: buffer_store_dword [[MUL2]] 58; GCN-DAG: buffer_store_dword [[MAD]] 59; GCN: s_endpgm 60define void @multiple_use_fadd_fmad_f32(float addrspace(1)* %out, float %x, float %y) #0 { 61 %out.gep.1 = getelementptr float, float addrspace(1)* %out, i32 1 62 %x.abs = call float @llvm.fabs.f32(float %x) 63 %mul2 = fmul fast float %x.abs, 2.0 64 %mad = fadd fast float %mul2, %y 65 store volatile float %mul2, float addrspace(1)* %out 66 store volatile float %mad, float addrspace(1)* %out.gep.1 67 ret void 68} 69 70; GCN-LABEL: {{^}}multiple_use_fadd_multi_fmad_f32: 71; GCN: v_mad_f32 {{v[0-9]+}}, |[[X:s[0-9]+]]|, 2.0, v{{[0-9]+}} 72; GCN: v_mad_f32 {{v[0-9]+}}, |[[X]]|, 2.0, v{{[0-9]+}} 73define void @multiple_use_fadd_multi_fmad_f32(float addrspace(1)* %out, float %x, float %y, float %z) #0 { 74 %out.gep.1 = getelementptr float, float addrspace(1)* %out, i32 1 75 %x.abs = call float @llvm.fabs.f32(float %x) 76 %mul2 = fmul fast float %x.abs, 2.0 77 %mad0 = fadd fast float %mul2, %y 78 %mad1 = fadd fast float %mul2, %z 79 store volatile float %mad0, float addrspace(1)* %out 80 store volatile float %mad1, float addrspace(1)* %out.gep.1 81 ret void 82} 83 84; GCN-LABEL: {{^}}fmul_x2_xn2_f32: 85; GCN: v_mul_f32_e64 [[TMP0:v[0-9]+]], [[X:s[0-9]+]], -4.0 86; GCN: v_mul_f32_e32 [[RESULT:v[0-9]+]], [[X]], [[TMP0]] 87; GCN: buffer_store_dword [[RESULT]] 88define void @fmul_x2_xn2_f32(float addrspace(1)* %out, float %x, float %y) #0 { 89 %out.gep.1 = getelementptr float, float addrspace(1)* %out, i32 1 90 %mul2 = fmul fast float %x, 2.0 91 %muln2 = fmul fast float %x, -2.0 92 %mul = fmul fast float %mul2, %muln2 93 store volatile float %mul, float addrspace(1)* %out 94 ret void 95} 96 97; GCN-LABEL: {{^}}fmul_x2_xn3_f32: 98; GCN: v_mov_b32_e32 [[K:v[0-9]+]], 0xc0c00000 99; GCN: v_mul_f32_e32 [[TMP0:v[0-9]+]], [[X:s[0-9]+]], [[K]] 100; GCN: v_mul_f32_e32 [[RESULT:v[0-9]+]], [[X]], [[TMP0]] 101; GCN: buffer_store_dword [[RESULT]] 102define void @fmul_x2_xn3_f32(float addrspace(1)* %out, float %x, float %y) #0 { 103 %out.gep.1 = getelementptr float, float addrspace(1)* %out, i32 1 104 %mul2 = fmul fast float %x, 2.0 105 %muln2 = fmul fast float %x, -3.0 106 %mul = fmul fast float %mul2, %muln2 107 store volatile float %mul, float addrspace(1)* %out 108 ret void 109} 110 111; GCN-LABEL: {{^}}multiple_fadd_use_test_f16: 112; VI: v_add_f16_e64 v{{[0-9]+}}, s{{[0-9]+}}, -1.0 113; VI: v_add_f16_e64 v{{[0-9]+}}, s{{[0-9]+}}, -1.0 114; VI: v_cmp_gt_f16_e64 vcc, |v{{[0-9]+}}|, |v{{[0-9]+}}| 115; VI: v_cndmask_b32_e32 116; VI: v_add_f16_e64 v{{[0-9]+}}, |v{{[0-9]+}}|, |v{{[0-9]+}}| 117; VI: v_mul_f16_e64 v{{[0-9]+}}, v{{[0-9]+}}, -v{{[0-9]+}} 118; VI: v_mad_f16 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}}, 1.0 119define void @multiple_fadd_use_test_f16(half addrspace(1)* %out, i16 zeroext %x.arg, i16 zeroext %y.arg, i16 zeroext %z.arg) #0 { 120 %x = bitcast i16 %x.arg to half 121 %y = bitcast i16 %y.arg to half 122 %z = bitcast i16 %z.arg to half 123 %a11 = fadd fast half %y, -1.0 124 %a12 = call half @llvm.fabs.f16(half %a11) 125 %a13 = fadd fast half %x, -1.0 126 %a14 = call half @llvm.fabs.f16(half %a13) 127 %a15 = fcmp ogt half %a12, %a14 128 %a16 = select i1 %a15, half %a12, half %a14 129 %a17 = fmul fast half %a16, 2.0 130 %a18 = fmul fast half %a17, %a17 131 %a19 = fmul fast half %a18, %a17 132 %a20 = fsub fast half 1.0, %a19 133 store half %a20, half addrspace(1)* %out 134 ret void 135} 136 137; GCN-LABEL: {{^}}multiple_use_fadd_fmac_f16: 138; GCN-DAG: v_add_f16_e64 [[MUL2:v[0-9]+]], [[X:s[0-9]+]], s{{[0-9]+}} 139; GCN-DAG: v_mac_f16_e64 [[MAD:v[0-9]+]], [[X]], 2.0 140; GCN-DAG: buffer_store_short [[MUL2]] 141; GCN-DAG: buffer_store_short [[MAD]] 142; GCN: s_endpgm 143define void @multiple_use_fadd_fmac_f16(half addrspace(1)* %out, i16 zeroext %x.arg, i16 zeroext %y.arg) #0 { 144 %x = bitcast i16 %x.arg to half 145 %y = bitcast i16 %y.arg to half 146 %out.gep.1 = getelementptr half, half addrspace(1)* %out, i32 1 147 %mul2 = fmul fast half %x, 2.0 148 %mad = fadd fast half %mul2, %y 149 store volatile half %mul2, half addrspace(1)* %out 150 store volatile half %mad, half addrspace(1)* %out.gep.1 151 ret void 152} 153 154; GCN-LABEL: {{^}}multiple_use_fadd_fmad_f16: 155; GCN-DAG: v_add_f16_e64 [[MUL2:v[0-9]+]], |[[X:s[0-9]+]]|, |s{{[0-9]+}}| 156; GCN-DAG: v_mad_f16 [[MAD:v[0-9]+]], |[[X]]|, 2.0, v{{[0-9]+}} 157; GCN-DAG: buffer_store_short [[MUL2]] 158; GCN-DAG: buffer_store_short [[MAD]] 159; GCN: s_endpgm 160define void @multiple_use_fadd_fmad_f16(half addrspace(1)* %out, i16 zeroext %x.arg, i16 zeroext %y.arg) #0 { 161 %x = bitcast i16 %x.arg to half 162 %y = bitcast i16 %y.arg to half 163 %out.gep.1 = getelementptr half, half addrspace(1)* %out, i32 1 164 %x.abs = call half @llvm.fabs.f16(half %x) 165 %mul2 = fmul fast half %x.abs, 2.0 166 %mad = fadd fast half %mul2, %y 167 store volatile half %mul2, half addrspace(1)* %out 168 store volatile half %mad, half addrspace(1)* %out.gep.1 169 ret void 170} 171 172; GCN-LABEL: {{^}}multiple_use_fadd_multi_fmad_f16: 173; GCN: v_mad_f16 {{v[0-9]+}}, |[[X:s[0-9]+]]|, 2.0, v{{[0-9]+}} 174; GCN: v_mad_f16 {{v[0-9]+}}, |[[X]]|, 2.0, v{{[0-9]+}} 175define void @multiple_use_fadd_multi_fmad_f16(half addrspace(1)* %out, i16 zeroext %x.arg, i16 zeroext %y.arg, i16 zeroext %z.arg) #0 { 176 %x = bitcast i16 %x.arg to half 177 %y = bitcast i16 %y.arg to half 178 %z = bitcast i16 %z.arg to half 179 %out.gep.1 = getelementptr half, half addrspace(1)* %out, i32 1 180 %x.abs = call half @llvm.fabs.f16(half %x) 181 %mul2 = fmul fast half %x.abs, 2.0 182 %mad0 = fadd fast half %mul2, %y 183 %mad1 = fadd fast half %mul2, %z 184 store volatile half %mad0, half addrspace(1)* %out 185 store volatile half %mad1, half addrspace(1)* %out.gep.1 186 ret void 187} 188 189; GCN-LABEL: {{^}}fmul_x2_xn2_f16: 190; GCN: v_mul_f16_e64 [[TMP0:v[0-9]+]], [[X:s[0-9]+]], -4.0 191; GCN: v_mul_f16_e32 [[RESULT:v[0-9]+]], [[X]], [[TMP0]] 192; GCN: buffer_store_short [[RESULT]] 193define void @fmul_x2_xn2_f16(half addrspace(1)* %out, i16 zeroext %x.arg, i16 zeroext %y.arg) #0 { 194 %x = bitcast i16 %x.arg to half 195 %y = bitcast i16 %y.arg to half 196 %out.gep.1 = getelementptr half, half addrspace(1)* %out, i32 1 197 %mul2 = fmul fast half %x, 2.0 198 %muln2 = fmul fast half %x, -2.0 199 %mul = fmul fast half %mul2, %muln2 200 store volatile half %mul, half addrspace(1)* %out 201 ret void 202} 203 204; GCN-LABEL: {{^}}fmul_x2_xn3_f16: 205; GCN: v_mov_b32_e32 [[K:v[0-9]+]], 0xc600 206; GCN: v_mul_f16_e32 [[TMP0:v[0-9]+]], [[X:s[0-9]+]], [[K]] 207; GCN: v_mul_f16_e32 [[RESULT:v[0-9]+]], [[X]], [[TMP0]] 208; GCN: buffer_store_short [[RESULT]] 209define void @fmul_x2_xn3_f16(half addrspace(1)* %out, i16 zeroext %x.arg, i16 zeroext %y.arg) #0 { 210 %x = bitcast i16 %x.arg to half 211 %y = bitcast i16 %y.arg to half 212 %out.gep.1 = getelementptr half, half addrspace(1)* %out, i32 1 213 %mul2 = fmul fast half %x, 2.0 214 %muln2 = fmul fast half %x, -3.0 215 %mul = fmul fast half %mul2, %muln2 216 store volatile half %mul, half addrspace(1)* %out 217 ret void 218} 219 220attributes #0 = { nounwind "unsafe-fp-math"="true" } 221attributes #1 = { nounwind readnone } 222