access-softek / llvm-project

Other
0 stars 0 forks source link

Strange code is generated for lshr by 1 #22

Closed atrosinenko closed 11 months ago

atrosinenko commented 4 years ago

When debugging compiler-rt tests failing only with optimizations enabled, I finally stumbled upon debugging machine code generated near uint64_t right shifted by (constant) 8 bits. The machine code was quite strange and hard to debug.

Then, I compiled some trivial example for uint32_t right-shifted by 1 bit and results were quite strange, too. Maybe I have mis-understood MSP430 instruction semantics, but I have not managed to find a number for which my 8-byte function diverges from "reference" 32-byte one (-O1).

// test_lshr32.c
#include <stdio.h>

uint32_t __attribute__((noinline)) test_c(uint32_t x)
{
  return x >> 1;
}

uint32_t test_asm(uint32_t x);

int main()
{
  const uint32_t x = TEST_X;
  printf("%lx\n", TEST_FUN(x));
  return 0;
}
// test_lshr32.S
.text
.global test_asm
test_asm:
  clrc
  rrc r13
  rrc r12
  ret
#!/bin/sh

srcs="test_lshr32.c test_lshr32.S"
opts="$1 -DTEST_X=$2"

rm test_lshr32_c test_lshr32_asm
$llvmroot/build-rel-assert/bin/clang -target msp430 -msim -lsim -Wall --gcc-toolchain=$sysroot --sysroot= $srcs $opts -DTEST_FUN=test_c -o test_lshr32_c
$sysroot/bin/msp430-elf-run test_lshr32_c
$llvmroot/build-rel-assert/bin/clang -target msp430 -msim -lsim -Wall --gcc-toolchain=$sysroot --sysroot= $srcs $opts -DTEST_FUN=test_asm -o test_lshr32_asm
$sysroot/bin/msp430-elf-run test_lshr32_asm

What is generated with -O1 (only two functions are shown):

00000630 <test_c>:
     630: 0e 4d                         mov     r13, r14
     632: 4e 4e                         mov.b   r14, r14
     634: 8e 10                         swpb    r14
     636: 12 c3                         clrc
     638: 0c 10                         rrc     r12
     63a: 0e 5e                         add     r14, r14
     63c: 0e 5e                         add     r14, r14
     63e: 0e 5e                         add     r14, r14
     640: 0e 5e                         add     r14, r14
     642: 0e 5e                         add     r14, r14
     644: 0e 5e                         add     r14, r14
     646: 0e 5e                         add     r14, r14
     648: 0c de                         bis     r14, r12
     64a: 12 c3                         clrc
     64c: 0d 10                         rrc     r13
     64e: 30 41                         ret

000006b8 <test_asm>:
     6b8: 12 c3                         clrc
     6ba: 0d 10                         rrc     r13
     6bc: 0c 10                         rrc     r12
     6be: 30 41                         ret

Looks like it is because 32-bit arithmetic is somehow autoexpanded for 16-bit registers in a way not very handly for MSP430 backend.

asl commented 4 years ago

This is the default lowering which emulates carry bit. Probably we'd need to implement _PARTS DAG nodes to improve the codegen :)