[llvm] 029f669 - [AVR] Emit 'eicall' for devices with large program memory

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 22 17:06:31 PST 2023


Author: Ben Shi
Date: 2023-01-23T09:06:10+08:00
New Revision: 029f669db3b471539bea25f30282784961952d2d

URL: https://github.com/llvm/llvm-project/commit/029f669db3b471539bea25f30282784961952d2d
DIFF: https://github.com/llvm/llvm-project/commit/029f669db3b471539bea25f30282784961952d2d.diff

LOG: [AVR] Emit 'eicall' for devices with large program memory

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

Reviewed By: aykevl

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

Added: 
    llvm/test/CodeGen/AVR/issue-58856-eicall.ll

Modified: 
    llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
    llvm/lib/Target/AVR/AVRMCInstLower.cpp
    llvm/lib/Target/AVR/AVRMCInstLower.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp b/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
index 36d2e8cb48d3..5511d53dfa31 100644
--- a/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AVR/AVRISelDAGToDAG.cpp
@@ -467,8 +467,9 @@ template <> bool AVRDAGToDAGISel::select<AVRISD::CALL>(SDNode *N) {
   Ops.push_back(Chain);
   Ops.push_back(Chain.getValue(1));
 
-  SDNode *ResNode =
-      CurDAG->getMachineNode(AVR::ICALL, DL, MVT::Other, MVT::Glue, Ops);
+  SDNode *ResNode = CurDAG->getMachineNode(
+      Subtarget->hasEIJMPCALL() ? AVR::EICALL : AVR::ICALL, DL, MVT::Other,
+      MVT::Glue, Ops);
 
   ReplaceUses(SDValue(N, 0), SDValue(ResNode, 0));
   ReplaceUses(SDValue(N, 1), SDValue(ResNode, 1));

diff  --git a/llvm/lib/Target/AVR/AVRMCInstLower.cpp b/llvm/lib/Target/AVR/AVRMCInstLower.cpp
index 2b8711656139..56de55567119 100644
--- a/llvm/lib/Target/AVR/AVRMCInstLower.cpp
+++ b/llvm/lib/Target/AVR/AVRMCInstLower.cpp
@@ -12,7 +12,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "AVRMCInstLower.h"
-
 #include "AVRInstrInfo.h"
 #include "MCTargetDesc/AVRMCExpr.h"
 
@@ -23,8 +22,9 @@
 
 namespace llvm {
 
-MCOperand AVRMCInstLower::lowerSymbolOperand(const MachineOperand &MO,
-                                             MCSymbol *Sym) const {
+MCOperand
+AVRMCInstLower::lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
+                                   const AVRSubtarget &Subtarget) const {
   unsigned char TF = MO.getTargetFlags();
   const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx);
 
@@ -42,15 +42,19 @@ MCOperand AVRMCInstLower::lowerSymbolOperand(const MachineOperand &MO,
 
   if (TF & AVRII::MO_LO) {
     if (IsFunction) {
-      // N.B. Should we use _GS fixups here to cope with >128k progmem?
-      Expr = AVRMCExpr::create(AVRMCExpr::VK_AVR_PM_LO8, Expr, IsNegated, Ctx);
+      Expr =
+          AVRMCExpr::create(Subtarget.hasEIJMPCALL() ? AVRMCExpr::VK_AVR_LO8_GS
+                                                     : AVRMCExpr::VK_AVR_PM_LO8,
+                            Expr, IsNegated, Ctx);
     } else {
       Expr = AVRMCExpr::create(AVRMCExpr::VK_AVR_LO8, Expr, IsNegated, Ctx);
     }
   } else if (TF & AVRII::MO_HI) {
     if (IsFunction) {
-      // N.B. Should we use _GS fixups here to cope with >128k progmem?
-      Expr = AVRMCExpr::create(AVRMCExpr::VK_AVR_PM_HI8, Expr, IsNegated, Ctx);
+      Expr =
+          AVRMCExpr::create(Subtarget.hasEIJMPCALL() ? AVRMCExpr::VK_AVR_HI8_GS
+                                                     : AVRMCExpr::VK_AVR_PM_HI8,
+                            Expr, IsNegated, Ctx);
     } else {
       Expr = AVRMCExpr::create(AVRMCExpr::VK_AVR_HI8, Expr, IsNegated, Ctx);
     }
@@ -63,6 +67,7 @@ MCOperand AVRMCInstLower::lowerSymbolOperand(const MachineOperand &MO,
 
 void AVRMCInstLower::lowerInstruction(const MachineInstr &MI,
                                       MCInst &OutMI) const {
+  auto &Subtarget = MI.getParent()->getParent()->getSubtarget<AVRSubtarget>();
   OutMI.setOpcode(MI.getOpcode());
 
   for (MachineOperand const &MO : MI.operands()) {
@@ -82,11 +87,12 @@ void AVRMCInstLower::lowerInstruction(const MachineInstr &MI,
       MCOp = MCOperand::createImm(MO.getImm());
       break;
     case MachineOperand::MO_GlobalAddress:
-      MCOp = lowerSymbolOperand(MO, Printer.getSymbol(MO.getGlobal()));
+      MCOp =
+          lowerSymbolOperand(MO, Printer.getSymbol(MO.getGlobal()), Subtarget);
       break;
     case MachineOperand::MO_ExternalSymbol:
       MCOp = lowerSymbolOperand(
-          MO, Printer.GetExternalSymbolSymbol(MO.getSymbolName()));
+          MO, Printer.GetExternalSymbolSymbol(MO.getSymbolName()), Subtarget);
       break;
     case MachineOperand::MO_MachineBasicBlock:
       MCOp = MCOperand::createExpr(
@@ -96,13 +102,15 @@ void AVRMCInstLower::lowerInstruction(const MachineInstr &MI,
       continue;
     case MachineOperand::MO_BlockAddress:
       MCOp = lowerSymbolOperand(
-          MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
+          MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()), Subtarget);
       break;
     case MachineOperand::MO_JumpTableIndex:
-      MCOp = lowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
+      MCOp = lowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()),
+                                Subtarget);
       break;
     case MachineOperand::MO_ConstantPoolIndex:
-      MCOp = lowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
+      MCOp = lowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()),
+                                Subtarget);
       break;
     }
 

diff  --git a/llvm/lib/Target/AVR/AVRMCInstLower.h b/llvm/lib/Target/AVR/AVRMCInstLower.h
index 7ad6d472ad87..d288cc0ba558 100644
--- a/llvm/lib/Target/AVR/AVRMCInstLower.h
+++ b/llvm/lib/Target/AVR/AVRMCInstLower.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_AVR_MCINST_LOWER_H
 #define LLVM_AVR_MCINST_LOWER_H
 
+#include "AVRSubtarget.h"
 #include "llvm/Support/Compiler.h"
 
 namespace llvm {
@@ -29,7 +30,8 @@ class AVRMCInstLower {
 
   /// Lowers a `MachineInstr` into a `MCInst`.
   void lowerInstruction(const MachineInstr &MI, MCInst &OutMI) const;
-  MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const;
+  MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
+                               const AVRSubtarget &Subtarget) const;
 
 private:
   MCContext &Ctx;

diff  --git a/llvm/test/CodeGen/AVR/issue-58856-eicall.ll b/llvm/test/CodeGen/AVR/issue-58856-eicall.ll
new file mode 100644
index 000000000000..82a908142f96
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/issue-58856-eicall.ll
@@ -0,0 +1,30 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=avr -mattr=-eijmpcall | FileCheck %s --check-prefix=ICALL
+; RUN: llc < %s -mtriple=avr -mattr=+eijmpcall | FileCheck %s --check-prefix=EICALL
+
+; This test verifies the bug https://github.com/llvm/llvm-project/issues/58856
+
+declare dso_local i16 @func()
+
+define i16 @foo() {
+; ICALL-LABEL: foo:
+; ICALL:       ; %bb.0:
+; ICALL-NEXT:    ldi r30, pm_lo8(func)
+; ICALL-NEXT:    ldi r31, pm_hi8(func)
+; ICALL-NEXT:    ;APP
+; ICALL-NEXT:    ;NO_APP
+; ICALL-NEXT:    icall
+; ICALL-NEXT:    ret
+;
+; EICALL-LABEL: foo:
+; EICALL:       ; %bb.0:
+; EICALL-NEXT:    ldi r30, lo8_gs(func)
+; EICALL-NEXT:    ldi r31, hi8_gs(func)
+; EICALL-NEXT:    ;APP
+; EICALL-NEXT:    ;NO_APP
+; EICALL-NEXT:    eicall
+; EICALL-NEXT:    ret
+  %1 = tail call addrspace(0) ptr addrspace(1) asm "", "=r,0"(ptr addrspace(1) @func)
+  %2 = tail call i16 %1()
+  ret i16 %2
+}


        


More information about the llvm-commits mailing list