Ada 对静态常量数组的优化效果如何?

ATL*_*DEV 5 optimization constants ada

假设我声明了一个常量值数组用作查找表:

function Square(num : Integer) return Integer is
use Ada.Text_IO;
type LookupItemsRange is range 1..10;
type LookupTable is array(LookupItemsRange) of integer;
A : constant LookupTable := (2312,2,3,4,5,6,7,8,9, 10);
begin
    Sqr := A(1);
    Sqr := 2 * A(2);
    return Sqr;
end Square;
Run Code Online (Sandbox Code Playgroud)

LookupTable 不应使用任何空间。编译器应该能够用实际的内联值替换数组访问。在最高优化设置下,Ada 的结果如下:

_ada_square:
        li      a0,4                #,
        ret     

Run Code Online (Sandbox Code Playgroud)

我计划用更清晰的查找表实现替换大量冗余的 MCU 代码。由于微控制器的资源有限,我想避免不必要的分配和索引。

什么情况下Ada会分配数组或者我完全安全?

Jef*_*ter 9

  1. 这取决于您的编译器和编译器选项。
  2. 正如您所演示的,无论您使用什么编译器,都可以出色地进行优化。
  3. 在 1992 年提出的《Ada 优于汇编:案例研究》中,Ada (83) 编译器生成的代码比专家团队手工优化的汇编器更快。想必优化器在过去 30 多年里已经变得更好了,所以在没有其他测量结果的情况下担心这种事情是浪费时间。


Jer*_*ere 5

因此,对于 Ada 语言规范,您将无法获得数组对象的保证。在即将发布的最新版本 (Ada2022) 中,Ada 开始赶上 constexpr,但只会向表达式函数提供其类似的属性( Ada 中的Static)(将它们视为与 constexpr 函数类似,但限制略有不同)。

因此,如果您不介意依赖编译器供应商,那么该数组很可能会正常工作(但不能保证)。如果您想要更多语言支持的优化保证,那么您将需要使用具有静态方面集的表达式函数来模拟数组(在最近的编译器中)。对于静态输入,静态表达式函数将给出静态结果(同样是 Ada 中的静态,而不是 C++ 中的静态,更像 constexpr)。

function Square return Integer is

    type Lookup_Items_Range is range 1..10;

    function A(Index : Lookup_Items_Range) return Integer is 
        (case Index is
            when 1 => 2312,
            when 2 => 2,
            when 3 => 3,
            when 4 => 4,
            when 5 => 5,
            when 6 => 6,
            when 7 => 7,
            when 8 => 8,
            when 9 => 9,
            when 10 => 10
         ) 
    with Static;

    Sqr : Integer;

begin

    Sqr := A(1);
    Sqr := 2 * A(2);
    return Sqr;
    
end Square;
Run Code Online (Sandbox Code Playgroud)

它比使用数组稍微冗长一些,但有语言支持,这在某些嵌入式编程领域非常重要。请注意,大多数最新的编译器都需要一个开关来启用此功能,因为它太新了,但它们通常会在错误消息中告诉您该开关。我使用 GNAT 12.1 在 godbolt 上进行了测试,并使用正确的开关进行了编译。