标签: compiler-optimization

是否可以使用整数运算实现按位运算符?

我面临一个相当特殊的问题.我正在研究一种不支持按位运算的体系结构的编译器.但是,它处理签名的16位整数算术,我想知道是否有可能只使用以下方式实现按位运算:

  • 加法(c = a + b)
  • 减法(c = a - b)
  • 分部(c = a/b)
  • 乘法(c = a*b)
  • 模数(c = a%b)
  • 最小值(c = min(a,b))
  • 最大值(c = max(a,b))
  • 比较(c =(a <b),c =(a == b),c =(a <= b),et.c.)
  • 跳转(goto,for,et.c.)

我希望能够支持的按位操作是:

  • 或者(c = a | b)
  • 并且(c = a&b) …

discrete-mathematics bitwise-operators compiler-optimization

53
推荐指数
3
解决办法
2万
查看次数

为什么允许gcc从结构中推测性地加载?

显示可能出错的gcc优化和用户代码的示例

下面的代码段中的函数'foo'将只加载一个结构成员A或B; 至少这是未经优化的代码的意图.

typedef struct {
  int A;
  int B;
} Pair;

int foo(const Pair *P, int c) {
  int x;
  if (c)
    x = P->A;
  else
    x = P->B;
  return c/102 + x;
}
Run Code Online (Sandbox Code Playgroud)

这是gcc -O3给出的:

mov eax, esi
mov edx, -1600085855
test esi, esi
mov ecx, DWORD PTR [rdi+4]   <-- ***load P->B**
cmovne ecx, DWORD PTR [rdi]  <-- ***load P->A***
imul edx
lea eax, [rdx+rsi]
sar esi, 31
sar eax, 6
sub eax, esi
add eax, ecx
ret …
Run Code Online (Sandbox Code Playgroud)

c x86 assembly gcc compiler-optimization

52
推荐指数
5
解决办法
4140
查看次数

为什么Clang会优化此代码?

代码的目的是找到32位浮点位模式的总数,它代表0到1之间的值.在我看来这应该可行,但由于某种原因,Clang的汇编输出基本上相当于return 0;.

我使用-std=c++1y -Wall -Wextra -pedantic -O2和编译了Clang 3.3和Clang 3.4.1-std=c++1y -Wall -Wextra -pedantic -O3

Clang 3.4使用-O2和-O3优化一切.

Clang 3.3仅使用-O3优化一切.

通过"优化一切",我的意思是这是程序的汇编输出:

main:                                   # @main
    xorl    %eax, %eax
    ret
Run Code Online (Sandbox Code Playgroud)
#include <limits>
#include <cstring>
#include <cstdint>

template <class TO, class FROM>
inline TO punning_cast(const FROM &input)
{
    TO out;
    std::memcpy(&out, &input, sizeof(TO));
    return out;
}

int main()
{
    uint32_t i = std::numeric_limits<uint32_t>::min();
    uint32_t count = 0;

    while (1)
    {
        float n = punning_cast<float>(i);
        if(n >= 0.0f && n <= 1.0f) …
Run Code Online (Sandbox Code Playgroud)

c++ clang compiler-optimization

51
推荐指数
1
解决办法
3618
查看次数

JIT没有优化涉及Integer.MAX_VALUE的循环

在写另一个问题的答案时,我注意到JIT优化的一个奇怪的边界情况.

以下程序不是 "Microbenchmark",也不是为了可靠地测量执行时间(如另一个问题的答案中所指出的).它仅用作MCVE来重现该问题:

class MissedLoopOptimization
{
    public static void main(String args[])
    {
        for (int j=0; j<3; j++)
        {
            for (int i=0; i<5; i++)
            {
                long before = System.nanoTime();
                runWithMaxValue();
                long after = System.nanoTime();
                System.out.println("With MAX_VALUE   : "+(after-before)/1e6);
            }
            for (int i=0; i<5; i++)
            {
                long before = System.nanoTime();
                runWithMaxValueMinusOne();
                long after = System.nanoTime();
                System.out.println("With MAX_VALUE-1 : "+(after-before)/1e6);
            }
        }
    }

    private static void runWithMaxValue()
    {
        final int n = Integer.MAX_VALUE;
        int i = …
Run Code Online (Sandbox Code Playgroud)

java jit jvm-hotspot compiler-optimization

49
推荐指数
1
解决办法
1394
查看次数

为什么将字符串初始化为“”比默认构造函数更有效?

一般来说,默认构造函数应该是创建空容器的最快方法。这就是为什么我惊讶地发现它比初始化为空字符串文字更糟糕:

#include <string>

std::string make_default() {
    return {};
}

std::string make_empty() {
    return "";
}
Run Code Online (Sandbox Code Playgroud)

编译为:(clang 16,libc++)

make_default():
        mov     rax, rdi
        xorps   xmm0, xmm0
        movups  xmmword ptr [rdi], xmm0
        mov     qword ptr [rdi + 16], 0
        ret
make_empty():
        mov     rax, rdi
        mov     word ptr [rdi], 0
        ret
Run Code Online (Sandbox Code Playgroud)

请参阅编译器资源管理器中的实时示例

请注意,返回{}总共将 24 个字节归零,但返回""仅将 2 个字节归零。怎么会return "";好很多呢?

c++ clang stdstring compiler-optimization libc++

49
推荐指数
1
解决办法
4755
查看次数

这是编译器优化错误还是未定义的行为?

我们有一个烦人的错误,我无法解释这段代码:

unsigned char bitmap[K_BITMAP_SIZE] = {0} ;
SetBit(bitmap, K_18); // Sets the bit #18 to 1

for(size_t i = 0; i < K_END; ++i)
{
    if(TestBit(bitmap, i)) // true for 18
    {
        size_t i2 = getData(i); // for 18, will return 15
        SetBit(bitmap, i2); // BUG: IS SUPPOSED TO set the bit #15 to 1
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 它发生在Visual C++ 2010上
  2. 它发生在32位和64位版本上
  3. 它仅在发布版本上发生(设置为"最大化速度(/ O2)")
  4. 它不会仅在"最小化大小(/ O1)"设置的发布版本中发生
  5. 只有当我们__forceinline使用getData函数时才会在Visual C++ 2008上发生(默认情况下,VC++ 2008不会内联该函数,而VC++ 2010会这样做)
  6. 它发生在下面给出的代码片段上,可能是因为循环内部有大量内联
  7. 如果我们删除循环并直接设置有趣的值就不会发生(18)

奖金信息:

1- BenJ评论说这个问题没有出现在Visual C++ 2012上,这意味着这可能是编译器中的一个错误

2-如果我们 …

c++ visual-studio-2010 compiler-optimization undefined-behavior visual-studio

48
推荐指数
2
解决办法
2939
查看次数

有没有理由不使用链接时优化(LTO)?

GCC,MSVC,LLVM以及可能的其他工具链支持链接时(整个程序)优化,以允许编译单元之间的调用优化.

在编译生产软件时是否有理由不启用此选项?

c c++ performance compilation compiler-optimization

48
推荐指数
3
解决办法
2万
查看次数

C#编译器是否将lambda表达式视为公共或私有方法?

在内部,编译器应该将lambda表达式转换为方法.在这种情况下,这些方法是私有还是公共(或其他),是否可以改变它?

c# compiler-optimization

47
推荐指数
3
解决办法
3711
查看次数

为什么编译器没有合并多余的std :: atomic写入?

我想知道为什么没有编译器准备将相同值的连续写入合并到单个原子变量,例如:

#include <atomic>
std::atomic<int> y(0);
void f() {
  auto order = std::memory_order_relaxed;
  y.store(1, order);
  y.store(1, order);
  y.store(1, order);
}
Run Code Online (Sandbox Code Playgroud)

我尝试过的每个编译器都会发出三次上面的编写.什么合法的,无种族的观察者可以看到上述代码与具有单次写入的优化版本之间的差异(即,不是"假设"规则适用)?

如果变量是易变的,那么显然不适用优化.在我的情况下有什么阻止它?

这是编译器资源管理器中的代码.

c++ multithreading compiler-optimization c++11 stdatomic

47
推荐指数
5
解决办法
4494
查看次数

为什么GCC不能优化C++中空指针的删除?

考虑一个简单的程序:

int main() {
  int* ptr = nullptr;
  delete ptr;
}
Run Code Online (Sandbox Code Playgroud)

对于GCC(7.2),在结果程序中有call关于的指令operator delete.对于Clang和Intel编译器,没有这样的指令,空指针删除被完全优化(-O2在所有情况下).你可以在这里测试:https://godbolt.org/g/JmdoJi.

我想知道这样的优化能否以某种方式与GCC一起开启?(我更广泛的动机源于自定义swapvs std::swap可移动类型的问题,其中删除空指针可能代表第二种情况下的性能损失; 有关详细信息,请参阅/sf/answers/3198249771/.)

UPDATE

为了澄清我对这个问题的动机:如果我在移动赋值运算符和某个类的析构函数中使用delete ptr;if (ptr)保护,那么该类的对象将产生3个GCC指令.这可能是相当大的性能损失,例如,在对这些对象的数组进行排序时.std::swapcall

此外,我可以if (ptr) delete ptr;在任何地方写作,但是想知道,这是否也不能成为性能损失,因为delete表达式也需要检查ptr.但是,在这里,我想,编译器只会生成一个检查.

此外,我真的很喜欢delete没有后卫的可能性,这对我来说是一个惊喜,它可以产生不同的(表现)结果.

UPDATE

我只是做了一个简单的基准测试,即排序对象,它们delete在移动赋值运算符和析构函数中调用.来源是:https://godbolt.org/g/7zGUvo

std::sort使用GCC 7.1测量的运行时间和-O2Xeon E2680v3上的标志:

链接代码中存在一个错误,它会比较指针,而不是指向值.更正结果如下:

  1. 没有if后卫:17.6 [s] 40.8 [s], …

c++ null gcc compiler-optimization delete-operator

46
推荐指数
5
解决办法
5976
查看次数