Issue 137968
Summary [RISCV] `clang` generates incorrect code and uses wrong register during array indexing when using any optimization level other than `-O0`
Labels clang
Assignees
Reporter thebigclub
    Found a case where `clang` misbehaves. The wrong register is being used to generate the memory address that's read. This causes the generated program to crash because an incorrect location (`0xffffffff`) is accessed:

```bash
$ cat << EOF > test.c
#include <stddef.h>

size_t fn(const char *str) {
	size_t ret = 4, sp = 4;

	char c0 = str[0 - sp], c3 = str[3 - sp];
	if (c0 == 0) return ret + 0 - sp;
	if (c3 == 0) return ret + 3 - sp;

	return 0;
}
EOF
$ clang -O3 -c test.c
$ llvm-objdump -d test.o

test.o:	file format elf32-littleriscv

Disassembly of section .text:

00000000 <fn>:
       0: ffc54503     	lbu	a0, -0x4(a0)
 4: c101         	beqz	a0, 0x4 <fn+0x4>
       6: fff04503     	lbu	a0, -0x1(zero)
       a: 00a03533     	snez	a0, a0
       e: 157d 	addi	a0, a0, -0x1
      10: 890d         	andi	a0, a0, 0x3
      12: 8082         	ret
$ clang -v
clang version 21.0.0git (https://github.com/llvm/llvm-project.git 4aca20c8b6dcf86696db03d860e635112601a7f9)
Target: riscv32-unknown-unknown-elf
```

Notice that the second load uses the `zero` register (`x0`). This register always returns the value zero when read. It should be using the `a0` register instead.

If you change the _expression_ `3 - sp` to `-1`, the correct code is generated:

```bash

test.o:	file format elf32-littleriscv

Disassembly of section .text:

00000000 <fn>:
 0: ffc54583     	lbu	a1, -0x4(a0)
       4: c181         	beqz	a1, 0x4 <fn+0x4>
       6: fff54503     	lbu	a0, -0x1(a0)
       a: 00a03533 	snez	a0, a0
       e: 157d         	addi	a0, a0, -0x1
      10: 890d 	andi	a0, a0, 0x3
      12: 8082         	ret
      14: 4501 	li	a0, 0x0
      16: 8082         	ret
```
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to