标签: llvm-codegen

LLVM的整数类型

LLVM语言将整数类型指定为iN,其中N是整数的位宽,范围从1到2 ^ 23-1(根据:http://llvm.org/docs/LangRef.html#integer-型)

我有两个问题:

  1. 将C程序编译为LLVM IR级别时,可以将哪些类型降低到i1,i2,i3等?看起来类型i8,i16,i32,i64必须足够,所以我想知道所有其他近800万个整数类型是什么.

  2. 将有符号和无符号整数类型都降低到i32是真的吗?是什么原因,为什么它不适用于32位浮点数(在LLVM中表示为f32)?

types llvm llvm-codegen

17
推荐指数
1
解决办法
7275
查看次数

如何用"ffast-math"编译?

我正在尝试对一些Rust代码进行基准测试,但我无法弄清楚如何设置"ffast-math"选项.

% rustc -C opt-level=3 -C llvm-args='-enable-unsafe-fp-math' unrolled.rs
rustc: Unknown command line argument '-enable-unsafe-fp-math'.  Try: 'rustc -help'
rustc: Did you mean '-enable-load-pre'?
Run Code Online (Sandbox Code Playgroud)

llvm-args='-ffast-math'并且llvm-args='-fast'也没有工作.我应该使用什么旗帜?

llvm rust fast-math llvm-codegen

15
推荐指数
2
解决办法
1058
查看次数

为什么这段代码比同等的C++/Clang生成更多的程序集?

我写了一个简单的C++函数来检查编译器优化:

bool f1(bool a, bool b) {
    return !a || (a && b);
}
Run Code Online (Sandbox Code Playgroud)

之后我检查了Rust中的等价物:

fn f1(a: bool, b: bool) -> bool {
    !a || (a && b)
}
Run Code Online (Sandbox Code Playgroud)

我用godbolt检查汇编器输出.

C++代码的结果(由clang -O3标志编译)如下:

f1(bool, bool):                                # @f1(bool, bool)
    xor     dil, 1
    or      dil, sil
    mov     eax, edi
    ret
Run Code Online (Sandbox Code Playgroud)

Rust等效的结果要长得多:

example::f1:
  push rbp
  mov rbp, rsp
  mov al, sil
  mov cl, dil
  mov dl, cl
  xor dl, -1
  test dl, 1
  mov byte ptr [rbp - 3], al
  mov byte …
Run Code Online (Sandbox Code Playgroud)

optimization rust llvm-codegen

15
推荐指数
2
解决办法
2145
查看次数

为什么 LLVM 似乎忽略了 Rust 的内在假设?

LLVM 似乎忽略core::intrinsics::assume(..)调用。它们最终会出现在字节码中,但不会更改生成的机器码。例如,采用以下(无意义的)代码:

pub fn one(xs: &mut Vec<i32>) {
    if let Some(x) = xs.pop() {
        xs.push(x);
    }
}
Run Code Online (Sandbox Code Playgroud)

这编译成一大堆程序集:

example::one:
        push    rbp
        push    r15
        push    r14
        push    r12
        push    rbx
        mov     rbx, qword ptr [rdi + 16]
        test    rbx, rbx
        je      .LBB0_9
        mov     r14, rdi
        lea     rsi, [rbx - 1]
        mov     qword ptr [rdi + 16], rsi
        mov     rdi, qword ptr [rdi]
        mov     ebp, dword ptr [rdi + 4*rbx - 4]
        cmp     rsi, qword ptr [r14 + 8]
        jne …
Run Code Online (Sandbox Code Playgroud)

performance llvm rust llvm-codegen

12
推荐指数
1
解决办法
324
查看次数

C LLI与LLVM

我有一个用LLVM编写的编译器,我正在寻求提高我的ABI合规性.例如,我发现很难在Windows x86或Linux上找到C ABI的规范文档.我发现的那些用RAX/EAX /等​​解释它,而不是我可以使用的IR术语.

到目前为止,我认为我已经认为LLVM无形地对待聚合 - 也就是说,它将每个成员视为一个独特的参数.因此,例如,在Windows x64上,如果我想处理像文档所说的聚合,我将需要强制转换为该大小的单个整数,如8,16,32或64位.否则,通过指针传递.

对于Windows x86,似乎__cdecl和__stdcall不需要我的任何操作,因为所有参数都在堆栈上传递.__fastcall说前两个32位或更小的参数是寄存器传递的,所以我需要强制大小或更小的聚合.__thiscall在寄存器中传递它,其余的在堆栈中传递,所以看起来我不需要在这里执行任何调整.

对于__vectorcall,通过整数强制传递不超过sizeof(void*)的聚合.对于其他聚合,如果它们是HVAs,则按值传递; else在x86上传递值或在x64上传递指针.

这似乎很简单(相对而言),但是LLVM文档sext清楚地表明"这表明代码生成器应该将参数或返回值符号扩展到目标的ABI所需的范围(通常是32位)由调用者(对于参数)或被调用者(对于返回值)." x86调用约定的Microsoft页面没有提及任何扩展到任何宽度的内容.

我观察到Clang生成的LLVM IR byval在Windows上生成属性.我从上面收集到的理解从未要求byval使用.

如何将各种平台C ABI降低到LLVM IR?

c abi llvm llvm-codegen

11
推荐指数
2
解决办法
1598
查看次数

为什么Rust优化器不会删除那些无用的指令(在Godbolt Compiler Explorer上测试)?

我想看看一个小的Rust函数的程序集输出:

pub fn double(n: u8) -> u8 {
    n + n
}
Run Code Online (Sandbox Code Playgroud)

我使用Godbolt Compiler Explorer来生成和查看程序集(-O当然还有标志).它显示了这个输出:

example::double:
    push    rbp
    mov     rbp, rsp
    add     dil, dil
    mov     eax, edi
    pop     rbp
    ret
Run Code Online (Sandbox Code Playgroud)

现在我有点困惑,因为有这似乎并没有做任何有用的几个指令:push rbp,mov rbp, rsppop rbp.根据我的理解,我认为单独执行这三个指令没有任何副作用.那么为什么Rust优化器不会删除那些无用的指令呢?


为了比较,我还测试了一个C++版本:

unsigned char doubleN(unsigned char n) {
    return n + n;
}
Run Code Online (Sandbox Code Playgroud)

程序集输出(带-O标志):

doubleN(unsigned char): # @doubleN(unsigned char)
    add dil, dil
    mov eax, edi
    ret
Run Code Online (Sandbox Code Playgroud)

事实上,这里缺少上面那些"无用的"指令,正如我对优化输出所期望的那样.

assembly x86-64 rust llvm-codegen

11
推荐指数
1
解决办法
518
查看次数

为什么空函数不会作为LLVM IR中的死代码删除?

从这个简单的C程序开始:

void nothing(void) {}
int main() {
  int i;
  for (i = 0; i < 10; ++i) {
    nothing();
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的传递输出如下:
注意:IR语句为绿色.

; Function Attrs: nounwind readnone ssp uwtable
define void @nothing() #0 {
entry:
  ret void
}

; Function Attrs: nounwind readnone ssp uwtable
define i32 @main() #0 {
entry:
  ret i32 0
}
Run Code Online (Sandbox Code Playgroud)

IR

问:使用O3其认为是最高级别的优化,为什么没有nothing功能尚未消除的死代码?

c clang llvm-clang llvm-ir llvm-codegen

10
推荐指数
1
解决办法
579
查看次数

我可以强制Rust不优化单个函数吗?

我有一个功能,Rust的/ LLVM的优化失败并导致恐慌(在发布版本中),而未优化的代码(调试版本)工作正常.如果我比较生成的汇编代码,我甚至无法理解优化器试图完成的任务.(原因可能是这个函数使用内联汇编程序.)

有没有办法告诉Rust在优化过程中单独保留某些功能,还是必须关闭所有优化?

这是具体功能:

#[naked]
pub extern "C" fn dispatch_svc(){
    Cpu::save_context();
    let mut nr: u32 = 0;
    unsafe {
        asm!("ldr r0, [lr, #-4]
              bic $0, r0, #0xff000000":"=r"(nr)::"r0":"volatile")
    };
    swi_service_routine(nr);
    Cpu::restore_context_and_return();
}
Run Code Online (Sandbox Code Playgroud)

optimization rust llvm-codegen

10
推荐指数
2
解决办法
1395
查看次数

为什么Rust编译器不能优化Box :: downcast的Err arm?

我有一个Box<dyn Any>,我知道基础类型,所以我想在Box::downcast()()中优化测试.

首先我试过std::hint::unreachable_unchecked():

pub unsafe fn downcast() -> Box<i32> {
    let value = any();
    if let Ok(value) = value.downcast() {
        value
    } else {
        std::hint::unreachable_unchecked()
    }
}
Run Code Online (Sandbox Code Playgroud)

pub unsafe fn downcast() -> Box<i32> {
    any().downcast().map_err(|_| std::hint::unreachable_unchecked()).unwrap()
}
Run Code Online (Sandbox Code Playgroud)

rustc -C opt-level=3两个结果在该(40行中省略):

example::downcast:
        push    rbx
        sub     rsp, 16
        call    any@PLT
        mov     rbx, rax
        mov     qword ptr [rsp], rax
        mov     qword ptr [rsp + 8], rdx
        mov     rdi, rax
        call    qword ptr …
Run Code Online (Sandbox Code Playgroud)

optimization assembly compiler-optimization rust llvm-codegen

10
推荐指数
1
解决办法
279
查看次数

编译器(特别是rustc)是否可以真正简化三角形求和以避免循环?怎么样?

在Blandy和Orendorff 的《Programming Rust》的第322页上是这样的说法:

...铁锈...认识到,有一种简单的方法可以将数字从1 n求和:总和始终等于n * (n+1) / 2

这当然是相当众所周知的等效项,但是编译器如何识别它?我猜这是在LLVM优化过程中进行的,但是LLVM是否以某种方式从第一原理中推导了等效性,或者它只是具有一些可以简化为算术运算的“公共循环计算”?

compiler-construction compiler-optimization rust llvm-codegen

10
推荐指数
1
解决办法
136
查看次数