<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/62452>62452</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Unnecessary mov instruction in two multiplications
</td>
</tr>
<tr>
<th>Labels</th>
<td>
backend:X86,
llvm:codegen,
missed-optimization
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
chfast
</td>
</tr>
</table>
<pre>
In the following C code the `test_a` computes the same as `test_b` just the order of instructions is different. However, codegen of `test_a` has single unnecessary `mov` instruction.
https://godbolt.org/z/MbKrKxKd6
```c
typedef unsigned long uint64_t;
uint64_t test_a(const uint64_t* x, uint64_t y) {
uint64_t q = x[1] * y;
uint64_t p = ((unsigned __int128)x[0] * y) >> 64;
return p + q;
}
uint64_t test_b(const uint64_t* x, uint64_t y) {
uint64_t p = ((unsigned __int128)x[0] * y) >> 64;
uint64_t q = x[1] * y;
return p + q;
}
```
```asm
test_a: # @test_a
mov rax, rsi
mul qword ptr [rdi]
mov rax, qword ptr [rdi + 8]
imul rax, rsi
add rax, rdx
ret
test_b: # @test_b
mov rax, rsi
mul qword ptr [rdi]
imul rsi, qword ptr [rdi + 8]
lea rax, [rsi + rdx]
ret
```
```llvm
define dso_local i64 @test_a(ptr nocapture noundef readonly %0, i64 noundef %1) local_unnamed_addr #0 {
%3 = getelementptr inbounds i64, ptr %0, i64 1
%4 = load i64, ptr %3, align 8, !tbaa !6
%5 = mul i64 %4, %1
%6 = load i64, ptr %0, align 8, !tbaa !6
%7 = zext i64 %6 to i128
%8 = zext i64 %1 to i128
%9 = mul nuw i128 %7, %8
%10 = lshr i128 %9, 64
%11 = trunc i128 %10 to i64
%12 = add i64 %5, %11
ret i64 %12
}
define dso_local i64 @test_b(ptr nocapture noundef readonly %0, i64 noundef %1) local_unnamed_addr #0 {
%3 = load i64, ptr %0, align 8, !tbaa !6
%4 = zext i64 %3 to i128
%5 = zext i64 %1 to i128
%6 = mul nuw i128 %4, %5
%7 = lshr i128 %6, 64
%8 = trunc i128 %7 to i64
%9 = getelementptr inbounds i64, ptr %0, i64 1
%10 = load i64, ptr %9, align 8, !tbaa !6
%11 = mul i64 %10, %1
%12 = add i64 %11, %8
ret i64 %12
}
attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0V92O2jgUfhpzYzFKTn4IF1wMpWhX1V6utHfIiQ_BrWOntjPAPP3KTggBpu10240QsXy-8_85tpm1olaIK5KtSbaZsc4dtFlVhz2zblZqfl79qag7IN1rKfVRqJp-oJXmGCZJHjm0bsdIHtFKN23n0AaJZQ1SZkdE6RGfO-uCVBuOhuo9Fco601VOaGWpsJSL_R4NKvdE_9BHfEFDoPdXo_IKNx4PzFIrVC2RdkphhdYyc_aYRr94wMT8E4k2JHru_w_OtZYkzwS2BLa15qWW7kmbmsD2lcD2r_KT-XT6xPOpEsmj_ldNZ925RY572qlQSU6lVjXthHJ5unMkWU_Bl2k65ABFpZV1Vzg805PPeASeCSwpWQxWKKVX0VdKkg09kWwdk2xDve559HeDbAOSQEGgGOPc7YRysZ9behvR1Yb3mHwkyUeapzcGDbrOKG8O1vTrNbfF5ttJlr-W5G8J_f0l-2GGFw68SQxmm4EUfXuTYPO7D4GEkvTC6TEO_zT6JbwNC9UyVtzJOxneX4_acNo6Q0m2NlyQbAj23sI9MCRZXOHDIwbDD34Z5zcB8dOtokE3Sb_82fTL353-mIgVP5G-RDb167G2x_qER_SY7PcpIeVLMxVw3AuFlFu9k7pikoo8nRAACh-f0hVrXWeQKt0p_3UxyLhW8kwJZJEPy6tdhASy2DM_GNx1SrEG-Y5xbnx9o8nKIpAlYQnU6FBig8p5f0KV3pT1Vr3xUKOJo_hSIQJZGvSlZvwOnfgxk6JWtAiFg9iVjPl3PtHPgr7vTMgcsrQHZ1Mn-becRO9zsgj6r3hyFy85dZoK_824oooHVHyHIpAtx3hVdwyy4GAIemoujvqo7cGMuKXH5ekUFQeUM52qRlgcBce3QAhAv-iG6LJLpcZSGbyGDm9-jL_Lt_L_5tuVcP-9l-lDl5I3epn9sJdXXt0388LA7IFBN73MH3pZvNHKxWMnl7-45C7Eeizh8n0lHDg3WXRx9Maqe2RcHN_z_MeMY84ZUYaDYM8Gv38v1rTprGuNrg1aS5XeG_R0M1h1xvqRPasqUOwoFKdHIeWwGTfYaHMmUDBTN9j4bcXT0zOwOzpWSqQEoBFqLrFmcv6CldNmfhTcHQgASTYEICIAHqb03BnWtkLV84ZNAM50OGCsY9WXeWu06y2VnT-Uzq14xRFeDFjHTI1uXrXdKDoV-dx3aSrfI_Pry44gAuvq5HtGYL0_WdOPmubUD6zFcQD96FQsLjY7hTcea1RoRBXEt814c3OiM75K-DJZshmu4ryAxQKKRTI7rJJluoh4VJUsiUtkaV7xfZQuYpbkrMIon4kVRJBEKSxjyNIkeUqrJALIoMwzHuEyImmEDRPyyW98_kQ9E9Z2uMohzWAmWYnShssGQMmqL6g4SZ7_KfJQkg8EIGyYyfNw5B-nG2Et8rlunWjEK_Mnei_LNjOz8irzsqstSSMprLNX5044iau_J5cDf6yYXAuoUNQdtV8bTrRSVMG0nXVGru5uCcIduvKp0g2BbYiyf3mifMbKEdiGVC2Bbcj23wAAAP__G0Otxg">