[llvm] 30d8f4e - [AVR] Fix incorrect flags of livein registers when spilling them

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 27 19:09:29 PST 2023


Author: Ben Shi
Date: 2023-02-28T11:08:54+08:00
New Revision: 30d8f4e8430cc757e2d1c5c6d18aa8c1c04c9256

URL: https://github.com/llvm/llvm-project/commit/30d8f4e8430cc757e2d1c5c6d18aa8c1c04c9256
DIFF: https://github.com/llvm/llvm-project/commit/30d8f4e8430cc757e2d1c5c6d18aa8c1c04c9256.diff

LOG: [AVR] Fix incorrect flags of livein registers when spilling them

In AVRFrameLowering::spillCalleeSavedRegisters(), when a 16-bit
livein register is spilled, two PUSH instructions are generated
for the higher and lower 8-bit registers. But these two 8-bit
registers are marked as killed in the two PUSH instructions, so
any future use of them will cause a crash.

This patch fixes the above issue by adding the two sub 8-bit
registers to the livein list.

Fixes https://github.com/llvm/llvm-project/issues/56423

Reviewed By: jacquesguan

Differential Revision: https://reviews.llvm.org/D144720

Added: 
    llvm/test/CodeGen/AVR/bug-56423.ll

Modified: 
    llvm/lib/Target/AVR/AVRFrameLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AVR/AVRFrameLowering.cpp b/llvm/lib/Target/AVR/AVRFrameLowering.cpp
index 904cdf8420eb0..aff2d5ed7b121 100644
--- a/llvm/lib/Target/AVR/AVRFrameLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRFrameLowering.cpp
@@ -260,6 +260,16 @@ bool AVRFrameLowering::spillCalleeSavedRegisters(
     Register Reg = I.getReg();
     bool IsNotLiveIn = !MBB.isLiveIn(Reg);
 
+    // Check if Reg is a sub register of a 16-bit livein register, and then
+    // add it to the livein list.
+    if (IsNotLiveIn)
+      for (const auto &LiveIn : MBB.liveins())
+        if (STI.getRegisterInfo()->isSubRegister(LiveIn.PhysReg, Reg)) {
+          IsNotLiveIn = false;
+          MBB.addLiveIn(Reg);
+          break;
+        }
+
     assert(TRI->getRegSizeInBits(*TRI->getMinimalPhysRegClass(Reg)) == 8 &&
            "Invalid register size");
 

diff  --git a/llvm/test/CodeGen/AVR/bug-56423.ll b/llvm/test/CodeGen/AVR/bug-56423.ll
new file mode 100644
index 0000000000000..1fd3cf0eb6d15
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/bug-56423.ll
@@ -0,0 +1,135 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=avr -mcpu=atmega328 | FileCheck %s --check-prefix=AVR51
+; RUN: llc < %s -mtriple=avr -mcpu=at90s8515 | FileCheck %s --check-prefix=AVR2
+
+; Test for bug https://github.com/llvm/llvm-project/issues/56423
+
+define i32 @foo(i32 %x, i32 %in_min, i32 %in_max, i32 %out_min, i32 %out_max) {
+; AVR51-LABEL: foo:
+; AVR51:       ; %bb.0: ; %entry
+; AVR51-NEXT:    push r6
+; AVR51-NEXT:    push r7
+; AVR51-NEXT:    push r8
+; AVR51-NEXT:    push r9
+; AVR51-NEXT:    push r14
+; AVR51-NEXT:    push r15
+; AVR51-NEXT:    push r16
+; AVR51-NEXT:    push r17
+; AVR51-NEXT:    push r28
+; AVR51-NEXT:    push r29
+; AVR51-NEXT:    in r28, 61
+; AVR51-NEXT:    in r29, 62
+; AVR51-NEXT:    movw r8, r20
+; AVR51-NEXT:    movw r6, r18
+; AVR51-NEXT:    movw r20, r24
+; AVR51-NEXT:    movw r18, r22
+; AVR51-NEXT:    ldd r22, Y+13
+; AVR51-NEXT:    ldd r23, Y+14
+; AVR51-NEXT:    ldd r24, Y+15
+; AVR51-NEXT:    ldd r25, Y+16
+; AVR51-NEXT:    sub r22, r10
+; AVR51-NEXT:    sbc r23, r11
+; AVR51-NEXT:    sbc r24, r12
+; AVR51-NEXT:    sbc r25, r13
+; AVR51-NEXT:    sub r18, r6
+; AVR51-NEXT:    sbc r19, r7
+; AVR51-NEXT:    sbc r20, r8
+; AVR51-NEXT:    sbc r21, r9
+; AVR51-NEXT:    call __mulsi3
+; AVR51-NEXT:    sub r14, r6
+; AVR51-NEXT:    sbc r15, r7
+; AVR51-NEXT:    sbc r16, r8
+; AVR51-NEXT:    sbc r17, r9
+; AVR51-NEXT:    movw r18, r14
+; AVR51-NEXT:    movw r20, r16
+; AVR51-NEXT:    call __divmodsi4
+; AVR51-NEXT:    add r18, r10
+; AVR51-NEXT:    adc r19, r11
+; AVR51-NEXT:    adc r20, r12
+; AVR51-NEXT:    adc r21, r13
+; AVR51-NEXT:    movw r22, r18
+; AVR51-NEXT:    movw r24, r20
+; AVR51-NEXT:    pop r29
+; AVR51-NEXT:    pop r28
+; AVR51-NEXT:    pop r17
+; AVR51-NEXT:    pop r16
+; AVR51-NEXT:    pop r15
+; AVR51-NEXT:    pop r14
+; AVR51-NEXT:    pop r9
+; AVR51-NEXT:    pop r8
+; AVR51-NEXT:    pop r7
+; AVR51-NEXT:    pop r6
+; AVR51-NEXT:    ret
+;
+; AVR2-LABEL: foo:
+; AVR2:       ; %bb.0: ; %entry
+; AVR2-NEXT:    push r6
+; AVR2-NEXT:    push r7
+; AVR2-NEXT:    push r8
+; AVR2-NEXT:    push r9
+; AVR2-NEXT:    push r14
+; AVR2-NEXT:    push r15
+; AVR2-NEXT:    push r16
+; AVR2-NEXT:    push r17
+; AVR2-NEXT:    push r28
+; AVR2-NEXT:    push r29
+; AVR2-NEXT:    in r28, 61
+; AVR2-NEXT:    in r29, 62
+; AVR2-NEXT:    mov r8, r20
+; AVR2-NEXT:    mov r9, r21
+; AVR2-NEXT:    mov r6, r18
+; AVR2-NEXT:    mov r7, r19
+; AVR2-NEXT:    mov r20, r24
+; AVR2-NEXT:    mov r21, r25
+; AVR2-NEXT:    mov r18, r22
+; AVR2-NEXT:    mov r19, r23
+; AVR2-NEXT:    ldd r22, Y+13
+; AVR2-NEXT:    ldd r23, Y+14
+; AVR2-NEXT:    ldd r24, Y+15
+; AVR2-NEXT:    ldd r25, Y+16
+; AVR2-NEXT:    sub r22, r10
+; AVR2-NEXT:    sbc r23, r11
+; AVR2-NEXT:    sbc r24, r12
+; AVR2-NEXT:    sbc r25, r13
+; AVR2-NEXT:    sub r18, r6
+; AVR2-NEXT:    sbc r19, r7
+; AVR2-NEXT:    sbc r20, r8
+; AVR2-NEXT:    sbc r21, r9
+; AVR2-NEXT:    rcall __mulsi3
+; AVR2-NEXT:    sub r14, r6
+; AVR2-NEXT:    sbc r15, r7
+; AVR2-NEXT:    sbc r16, r8
+; AVR2-NEXT:    sbc r17, r9
+; AVR2-NEXT:    mov r18, r14
+; AVR2-NEXT:    mov r19, r15
+; AVR2-NEXT:    mov r20, r16
+; AVR2-NEXT:    mov r21, r17
+; AVR2-NEXT:    rcall __divmodsi4
+; AVR2-NEXT:    add r18, r10
+; AVR2-NEXT:    adc r19, r11
+; AVR2-NEXT:    adc r20, r12
+; AVR2-NEXT:    adc r21, r13
+; AVR2-NEXT:    mov r22, r18
+; AVR2-NEXT:    mov r23, r19
+; AVR2-NEXT:    mov r24, r20
+; AVR2-NEXT:    mov r25, r21
+; AVR2-NEXT:    pop r29
+; AVR2-NEXT:    pop r28
+; AVR2-NEXT:    pop r17
+; AVR2-NEXT:    pop r16
+; AVR2-NEXT:    pop r15
+; AVR2-NEXT:    pop r14
+; AVR2-NEXT:    pop r9
+; AVR2-NEXT:    pop r8
+; AVR2-NEXT:    pop r7
+; AVR2-NEXT:    pop r6
+; AVR2-NEXT:    ret
+entry:
+  %sub = sub nsw i32 %x, %in_min
+  %sub1 = sub nsw i32 %out_max, %out_min
+  %mul = mul nsw i32 %sub1, %sub
+  %sub2 = sub nsw i32 %in_max, %in_min
+  %div = sdiv i32 %mul, %sub2
+  %add = add nsw i32 %div, %out_min
+  ret i32 %add
+}


        


More information about the llvm-commits mailing list