[llvm] [AVR] Fix a crash in AVRInstrInfo::insertIndirectBranch (PR #67324)

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 26 22:22:11 PDT 2023


https://github.com/benshi001 updated https://github.com/llvm/llvm-project/pull/67324

>From 42dfa0b03188ab3b7a59bb2792dec6ab9c97f1f6 Mon Sep 17 00:00:00 2001
From: Ben Shi <bennshi at tencent.com>
Date: Mon, 25 Sep 2023 20:38:26 +0800
Subject: [PATCH] [AVR] Fix a crash in AVRInstrInfo::insertIndirectBranch

Skip the BranchRelaxation pass on AVR devices without FeatureJMPCALL.
Current branch relaxation relies on the long jump instruction which
is not available on earlier devices.

A full solution should be introducing '--code-model' for AVR, and
emitting indirect jump instead of short direct jump if a larger code
model is specified.

Fixes https://github.com/llvm/llvm-project/issues/67042
---
 llvm/lib/Target/AVR/AVRTargetMachine.cpp      |  4 +++-
 .../CodeGen/AVR/branch-relaxation-long.ll     | 19 ++++++++++++++++++-
 llvm/test/CodeGen/AVR/branch-relaxation.ll    |  6 +++---
 llvm/test/CodeGen/AVR/ctlz.ll                 |  4 ++--
 llvm/test/CodeGen/AVR/rot.ll                  | 16 ++++++++--------
 llvm/test/CodeGen/AVR/rotate.ll               |  8 ++++----
 llvm/test/CodeGen/AVR/shift.ll                | 14 +++++++-------
 7 files changed, 45 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/Target/AVR/AVRTargetMachine.cpp b/llvm/lib/Target/AVR/AVRTargetMachine.cpp
index e0776a6cab432f1..907310179a55547 100644
--- a/llvm/lib/Target/AVR/AVRTargetMachine.cpp
+++ b/llvm/lib/Target/AVR/AVRTargetMachine.cpp
@@ -132,7 +132,9 @@ void AVRPassConfig::addPreSched2() {
 
 void AVRPassConfig::addPreEmitPass() {
   // Must run branch selection immediately preceding the asm printer.
-  addPass(&BranchRelaxationPassID);
+  // However we skip devices without FeatureJMPCALL.
+  if (getAVRTargetMachine().getSubtargetImpl()->hasJMPCALL())
+    addPass(&BranchRelaxationPassID);
 }
 
 } // end of namespace llvm
diff --git a/llvm/test/CodeGen/AVR/branch-relaxation-long.ll b/llvm/test/CodeGen/AVR/branch-relaxation-long.ll
index b09976320b56221..24425a4c3c0c976 100644
--- a/llvm/test/CodeGen/AVR/branch-relaxation-long.ll
+++ b/llvm/test/CodeGen/AVR/branch-relaxation-long.ll
@@ -1,4 +1,5 @@
-; RUN: llc < %s -march=avr  -mattr=avr3 | FileCheck %s
+; RUN: llc < %s -march=avr -mattr=avr3 | FileCheck %s
+; RUN: llc < %s -march=avr -mattr=avr2 | FileCheck --check-prefix=AVR2 %s
 
 ; CHECK-LABEL: relax_to_jmp:
 ; CHECK: cpi     r{{[0-9]+}}, 0
@@ -7,6 +8,14 @@
 ; CHECK: [[BB1]]:
 ; CHECK: nop
 ; CHECK: [[BB2]]:
+
+; AVR2-LABEL: relax_to_jmp:
+; AVR2:     cpi     r{{[0-9]+}}, 0
+; AVR2:     breq    [[BB2:.LBB[0-9]+_[0-9]+]]
+; AVR2:     nop
+; AVR2:     [[BB2]]:
+; AVR2-NOT: jmp .LBB
+
 define i8 @relax_to_jmp(i1 %a) {
 entry-block:
   br i1 %a, label %hello, label %finished
@@ -2075,6 +2084,14 @@ finished:
 ; CHECK: breq    [[BB2:.LBB[0-9]+_[0-9]+]]
 ; CHECK: jmp     [[BB1]]
 ; CHECK: [[BB2]]:
+
+; AVR2-LABEL: relax_to_jmp_backwards:
+; AVR2:     [[BB1:.LBB[0-9]+_[0-9]+]]
+; AVR2:     nop
+; AVR2:     cpi     r{{[0-9]+}}, 0
+; AVR2:     brne    [[BB1:.LBB[0-9]+_[0-9]+]]
+; AVR2-NOT: jmp     .LBB
+
 define i8 @relax_to_jmp_backwards(i1 %a) {
 entry-block:
   br label %hello
diff --git a/llvm/test/CodeGen/AVR/branch-relaxation.ll b/llvm/test/CodeGen/AVR/branch-relaxation.ll
index cee3963c1ee3efb..0343f8c3649d2da 100644
--- a/llvm/test/CodeGen/AVR/branch-relaxation.ll
+++ b/llvm/test/CodeGen/AVR/branch-relaxation.ll
@@ -2,9 +2,9 @@
 
 ; CHECK-LABEL: relax_breq
 ; CHECK: cpi     r{{[0-9]+}}, 0
-; CHECK: brne    .LBB0_1
-; CHECK: rjmp    .LBB0_2
-; .LBB0_1:
+; CHECK: breq    .LBB0_2
+; CHECK: nop
+; CHECK: .LBB0_2:
 
 define i8 @relax_breq(i1 %a) {
 entry-block:
diff --git a/llvm/test/CodeGen/AVR/ctlz.ll b/llvm/test/CodeGen/AVR/ctlz.ll
index 93c2f0bdfa41e9e..ae963ed32e6e12e 100644
--- a/llvm/test/CodeGen/AVR/ctlz.ll
+++ b/llvm/test/CodeGen/AVR/ctlz.ll
@@ -10,7 +10,7 @@ declare i8 @llvm.ctlz.i8(i8)
 
 ; CHECK-LABEL: count_leading_zeros:
 ; CHECK: cpi    [[RESULT:r[0-9]+]], 0
-; CHECK: breq   .LBB0_2
+; CHECK: breq   .LBB0_1
 ; CHECK: mov    [[SCRATCH:r[0-9]+]], {{.*}}[[RESULT]]
 ; CHECK: lsr    {{.*}}[[SCRATCH]]
 ; CHECK: or     {{.*}}[[SCRATCH]], {{.*}}[[RESULT]]
@@ -38,6 +38,6 @@ declare i8 @llvm.ctlz.i8(i8)
 ; CHECK: add    {{.*}}[[RESULT]], {{.*}}[[SCRATCH]]
 ; CHECK: andi   {{.*}}[[RESULT]], 15
 ; CHECK: ret
-; CHECK: LBB0_2:
+; CHECK: LBB0_1:
 ; CHECK: ldi    {{.*}}[[RESULT]], 8
 ; CHECK: ret
diff --git a/llvm/test/CodeGen/AVR/rot.ll b/llvm/test/CodeGen/AVR/rot.ll
index 1a6b917af95b7aa..8e160009be10a39 100644
--- a/llvm/test/CodeGen/AVR/rot.ll
+++ b/llvm/test/CodeGen/AVR/rot.ll
@@ -7,26 +7,26 @@ define i8 @rol8(i8 %val, i8 %amt) {
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    andi r22, 7
 ; CHECK-NEXT:    dec r22
-; CHECK-NEXT:    brmi .LBB0_2
+; CHECK-NEXT:    brmi .LBB0_3
 ; CHECK-NEXT:  .LBB0_1: ; =>This Inner Loop Header: Depth=1
 ; CHECK-NEXT:    lsl r24
 ; CHECK-NEXT:    adc r24, r1
 ; CHECK-NEXT:    dec r22
 ; CHECK-NEXT:    brpl .LBB0_1
-; CHECK-NEXT:  .LBB0_2:
+; CHECK-NEXT:  .LBB0_3:
 ; CHECK-NEXT:    ret
 ;
 ; TINY-LABEL: rol8:
 ; TINY:       ; %bb.0:
 ; TINY-NEXT:    andi r22, 7
 ; TINY-NEXT:    dec r22
-; TINY-NEXT:    brmi .LBB0_2
+; TINY-NEXT:    brmi .LBB0_3
 ; TINY-NEXT:  .LBB0_1: ; =>This Inner Loop Header: Depth=1
 ; TINY-NEXT:    lsl r24
 ; TINY-NEXT:    adc r24, r17
 ; TINY-NEXT:    dec r22
 ; TINY-NEXT:    brpl .LBB0_1
-; TINY-NEXT:  .LBB0_2:
+; TINY-NEXT:  .LBB0_3:
 ; TINY-NEXT:    ret
   %mod = urem i8 %amt, 8
   %inv = sub i8 8, %mod
@@ -42,28 +42,28 @@ define i8 @ror8(i8 %val, i8 %amt) {
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    andi r22, 7
 ; CHECK-NEXT:    dec r22
-; CHECK-NEXT:    brmi .LBB1_2
+; CHECK-NEXT:    brmi .LBB1_3
 ; CHECK-NEXT:  .LBB1_1: ; =>This Inner Loop Header: Depth=1
 ; CHECK-NEXT:    bst r24, 0
 ; CHECK-NEXT:    ror r24
 ; CHECK-NEXT:    bld r24, 7
 ; CHECK-NEXT:    dec r22
 ; CHECK-NEXT:    brpl .LBB1_1
-; CHECK-NEXT:  .LBB1_2:
+; CHECK-NEXT:  .LBB1_3:
 ; CHECK-NEXT:    ret
 ;
 ; TINY-LABEL: ror8:
 ; TINY:       ; %bb.0:
 ; TINY-NEXT:    andi r22, 7
 ; TINY-NEXT:    dec r22
-; TINY-NEXT:    brmi .LBB1_2
+; TINY-NEXT:    brmi .LBB1_3
 ; TINY-NEXT:  .LBB1_1: ; =>This Inner Loop Header: Depth=1
 ; TINY-NEXT:    bst r24, 0
 ; TINY-NEXT:    ror r24
 ; TINY-NEXT:    bld r24, 7
 ; TINY-NEXT:    dec r22
 ; TINY-NEXT:    brpl .LBB1_1
-; TINY-NEXT:  .LBB1_2:
+; TINY-NEXT:  .LBB1_3:
 ; TINY-NEXT:    ret
   %mod = urem i8 %amt, 8
   %inv = sub i8 8, %mod
diff --git a/llvm/test/CodeGen/AVR/rotate.ll b/llvm/test/CodeGen/AVR/rotate.ll
index 79ff7928b3a3984..2c54763c6150d6f 100644
--- a/llvm/test/CodeGen/AVR/rotate.ll
+++ b/llvm/test/CodeGen/AVR/rotate.ll
@@ -54,14 +54,14 @@ define i8 @rotl8_dyn(i8 %x, i8 %y) {
 ; CHECK:       ; %bb.0: ; %start
 ; CHECK-NEXT:    andi r22, 7
 ; CHECK-NEXT:    dec r22
-; CHECK-NEXT:    brmi .LBB4_2
+; CHECK-NEXT:    brmi .LBB4_3
 ; CHECK-NEXT:  .LBB4_1: ; %start
 ; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
 ; CHECK-NEXT:    lsl r24
 ; CHECK-NEXT:    adc r24, r1
 ; CHECK-NEXT:    dec r22
 ; CHECK-NEXT:    brpl .LBB4_1
-; CHECK-NEXT:  .LBB4_2: ; %start
+; CHECK-NEXT:  .LBB4_3: ; %start
 ; CHECK-NEXT:    ret
 start:
   %0 = call i8 @llvm.fshl.i8(i8 %x, i8 %x, i8 %y)
@@ -121,7 +121,7 @@ define i8 @rotr8_dyn(i8 %x, i8 %y) {
 ; CHECK:       ; %bb.0: ; %start
 ; CHECK-NEXT:    andi r22, 7
 ; CHECK-NEXT:    dec r22
-; CHECK-NEXT:    brmi .LBB9_2
+; CHECK-NEXT:    brmi .LBB9_3
 ; CHECK-NEXT:  .LBB9_1: ; %start
 ; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
 ; CHECK-NEXT:    bst r24, 0
@@ -129,7 +129,7 @@ define i8 @rotr8_dyn(i8 %x, i8 %y) {
 ; CHECK-NEXT:    bld r24, 7
 ; CHECK-NEXT:    dec r22
 ; CHECK-NEXT:    brpl .LBB9_1
-; CHECK-NEXT:  .LBB9_2: ; %start
+; CHECK-NEXT:  .LBB9_3: ; %start
 ; CHECK-NEXT:    ret
 start:
   %0 = call i8 @llvm.fshr.i8(i8 %x, i8 %x, i8 %y)
diff --git a/llvm/test/CodeGen/AVR/shift.ll b/llvm/test/CodeGen/AVR/shift.ll
index c0abc77c9b14ae1..47b8b537b9ba7f6 100644
--- a/llvm/test/CodeGen/AVR/shift.ll
+++ b/llvm/test/CodeGen/AVR/shift.ll
@@ -6,12 +6,12 @@ define i8 @shift_i8_i8_speed(i8 %a, i8 %b) {
 ; CHECK-LABEL: shift_i8_i8_speed:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    dec r22
-; CHECK-NEXT:    brmi .LBB0_2
+; CHECK-NEXT:    brmi .LBB0_3
 ; CHECK-NEXT:  .LBB0_1: ; =>This Inner Loop Header: Depth=1
 ; CHECK-NEXT:    lsl r24
 ; CHECK-NEXT:    dec r22
 ; CHECK-NEXT:    brpl .LBB0_1
-; CHECK-NEXT:  .LBB0_2:
+; CHECK-NEXT:  .LBB0_3:
 ; CHECK-NEXT:    ret
   %result = shl i8 %a, %b
   ret i8 %result
@@ -21,12 +21,12 @@ define i8 @shift_i8_i8_speed(i8 %a, i8 %b) {
 define i8 @shift_i8_i8_size(i8 %a, i8 %b) optsize {
 ; CHECK-LABEL: shift_i8_i8_size:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:  .LBB1_1: ; =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:  .LBB1_2: ; =>This Inner Loop Header: Depth=1
 ; CHECK-NEXT:    dec r22
 ; CHECK-NEXT:    brmi .LBB1_3
-; CHECK-NEXT:  ; %bb.2: ; in Loop: Header=BB1_1 Depth=1
+; CHECK-NEXT:  ; %bb.1: ; in Loop: Header=BB1_2 Depth=1
 ; CHECK-NEXT:    lsl r24
-; CHECK-NEXT:    rjmp .LBB1_1
+; CHECK-NEXT:    rjmp .LBB1_2
 ; CHECK-NEXT:  .LBB1_3:
 ; CHECK-NEXT:    ret
   %result = shl i8 %a, %b
@@ -37,13 +37,13 @@ define i16 @shift_i16_i16(i16 %a, i16 %b) {
 ; CHECK-LABEL: shift_i16_i16:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    dec r22
-; CHECK-NEXT:    brmi .LBB2_2
+; CHECK-NEXT:    brmi .LBB2_3
 ; CHECK-NEXT:  .LBB2_1: ; =>This Inner Loop Header: Depth=1
 ; CHECK-NEXT:    lsl r24
 ; CHECK-NEXT:    rol r25
 ; CHECK-NEXT:    dec r22
 ; CHECK-NEXT:    brpl .LBB2_1
-; CHECK-NEXT:  .LBB2_2:
+; CHECK-NEXT:  .LBB2_3:
 ; CHECK-NEXT:    ret
   %result = shl i16 %a, %b
   ret i16 %result



More information about the llvm-commits mailing list