Sub-optimal x86_64 assembly code generation
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The following code generates sub-optimal x86 assembly
```c
#include
#include
struct RandStruct {
char __pad1[0x10f2];
uint16_t class_array[4000];
char __pad2[0x45cc - (0x10f2 + 4000 * 2)];
uint32_t class_to_size[100];
};
static_assert(offsetof(RandStruct, class_array) == 0x10f2, "Offset mismatch class_array");
static_assert(offsetof(RandStruct, class_to_size) == 0x45cc, "Offset mismatch class_to_size");
constexpr uintptr_t kFixedAddr = 0x20000000;
#define FixedAddr reinterpret_cast(kFixedAddr)
volatile size_t g_align = 16;
volatile size_t g_idx = 5;
volatile size_t g_out = 0;
__attribute__((noinline)) void test5() {
size_t align = g_align - 1;
size_t idx = g_idx;
RandStruct* ptr = FixedAddr;
// Simulate the GetSizeClass lookup
size_t size_class = ptr->class_array[idx];
if (__builtin_expect(ptr->class_to_size[size_class] & align, 0)) {
do {
++size_class;
} while (__builtin_expect(ptr->class_to_size[size_class] & align, 0));
}
// Write out so it's not optimized entirely out
g_out = size_class;
}
int main()
{
test5();
}
```
with an -emit-llvm of:
```
; Function Attrs: mustprogress nofree noinline norecurse nounwind memory(readwrite, argmem: read) uwtable
define dso_local void @_Z5test5v() local_unnamed_addr #0 {
%1 = load volatile i64, ptr @g_align, align 8, !tbaa !5
%2 = add i64 %1, -1
%3 = load volatile i64, ptr @g_idx, align 8, !tbaa !5
%4 = getelementptr inbounds [4000 x i16], ptr inttoptr (i64 536875250 to ptr), i64 0, i64 %3
%5 = load i16, ptr %4, align 2, !tbaa !9
%6 = zext i16 %5 to i64
%7 = getelementptr inbounds [100 x i32], ptr inttoptr (i64 536888780 to ptr), i64 0, i64 %6
%8 = load i32, ptr %7, align 4, !tbaa !11
%9 = zext i32 %8 to i64
%10 = and i64 %2, %9
%11 = icmp eq i64 %10, 0
br i1 %11, label %20, label %12, !prof !13
12: ; preds = %0, %12
%13 = phi i64 [ %14, %12 ], [ %6, %0 ]
%14 = add i64 %13, 1
%15 = getelementptr inbounds [100 x i32], ptr inttoptr (i64 536888780 to ptr), i64 0, i64 %14
%16 = load i32, ptr %15, align 4, !tbaa !11
%17 = zext i32 %16 to i64
%18 = and i64 %2, %17
%19 = icmp eq i64 %18, 0
br i1 %19, label %20, label %12, !prof !13, !llvm.loop !14
20: ; preds = %12, %0
%21 = phi i64 [ %6, %0 ], [ %14, %12 ]
store volatile i64 %21, ptr @g_out, align 8, !tbaa !5
ret void
}
```
generates the following assembly code:
```asm
_Z5test5v():
1130: 48 8b 05 d9 2e 00 00 mov 0x2ed9(%rip),%rax # 4010
1137: 48 ff c8 dec %rax
113a: 48 8b 0d d7 2e 00 00 mov 0x2ed7(%rip),%rcx # 4018
1141: 0f b7 8c 09 f2 10 00 movzwl 0x200010f2(%rcx,%rcx,1),%ecx
1148: 20
1149: 85 04 8d cc 45 00 20 test %eax,0x200045cc(,%rcx,4)
1150: 75 08 jne 115a <_Z5test5v+0x2a>
1152: 48 89 0d cf 2e 00 00 mov %rcx,0x2ecf(%rip) # 4028
1159: c3 ret
115a: ba f2 10 00 20 mov $0x200010f2,%edx
115f: 48 8d 71 01 lea 0x1(%rcx),%rsi
1163: 85 84 8a de 34 00 00 test %eax,0x34de(%rdx,%rcx,4)
116a: 48 89 f1 mov %rsi,%rcx
116d: 75 f0 jne 115f <_Z5test5v+0x2f>
116f: 48 89 35 b2 2e 00 00 mov %rsi,0x2eb2(%rip) # 4028
1176: c3 ret
1177: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
117e: 00 00
```
The issue lies at
```asm
115a: ba f2 10 00 20 mov $0x200010f2,%edx
..
1163: 85 84 8a de 34 00 00 test %eax,0x34de(%rdx,%rcx,4)
```
the instructions could have been folded together, i.e.:
```
test %eax, 0x200045d0(,%rcx,4)
```
Contributor guide
Assessment
This issue has not been assessed yet.