Environment :
llvm-project-llvmorg-10.0.0
ubuntu 20.04
Question :
I’m developing a new backend for LoongArch. For LLVM ISD SMUL_LOHI, which multiply two integers of type iN, producing a signed/unsigned value of type i[2*N], and return the full value as two results, each of type iN (Some thing like :
t42: i32,i32 = smul_lohi t38, t35
I need to replace it by LoongArch instruction MULH_W and MUL_W. The two instructions’ format as below:
That is, to use MUL_W to get the Lo result of mutiplicaiton and use MULH_W to get the High result of mutipication, and then replace the 2 results of UMUL_LOHI. I catched SMUL_LOHI by trySelect() in LoongArchSEISelDAGToDAG as below:
I’m sure the trySelect() run correctly and it does catched UMUL_LOHI Node, I use gdb to test this:
I can run llc command and generate .s file successfully, but its output is out of logic
I use the following code to test UMUL_LOHI :
long long test()
{
long long a = 0x300000002;
long long b = 0x100000001;
long long d = a * b; // d = 0x00000005,00000002
return d;
}
the .ll file corresponding to the C program is :
define dso_local i64 @test() #0 {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
%3 = alloca i64, align 8
store i64 12884901890, i64* %1, align 8
store i64 4294967297, i64* %2, align 8
%4 = load i64, i64* %1, align 8
%5 = load i64, i64* %2, align 8
%6 = mul nsw i64 %4, %5
store i64 %6, i64* %3, align 8
%7 = load i64, i64* %3, align 8
ret i64 %7
}
the corresponding .s file is:
test:
# %bb.0:
addi.w $r3, $r3, -32
addi.w $r4, $r3, 24
ori $r4, $r4, 4
addi.w $r5, $r0, 3
st.w $r5, $r4, 0
addi.w $r5, $r0, 2
st.w $r5, $r3, 24
addi.w $r5, $r3, 16
ori $r5, $r5, 4
addi.w $r6, $r0, 1
st.w $r6, $r5, 0
st.w $r6, $r3, 16
ld.w $r4, $r4, 0
ld.w $r6, $r3, 24
ld.w $r5, $r5, 0
ld.w $r7, $r3, 16
mul.w $r5, $r6, $r5
mulh.wu $r8, $r6, $r7
add.w $r5, $r8, $r5
mul.w $r4, $r4, $r7
add.w $r4, $r5, $r4
mul.w $r5, $r6, $r7
addi.w $r6, $r3, 8
ori $r6, $r6, 4
st.w $r4, $r6, 0
st.w $r5, $r3, 8
ld.w $r5, $r6, 0
ld.w $r4, $r3, 8
addi.w $r3, $r3, 32
jr $r1
As you can see, there is a i64 mul instruction in IR, which will be translated to llvm UMUL_LOHI,
my backend catched, and translate it to mul.w and mulh.wu successfully. But my backend misuse the result of them. For the following Code fragment in .s file :
mul.w $r5, $r6, $r5
mulh.wu $r8, $r6, $r7
add.w $r5, $r8, $r5
It gets the Lo result in r5 and the hi result in r8, the next work it needs to do is to store them into stack, but it add them up My register is 32-bit , so this add operation is definely incorrect. I guess this strange output is because I did something wrong when I replaced the node .
I am really a beginner of LLVM, Could any one help me with it? Thank you very much !
If you want to check out the whole project, please check :