[llvm] [AVR] Adapt getPostIndexedAddressParts() and getPreIndexedAddressParts (PR #145040)
Tom Vijlbrief via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 20 06:59:16 PDT 2025
https://github.com/tomtor created https://github.com/llvm/llvm-project/pull/145040
Fixes https://github.com/llvm/llvm-project/issues/143247
For testing this PR I used the following code:
```
#if 1
#define PA 0x1 // Bad
#else
#define PA 0x2 // Good
#endif
volatile char *const PORT = (char *const) PA;
extern void nil(short);
void bug()
{
short s= 0;
while (1) {
s++;
*PORT = *PORT | 0x80;
nil((s & 0xF) + PA);
}
}
unsigned
demo_post (unsigned short value, unsigned short *buffer, unsigned short *bufend)
{
unsigned short *tmp;
for (tmp = buffer; tmp < bufend; tmp++)
value -= *tmp;
return value;
}
const char *
demo_2 (const char *in, char *out)
{
while (1)
{
if (*in == 'a')
{
const char *p = in + 1;
while (*p == 'x')
++p;
if (*p == 'b')
return p;
while (in < p)
*out++ = *in++;
}
}
}
```
It contains the code which triggers the original bug and two demo functions which still emit post/pre-index code triggered by `getPreIndexedAddressParts`.
When comparing the generated assembly the only difference is in the generated code for `bug()`
```
16,17c16,17
< ldi r24, 0
< ldi r25, 0
---
> ldi r26, 0
> ldi r27, 0
20,25c20,26
< sbi 1, 7
< adiw r24, 1
< movw r16, r24
< andi r24, 15
< andi r25, 0
< adiw r24, 1
---
> ld r24, X+
> ori r24, -128
> movw r16, r26
> andi r26, 15
> andi r27, 0
> st X+, r24
> movw r24, r26
27c28
< movw r24, r16
---
> movw r26, r16
```
For future reference, I examined tests from the gcc torture collection, and determined that only the few following tests (from 1930 tests) generate pre/post index code:
```
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/20000412-6.c
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/20011126-2.c
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/980205.c
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/990524-1.c
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/pr20601-1.c
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/pr38051.c
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/pr44852.c
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/pr44942.c
#$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/pr67037.c
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/stdarg-2.c
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/stdarg-3.c
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/va-arg-22.c
$C -O2 -target avr-none $M -S gcc/gcc/testsuite/gcc.c-torture/execute/va-arg-26.c
```
The commented out test crashes clang, as do many others.
So for some reason, the AVR pre/post index only is generated in a few cases, less then I would expect, but that is not related to this PR.
The reason why this PR is effective for the specific `bug()` code generation is not clear to me.
The fix can be suboptimal, but it only removes a certain case of optimization which is incorrect for the `bug()` code, so there is minimal danger of an regression. I would really appreciate any feedback from experienced LLVM contributors about the root cause or alternative ways to handle the issue.
>From a9df1888755677f3b5cba65bc34927aace073c5f Mon Sep 17 00:00:00 2001
From: Tom Vijlbrief <tvijlbrief at gmail.com>
Date: Tue, 17 Jun 2025 15:11:51 +0200
Subject: [PATCH] [AVR] Adapt getPostIndexedAddressParts() and
getPreIndexedAddressParts
Fixes https://github.com/llvm/llvm-project/issues/143247
---
llvm/lib/Target/AVR/AVRISelLowering.cpp | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp
index 9747ad0c5cd58..00e1fb8fd5528 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp
@@ -1052,6 +1052,10 @@ bool AVRTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base,
return false;
}
+ // Fixes https://github.com/llvm/llvm-project/issues/143247
+ if (Op->getOperand(0)->hasOneUse())
+ return false;
+
Base = Op->getOperand(0);
Offset = DAG.getSignedConstant(RHSC, DL, MVT::i8);
AM = ISD::PRE_DEC;
@@ -1114,6 +1118,10 @@ bool AVRTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
if (AVR::isProgramMemoryAccess(LD))
return false;
+ // Fixes https://github.com/llvm/llvm-project/issues/143247
+ if (Op->getOperand(0)->hasOneUse())
+ return false;
+
Base = Op->getOperand(0);
Offset = DAG.getConstant(RHSC, DL, MVT::i8);
AM = ISD::POST_INC;
More information about the llvm-commits
mailing list