SEGGER Embedded Studio for RISC-V 代码优化等级与 LTO 优化等级 配置说明

 上面只是对局部代码进行优化。由于编译器一次只编译优化一个编译单元,所以只是在做局部优化,而利用 LTO,利用链接时的全局视角进行操作,从而得到能够进行更加极致的优化。开启LTO优化部分,位置:

1、LTO定义

“Link-Time Optimization.” Any kind of optimization that requires looking at the whole program, LLVM features powerful intermodular optimizations which can be used at link time.

LTO(Link-Time Optimization) 就是对整个程序代码进行的一种优化,是 LLVM 里在链接时进行跨模块间的优化。

LTO 属于 IPO(interprocedural optimization) 当中的一种优化,根据维基百科的解释,IPO 是优化代码的一系列编译器优化技术的集合,不同于其他的优化技术,IPO 聚焦于分析整个程序代码。

2、LTO主要优化

跨模块优化的效果,也即开启LTO主要有这几点好处:

(1)将一些函数內联化

(2)去除了一些无用代码

(3)对程序有全局的优化作用

PGO(Profile Guided Optimization) 对于进行 LTO 优化也很有帮助。

3、LTO 的问题

开启 lto 后导致产生的 linkmap 可读性变差,如文件名信息可能会变成 8.arm64.thinlto.o 这样的数字,可以对 libLTO.dylib 的行为进行修改,使用 -lto_library 让链接器使用我们指定的 dylib 库。

比较体验不好的是,LTO 会导致编译和链接变慢,以及会使用更多的内存,所以即使到现在,也没有看到 LTO 被广泛地使用。

SEGGER 官网介绍:Link Time Optimization (segger.cn)

 开启 LTO 优化等级后配置如下:

这里按照SEGGER 官方说法:https://wiki.segger.com/Link_Time_Optimization

开启这个功能要实现几个函数 :

__SEGGER_RTL_X_file_bufsize, 
__SEGGER_RTL_X_file_stat, 
__SEGGER_RTL_X_file_write, 
stdout

具体实现方法参考链接:https://wiki.segger.com/Embedded_Studio_Library_IO

/*********************************************************************
*                   (c) SEGGER Microcontroller GmbH                  *
*                        The Embedded Experts                        *
*                           www.segger.com                           *
**********************************************************************

-------------------------- END-OF-HEADER -----------------------------
Purpose : Implementation of low-level functions for I/O with the
          SEGGER Runtime Library
          using a UART (SEGGER's BSP UART module)
*/

/*********************************************************************
*
*       #include section
*
**********************************************************************
*/

#include "__SEGGER_RTL_Int.h"
#include "stdio.h"
#include "BSP_UART.h"

/*********************************************************************
*
*       Prototypes
*
**********************************************************************
*/
void RTL_UART_Init(unsigned int Unit, unsigned long Baudrate, unsigned char NumDataBits, unsigned char Parity, unsigned char NumStopBits);

/*********************************************************************
*
*       Local types
*
**********************************************************************
*/

struct __SEGGER_RTL_FILE_impl {         // NOTE: Provides implementation for FILE
  int stub; // only needed so impl has size != 0.
};

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/

static FILE __SEGGER_RTL_stdin_file  = { 0 };  // stdin reads from UART
static FILE __SEGGER_RTL_stdout_file = { 0 };  // stdout writes to UART
static FILE __SEGGER_RTL_stderr_file = { 0 };  // stderr writes to UART

static unsigned int _UART_Port    = 0;
static int          _stdin_ungot  = EOF;

/*********************************************************************
*
*       Public data
*
**********************************************************************
*/

FILE *stdin  = &__SEGGER_RTL_stdin_file;  // NOTE: Provide implementation of stdin for RTL.
FILE *stdout = &__SEGGER_RTL_stdout_file; // NOTE: Provide implementation of stdout for RTL.
FILE *stderr = &__SEGGER_RTL_stderr_file; // NOTE: Provide implementation of stderr for RTL.

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/

/*********************************************************************
*
*       _stdin_getc()
*
*  Function description
*    Get character from standard input.
*
*  Return value
*    Character received.
*
*  Additional information
*    This function never fails to deliver a character.
*/
static char _stdin_getc(void) {
  unsigned char c;

  if (_stdin_ungot != EOF) {
    c = _stdin_ungot;
    _stdin_ungot = EOF;
  } else {
    BSP_UART_ReadBlocking(_UART_Port, &c, sizeof(c));
  }
  return c;
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/

/*********************************************************************
*
*       RTL_UART_Init()
*
*  Function description
*    Initialize RTL to use given UART for stdio.
*
*  Parameters
*    Unit       : UART unit number (typically zero-based).
*    Baudrate   : Baud rate to configure [Hz].
*    NumDataBits: Number of data bits to use.
*    Parity     : One of the following values:
*                   * BSP_UART_PARITY_NONE
*                   * BSP_UART_PARITY_ODD
*                   * BSP_UART_PARITY_EVEN
*    NumStopBits: Number of stop bits to use.
*
*  Additional description
*    Parameters are same as for BSP_UART_Init().
*    This also sets appropriate RX and TX interrupt handlers.
*/
void RTL_UART_Init(unsigned int Unit, unsigned long Baudrate, unsigned char NumDataBits, unsigned char Parity, unsigned char NumStopBits) {
  _UART_Port = Unit;
  BSP_UART_Init(_UART_Port, Baudrate, NumDataBits, Parity, NumStopBits);
}

/*********************************************************************
*
*       __SEGGER_RTL_X_file_stat()
*
*  Function description
*    Get file status.
*
*  Parameters
*    stream - Pointer to file.
*
*  Additional information
*    Low-overhead test to determine if stream is valid.  If stream
*    is a valid pointer and the stream is open, this function must
*    succeed.  If stream is a valid pointer and the stream is closed,
*    this function must fail.
*
*    The implementation may optionally determine whether stream is
*    a valid pointer: this may not always be possible and is not
*    required, but may assist debugging when clients provide wild
*    pointers.
*
*  Return value
*    <  0 - Failure, stream is not a valid file.
*    >= 0 - Success, stream is a valid file.
*/
int __SEGGER_RTL_X_file_stat(FILE *stream) {
  if (stream == stdin || stream == stdout || stream == stderr) {
    return 0;       // NOTE: stdin, stdout, and stderr are assumed to be valid.
  } else {
    return EOF;
  }
}

/*********************************************************************
*
*       __SEGGER_RTL_X_file_bufsize()
*
*  Function description
*    Get stream buffer size.
*
*  Parameters
*    stream - Pointer to file.
*
*  Additional information
*    Returns the number of characters to use for buffered I/O on
*    the file stream.  The I/O buffer is allocated on the stack
*    for the duration of the I/O call, therefore this value should
*    not be set arbitrarily large.
*
*    For unbuffered I/O, return 1.
*
*  Return value
*    Nonzero number of characters to use for buffered I/O; for
*    unbuffered I/O, return 1.
*/
int __SEGGER_RTL_X_file_bufsize(FILE *stream) {
  (void)stream;
  return 1;
}

/*********************************************************************
*
*       __SEGGER_RTL_X_file_read()
*
*  Function description
*    Read data from file.
*
*  Parameters
*    stream - Pointer to file to read from.
*    s      - Pointer to object that receives the input.
*    len    - Number of characters to read from file.
*
*  Return value
*    >= 0 - Success, amount of data read.
*    <  0 - Failure.
*
*  Additional information
*    Reading from any stream other than stdin results in an error.
*/
int __SEGGER_RTL_X_file_read(FILE *stream, char *s, unsigned len) {
  int c;

  if (stream == stdin) {
    c = 0;
    while (len > 0) {
      *s = _stdin_getc();
      ++s;
      ++c;
      --len;
    }
  } else {
    c = EOF;
  }
  return c;
}

/*********************************************************************
*
*       __SEGGER_RTL_X_file_write()
*
*  Function description
*    Write data to file.
*
*  Parameters
*    stream - Pointer to file to write to.
*    s      - Pointer to object to write to file.
*    len    - Number of characters to write to the file.
*
*  Return value
*    >= 0 - Success.
*    <  0 - Failure.
*
*  Additional information
*    this version is NOT reentrant!
*    stdout and stderr are directed to UART;
*    writing to any stream other than stdout or stderr results in an error
*/
int __SEGGER_RTL_X_file_write(FILE *stream, const char *s, unsigned len) {
  if ((stream == stdout) || (stream == stderr)) {
    BSP_UART_WriteBlocking(_UART_Port, (const unsigned char*) s, len);
    return len;
  } else {
    return EOF;
  }
}

/*********************************************************************
*
*       __SEGGER_RTL_X_file_unget()
*
*  Function description
*    Push character back to stream.
*
*  Parameters
*    stream - Pointer to file to push back to.
*    c      - Character to push back.
*
*  Return value
*    >= 0 - Success.
*    <  0 - Failure.
*
*  Additional information
*    Push-back is only supported for standard input, and
*    only a single-character pushback buffer is implemented.
*/
int __SEGGER_RTL_X_file_unget(FILE *stream, int c) {
  if (stream == stdin) {
    if (c != EOF && _stdin_ungot == EOF) {
      _stdin_ungot = c;
    } else {
      c = EOF;
    }
  } else {
    c = EOF;
  }
  return c;
}

/*************************** End of file ****************************/

 

注意这里 Library IO 库需要使用RTT的,否则编译会报错,配置位置:

 

posted @ 2023-12-21 19:32  求隐  阅读(1077)  评论(0)    收藏  举报