Patryk27 updated this revision to Diff 402203.
Herald added subscribers: cfe-commits, mgorny.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D114611

Files:
  clang/docs/tools/clang-formatted-files.txt
  llvm/lib/Target/AVR/AVR.h
  llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
  llvm/lib/Target/AVR/AVRFrameLowering.cpp
  llvm/lib/Target/AVR/AVRRegisterInfo.cpp
  llvm/lib/Target/AVR/AVRRelaxMemOperations.cpp
  llvm/lib/Target/AVR/AVRSubtarget.h
  llvm/lib/Target/AVR/AVRTargetMachine.cpp
  llvm/lib/Target/AVR/CMakeLists.txt
  llvm/test/CodeGen/AVR/PR31344.ll
  llvm/test/CodeGen/AVR/PR31345.ll
  llvm/test/CodeGen/AVR/PR37143.ll
  llvm/test/CodeGen/AVR/avr-rust-issue-123.ll
  llvm/test/CodeGen/AVR/frmidx-iterator-bug.ll
  llvm/test/CodeGen/AVR/hardware-mul.ll
  llvm/test/CodeGen/AVR/mul-hardware.ll
  llvm/test/CodeGen/AVR/mul-software.ll
  llvm/test/CodeGen/AVR/past-bugs/D114611.ll
  llvm/test/CodeGen/AVR/past-bugs/PR31344.ll
  llvm/test/CodeGen/AVR/past-bugs/PR31345.ll
  llvm/test/CodeGen/AVR/past-bugs/PR37143.ll
  llvm/test/CodeGen/AVR/past-bugs/avr-rust-issue-123.ll
  llvm/test/CodeGen/AVR/past-bugs/frmidx-iterator-bug.ll
  llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-112.ll
  llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-37.ll
  llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-95.ll
  llvm/test/CodeGen/AVR/past-bugs/rust-avr-bug-99.ll
  llvm/test/CodeGen/AVR/pseudo/STDSPQRr.mir
  llvm/test/CodeGen/AVR/pseudo/STDWPtrQRr.mir
  llvm/test/CodeGen/AVR/pseudo/STDWSPQRr.mir
  llvm/test/CodeGen/AVR/relax-mem/STDWPtrQRr.mir
  llvm/test/CodeGen/AVR/rust-avr-bug-112.ll
  llvm/test/CodeGen/AVR/rust-avr-bug-37.ll
  llvm/test/CodeGen/AVR/rust-avr-bug-95.ll
  llvm/test/CodeGen/AVR/rust-avr-bug-99.ll
  llvm/test/CodeGen/AVR/software-mul.ll
  llvm/utils/UpdateTestChecks/asm.py
  llvm/utils/gn/secondary/llvm/lib/Target/AVR/BUILD.gn

Index: llvm/utils/gn/secondary/llvm/lib/Target/AVR/BUILD.gn
===================================================================
--- llvm/utils/gn/secondary/llvm/lib/Target/AVR/BUILD.gn
+++ llvm/utils/gn/secondary/llvm/lib/Target/AVR/BUILD.gn
@@ -37,7 +37,6 @@
     "AVRInstrInfo.cpp",
     "AVRMCInstLower.cpp",
     "AVRRegisterInfo.cpp",
-    "AVRRelaxMemOperations.cpp",
     "AVRShiftExpand.cpp",
     "AVRSubtarget.cpp",
     "AVRTargetMachine.cpp",
Index: llvm/utils/UpdateTestChecks/asm.py
===================================================================
--- llvm/utils/UpdateTestChecks/asm.py
+++ llvm/utils/UpdateTestChecks/asm.py
@@ -391,6 +391,7 @@
 def get_triple_from_march(march):
   triples = {
       'amdgcn': 'amdgcn',
+      'avr': 'avr',
       'r600': 'r600',
       'mips': 'mips',
       'sparc': 'sparc',
Index: llvm/test/CodeGen/AVR/relax-mem/STDWPtrQRr.mir
===================================================================
--- llvm/test/CodeGen/AVR/relax-mem/STDWPtrQRr.mir
+++ /dev/null
@@ -1,31 +0,0 @@
-# RUN: llc -O0 -run-pass=avr-relax-mem %s -o - | FileCheck %s
-
---- |
-  target triple = "avr--"
-  define void @test() {
-  entry:
-    ret void
-  }
-...
-
----
-name:            test
-body: |
-  bb.0.entry:
-
-    ; CHECK-LABEL: test
-
-    ; We shouldn't expand things which already have 6-bit imms.
-    ; CHECK: STDWPtrQRr $r29r28, 63, $r1r0
-    STDWPtrQRr $r29r28, 63, $r1r0
-
-    ; We shouldn't expand things which already have 6-bit imms.
-    ; CHECK-NEXT: STDWPtrQRr $r29r28, 0, $r1r0
-    STDWPtrQRr $r29r28, 0, $r1r0
-
-    ; CHECK-NEXT: PUSHWRr $r29r28, implicit-def $sp, implicit $sp
-    ; CHECK-NEXT: $r29r28 = SBCIWRdK $r29r28, -64, implicit-def $sreg, implicit $sreg
-    ; CHECK-NEXT: STWPtrRr $r29r28, $r1r0
-    ; CHECK-NEXT: $r29r28 = POPWRd implicit-def $sp, implicit $sp
-    STDWPtrQRr $r29r28, 64, $r1r0
-...
Index: llvm/test/CodeGen/AVR/pseudo/STDWSPQRr.mir
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/AVR/pseudo/STDWSPQRr.mir
@@ -0,0 +1,20 @@
+# 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:
+
+    ; CHECK: STDPtrQRr $r31r30, 10, $r9
+    ; CHECK-NEXT: STDPtrQRr $r31r30, 11, $r10
+
+    STDWSPQRr $sp, 10, $r10r9, implicit-def $sp
+...
Index: llvm/test/CodeGen/AVR/pseudo/STDWPtrQRr.mir
===================================================================
--- llvm/test/CodeGen/AVR/pseudo/STDWPtrQRr.mir
+++ llvm/test/CodeGen/AVR/pseudo/STDWPtrQRr.mir
@@ -15,8 +15,52 @@
 
     ; CHECK-LABEL: test
 
-    ; CHECK:      STDPtrQRr $r29r28, 10, $r0
-    ; CHECK-NEXT: STDPtrQRr $r29r28, 11, $r1
+    ; Small displacement (<63):
+    ; CHECK:      STDPtrQRr $r29r28, 3, $r0
+    ; CHECK-NEXT: STDPtrQRr $r29r28, 4, $r1
+    STDWPtrQRr $r29r28, 3, $r1r0
 
-    STDWPtrQRr $r29r28, 10, $r1r0
+    ; Small displacement where the destination register is killed:
+    ; CHECK:      STDPtrQRr $r29r28, 3, $r0
+    ; CHECK-NEXT: STDPtrQRr killed $r29r28, 4, $r1
+    STDWPtrQRr killed $r29r28, 3, $r1r0
+
+    ; Small displacement where the source register is killed:
+    ; CHECK:      STDPtrQRr $r29r28, 3, killed $r0
+    ; CHECK-NEXT: STDPtrQRr $r29r28, 4, killed $r1
+    STDWPtrQRr $r29r28, 3, killed $r1r0
+
+    ; Small displacement, near the limit:
+    ; CHECK:      STDPtrQRr $r29r28, 62, $r0
+    ; CHECK-NEXT: STDPtrQRr $r29r28, 63, $r1
+    STDWPtrQRr $r29r28, 62, $r1r0
+
+    ; Large displacement:
+    ; CHECK: PUSHRr $r28, implicit-def $sp, implicit $sp
+    ; CHECK-NEXT: PUSHRr $r29, implicit-def $sp, implicit $sp
+    ; CHECK-NEXT: $r28 = SBCIRdK $r28, 193, implicit-def $sreg, implicit killed $sreg
+    ; CHECK-NEXT: $r29 = SBCIRdK $r29, 255, implicit-def $sreg, implicit killed $sreg
+    ; CHECK-NEXT: STPtrRr $r29r28, $r0
+    ; CHECK-NEXT: STDPtrQRr $r29r28, 1, $r1
+    ; CHECK-NEXT: $r29 = POPRd implicit-def $sp, implicit $sp
+    ; CHECK-NEXT: $r28 = POPRd implicit-def $sp, implicit $sp
+    STDWPtrQRr $r29r28, 63, $r1r0
+
+    ; Large displacement where the destination register is killed:
+    ; CHECK: $r28 = SBCIRdK $r28, 193, implicit-def $sreg, implicit killed $sreg
+    ; CHECK-NEXT: $r29 = SBCIRdK $r29, 255, implicit-def $sreg, implicit killed $sreg
+    ; CHECK-NEXT: STPtrRr $r29r28, $r0
+    ; CHECK-NEXT: STDPtrQRr $r29r28, 1, $r1
+    STDWPtrQRr killed $r29r28, 63, $r1r0
+
+    ; Large displacement where the source register is killed:
+    ; CHECK: PUSHRr $r28, implicit-def $sp, implicit $sp
+    ; CHECK-NEXT: PUSHRr $r29, implicit-def $sp, implicit $sp
+    ; CHECK-NEXT: $r28 = SBCIRdK $r28, 193, implicit-def $sreg, implicit killed $sreg
+    ; CHECK-NEXT: $r29 = SBCIRdK $r29, 255, implicit-def $sreg, implicit killed $sreg
+    ; CHECK-NEXT: STPtrRr $r29r28, killed $r0
+    ; CHECK-NEXT: STDPtrQRr $r29r28, 1, killed $r1
+    ; CHECK-NEXT: $r29 = POPRd implicit-def $sp, implicit $sp
+    ; CHECK-NEXT: $r28 = POPRd implicit-def $sp, implicit $sp
+    STDWPtrQRr $r29r28, 63, killed $r1r0
 ...
Index: llvm/test/CodeGen/AVR/pseudo/STDSPQRr.mir
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/AVR/pseudo/STDSPQRr.mir
@@ -0,0 +1,19 @@
+# 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:
+
+    ; CHECK: STDPtrQRr $r31r30, 10, $r1, implicit-def $sp
+
+    STDSPQRr $sp, 10, $r1, implicit-def $sp
+...
Index: llvm/test/CodeGen/AVR/past-bugs/D114611.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/AVR/past-bugs/D114611.ll
@@ -0,0 +1,16 @@
+; RUN: llc < %s -march=avr | FileCheck %s
+
+declare { } @foo(i128, i128) addrspace(1)
+
+define i128 @bar(i128 %a, i128 %b) addrspace(1) {
+  call void asm "nop", "" ()
+; CHECK:      nop
+; CHECK-NEXT: ;NO_APP
+; CHECK-NEXT: Y+15, r20
+; CHECK-NEXT: Y+16, r21
+  %b_neg = icmp slt i128 %b, 0
+  %divisor = select i1 %b_neg, i128 0, i128 %b
+  %result = tail call fastcc addrspace(1) { } @foo(i128 undef, i128 %divisor)
+
+  ret i128 0
+}
Index: llvm/lib/Target/AVR/CMakeLists.txt
===================================================================
--- llvm/lib/Target/AVR/CMakeLists.txt
+++ llvm/lib/Target/AVR/CMakeLists.txt
@@ -22,7 +22,6 @@
   AVRISelDAGToDAG.cpp
   AVRISelLowering.cpp
   AVRMCInstLower.cpp
-  AVRRelaxMemOperations.cpp
   AVRRegisterInfo.cpp
   AVRShiftExpand.cpp
   AVRSubtarget.cpp
Index: llvm/lib/Target/AVR/AVRTargetMachine.cpp
===================================================================
--- llvm/lib/Target/AVR/AVRTargetMachine.cpp
+++ llvm/lib/Target/AVR/AVRTargetMachine.cpp
@@ -28,7 +28,6 @@
 static const char *AVRDataLayout =
     "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8";
 
-/// Processes a CPU name.
 static StringRef getCPU(StringRef CPU) {
   if (CPU.empty() || CPU == "generic") {
     return "avr2";
@@ -87,12 +86,10 @@
 }
 
 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRTarget() {
-  // Register the target.
   RegisterTargetMachine<AVRTargetMachine> X(getTheAVRTarget());
 
   auto &PR = *PassRegistry::getPassRegistry();
   initializeAVRExpandPseudoPass(PR);
-  initializeAVRRelaxMemPass(PR);
   initializeAVRShiftExpandPass(PR);
 }
 
@@ -118,7 +115,6 @@
 }
 
 void AVRPassConfig::addPreSched2() {
-  addPass(createAVRRelaxMemPass());
   addPass(createAVRExpandPseudoPass());
 }
 
Index: llvm/lib/Target/AVR/AVRSubtarget.h
===================================================================
--- llvm/lib/Target/AVR/AVRSubtarget.h
+++ llvm/lib/Target/AVR/AVRSubtarget.h
@@ -87,7 +87,7 @@
   /// of an ELF object file.
   unsigned getELFArch() const {
     assert(ELFArch != 0 &&
-           "every device must have an associate ELF architecture");
+           "every device must have an associated ELF architecture");
     return ELFArch;
   }
 
Index: llvm/lib/Target/AVR/AVRRelaxMemOperations.cpp
===================================================================
--- llvm/lib/Target/AVR/AVRRelaxMemOperations.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-//===-- AVRRelaxMemOperations.cpp - Relax out of range loads/stores -------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains a pass which relaxes out of range memory operations into
-// equivalent operations which handle bigger addresses.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AVR.h"
-#include "AVRInstrInfo.h"
-#include "AVRTargetMachine.h"
-#include "MCTargetDesc/AVRMCTargetDesc.h"
-
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/TargetRegisterInfo.h"
-
-using namespace llvm;
-
-#define AVR_RELAX_MEM_OPS_NAME "AVR memory operation relaxation pass"
-
-namespace {
-
-class AVRRelaxMem : public MachineFunctionPass {
-public:
-  static char ID;
-
-  AVRRelaxMem() : MachineFunctionPass(ID) {
-    initializeAVRRelaxMemPass(*PassRegistry::getPassRegistry());
-  }
-
-  bool runOnMachineFunction(MachineFunction &MF) override;
-
-  StringRef getPassName() const override { return AVR_RELAX_MEM_OPS_NAME; }
-
-private:
-  typedef MachineBasicBlock Block;
-  typedef Block::iterator BlockIt;
-
-  const TargetInstrInfo *TII;
-
-  template <unsigned OP> bool relax(Block &MBB, BlockIt MBBI);
-
-  bool runOnBasicBlock(Block &MBB);
-  bool runOnInstruction(Block &MBB, BlockIt MBBI);
-
-  MachineInstrBuilder buildMI(Block &MBB, BlockIt MBBI, unsigned Opcode) {
-    return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode));
-  }
-};
-
-char AVRRelaxMem::ID = 0;
-
-bool AVRRelaxMem::runOnMachineFunction(MachineFunction &MF) {
-  bool Modified = false;
-
-  const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
-  TII = STI.getInstrInfo();
-
-  for (Block &MBB : MF) {
-    bool BlockModified = runOnBasicBlock(MBB);
-    Modified |= BlockModified;
-  }
-
-  return Modified;
-}
-
-bool AVRRelaxMem::runOnBasicBlock(Block &MBB) {
-  bool Modified = false;
-
-  BlockIt MBBI = MBB.begin(), E = MBB.end();
-  while (MBBI != E) {
-    BlockIt NMBBI = std::next(MBBI);
-    Modified |= runOnInstruction(MBB, MBBI);
-    MBBI = NMBBI;
-  }
-
-  return Modified;
-}
-
-template <> bool AVRRelaxMem::relax<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
-  MachineInstr &MI = *MBBI;
-
-  MachineOperand &Ptr = MI.getOperand(0);
-  MachineOperand &Src = MI.getOperand(2);
-  int64_t Imm = MI.getOperand(1).getImm();
-
-  // We can definitely optimise this better.
-  if (Imm > 63) {
-    // Push the previous state of the pointer register.
-    // This instruction must preserve the value.
-    buildMI(MBB, MBBI, AVR::PUSHWRr).addReg(Ptr.getReg());
-
-    // Add the immediate to the pointer register.
-    buildMI(MBB, MBBI, AVR::SBCIWRdK)
-        .addReg(Ptr.getReg(), RegState::Define)
-        .addReg(Ptr.getReg())
-        .addImm(-Imm);
-
-    // Store the value in the source register to the address
-    // pointed to by the pointer register.
-    buildMI(MBB, MBBI, AVR::STWPtrRr)
-        .addReg(Ptr.getReg())
-        .addReg(Src.getReg(), getKillRegState(Src.isKill()));
-
-    // Pop the original state of the pointer register.
-    buildMI(MBB, MBBI, AVR::POPWRd)
-        .addDef(Ptr.getReg(), getKillRegState(Ptr.isKill()));
-
-    MI.removeFromParent();
-  }
-
-  return false;
-}
-
-bool AVRRelaxMem::runOnInstruction(Block &MBB, BlockIt MBBI) {
-  MachineInstr &MI = *MBBI;
-  int Opcode = MBBI->getOpcode();
-
-#define RELAX(Op)                                                              \
-  case Op:                                                                     \
-    return relax<Op>(MBB, MI)
-
-  switch (Opcode) { RELAX(AVR::STDWPtrQRr); }
-#undef RELAX
-  return false;
-}
-
-} // end of anonymous namespace
-
-INITIALIZE_PASS(AVRRelaxMem, "avr-relax-mem", AVR_RELAX_MEM_OPS_NAME, false,
-                false)
-
-namespace llvm {
-
-FunctionPass *createAVRRelaxMemPass() { return new AVRRelaxMem(); }
-
-} // end of namespace llvm
Index: llvm/lib/Target/AVR/AVRRegisterInfo.cpp
===================================================================
--- llvm/lib/Target/AVR/AVRRegisterInfo.cpp
+++ llvm/lib/Target/AVR/AVRRegisterInfo.cpp
@@ -61,7 +61,7 @@
   Reserved.set(AVR::SPH);
   Reserved.set(AVR::SP);
 
-  // We tenatively reserve the frame pointer register r29:r28 because the
+  // We tentatively reserve the frame pointer register r29:r28 because the
   // function may require one, but we cannot tell until register allocation
   // is complete, which can be too late.
   //
Index: llvm/lib/Target/AVR/AVRFrameLowering.cpp
===================================================================
--- llvm/lib/Target/AVR/AVRFrameLowering.cpp
+++ llvm/lib/Target/AVR/AVRFrameLowering.cpp
@@ -295,47 +295,13 @@
   return true;
 }
 
-/// Replace pseudo store instructions that pass arguments through the stack with
-/// real instructions.
-static void fixStackStores(MachineBasicBlock &MBB,
-                           MachineBasicBlock::iterator MI,
-                           const TargetInstrInfo &TII, Register FP) {
-  // Iterate through the BB until we hit a call instruction or we reach the end.
-  for (MachineInstr &MI :
-       llvm::make_early_inc_range(llvm::make_range(MI, MBB.end()))) {
-    if (MI.isCall())
-      break;
-
-    unsigned Opcode = MI.getOpcode();
-
-    // Only care of pseudo store instructions where SP is the base pointer.
-    if (Opcode != AVR::STDSPQRr && Opcode != AVR::STDWSPQRr)
-      continue;
-
-    assert(MI.getOperand(0).getReg() == AVR::SP &&
-           "Invalid register, should be SP!");
-
-    // Replace this instruction with a regular store. Use Y as the base
-    // pointer since it is guaranteed to contain a copy of SP.
-    unsigned STOpc =
-        (Opcode == AVR::STDWSPQRr) ? AVR::STDWPtrQRr : AVR::STDPtrQRr;
-
-    MI.setDesc(TII.get(STOpc));
-    MI.getOperand(0).setReg(FP);
-  }
-}
-
 MachineBasicBlock::iterator AVRFrameLowering::eliminateCallFramePseudoInstr(
     MachineFunction &MF, MachineBasicBlock &MBB,
     MachineBasicBlock::iterator MI) const {
   const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
   const AVRInstrInfo &TII = *STI.getInstrInfo();
 
-  // There is nothing to insert when the call frame memory is allocated during
-  // function entry. Delete the call frame pseudo and replace all pseudo stores
-  // with real store instructions.
   if (hasReservedCallFrame(MF)) {
-    fixStackStores(MBB, MI, TII, AVR::R29R28);
     return MBB.erase(MI);
   }
 
@@ -343,57 +309,53 @@
   unsigned int Opcode = MI->getOpcode();
   int Amount = TII.getFrameSize(*MI);
 
-  // ADJCALLSTACKUP and ADJCALLSTACKDOWN are converted to adiw/subi
-  // instructions to read and write the stack pointer in I/O space.
-  if (Amount != 0) {
-    assert(getStackAlign() == Align(1) && "Unsupported stack alignment");
-
-    if (Opcode == TII.getCallFrameSetupOpcode()) {
-      // Update the stack pointer.
-      // In many cases this can be done far more efficiently by pushing the
-      // relevant values directly to the stack. However, doing that correctly
-      // (in the right order, possibly skipping some empty space for undef
-      // values, etc) is tricky and thus left to be optimized in the future.
-      BuildMI(MBB, MI, DL, TII.get(AVR::SPREAD), AVR::R31R30).addReg(AVR::SP);
-
-      MachineInstr *New =
-          BuildMI(MBB, MI, DL, TII.get(AVR::SUBIWRdK), AVR::R31R30)
-              .addReg(AVR::R31R30, RegState::Kill)
-              .addImm(Amount);
-      New->getOperand(3).setIsDead();
-
-      BuildMI(MBB, MI, DL, TII.get(AVR::SPWRITE), AVR::SP).addReg(AVR::R31R30);
-
-      // Make sure the remaining stack stores are converted to real store
-      // instructions.
-      fixStackStores(MBB, MI, TII, AVR::R31R30);
+  if (Amount == 0) {
+    return MBB.erase(MI);
+  }
+
+  assert(getStackAlign() == Align(1) && "Unsupported stack alignment");
+
+  if (Opcode == TII.getCallFrameSetupOpcode()) {
+    // Update the stack pointer.
+    // In many cases this can be done far more efficiently by pushing the
+    // relevant values directly to the stack. However, doing that correctly
+    // (in the right order, possibly skipping some empty space for undef
+    // values, etc) is tricky and thus left to be optimized in the future.
+    BuildMI(MBB, MI, DL, TII.get(AVR::SPREAD), AVR::R31R30).addReg(AVR::SP);
+
+    MachineInstr *New =
+        BuildMI(MBB, MI, DL, TII.get(AVR::SUBIWRdK), AVR::R31R30)
+            .addReg(AVR::R31R30, RegState::Kill)
+            .addImm(Amount);
+    New->getOperand(3).setIsDead();
+
+    BuildMI(MBB, MI, DL, TII.get(AVR::SPWRITE), AVR::SP).addReg(AVR::R31R30);
+  } else {
+    assert(Opcode == TII.getCallFrameDestroyOpcode());
+
+    // Note that small stack changes could be implemented more efficiently
+    // with a few pop instructions instead of the 8-9 instructions now
+    // required.
+
+    // Select the best opcode to adjust SP based on the offset size.
+    unsigned addOpcode;
+    if (isUInt<6>(Amount)) {
+      addOpcode = AVR::ADIWRdK;
     } else {
-      assert(Opcode == TII.getCallFrameDestroyOpcode());
-
-      // Note that small stack changes could be implemented more efficiently
-      // with a few pop instructions instead of the 8-9 instructions now
-      // required.
-
-      // Select the best opcode to adjust SP based on the offset size.
-      unsigned addOpcode;
-      if (isUInt<6>(Amount)) {
-        addOpcode = AVR::ADIWRdK;
-      } else {
-        addOpcode = AVR::SUBIWRdK;
-        Amount = -Amount;
-      }
+      addOpcode = AVR::SUBIWRdK;
+      Amount = -Amount;
+    }
 
-      // Build the instruction sequence.
-      BuildMI(MBB, MI, DL, TII.get(AVR::SPREAD), AVR::R31R30).addReg(AVR::SP);
+    // Build the instruction sequence.
+    BuildMI(MBB, MI, DL, TII.get(AVR::SPREAD), AVR::R31R30).addReg(AVR::SP);
 
-      MachineInstr *New = BuildMI(MBB, MI, DL, TII.get(addOpcode), AVR::R31R30)
-                              .addReg(AVR::R31R30, RegState::Kill)
-                              .addImm(Amount);
-      New->getOperand(3).setIsDead();
+    MachineInstr *New = BuildMI(MBB, MI, DL, TII.get(addOpcode), AVR::R31R30)
+                            .addReg(AVR::R31R30, RegState::Kill)
+                            .addImm(Amount);
+    New->getOperand(3).setIsDead();
 
-      BuildMI(MBB, MI, DL, TII.get(AVR::SPWRITE), AVR::SP)
-          .addReg(AVR::R31R30, RegState::Kill);
-    }
+    BuildMI(MBB, MI, DL, TII.get(AVR::SPWRITE), AVR::SP)
+        .addReg(AVR::R31R30, RegState::Kill);
   }
 
   return MBB.erase(MI);
@@ -410,6 +372,7 @@
     SavedRegs.set(AVR::R28);
   }
 }
+
 /// The frame analyzer pass.
 ///
 /// Scans the function for allocas and used arguments
@@ -420,7 +383,7 @@
 
   bool runOnMachineFunction(MachineFunction &MF) override {
     const MachineFrameInfo &MFI = MF.getFrameInfo();
-    AVRMachineFunctionInfo *FuncInfo = MF.getInfo<AVRMachineFunctionInfo>();
+    AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
 
     // If there are no fixed frame indexes during this stage it means there
     // are allocas present in the function.
@@ -431,7 +394,7 @@
       for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) {
         // Variable sized objects have size 0.
         if (MFI.getObjectSize(i)) {
-          FuncInfo->setHasAllocas(true);
+          AFI->setHasAllocas(true);
           break;
         }
       }
@@ -460,7 +423,7 @@
           }
 
           if (MFI.isFixedObjectIndex(MO.getIndex())) {
-            FuncInfo->setHasStackArgs(true);
+            AFI->setHasStackArgs(true);
             return false;
           }
         }
@@ -475,7 +438,6 @@
 
 char AVRFrameAnalyzer::ID = 0;
 
-/// Creates instance of the frame analyzer pass.
 FunctionPass *createAVRFrameAnalyzerPass() { return new AVRFrameAnalyzer(); }
 
 } // end of namespace llvm
Index: llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
===================================================================
--- llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
+++ llvm/lib/Target/AVR/AVRExpandPseudoInsts.cpp
@@ -1230,37 +1230,93 @@
 template <>
 bool AVRExpandPseudo::expand<AVR::STDWPtrQRr>(Block &MBB, BlockIt MBBI) {
   MachineInstr &MI = *MBBI;
-  Register SrcLoReg, SrcHiReg;
-  Register DstReg = MI.getOperand(0).getReg();
-  Register SrcReg = MI.getOperand(2).getReg();
-  unsigned Imm = MI.getOperand(1).getImm();
+
+  MachineOperand &Dst = MI.getOperand(0);
+  Register DstReg = Dst.getReg();
   bool DstIsKill = MI.getOperand(0).isKill();
+
+  int64_t Imm = MI.getOperand(1).getImm();
+
+  MachineOperand &Src = MI.getOperand(2);
+  Register SrcReg = Src.getReg();
   bool SrcIsKill = MI.getOperand(2).isKill();
-  unsigned OpLo = AVR::STDPtrQRr;
-  unsigned OpHi = AVR::STDPtrQRr;
-  TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
 
-  // Since we add 1 to the Imm value for the high byte below, and 63 is the
-  // highest Imm value allowed for the instruction, 62 is the limit here.
-  assert(Imm <= 62 && "Offset is out of range");
+  // STD's maximum displacement is 63, so larger stores have to be split into a
+  // few operations
+  if (Imm >= 63) {
+    if (!DstIsKill) {
+      buildMI(MBB, MBBI, AVR::PUSHWRr).addReg(DstReg);
+    }
 
-  auto MIBLO = buildMI(MBB, MBBI, OpLo)
-                   .addReg(DstReg)
-                   .addImm(Imm)
-                   .addReg(SrcLoReg, getKillRegState(SrcIsKill));
+    buildMI(MBB, MBBI, AVR::SBCIWRdK)
+        .addReg(DstReg, RegState::Define)
+        .addReg(DstReg)
+        .addImm(-Imm);
 
-  auto MIBHI = buildMI(MBB, MBBI, OpHi)
-                   .addReg(DstReg, getKillRegState(DstIsKill))
-                   .addImm(Imm + 1)
-                   .addReg(SrcHiReg, getKillRegState(SrcIsKill));
+    buildMI(MBB, MBBI, AVR::STWPtrRr)
+        .addReg(Dst.getReg())
+        .addReg(Src.getReg(), getKillRegState(SrcIsKill));
 
-  MIBLO.setMemRefs(MI.memoperands());
-  MIBHI.setMemRefs(MI.memoperands());
+    if (!DstIsKill) {
+      buildMI(MBB, MBBI, AVR::POPWRd).addDef(Dst.getReg());
+    }
+  } else {
+    Register SrcLoReg, SrcHiReg;
+    TRI->splitReg(SrcReg, SrcLoReg, SrcHiReg);
+
+    unsigned OpLo = AVR::STDPtrQRr;
+    unsigned OpHi = AVR::STDPtrQRr;
+
+    auto MIBLO = buildMI(MBB, MBBI, OpLo)
+                     .addReg(DstReg)
+                     .addImm(Imm)
+                     .addReg(SrcLoReg, getKillRegState(SrcIsKill));
+
+    auto MIBHI = buildMI(MBB, MBBI, OpHi)
+                     .addReg(DstReg, getKillRegState(DstIsKill))
+                     .addImm(Imm + 1)
+                     .addReg(SrcHiReg, getKillRegState(SrcIsKill));
+
+    MIBLO.setMemRefs(MI.memoperands());
+    MIBHI.setMemRefs(MI.memoperands());
+  }
 
   MI.eraseFromParent();
   return true;
 }
 
+template <>
+bool AVRExpandPseudo::expand<AVR::STDSPQRr>(Block &MBB, BlockIt MBBI) {
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
+
+  assert(MI.getOperand(0).getReg() == AVR::SP && "Unexpected register");
+
+  MI.setDesc(TII->get(AVR::STDPtrQRr));
+  MI.getOperand(0).setReg(STI.getFrameLowering()->hasReservedCallFrame(MF)
+                              ? AVR::R29R28
+                              : AVR::R31R30);
+
+  return true;
+}
+
+template <>
+bool AVRExpandPseudo::expand<AVR::STDWSPQRr>(Block &MBB, BlockIt MBBI) {
+  MachineInstr &MI = *MBBI;
+  const MachineFunction &MF = *MBB.getParent();
+  const AVRSubtarget &STI = MF.getSubtarget<AVRSubtarget>();
+
+  assert(MI.getOperand(0).getReg() == AVR::SP && "Unexpected register");
+
+  MI.setDesc(TII->get(AVR::STDWPtrQRr));
+  MI.getOperand(0).setReg(STI.getFrameLowering()->hasReservedCallFrame(MF)
+                              ? AVR::R29R28
+                              : AVR::R31R30);
+
+  return true;
+}
+
 template <>
 bool AVRExpandPseudo::expand<AVR::INWRdA>(Block &MBB, BlockIt MBBI) {
   MachineInstr &MI = *MBBI;
@@ -2346,6 +2402,8 @@
     EXPAND(AVR::STWPtrPiRr);
     EXPAND(AVR::STWPtrPdRr);
     EXPAND(AVR::STDWPtrQRr);
+    EXPAND(AVR::STDSPQRr);
+    EXPAND(AVR::STDWSPQRr);
     EXPAND(AVR::INWRdA);
     EXPAND(AVR::OUTWARr);
     EXPAND(AVR::PUSHWRr);
Index: llvm/lib/Target/AVR/AVR.h
===================================================================
--- llvm/lib/Target/AVR/AVR.h
+++ llvm/lib/Target/AVR/AVR.h
@@ -27,12 +27,10 @@
                                CodeGenOpt::Level OptLevel);
 FunctionPass *createAVRExpandPseudoPass();
 FunctionPass *createAVRFrameAnalyzerPass();
-FunctionPass *createAVRRelaxMemPass();
 FunctionPass *createAVRBranchSelectionPass();
 
 void initializeAVRShiftExpandPass(PassRegistry &);
 void initializeAVRExpandPseudoPass(PassRegistry &);
-void initializeAVRRelaxMemPass(PassRegistry &);
 
 /// Contains the AVR backend.
 namespace AVR {
Index: clang/docs/tools/clang-formatted-files.txt
===================================================================
--- clang/docs/tools/clang-formatted-files.txt
+++ clang/docs/tools/clang-formatted-files.txt
@@ -5990,7 +5990,6 @@
 llvm/lib/Target/AVR/AVRMCInstLower.h
 llvm/lib/Target/AVR/AVRRegisterInfo.cpp
 llvm/lib/Target/AVR/AVRRegisterInfo.h
-llvm/lib/Target/AVR/AVRRelaxMemOperations.cpp
 llvm/lib/Target/AVR/AVRSelectionDAGInfo.h
 llvm/lib/Target/AVR/AVRShiftExpand.cpp
 llvm/lib/Target/AVR/AVRSubtarget.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D114611: [AVR] ... Patryk Wychowaniec via Phabricator via cfe-commits

Reply via email to