小编Bee*_*ope的帖子

在x86-64 SysV ABI中,高位参数和返回值寄存器是否允许垃圾?

除了其他方面,x86-64 SysV ABI指定了如何在寄存器中传递函数参数(第一个参数in rdi,then rsi等等),以及如何传回整数返回值(in rax和then rdx表示非常大的值).

然而,我找不到的是当传递小于64位的类型时,参数或返回值寄存器的高位应该是什么.

例如,对于以下功能:

void foo(unsigned x, unsigned y);
Run Code Online (Sandbox Code Playgroud)

... x将被传入rdiyrsi,但他们只是32位.不要的高32位rdirsi必须为零?直观地说,我会假设是,但是所有gcc,clang和icc 生成代码mov在开始时都有特定的指令将高位清零,所以看起来编译器假定不然.

类似地,编译器似乎假设rax如果返回值小于64 位,则返回值的高位可能具有垃圾位.例如,以下代码中的循环:

unsigned gives32();
unsigned short gives16();

long sum32_64() {
  long total = 0;
  for (int i=1000; i--; ) {
    total += gives32();
  }
  return total;
}

long sum16_64() {
  long total = 0;
  for (int i=1000; i--; ) {
    total += …
Run Code Online (Sandbox Code Playgroud)

linux x86 x86-64 calling-convention

8
推荐指数
1
解决办法
403
查看次数

-XX:+ PrintCompilation输出中的新列是什么?

-XX:+PrintCompilation最近使用(JDK 8r111)来检查方法编译时,我注意到一个新列,它没有出现在我可以在该主题上找到文档中:

          this column
               |
               |
               v
600    1  s    3       java.util.Hashtable::get (69 bytes)
601    4       3       java.lang.Character::toLowerCase (6 bytes)
601    8       3       java.io.UnixFileSystem::normalize (75 bytes)
602   12       3       java.lang.ThreadLocal::get (38 bytes)
602   14       3       java.lang.ThreadLocal$ThreadLocalMap::getEntry (42 bytes)
602   18       2       java.lang.String::startsWith (72 bytes)
602   10       4       java.lang.String::equals (81 bytes)
602    2 %     4       java.lang.String::hashCode @ 24 (55 bytes)
602   16  s!   3       sun.misc.URLClassPath::getLoader (197 bytes)
603   23     n 0       java.lang.System::arraycopy (native)   (static)
604 …
Run Code Online (Sandbox Code Playgroud)

java optimization jvm-hotspot java-8

8
推荐指数
1
解决办法
762
查看次数

是否保证sizeof(T [N])== N*sizeof(T)?

我一直假定类型的N个元件的阵列的大小T,如通过返回sizeof被保证是确切的N倍sizeof(T).

对这个问题评论让我对此表示怀疑.有信誉的用户声称数组可能包含填充,这会破坏相等性.当然这些平台可能不存在,但它们是否被允许?

如果允许,这将破坏许多常见的习惯用法,例如计算数组所需的存储空间N * sizeof(T),或使用计算数组中元素的数量sizeof(a)/sizeof(a[0]).

c++ arrays sizeof language-lawyer

8
推荐指数
2
解决办法
265
查看次数

可以使用realloc安全地重新分配普通可复制对象的存储吗?

我知道可以安全地将简单的可复制对象复制malloc到适当的存储位置1,并且目标对象将具有与源相同的值.

这也可能realloc吗?也就是说,如果realloc某个存储包含某些类型的对象T,并realloc决定移动并复制该块,新分配的存储中的对象是否完整并且已经开始其生命周期,并且旧存储中的对象的生命周期将是安全的结束了?


1在提出这个问题时,我曾假设"适当的存储位置"包括适当对齐和大小的未初始化存储,但正如MM的答案所述,这并不是标准所支持的.这会让人realloc怀疑,因为它总是复制到未初始化的存储中.

c++ realloc object-lifetime language-lawyer c++11

8
推荐指数
1
解决办法
216
查看次数

优化商店/构建易变的堆栈变量是否合法?

struct在某些情况下,我注意到clang和gcc优化了堆栈中声明的volatile的构造或赋值.例如,以下代码:

struct nonvol2 {
    uint32_t a, b;
};

void volatile_struct2()
{
    volatile nonvol2 temp = {1, 2};
}
Run Code Online (Sandbox Code Playgroud)

编译 clang:

volatile_struct2(): # @volatile_struct2()
  ret
Run Code Online (Sandbox Code Playgroud)

另一方面,gcc不会删除商店,尽管它确实将两个隐含商店优化为一个商店:

volatile_struct2():
        movabs  rax, 8589934593
        mov     QWORD PTR [rsp-8], rax
        ret
Run Code Online (Sandbox Code Playgroud)

奇怪的是,clang不会将易失性存储优化为单个int变量:

void volatile_int() {
    volatile int x = 42;
}
Run Code Online (Sandbox Code Playgroud)

编译为:

volatile_int(): # @volatile_int()
  mov dword ptr [rsp - 4], 1
  ret
Run Code Online (Sandbox Code Playgroud)

此外,没有优化具有1个成员而不是2个成员的结构.

虽然gcc在这种特殊情况下不会删除构造,但在struct成员本身被声明的情况下,它可能甚至更积极的优化volatile,而不是在struct构造点本身:

typedef struct {
    volatile uint32_t a, b;
} vol2;

void volatile_def2()
{ …
Run Code Online (Sandbox Code Playgroud)

c++ optimization x86 volatile language-lawyer

8
推荐指数
1
解决办法
226
查看次数

最快的Linux系统调用

在支持的英特尔x86-64的系统syscallsysret什么是从64位用户代码"最快"的系统调用在香草内核?

特别是,它必须是一个系统调用来执行syscall/ sysretuser < - >内核转换1,但除此之外的工作量最少.它甚至不需要进行系统调用本身:某种类型的早期错误从未调度到内核端的特定调用,这是好的,只要它不会因为这样而走慢路径.

这样的调用可用于估计原始syscallsysret开销,而与呼叫完成的任何工作无关.


1特别是,这排除了似乎是系统调用但在VDSO中实现的内容(例如,clock_gettime)或由运行时缓存(例如getpid).

linux performance x86-64 microbenchmark

8
推荐指数
2
解决办法
1464
查看次数

一系列x86调用/ ret指令是否形成依赖链?

考虑以下x86-64程序集:

inner:
   ...
   ret

outer:
.top:
   call inner
   dec  rdi
   jnz  .top
   ret
Run Code Online (Sandbox Code Playgroud)

该函数outer只是重复call地对函数inner(其主体未显示) - 它可能是空的.

内部的一系列call指令outer和相应的ret指令是否inner在实践中形成一个依赖链(为了估计性能)?

这条链可以形成多种方式.例如,是否ret依赖于前一条call指令的延迟,然后后续call指令是否依赖于ret,形成call -> ret -> call链?或者也许ret是独立但call不是,形成一个call -> call链?如果有链,是通过内存,寄存器,堆栈引擎,返回地址预测器1还是什么?

动机:这个问题起源于对另一个问题的一系列评论,主要是这个评论和早期评论.


1这里的术语可能有些不清楚:堆栈引擎通常被理解为将转换rsp修改指令处理为具有适当偏移的单个访问,因此push rax; push rbx可能会转换为某些临时寄存器,mov [t0], rax; mov [t0 - 8], …

performance x86 assembly

8
推荐指数
1
解决办法
230
查看次数

具有自动存储持续时间的两个不同对象在地址比较下是否相等?

特别是,允许​​不同函数中两个自动变量的地址比较如下:

sink.c

#include <stdio.h>
#include <stdlib.h>

void sink(void *l, void *r) {
    puts(l == r ? "equal" : "not equal");
    exit(0);
}
Run Code Online (Sandbox Code Playgroud)

main.c中

typedef struct { char x[32]; } Foo;

void sink(void *l, void *r);

Foo make(void *p) {
    Foo f2;
    sink(&f2, p);
    return f2;
}

int main() {
    Foo f1 = make(&f1);
}
Run Code Online (Sandbox Code Playgroud)

我希望它可以打印not equalf1f2是不同的对象.使用gcc我得到了not equal,但是使用我的本地版本的clang 3.8 1,它在打印equal时编译为clang -O1 sink.c main.c2.

拆卸makemain …

c x86 clang

8
推荐指数
1
解决办法
148
查看次数

创建一个设置了N个最低有效位的掩码

我想创建一个宏或函数1 mask(n),给定一个数字n返回一个无符号整数,其n最低有效位设置.虽然这似乎应该是一个基本的原语,经过大量讨论的实现有效编译 - 似乎并非如此.

当然,各种实现对于原始整数类型可能具有不同的大小unsigned int,因此,为了具体起见,我们假设我们正在讨论uint64_t具体返回,尽管当然可接受的解决方案对于任何无符号整数类型都有效(具有不同的定义).特别是,当返回的类型等于或小于平台的原始宽度时,解决方案应该是高效的.

重要的是,这必须适用于所有人n[0,64].尤其是mask(0) == 0mask(64) == (uint64_t)-1.许多"明显的"解决方案不适用于这两种情况之一.

最重要的标准是正确性:只有不依赖于未定义行为的正确解决方案才是有趣的.

第二个最重要的标准是性能:理想情况下,成语应该编译成大致最有效的平台特定方式,以便在通用平台上执行此操作.

在性能名称中牺牲简单性的解决方案,例如,在不同平台上使用不同的实现,是很好的.


1最常见的情况是一个函数,但理想情况下它也可以作为宏工作,而不必多次重新评估它的任何参数.

c performance bit-manipulation bitmask

8
推荐指数
2
解决办法
392
查看次数

const_iterator &lt;T&gt;和iterator &lt;const T&gt;有什么区别?

假设我正在实现一个集合,例如std::vector。我需要实现iteratorconst_iterator,但是一旦完成,iteratorconst_iterator不能仅实现为iterator<const T>T集合中的类型在哪里)?

一定有原因为什么它不起作用,因为有上百万个问题有关如何在实现时重用代码iteratorconst_iterator但是没有一个说“仅const T作为类型使用”。

c++ iterator const const-iterator

8
推荐指数
1
解决办法
465
查看次数