1*9880d681SAndroid Build Coastguard Worker; RUN: llc -march=amdgcn -mcpu=verde -verify-machineinstrs < %s | FileCheck -check-prefix=SI -check-prefix=FUNC %s 2*9880d681SAndroid Build Coastguard Worker; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=SI -check-prefix=FUNC %s 3*9880d681SAndroid Build Coastguard Worker; RUN: llc -march=r600 -mcpu=redwood < %s | FileCheck -check-prefix=EG %s -check-prefix=FUNC 4*9880d681SAndroid Build Coastguard Worker 5*9880d681SAndroid Build Coastguard Worker; mul24 and mad24 are affected 6*9880d681SAndroid Build Coastguard Worker 7*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}test_mul_v2i32: 8*9880d681SAndroid Build Coastguard Worker; EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} 9*9880d681SAndroid Build Coastguard Worker; EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} 10*9880d681SAndroid Build Coastguard Worker 11*9880d681SAndroid Build Coastguard Worker; SI: v_mul_lo_i32 v{{[0-9]+, v[0-9]+, v[0-9]+}} 12*9880d681SAndroid Build Coastguard Worker; SI: v_mul_lo_i32 v{{[0-9]+, v[0-9]+, v[0-9]+}} 13*9880d681SAndroid Build Coastguard Worker 14*9880d681SAndroid Build Coastguard Workerdefine void @test_mul_v2i32(<2 x i32> addrspace(1)* %out, <2 x i32> addrspace(1)* %in) { 15*9880d681SAndroid Build Coastguard Worker %b_ptr = getelementptr <2 x i32>, <2 x i32> addrspace(1)* %in, i32 1 16*9880d681SAndroid Build Coastguard Worker %a = load <2 x i32>, <2 x i32> addrspace(1) * %in 17*9880d681SAndroid Build Coastguard Worker %b = load <2 x i32>, <2 x i32> addrspace(1) * %b_ptr 18*9880d681SAndroid Build Coastguard Worker %result = mul <2 x i32> %a, %b 19*9880d681SAndroid Build Coastguard Worker store <2 x i32> %result, <2 x i32> addrspace(1)* %out 20*9880d681SAndroid Build Coastguard Worker ret void 21*9880d681SAndroid Build Coastguard Worker} 22*9880d681SAndroid Build Coastguard Worker 23*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}v_mul_v4i32: 24*9880d681SAndroid Build Coastguard Worker; EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} 25*9880d681SAndroid Build Coastguard Worker; EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} 26*9880d681SAndroid Build Coastguard Worker; EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} 27*9880d681SAndroid Build Coastguard Worker; EG: MULLO_INT {{\*? *}}T{{[0-9]+\.[XYZW], T[0-9]+\.[XYZW], T[0-9]+\.[XYZW]}} 28*9880d681SAndroid Build Coastguard Worker 29*9880d681SAndroid Build Coastguard Worker; SI: v_mul_lo_i32 v{{[0-9]+, v[0-9]+, v[0-9]+}} 30*9880d681SAndroid Build Coastguard Worker; SI: v_mul_lo_i32 v{{[0-9]+, v[0-9]+, v[0-9]+}} 31*9880d681SAndroid Build Coastguard Worker; SI: v_mul_lo_i32 v{{[0-9]+, v[0-9]+, v[0-9]+}} 32*9880d681SAndroid Build Coastguard Worker; SI: v_mul_lo_i32 v{{[0-9]+, v[0-9]+, v[0-9]+}} 33*9880d681SAndroid Build Coastguard Worker 34*9880d681SAndroid Build Coastguard Workerdefine void @v_mul_v4i32(<4 x i32> addrspace(1)* %out, <4 x i32> addrspace(1)* %in) { 35*9880d681SAndroid Build Coastguard Worker %b_ptr = getelementptr <4 x i32>, <4 x i32> addrspace(1)* %in, i32 1 36*9880d681SAndroid Build Coastguard Worker %a = load <4 x i32>, <4 x i32> addrspace(1) * %in 37*9880d681SAndroid Build Coastguard Worker %b = load <4 x i32>, <4 x i32> addrspace(1) * %b_ptr 38*9880d681SAndroid Build Coastguard Worker %result = mul <4 x i32> %a, %b 39*9880d681SAndroid Build Coastguard Worker store <4 x i32> %result, <4 x i32> addrspace(1)* %out 40*9880d681SAndroid Build Coastguard Worker ret void 41*9880d681SAndroid Build Coastguard Worker} 42*9880d681SAndroid Build Coastguard Worker 43*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}s_trunc_i64_mul_to_i32: 44*9880d681SAndroid Build Coastguard Worker; SI: s_load_dword 45*9880d681SAndroid Build Coastguard Worker; SI: s_load_dword 46*9880d681SAndroid Build Coastguard Worker; SI: s_mul_i32 47*9880d681SAndroid Build Coastguard Worker; SI: buffer_store_dword 48*9880d681SAndroid Build Coastguard Workerdefine void @s_trunc_i64_mul_to_i32(i32 addrspace(1)* %out, i64 %a, i64 %b) { 49*9880d681SAndroid Build Coastguard Worker %mul = mul i64 %b, %a 50*9880d681SAndroid Build Coastguard Worker %trunc = trunc i64 %mul to i32 51*9880d681SAndroid Build Coastguard Worker store i32 %trunc, i32 addrspace(1)* %out, align 8 52*9880d681SAndroid Build Coastguard Worker ret void 53*9880d681SAndroid Build Coastguard Worker} 54*9880d681SAndroid Build Coastguard Worker 55*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}v_trunc_i64_mul_to_i32: 56*9880d681SAndroid Build Coastguard Worker; SI: s_load_dword 57*9880d681SAndroid Build Coastguard Worker; SI: s_load_dword 58*9880d681SAndroid Build Coastguard Worker; SI: v_mul_lo_i32 59*9880d681SAndroid Build Coastguard Worker; SI: buffer_store_dword 60*9880d681SAndroid Build Coastguard Workerdefine void @v_trunc_i64_mul_to_i32(i32 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr) nounwind { 61*9880d681SAndroid Build Coastguard Worker %a = load i64, i64 addrspace(1)* %aptr, align 8 62*9880d681SAndroid Build Coastguard Worker %b = load i64, i64 addrspace(1)* %bptr, align 8 63*9880d681SAndroid Build Coastguard Worker %mul = mul i64 %b, %a 64*9880d681SAndroid Build Coastguard Worker %trunc = trunc i64 %mul to i32 65*9880d681SAndroid Build Coastguard Worker store i32 %trunc, i32 addrspace(1)* %out, align 8 66*9880d681SAndroid Build Coastguard Worker ret void 67*9880d681SAndroid Build Coastguard Worker} 68*9880d681SAndroid Build Coastguard Worker 69*9880d681SAndroid Build Coastguard Worker; This 64-bit multiply should just use MUL_HI and MUL_LO, since the top 70*9880d681SAndroid Build Coastguard Worker; 32-bits of both arguments are sign bits. 71*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}mul64_sext_c: 72*9880d681SAndroid Build Coastguard Worker; EG-DAG: MULLO_INT 73*9880d681SAndroid Build Coastguard Worker; EG-DAG: MULHI_INT 74*9880d681SAndroid Build Coastguard Worker; SI-DAG: s_mul_i32 75*9880d681SAndroid Build Coastguard Worker; SI-DAG: v_mul_hi_i32 76*9880d681SAndroid Build Coastguard Workerdefine void @mul64_sext_c(i64 addrspace(1)* %out, i32 %in) { 77*9880d681SAndroid Build Coastguard Workerentry: 78*9880d681SAndroid Build Coastguard Worker %0 = sext i32 %in to i64 79*9880d681SAndroid Build Coastguard Worker %1 = mul i64 %0, 80 80*9880d681SAndroid Build Coastguard Worker store i64 %1, i64 addrspace(1)* %out 81*9880d681SAndroid Build Coastguard Worker ret void 82*9880d681SAndroid Build Coastguard Worker} 83*9880d681SAndroid Build Coastguard Worker 84*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}v_mul64_sext_c: 85*9880d681SAndroid Build Coastguard Worker; EG-DAG: MULLO_INT 86*9880d681SAndroid Build Coastguard Worker; EG-DAG: MULHI_INT 87*9880d681SAndroid Build Coastguard Worker; SI-DAG: v_mul_lo_i32 88*9880d681SAndroid Build Coastguard Worker; SI-DAG: v_mul_hi_i32 89*9880d681SAndroid Build Coastguard Worker; SI: s_endpgm 90*9880d681SAndroid Build Coastguard Workerdefine void @v_mul64_sext_c(i64 addrspace(1)* %out, i32 addrspace(1)* %in) { 91*9880d681SAndroid Build Coastguard Worker %val = load i32, i32 addrspace(1)* %in, align 4 92*9880d681SAndroid Build Coastguard Worker %ext = sext i32 %val to i64 93*9880d681SAndroid Build Coastguard Worker %mul = mul i64 %ext, 80 94*9880d681SAndroid Build Coastguard Worker store i64 %mul, i64 addrspace(1)* %out, align 8 95*9880d681SAndroid Build Coastguard Worker ret void 96*9880d681SAndroid Build Coastguard Worker} 97*9880d681SAndroid Build Coastguard Worker 98*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}v_mul64_sext_inline_imm: 99*9880d681SAndroid Build Coastguard Worker; SI-DAG: v_mul_lo_i32 v{{[0-9]+}}, v{{[0-9]+}}, 9 100*9880d681SAndroid Build Coastguard Worker; SI-DAG: v_mul_hi_i32 v{{[0-9]+}}, v{{[0-9]+}}, 9 101*9880d681SAndroid Build Coastguard Worker; SI: s_endpgm 102*9880d681SAndroid Build Coastguard Workerdefine void @v_mul64_sext_inline_imm(i64 addrspace(1)* %out, i32 addrspace(1)* %in) { 103*9880d681SAndroid Build Coastguard Worker %val = load i32, i32 addrspace(1)* %in, align 4 104*9880d681SAndroid Build Coastguard Worker %ext = sext i32 %val to i64 105*9880d681SAndroid Build Coastguard Worker %mul = mul i64 %ext, 9 106*9880d681SAndroid Build Coastguard Worker store i64 %mul, i64 addrspace(1)* %out, align 8 107*9880d681SAndroid Build Coastguard Worker ret void 108*9880d681SAndroid Build Coastguard Worker} 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}s_mul_i32: 111*9880d681SAndroid Build Coastguard Worker; SI: s_load_dword [[SRC0:s[0-9]+]], 112*9880d681SAndroid Build Coastguard Worker; SI: s_load_dword [[SRC1:s[0-9]+]], 113*9880d681SAndroid Build Coastguard Worker; SI: s_mul_i32 [[SRESULT:s[0-9]+]], [[SRC0]], [[SRC1]] 114*9880d681SAndroid Build Coastguard Worker; SI: v_mov_b32_e32 [[VRESULT:v[0-9]+]], [[SRESULT]] 115*9880d681SAndroid Build Coastguard Worker; SI: buffer_store_dword [[VRESULT]], 116*9880d681SAndroid Build Coastguard Worker; SI: s_endpgm 117*9880d681SAndroid Build Coastguard Workerdefine void @s_mul_i32(i32 addrspace(1)* %out, i32 %a, i32 %b) nounwind { 118*9880d681SAndroid Build Coastguard Worker %mul = mul i32 %a, %b 119*9880d681SAndroid Build Coastguard Worker store i32 %mul, i32 addrspace(1)* %out, align 4 120*9880d681SAndroid Build Coastguard Worker ret void 121*9880d681SAndroid Build Coastguard Worker} 122*9880d681SAndroid Build Coastguard Worker 123*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}v_mul_i32: 124*9880d681SAndroid Build Coastguard Worker; SI: v_mul_lo_i32 v{{[0-9]+}}, v{{[0-9]+}}, v{{[0-9]+}} 125*9880d681SAndroid Build Coastguard Workerdefine void @v_mul_i32(i32 addrspace(1)* %out, i32 addrspace(1)* %in) { 126*9880d681SAndroid Build Coastguard Worker %b_ptr = getelementptr i32, i32 addrspace(1)* %in, i32 1 127*9880d681SAndroid Build Coastguard Worker %a = load i32, i32 addrspace(1)* %in 128*9880d681SAndroid Build Coastguard Worker %b = load i32, i32 addrspace(1)* %b_ptr 129*9880d681SAndroid Build Coastguard Worker %result = mul i32 %a, %b 130*9880d681SAndroid Build Coastguard Worker store i32 %result, i32 addrspace(1)* %out 131*9880d681SAndroid Build Coastguard Worker ret void 132*9880d681SAndroid Build Coastguard Worker} 133*9880d681SAndroid Build Coastguard Worker 134*9880d681SAndroid Build Coastguard Worker; A standard 64-bit multiply. The expansion should be around 6 instructions. 135*9880d681SAndroid Build Coastguard Worker; It would be difficult to match the expansion correctly without writing 136*9880d681SAndroid Build Coastguard Worker; a really complicated list of FileCheck expressions. I don't want 137*9880d681SAndroid Build Coastguard Worker; to confuse people who may 'break' this test with a correct optimization, 138*9880d681SAndroid Build Coastguard Worker; so this test just uses FUNC-LABEL to make sure the compiler does not 139*9880d681SAndroid Build Coastguard Worker; crash with a 'failed to select' error. 140*9880d681SAndroid Build Coastguard Worker 141*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}s_mul_i64: 142*9880d681SAndroid Build Coastguard Workerdefine void @s_mul_i64(i64 addrspace(1)* %out, i64 %a, i64 %b) nounwind { 143*9880d681SAndroid Build Coastguard Worker %mul = mul i64 %a, %b 144*9880d681SAndroid Build Coastguard Worker store i64 %mul, i64 addrspace(1)* %out, align 8 145*9880d681SAndroid Build Coastguard Worker ret void 146*9880d681SAndroid Build Coastguard Worker} 147*9880d681SAndroid Build Coastguard Worker 148*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}v_mul_i64: 149*9880d681SAndroid Build Coastguard Worker; SI: v_mul_lo_i32 150*9880d681SAndroid Build Coastguard Workerdefine void @v_mul_i64(i64 addrspace(1)* %out, i64 addrspace(1)* %aptr, i64 addrspace(1)* %bptr) { 151*9880d681SAndroid Build Coastguard Worker %a = load i64, i64 addrspace(1)* %aptr, align 8 152*9880d681SAndroid Build Coastguard Worker %b = load i64, i64 addrspace(1)* %bptr, align 8 153*9880d681SAndroid Build Coastguard Worker %mul = mul i64 %a, %b 154*9880d681SAndroid Build Coastguard Worker store i64 %mul, i64 addrspace(1)* %out, align 8 155*9880d681SAndroid Build Coastguard Worker ret void 156*9880d681SAndroid Build Coastguard Worker} 157*9880d681SAndroid Build Coastguard Worker 158*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}mul32_in_branch: 159*9880d681SAndroid Build Coastguard Worker; SI: s_mul_i32 160*9880d681SAndroid Build Coastguard Workerdefine void @mul32_in_branch(i32 addrspace(1)* %out, i32 addrspace(1)* %in, i32 %a, i32 %b, i32 %c) { 161*9880d681SAndroid Build Coastguard Workerentry: 162*9880d681SAndroid Build Coastguard Worker %0 = icmp eq i32 %a, 0 163*9880d681SAndroid Build Coastguard Worker br i1 %0, label %if, label %else 164*9880d681SAndroid Build Coastguard Worker 165*9880d681SAndroid Build Coastguard Workerif: 166*9880d681SAndroid Build Coastguard Worker %1 = load i32, i32 addrspace(1)* %in 167*9880d681SAndroid Build Coastguard Worker br label %endif 168*9880d681SAndroid Build Coastguard Worker 169*9880d681SAndroid Build Coastguard Workerelse: 170*9880d681SAndroid Build Coastguard Worker %2 = mul i32 %a, %b 171*9880d681SAndroid Build Coastguard Worker br label %endif 172*9880d681SAndroid Build Coastguard Worker 173*9880d681SAndroid Build Coastguard Workerendif: 174*9880d681SAndroid Build Coastguard Worker %3 = phi i32 [%1, %if], [%2, %else] 175*9880d681SAndroid Build Coastguard Worker store i32 %3, i32 addrspace(1)* %out 176*9880d681SAndroid Build Coastguard Worker ret void 177*9880d681SAndroid Build Coastguard Worker} 178*9880d681SAndroid Build Coastguard Worker 179*9880d681SAndroid Build Coastguard Worker; FUNC-LABEL: {{^}}mul64_in_branch: 180*9880d681SAndroid Build Coastguard Worker; SI-DAG: s_mul_i32 181*9880d681SAndroid Build Coastguard Worker; SI-DAG: v_mul_hi_u32 182*9880d681SAndroid Build Coastguard Worker; SI: s_endpgm 183*9880d681SAndroid Build Coastguard Workerdefine void @mul64_in_branch(i64 addrspace(1)* %out, i64 addrspace(1)* %in, i64 %a, i64 %b, i64 %c) { 184*9880d681SAndroid Build Coastguard Workerentry: 185*9880d681SAndroid Build Coastguard Worker %0 = icmp eq i64 %a, 0 186*9880d681SAndroid Build Coastguard Worker br i1 %0, label %if, label %else 187*9880d681SAndroid Build Coastguard Worker 188*9880d681SAndroid Build Coastguard Workerif: 189*9880d681SAndroid Build Coastguard Worker %1 = load i64, i64 addrspace(1)* %in 190*9880d681SAndroid Build Coastguard Worker br label %endif 191*9880d681SAndroid Build Coastguard Worker 192*9880d681SAndroid Build Coastguard Workerelse: 193*9880d681SAndroid Build Coastguard Worker %2 = mul i64 %a, %b 194*9880d681SAndroid Build Coastguard Worker br label %endif 195*9880d681SAndroid Build Coastguard Worker 196*9880d681SAndroid Build Coastguard Workerendif: 197*9880d681SAndroid Build Coastguard Worker %3 = phi i64 [%1, %if], [%2, %else] 198*9880d681SAndroid Build Coastguard Worker store i64 %3, i64 addrspace(1)* %out 199*9880d681SAndroid Build Coastguard Worker ret void 200*9880d681SAndroid Build Coastguard Worker} 201