强制/说服/欺骗 GCC 展开_更长_循环?

2024-04-19

如何说服 GCC 展开迭代次数已知但很大的循环?

我正在编译-O3.

当然,所讨论的实际代码更复杂,但这里有一个具有相同行为的简化示例:

int const constants[] = { 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144 };

int get_sum_1()
{
    int total = 0;
    for (int i = 0; i < CONSTANT_COUNT; ++i)
    {
        total += constants[i];
    }
    return total;
}

...if CONSTANT_COUNT定义为 8(或更少),那么 GCC 将展开循环,传播常量,并将整个函数简化为一个简单的函数return <value>;。另一方面,如果CONSTANT_COUNT是 9 (或更大),则循环不会展开,并且 GCC 会生成一个二进制文件,该二进制文件会循环、读取常量并在运行时添加它们 - 尽管从理论上讲,该函数仍然可以优化为仅返回持续的。 (是的,我看过反编译的二进制文件。)

If I manually展开循环,如下所示:

int get_sum_2()
{
    int total = 0;
    total += constants[0];
    total += constants[1];
    total += constants[2];
    total += constants[3];
    total += constants[4];
    total += constants[5];
    total += constants[6];
    total += constants[7];
    total += constants[8];
    //total += constants[9];
    return total;
}

Or this:

#define ADD_CONSTANT(z, v, c) total += constants[v];

int get_sum_2()
{
    int total = 0;
    BOOST_PP_REPEAT(CONSTANT_COUNT, ADD_CONSTANT, _)
    return total;
}

...然后该函数被优化为返回一个常量。因此,一旦展开,GCC 似乎能够处理较大循环的恒定传播;这个挂断似乎只是让 GCC 考虑首先展开更长的循环。

然而,无论是手动展开还是BOOST_PP_REPEAT是可行的选择,因为有some情况下CONSTANT_COUNT是一个运行时表达式,并且same对于这些情况,代码仍然需要正确工作。 (在这些情况下,性能并不那么重要。)

我正在使用 C (不是 C++),所以模板元编程和constexpr可供我使用。

我试过了-funroll-loops, -funroll-all-loops, -fpeel-loops,并为max-unrolled-insns, max-average-unrolled-insns, max-unroll-times, max-peeled-insns, max-peel-times, max-completely-peeled-insns, and max-completely-peel-times,这些似乎都没有什么区别。

我在 Linux x86_64 上使用 GCC 4.8.2。

有任何想法吗?是否有我缺少的标志或参数...?


我不确定这个解决方法是否适用于您的实际问题,但我发现运行 Parabola GNU/Linux 的 x86_64 上的 GCC 4.9.0 20140604(预发布)展开以下循环,直到并包括CONSTANT_COUNT == 33.

int
get_sum()
{
  int total = 0;
  int i, j, k = 0;
  for (j = 0; j < 2; ++j)
    {
      for (i = 0; i < CONSTANT_COUNT / 2; ++i)
        {
          total += constants[k++];
        }
    }
  if (CONSTANT_COUNT % 2)
    total += constants[k];
  return total;
}

我只通过了-O3旗帜。汇编代码为get_sum真的只是

movl $561, %eax
ret

我没有尝试,但也许该模式可以进一步扩展。

对我来说,这似乎很奇怪,因为——至少在我的肉眼看来——代码现在看起来要复杂得多。不幸的是,这是一种相当侵入性的强制展开方式。编译器标志会好得多。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

强制/说服/欺骗 GCC 展开_更长_循环? 的相关文章

  • 隐式将 string 转换为 string_view

    void Foo1 string view view string str one two three Foo1 one two three Implicitly convert char to string view Foo1 str I
  • Qt:更改 Mac OS X 上的应用程序 QMenuBar 内容

    我的应用程序对多个 页面 使用 QTabWidget 其中顶级菜单根据用户所在的页面而变化 我的问题是 尝试重新创建菜单栏的内容会导致严重的显示问题 它在除 Mac OS X 之外的所有平台上按预期使用第一种和第三种样式 尚未测试第二种 但
  • 输出 objdump -t 的输出中的“.hidden”是什么意思?

    Example objdump Logger cpp o t 00000000 g F text 00000000 hidden sti 10 Logger cpp 0b2ae32b 这意味着符号的可见性被隐藏 https develope
  • Swashbuckle 在 ASP.NET Core 中失败并出现 NotSupportedException 异常

    我跟着这个关于如何在我的 asp net core 2 2 项目中添加 swashbuckle 当我运行该项目时 我收到以下错误 处理请求时发生未处理的异常 NotSupportedException HTTP 方法 GET 和路径 id
  • 尽管 if 语句,Visual Studio 仍尝试包含 Linux 标头

    我正在尝试创建一个强大的头文件 无需更改即可在 Windows 和 Linux 上进行编译 为此 我的包含内容中有一个 if 语句 如下所示 if defined WINDOWS include
  • tmpnam 的 C/C++ 线程安全性?

    我需要使用tmpnamC 中的函数 但我需要了解它的线程安全性 也就是说 如果我有多个线程 每个线程都需要为临时文件获取不同的名称 我是否可以保证每个线程都会收到具有不同名称的文件 tmpnam 仅保证该文件当时不存在 但它可能会在您自己创
  • pybind11 返回 numpy 对象数组

    使用 pybind11 C API 和 python3 我们如何在 C 实现中正确创建一个 numpy 对象数组 即 unicode 字符串 并将其返回给 python 传递到 pybind11 array 的底层数据数组的确切内存布局是什
  • 清理 STL 指针列表/向量

    您可以想出的最短的 C 块是多少来安全地清理std vector or std list指针 假设您必须对指针调用删除 list
  • 如何使用 Unity 动态注册通用类?

    我有一个包含很多类 300 和 BaseClass 的程序集 我想用接口注册一个泛型类 统一后 您必须在 Name如果你想解析接口的对象数组 我想要一个对象数组主视图模型自动地 有没有办法通过反射来自动执行此操作 有什么建议么 示例 伪 p
  • 使用迭代器遍历 boost::ublas 矩阵

    我只是想从头到尾遍历一个矩阵 触及每个元素 然而 我发现升压矩阵没有一个迭代器 而是有两个迭代器 而且我无法弄清楚如何使它们工作以便您可以遍历整个矩阵 typedef boost numeric ublas matrix
  • SolrNet:尝试添加和提交时 SolrConnectionException (400) 错误请求

    我已经到了 SolrNet 执行 Add 方法的地步 但是当我尝试 Commit 时 我收到了错误 以下是我的 schema xml 模型 调用它的代码以及我得到的错误 更奇怪的是 尽管出现错误 但在我重新启动 Tomcat 后 该模型仍会
  • 使用 C# 从文本中删除数字

    我有一个要处理的文本文件 其中有一些数字 我只想要其中的文字 而不是其他任何东西 我成功删除了标点符号 但是如何删除数字呢 我想要使 用 C 代码 另外 我想删除长度大于 10 的单词 如何使用 Reg 表达式来做到这一点 您可以使用正则表
  • 如何用C语言创建字典?

    我正在用 C 语言编写一个微控制器 作为它的一部分 我想在 7 段显示器上显示某些字母 每个字母都有一个对应的数字 使 7 段显示屏显示该字母 它没有真正的模式 因为数字只是通过将显示字母所需的 7 段显示器上的位相加而成 因此如果我可以创
  • 以编程方式打开网页并以字符串形式检索其 html 包含内容

    我有一个 Facebook 帐户 我想提取我朋友的照片及其个人详细信息 例如 出生日期 就读学校 等 我能够提取我每个朋友帐户的 Facebook 首页的地址 但我不知道如何以编程方式打开我每个朋友首页的网页并将 html 包含保存为字符串
  • 如何将日期格式从 DD/MM/YYYY 或 MM/DD/YYYY 更改为 YYYY-MM-DD?

    我需要使用 C 更改日期字符串的格式 来自 06 16 2010 或 16 06 2010 至 2010 06 16 你能帮我实现这个目标吗 thanks 如果您已经将其作为DateTime use string x dt ToString
  • 我们还需要迭代器设计模式吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • MonoMac 窗口关闭时没有错误

    我刚刚开始在 Xamarin Studio 中使用 MonoMac 并且遇到了最奇怪的问题 我有一个带有 NSButton 和 NSTextField 的窗口 至此 我已经删除了按钮上的事件处理程序 因此它不会执行任何操作 除了在单击它时突
  • 如果未先将 lambda 表达式强制转换为委托或表达式树类型,则无法将其用作动态分派操作的参数

    我正在使用 NET4 5 和 VS2013 我有这个查询dynamic来自数据库的结果 dynamic topAgents this dataContext Sql select t create user id as User sum t
  • 如何将 .ashx 处理程序与 asp:Image 对象一起使用?

    我有一个 ashx 处理程序 using System using System Web public class Thumbnail IHttpHandler public void ProcessRequest HttpContext
  • 我的 Visual Studio 2008 模板有什么问题?

    我正在尝试为 Visual Studio 创建自己的类模板 称为 公共类 我跟着有关如何手动创建项目模板的官方 MSDN 说明 http msdn microsoft com en us library ms247113 aspx几乎一字不

随机推荐