[AVR] Fix incorrect expansion of pseudo instruction ROLBRd
authorBen Shi <2283975856@qq.com>
Wed, 7 Jun 2023 09:59:02 +0000 (17:59 +0800)
committerBen Shi <2283975856@qq.com>
Sat, 10 Jun 2023 16:20:43 +0000 (00:20 +0800)
Since ROLBRd needs an implicit R1 (on AVR) or an implicit R17 (on AVRTiny),
we split ROLBRd to ROLBRdR1 (on AVR) and ROLBRdR17 (on AVRTiny).

Reviewed By: aykevl, Patryk27

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

llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
llvm/lib/Target/AVR/AVRISelLowering.cpp
llvm/lib/Target/AVR/AVRISelLowering.h
llvm/lib/Target/AVR/AVRInstrInfo.td
llvm/test/CodeGen/AVR/pseudo/ROLBRdR1.mir [new file with mode: 0644]
llvm/test/CodeGen/AVR/pseudo/ROLBRdR17.mir [new file with mode: 0644]
llvm/test/CodeGen/AVR/pseudo/ROLBrd.mir [deleted file]
llvm/test/CodeGen/AVR/rot.ll

index f9a013b6b153dd8750c34d511ab9cca99e1c5797..f257ccea6c50a916202cadeab54da82cb89668fc 100644 (file)
@@ -101,6 +101,8 @@ private:
   bool expandLPMWELPMW(Block &MBB, BlockIt MBBI, bool IsELPM);
   // Common implementation of LPMBRdZ and ELPMBRdZ.
   bool expandLPMBELPMB(Block &MBB, BlockIt MBBI, bool IsELPM);
+  // Common implementation of ROLBRdR1 and ROLBRdR17.
+  bool expandROLBRd(Block &MBB, BlockIt MBBI);
 };
 
 char AVRExpandPseudo::ID = 0;
@@ -1479,20 +1481,17 @@ bool AVRExpandPseudo::expand<AVR::POPWRd>(Block &MBB, BlockIt MBBI) {
   return true;
 }
 
-template <>
-bool AVRExpandPseudo::expand<AVR::ROLBRd>(Block &MBB, BlockIt MBBI) {
+bool AVRExpandPseudo::expandROLBRd(Block &MBB, BlockIt MBBI) {
   // In AVR, the rotate instructions behave quite unintuitively. They rotate
   // bits through the carry bit in SREG, effectively rotating over 9 bits,
   // instead of 8. This is useful when we are dealing with numbers over
   // multiple registers, but when we actually need to rotate stuff, we have
   // to explicitly add the carry bit.
 
-  const AVRSubtarget &STI = MBB.getParent()->getSubtarget<AVRSubtarget>();
-
   MachineInstr &MI = *MBBI;
   unsigned OpShift, OpCarry;
   Register DstReg = MI.getOperand(0).getReg();
-  Register ZeroReg = STI.getZeroRegister();
+  Register ZeroReg = MI.getOperand(3).getReg();
   bool DstIsDead = MI.getOperand(0).isDead();
   bool DstIsKill = MI.getOperand(1).isKill();
   OpShift = AVR::ADDRdRr;
@@ -1520,6 +1519,16 @@ bool AVRExpandPseudo::expand<AVR::ROLBRd>(Block &MBB, BlockIt MBBI) {
   return true;
 }
 
+template <>
+bool AVRExpandPseudo::expand<AVR::ROLBRdR1>(Block &MBB, BlockIt MBBI) {
+  return expandROLBRd(MBB, MBBI);
+}
+
+template <>
+bool AVRExpandPseudo::expand<AVR::ROLBRdR17>(Block &MBB, BlockIt MBBI) {
+  return expandROLBRd(MBB, MBBI);
+}
+
 template <>
 bool AVRExpandPseudo::expand<AVR::RORBRd>(Block &MBB, BlockIt MBBI) {
   // In AVR, the rotate instructions behave quite unintuitively. They rotate
@@ -2604,7 +2613,8 @@ bool AVRExpandPseudo::expandMI(Block &MBB, BlockIt MBBI) {
     EXPAND(AVR::OUTWARr);
     EXPAND(AVR::PUSHWRr);
     EXPAND(AVR::POPWRd);
-    EXPAND(AVR::ROLBRd);
+    EXPAND(AVR::ROLBRdR1);
+    EXPAND(AVR::ROLBRdR17);
     EXPAND(AVR::RORBRd);
     EXPAND(AVR::LSLWRd);
     EXPAND(AVR::LSRWRd);
index 5d7d08a5b958785d7ebe78688ab45d7f03c75b16..606e70b32f170b4a7f75d059d3f0b1d356ae0990 100644 (file)
@@ -1747,7 +1747,8 @@ AVRTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
 //===----------------------------------------------------------------------===//
 
 MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI,
-                                                  MachineBasicBlock *BB) const {
+                                                  MachineBasicBlock *BB,
+                                                  bool Tiny) const {
   unsigned Opc;
   const TargetRegisterClass *RC;
   bool HasRepeatedOperand = false;
@@ -1785,7 +1786,7 @@ MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI,
     RC = &AVR::DREGSRegClass;
     break;
   case AVR::Rol8:
-    Opc = AVR::ROLBRd;
+    Opc = Tiny ? AVR::ROLBRdR17 : AVR::ROLBRdR1;
     RC = &AVR::GPR8RegClass;
     break;
   case AVR::Rol16:
@@ -2328,6 +2329,7 @@ MachineBasicBlock *
 AVRTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
                                                MachineBasicBlock *MBB) const {
   int Opc = MI.getOpcode();
+  const AVRSubtarget &STI = MBB->getParent()->getSubtarget<AVRSubtarget>();
 
   // Pseudo shift instructions with a non constant shift amount are expanded
   // into a loop.
@@ -2342,7 +2344,7 @@ AVRTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
   case AVR::Ror16:
   case AVR::Asr8:
   case AVR::Asr16:
-    return insertShift(MI, MBB);
+    return insertShift(MI, MBB, STI.hasTinyEncoding());
   case AVR::Lsl32:
   case AVR::Lsr32:
   case AVR::Asr32:
index c4f73b0ffc919787880cc649d3972590e53ed1a6..b696bebe7136f42cb6be6d307350e2dfc04f9df1 100644 (file)
@@ -194,7 +194,8 @@ protected:
   const AVRSubtarget &Subtarget;
 
 private:
-  MachineBasicBlock *insertShift(MachineInstr &MI, MachineBasicBlock *BB) const;
+  MachineBasicBlock *insertShift(MachineInstr &MI, MachineBasicBlock *BB,
+                                 bool Tiny) const;
   MachineBasicBlock *insertWideShift(MachineInstr &MI,
                                      MachineBasicBlock *BB) const;
   MachineBasicBlock *insertMul(MachineInstr &MI, MachineBasicBlock *BB) const;
index d0e75733114ac80021ac0bc0c7d8f26922d0f093..f93248b4940c1d6ccce46962d59ad5140176b9ee 100644 (file)
@@ -2028,16 +2028,21 @@ let Constraints = "$src = $rd", Defs = [SREG] in {
 
   def ASRWLoRd : Pseudo<(outs DREGS:$rd), (ins DREGS:$src), "asrwlo\t$rd",
                         [(set i16:$rd, (AVRasrlo i16:$src)), (implicit SREG)]>;
-
-  def ROLBRd : Pseudo<(outs GPR8
-                       : $rd),
-                      (ins GPR8
-                       : $src),
-                      "rolb\t$rd",
-                      [(set i8
-                        : $rd, (AVRrol i8
-                                : $src)),
-                       (implicit SREG)]>;
+  let Uses = [R1] in
+  def ROLBRdR1 : Pseudo<(outs GPR8:$rd),
+                        (ins GPR8:$src),
+                        "rolb\t$rd",
+                        [(set i8:$rd, (AVRrol i8:$src)),
+                        (implicit SREG)]>,
+                 Requires<[HasNonTinyEncoding]>;
+
+  let Uses = [R17] in
+  def ROLBRdR17 : Pseudo<(outs GPR8:$rd),
+                         (ins GPR8:$src),
+                         "rolb\t$rd",
+                         [(set i8:$rd, (AVRrol i8:$src)),
+                         (implicit SREG)]>,
+                  Requires<[HasTinyEncoding]>;
 
   def RORBRd : Pseudo<(outs GPR8
                        : $rd),
diff --git a/llvm/test/CodeGen/AVR/pseudo/ROLBRdR1.mir b/llvm/test/CodeGen/AVR/pseudo/ROLBRdR1.mir
new file mode 100644 (file)
index 0000000..10f7041
--- /dev/null
@@ -0,0 +1,24 @@
+# RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - | FileCheck %s
+
+# This test checks the expansion of the 8-bit ROLB (rotate) pseudo instruction.
+
+--- |
+  target triple = "avr--"
+  define void @test_rolbrd() {
+  entry:
+    ret void
+  }
+...
+
+---
+name:            test_rolbrd
+body: |
+  bb.0.entry:
+    liveins: $r14
+
+    ; CHECK-LABEL: test_rolbrd
+    ; CHECK:         $r14 = ADDRdRr killed $r14, killed $r14, implicit-def $sreg
+    ; CHECK-NEXT:    $r14 = ADCRdRr $r14, $r1, implicit-def dead $sreg, implicit killed $sreg
+
+    $r14 = ROLBRdR1  $r14, implicit-def $sreg, implicit $r1
+...
diff --git a/llvm/test/CodeGen/AVR/pseudo/ROLBRdR17.mir b/llvm/test/CodeGen/AVR/pseudo/ROLBRdR17.mir
new file mode 100644 (file)
index 0000000..2a26d18
--- /dev/null
@@ -0,0 +1,24 @@
+# RUN: llc -O0 -run-pass=avr-expand-pseudo -mattr=+avrtiny %s -o - | FileCheck %s
+
+# This test checks the expansion of the 8-bit ROLB (rotate) pseudo instruction
+# on AVRTiny.
+
+--- |
+  target triple = "avr--"
+  define void @test_rolbrd() {
+  entry:
+    ret void
+  }
+...
+
+---
+name:            test_rolbrd
+body: |
+  bb.0.entry:
+    liveins: $r24
+
+    ; CHECK-LABEL: test_rolbrd
+    ; CHECK:         $r24 = ADDRdRr killed $r24, killed $r24, implicit-def $sreg
+    ; CHECK-NEXT:    $r24 = ADCRdRr $r24, $r17, implicit-def dead $sreg, implicit killed $sreg
+    $r24 = ROLBRdR17 $r24, implicit-def $sreg, implicit $r17
+...
diff --git a/llvm/test/CodeGen/AVR/pseudo/ROLBrd.mir b/llvm/test/CodeGen/AVR/pseudo/ROLBrd.mir
deleted file mode 100644 (file)
index 023120b..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-# RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - | FileCheck %s
-
-# This test checks the expansion of the 8-bit ROLB (rotate) pseudo instruction.
-
---- |
-  target triple = "avr--"
-  define void @test_rolbrd() {
-  entry:
-    ret void
-  }
-...
-
----
-name:            test_rolbrd
-body: |
-  bb.0.entry:
-    liveins: $r14
-
-    ; CHECK-LABEL: test_rolbrd
-
-    ; CHECK:      $r14 = ADDRdRr killed $r14, killed $r14, implicit-def $sreg
-    ; CHECK-NEXT: $r14 = ADCRdRr $r14, $r1, implicit-def dead $sreg, implicit killed $sreg
-    $r14 = ROLBRd $r14, implicit-def $sreg
-...
index 210031588005d42e7b2bcef24f18115335a1496c..1a6b917af95b7aa7a31f26fc98728ae7e466065d 100644 (file)
@@ -1,58 +1,75 @@
-; RUN: llc < %s -march=avr | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
+; RUN: llc < %s -mtriple=avr | FileCheck %s
+; RUN: llc < %s -mtriple=avr -mattr=+avrtiny | FileCheck --check-prefix=TINY %s
 
-; Bit rotation tests.
-
-; CHECK-LABEL: rol8:
 define i8 @rol8(i8 %val, i8 %amt) {
-  ; CHECK:      andi r22, 7
-
-  ; CHECK-NEXT: dec r22
-  ; CHECK-NEXT: brmi .LBB0_2
-
-; CHECK-NEXT: .LBB0_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: ret
+; CHECK-LABEL: rol8:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    andi r22, 7
+; CHECK-NEXT:    dec r22
+; CHECK-NEXT:    brmi .LBB0_2
+; 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:    ret
+;
+; TINY-LABEL: rol8:
+; TINY:       ; %bb.0:
+; TINY-NEXT:    andi r22, 7
+; TINY-NEXT:    dec r22
+; TINY-NEXT:    brmi .LBB0_2
+; 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:    ret
   %mod = urem i8 %amt, 8
-
   %inv = sub i8 8, %mod
   %parta = shl i8 %val, %mod
   %partb = lshr i8 %val, %inv
-
   %rotl = or i8 %parta, %partb
-
   ret i8 %rotl
 }
 
 
-; CHECK-LABEL: ror8:
 define i8 @ror8(i8 %val, i8 %amt) {
-  ; CHECK:      andi r22, 7
-
-  ; CHECK-NEXT: dec r22
-  ; CHECK-NEXT: brmi .LBB1_2
-
-; CHECK-NEXT: .LBB1_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: ret
+; CHECK-LABEL: ror8:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    andi r22, 7
+; CHECK-NEXT:    dec r22
+; CHECK-NEXT:    brmi .LBB1_2
+; 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:    ret
+;
+; TINY-LABEL: ror8:
+; TINY:       ; %bb.0:
+; TINY-NEXT:    andi r22, 7
+; TINY-NEXT:    dec r22
+; TINY-NEXT:    brmi .LBB1_2
+; 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:    ret
   %mod = urem i8 %amt, 8
-
   %inv = sub i8 8, %mod
   %parta = lshr i8 %val, %mod
   %partb = shl i8 %val, %inv
-
   %rotr = or i8 %parta, %partb
-
   ret i8 %rotr
 }