[llvm] c7a4efa - [AVR] Fix 16-bit LDDs with immediate overflows (#104923)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 29 00:28:20 PDT 2024
Author: Patryk Wychowaniec
Date: 2024-08-29T15:28:17+08:00
New Revision: c7a4efa4294789b1116f0c4a320c16fcb27cb62c
URL: https://github.com/llvm/llvm-project/commit/c7a4efa4294789b1116f0c4a320c16fcb27cb62c
DIFF: https://github.com/llvm/llvm-project/commit/c7a4efa4294789b1116f0c4a320c16fcb27cb62c.diff
LOG: [AVR] Fix 16-bit LDDs with immediate overflows (#104923)
16-bit loads are expanded into a pair of 8-bit loads, so the maximum
offset of such 16-bit loads must be 62, not 63.
Added:
llvm/test/CodeGen/AVR/ldd-immediate-overflow.ll
llvm/test/CodeGen/AVR/std-immediate-overflow.ll
Modified:
llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp b/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
index 77db876d47e446..a8927d834630ea 100644
--- a/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
@@ -122,8 +122,13 @@ bool AVRDAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base,
// offset allowed.
MVT VT = cast<MemSDNode>(Op)->getMemoryVT().getSimpleVT();
- // We only accept offsets that fit in 6 bits (unsigned).
- if (isUInt<6>(RHSC) && (VT == MVT::i8 || VT == MVT::i16)) {
+ // We only accept offsets that fit in 6 bits (unsigned), with the exception
+ // of 16-bit loads - those can only go up to 62, because we desugar them
+ // into a pair of 8-bit loads like `ldd rx, RHSC` + `ldd ry, RHSC + 1`.
+ bool OkI8 = VT == MVT::i8 && RHSC <= 63;
+ bool OkI16 = VT == MVT::i16 && RHSC <= 62;
+
+ if (OkI8 || OkI16) {
Base = N.getOperand(0);
Disp = CurDAG->getTargetConstant(RHSC, dl, MVT::i8);
diff --git a/llvm/test/CodeGen/AVR/ldd-immediate-overflow.ll b/llvm/test/CodeGen/AVR/ldd-immediate-overflow.ll
new file mode 100644
index 00000000000000..6f1a4b32bb054c
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/ldd-immediate-overflow.ll
@@ -0,0 +1,144 @@
+; RUN: llc -march=avr -filetype=asm -O1 < %s | FileCheck %s
+
+define void @check60(ptr %1) {
+; CHECK-LABEL: check60:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: ldd r24, Z+60
+; CHECK-NEXT: ldd r25, Z+61
+; CHECK-NEXT: ldd r18, Z+62
+; CHECK-NEXT: ldd r19, Z+63
+; CHECK-NEXT: sts 3, r19
+; CHECK-NEXT: sts 2, r18
+; CHECK-NEXT: sts 1, r25
+; CHECK-NEXT: sts 0, r24
+; CHECK-NEXT: ret
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i16 60
+ %3 = load i32, ptr %2, align 1
+ store i32 %3, ptr null, align 1
+ ret void
+}
+
+define void @check61(ptr %1) {
+; CHECK-LABEL: check61:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: ldd r18, Z+61
+; CHECK-NEXT: ldd r19, Z+62
+; CHECK-NEXT: adiw r24, 63
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: ld r24, Z
+; CHECK-NEXT: ldd r25, Z+1
+; CHECK-NEXT: sts 3, r25
+; CHECK-NEXT: sts 2, r24
+; CHECK-NEXT: sts 1, r19
+; CHECK-NEXT: sts 0, r18
+; CHECK-NEXT: ret
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i16 61
+ %3 = load i32, ptr %2, align 1
+ store i32 %3, ptr null, align 1
+ ret void
+}
+
+define void @check62(ptr %1) {
+; CHECK-LABEL: check62:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: ldd r18, Z+62
+; CHECK-NEXT: ldd r19, Z+63
+; CHECK-NEXT: adiw r24, 62
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: ldd r24, Z+2
+; CHECK-NEXT: ldd r25, Z+3
+; CHECK-NEXT: sts 3, r25
+; CHECK-NEXT: sts 2, r24
+; CHECK-NEXT: sts 1, r19
+; CHECK-NEXT: sts 0, r18
+; CHECK-NEXT: ret
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i16 62
+ %3 = load i32, ptr %2, align 1
+ store i32 %3, ptr null, align 1
+ ret void
+}
+
+define void @check63(ptr %1) {
+; CHECK-LABEL: check63:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: adiw r24, 63
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: ld r24, Z
+; CHECK-NEXT: ldd r25, Z+1
+; CHECK-NEXT: ldd r18, Z+2
+; CHECK-NEXT: ldd r19, Z+3
+; CHECK-NEXT: sts 3, r19
+; CHECK-NEXT: sts 2, r18
+; CHECK-NEXT: sts 1, r25
+; CHECK-NEXT: sts 0, r24
+; CHECK-NEXT: ret
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i16 63
+ %3 = load i32, ptr %2, align 1
+ store i32 %3, ptr null, align 1
+ ret void
+}
+
+define void @check64(ptr %1) {
+; CHECK-LABEL: check64:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: subi r24, 192
+; CHECK-NEXT: sbci r25, 255
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: ld r24, Z
+; CHECK-NEXT: ldd r25, Z+1
+; CHECK-NEXT: ldd r18, Z+2
+; CHECK-NEXT: ldd r19, Z+3
+; CHECK-NEXT: sts 3, r19
+; CHECK-NEXT: sts 2, r18
+; CHECK-NEXT: sts 1, r25
+; CHECK-NEXT: sts 0, r24
+; CHECK-NEXT: ret
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i16 64
+ %3 = load i32, ptr %2, align 1
+ store i32 %3, ptr null, align 1
+ ret void
+}
+
+define void @check65(ptr %1) {
+; CHECK-LABEL: check65:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: subi r24, 191
+; CHECK-NEXT: sbci r25, 255
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: ld r24, Z
+; CHECK-NEXT: ldd r25, Z+1
+; CHECK-NEXT: ldd r18, Z+2
+; CHECK-NEXT: ldd r19, Z+3
+; CHECK-NEXT: sts 3, r19
+; CHECK-NEXT: sts 2, r18
+; CHECK-NEXT: sts 1, r25
+; CHECK-NEXT: sts 0, r24
+; CHECK-NEXT: ret
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i16 65
+ %3 = load i32, ptr %2, align 1
+ store i32 %3, ptr null, align 1
+ ret void
+}
diff --git a/llvm/test/CodeGen/AVR/std-immediate-overflow.ll b/llvm/test/CodeGen/AVR/std-immediate-overflow.ll
new file mode 100644
index 00000000000000..18ccb79d3a5f89
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/std-immediate-overflow.ll
@@ -0,0 +1,137 @@
+; RUN: llc -march=avr -filetype=asm -O1 < %s | FileCheck %s
+
+define void @check60(ptr %1) {
+; CHECK-LABEL: check60:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: ldi r18, 0
+; CHECK-NEXT: ldi r19, 0
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: std Z+63, r19
+; CHECK-NEXT: std Z+62, r18
+; CHECK-NEXT: ldi r24, 210
+; CHECK-NEXT: ldi r25, 4
+; CHECK-NEXT: std Z+61, r25
+; CHECK-NEXT: std Z+60, r24
+; CHECK-NEXT: ret
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i8 60
+ store i32 1234, ptr %2
+ ret void
+}
+
+define void @check61(ptr %1) {
+; CHECK-LABEL: check61:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: ldi r18, 210
+; CHECK-NEXT: ldi r19, 4
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: std Z+62, r19
+; CHECK-NEXT: std Z+61, r18
+; CHECK-NEXT: adiw r24, 63
+; CHECK-NEXT: ldi r18, 0
+; CHECK-NEXT: ldi r19, 0
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: std Z+1, r19
+; CHECK-NEXT: st Z, r18
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i8 61
+ store i32 1234, ptr %2
+ ret void
+}
+
+define void @check62(ptr %1) {
+; CHECK-LABEL: check62:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: ldi r18, 210
+; CHECK-NEXT: ldi r19, 4
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: std Z+63, r19
+; CHECK-NEXT: std Z+62, r18
+; CHECK-NEXT: adiw r24, 62
+; CHECK-NEXT: ldi r18, 0
+; CHECK-NEXT: ldi r19, 0
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: std Z+3, r19
+; CHECK-NEXT: std Z+2, r18
+; CHECK-NEXT: ret
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i8 62
+ store i32 1234, ptr %2
+ ret void
+}
+
+define void @check63(ptr %1) {
+; CHECK-LABEL: check63:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: adiw r24, 63
+; CHECK-NEXT: ldi r18, 0
+; CHECK-NEXT: ldi r19, 0
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: std Z+3, r19
+; CHECK-NEXT: std Z+2, r18
+; CHECK-NEXT: ldi r24, 210
+; CHECK-NEXT: ldi r25, 4
+; CHECK-NEXT: std Z+1, r25
+; CHECK-NEXT: st Z, r24
+; CHECK-NEXT: ret
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i8 63
+ store i32 1234, ptr %2
+ ret void
+}
+
+define void @check64(ptr %1) {
+; CHECK-LABEL: check64:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: subi r24, 192
+; CHECK-NEXT: sbci r25, 255
+; CHECK-NEXT: ldi r18, 0
+; CHECK-NEXT: ldi r19, 0
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: std Z+3, r19
+; CHECK-NEXT: std Z+2, r18
+; CHECK-NEXT: ldi r24, 210
+; CHECK-NEXT: ldi r25, 4
+; CHECK-NEXT: std Z+1, r25
+; CHECK-NEXT: st Z, r24
+; CHECK-NEXT: ret
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i8 64
+ store i32 1234, ptr %2
+ ret void
+}
+
+define void @check65(ptr %1) {
+; CHECK-LABEL: check65:
+; CHECK-NEXT: %bb.0
+; CHECK-NEXT: subi r24, 191
+; CHECK-NEXT: sbci r25, 255
+; CHECK-NEXT: ldi r18, 0
+; CHECK-NEXT: ldi r19, 0
+; CHECK-NEXT: mov r30, r24
+; CHECK-NEXT: mov r31, r25
+; CHECK-NEXT: std Z+3, r19
+; CHECK-NEXT: std Z+2, r18
+; CHECK-NEXT: ldi r24, 210
+; CHECK-NEXT: ldi r25, 4
+; CHECK-NEXT: std Z+1, r25
+; CHECK-NEXT: st Z, r24
+; CHECK-NEXT: ret
+
+bb0:
+ %2 = getelementptr i8, ptr %1, i8 65
+ store i32 1234, ptr %2
+ ret void
+}
More information about the llvm-commits
mailing list