[PATCH] D115618: [AVR] Optimize int16 airthmetic right shift for shift amount 7/14/15

Ayke via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 17 04:27:41 PST 2022


aykevl added a comment.
Herald added a subscriber: jacquesguan.

Can you please add some .mir tests? As an example, I have created one for ASRW7Rd and ASRW8Rd:

  # RUN: llc -O0 -run-pass=avr-expand-pseudo %s -o - | FileCheck %s
  
  --- |
    target triple = "avr--"
    define void @test() {
    entry:
      ret void
    }
  ...
  
  ---
  name:            test
  body: |
    bb.0.entry:
      liveins: $r15r14
  
      ; CHECK-LABEL: test
  
      ; CHECK:      $r14 = ADDRdRr $r14, $r14, implicit-def undef $sreg
      ; CHECK-NEXT: $r14 = MOVRdRr $r15
      ; CHECK-NEXT: $r14 = ADCRdRr $r14, $r14, implicit-def $sreg, implicit $sreg
      ; CHECK-NEXT: $r15 = SBCRdRr $r15, $r15, implicit-def $sreg, implicit killed $sreg
      $r15r14 = ASRWNRd $r15r14, 7, implicit-def $sreg
  
      ; CHECK:      $r14 = MOVRdRr $r15
      ; CHECK-NEXT: $r15 = ADDRdRr $r15, $r15, implicit-def $sreg
      ; CHECK-NEXT: $r15 = SBCRdRr $r15, $r15, implicit-def $sreg, implicit killed $sreg
      $r15r14 = ASRWNRd $r15r14, 8, implicit-def $sreg
  ...

Here you can easily see the register states (undef, dead, kill, etc).

Also, I have found that `ASRWNRd` has `DLDREGS` as the output register, but I think the whole range (`DREGS`) is supported? `DLDREGS` are only the upper wide register (R17r16 to r31r3). That's perhaps a missed optimization.

While running this test locally, I also found the following error which I haven't investigated yet but is probably due to an incorrect kill flag (`$r20 = MOVRdRr killed $r21`):

  FAIL: LLVM :: CodeGen/AVR/sign-extension.ll (11 of 144)
  ******************** TEST 'LLVM :: CodeGen/AVR/sign-extension.ll' FAILED ********************
  Script:
  --
  : 'RUN: at line 1';   llc -verify-machineinstrs -march=avr < /home/ayke/src/github.com/tinygo-org/tinygo/llvm-project.main/llvm/test/CodeGen/AVR/sign-extension.ll | /home/ayke/src/github.com/tinygo-org/tinygo/llvm-build.main/bin/FileCheck /home/ayke/src/github.com/tinygo-org/tinygo/llvm-project.main/llvm/test/CodeGen/AVR/sign-extension.ll
  --
  Exit Code: 2
  
  Command Output (stderr):
  --
  
  # After AVR pseudo instruction expansion pass
  # Machine code for function sign_extended_8_to_64: NoPHIs, TracksLiveness, NoVRegs, TiedOpsRewritten, TracksDebugUserValues
  Function Live Ins: $r24
  
  bb.0.entry-block:
    liveins: $r24
    $r18 = MOVRdRr $r24
    $r19 = MOVRdRr killed $r24
    $r19 = ADDRdRr $r19(tied-def 0), killed $r19, implicit-def $sreg
    $r19 = SBCRdRr killed $r19(tied-def 0), killed $r19, implicit-def dead $sreg, implicit killed $sreg
    $r20 = MOVRdRr $r18
    $r21 = MOVRdRr $r19
    $r21 = ADDRdRr killed $r21(tied-def 0), killed $r21, implicit-def undef $sreg
    $r21 = SBCRdRr killed $r21(tied-def 0), killed $r21, implicit-def dead $sreg, implicit killed $sreg
    $r20 = MOVRdRr killed $r21
    $r22 = MOVRdRr $r20
    $r23 = MOVRdRr $r21
    $r24 = MOVRdRr $r20
    $r25 = MOVRdRr $r21
    RET implicit $r19r18, implicit $r21r20, implicit killed $r23r22, implicit $r25r24, implicit $r1
  
  # End machine code for function sign_extended_8_to_64.
  
  *** Bad machine code: Using an undefined physical register ***
  - function:    sign_extended_8_to_64
  - basic block: %bb.0 entry-block (0x556ea4da46f0)
  - instruction: $r23 = MOVRdRr $r21
  - operand 1:   $r21
  
  *** Bad machine code: Using an undefined physical register ***
  - function:    sign_extended_8_to_64
  - basic block: %bb.0 entry-block (0x556ea4da46f0)
  - instruction: $r25 = MOVRdRr $r21
  - operand 1:   $r21
  LLVM ERROR: Found 2 machine code errors.
  PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
  Stack dump:
  0.	Program arguments: llc -verify-machineinstrs -march=avr
  1.	Running pass 'Function Pass Manager' on module '<stdin>'.
  2.	Running pass 'Verify generated machine code' on function '@sign_extended_8_to_64'
   #0 0x0000556ea28279cf PrintStackTraceSignalHandler(void*) Signals.cpp:0:0
   #1 0x0000556ea282519e SignalHandler(int) Signals.cpp:0:0
   #2 0x00007ff051608730 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x12730)
   #3 0x00007ff05113a7bb raise (/lib/x86_64-linux-gnu/libc.so.6+0x377bb)
   #4 0x00007ff051125535 abort (/lib/x86_64-linux-gnu/libc.so.6+0x22535)
   #5 0x0000556ea2768435 llvm::report_fatal_error(llvm::Twine const&, bool) (/home/ayke/src/github.com/tinygo-org/tinygo/llvm-build.main/bin/llc+0x3f9c435)
   #6 0x0000556ea1b5f3e0 (anonymous namespace)::MachineVerifierPass::runOnMachineFunction(llvm::MachineFunction&) MachineVerifier.cpp:0:0
   #7 0x0000556ea1b5f40c (anonymous namespace)::MachineVerifierPass::runOnMachineFunction(llvm::MachineFunction&) MachineVerifier.cpp:0:0
   #8 0x0000556ea1a67420 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/home/ayke/src/github.com/tinygo-org/tinygo/llvm-build.main/bin/llc+0x329b420)
   #9 0x0000556ea1f215f0 llvm::FPPassManager::runOnFunction(llvm::Function&) (/home/ayke/src/github.com/tinygo-org/tinygo/llvm-build.main/bin/llc+0x37555f0)
  #10 0x0000556ea1f21811 llvm::FPPassManager::runOnModule(llvm::Module&) (/home/ayke/src/github.com/tinygo-org/tinygo/llvm-build.main/bin/llc+0x3755811)
  #11 0x0000556ea1f222f5 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/home/ayke/src/github.com/tinygo-org/tinygo/llvm-build.main/bin/llc+0x37562f5)
  #12 0x0000556ea0bac6bb compileModule(char**, llvm::LLVMContext&) llc.cpp:0:0
  #13 0x0000556ea0bad69a main (/home/ayke/src/github.com/tinygo-org/tinygo/llvm-build.main/bin/llc+0x23e169a)
  #14 0x00007ff05112709b __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2409b)
  #15 0x0000556ea0ba018a _start (/home/ayke/src/github.com/tinygo-org/tinygo/llvm-build.main/bin/llc+0x23d418a)
  FileCheck error: '<stdin>' is empty.
  FileCheck command line:  /home/ayke/src/github.com/tinygo-org/tinygo/llvm-build.main/bin/FileCheck /home/ayke/src/github.com/tinygo-org/tinygo/llvm-project.main/llvm/test/CodeGen/AVR/sign-extension.ll

You can reproduce this with the following command:

  llvm-build/bin/llc -verify-machineinstrs -march=avr < path/to/llvm/test/CodeGen/AVR/sign-extension.ll



================
Comment at: llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp:1868
+  buildMI(MBB, MBBI, AVR::ADDRdRr)
+      .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+      .addReg(DstLoReg, getKillRegState(DstIsKill))
----------------
This register is always dead. It's overwritten (killed) by the `mov` instruction on the next line.


================
Comment at: llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp:1869-1870
+      .addReg(DstLoReg, RegState::Define | getDeadRegState(DstIsDead))
+      .addReg(DstLoReg, getKillRegState(DstIsKill))
+      .addReg(DstLoReg, getKillRegState(DstIsKill))
+      ->getOperand(3)
----------------
These two input operands are always killed: they are the last use of this input value.


================
Comment at: llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp:1871-1872
+      .addReg(DstLoReg, getKillRegState(DstIsKill))
+      ->getOperand(3)
+      .setIsUndef(true);
+
----------------
You are setting the output operand `SREG` to undef? I don't think that's correct. AFAIK only input operands can be set to undef. Also, you are going to use the output of the SREG later, so I don't think it should be set to undef.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D115618/new/

https://reviews.llvm.org/D115618



More information about the llvm-commits mailing list