LLVM inline assembly 之 asm goto

clang 的asm goto是从gcc而来的,它意在实现从inline asm 内部 跳转 到inline asm 外部label的功能。

用例

  1 int test1(int cond) {
  2   asm volatile goto("testl %0, %0; jne %l1;" :: "r"(cond)::label_true, loop);
  //                            ^0: cond     ^ 1: label_true  ^ 注意 多了个 “:”
  // asm.fallthrough:
  3   return 0;
  4 loop:
  5   return 1;
  6 label_true:
  7   return 2;
  8 }
  9
 10 int main(){
 11   int ret = test1(1);
 12   return ret;
 13 }

上面的例子(行2) 实际上是实现 从inline asm内部jump到 label_true(或fallthrough)的功能。
注意
asm goto 与普通的inline asm相比,主要多了一个“:”。所以
asm goto其实就是在outputs,inputs,registers-modified之外提供了嵌入式汇编的第4个“:”,后面可以跟一系列的c语言的label,然后你可以在嵌入式汇编中go to到这些label中一个。

IR
生成的IR如下:
在IR中 callbr 实现且仅用于实现 asm goto

clang -target x86_64-pc-linux-gnu -O0 -emit-llvm -S

  7 define dso_local i32 @test1(i32 noundef %cond) #0 {
  8 entry:
  9   %retval = alloca i32, align 4
 10   %cond.addr = alloca i32, align 4
 11   store i32 %cond, i32* %cond.addr, align 4
 12   %0 = load i32, i32* %cond.addr, align 4
 13   callbr void asm sideeffect "testl $0, $0; jne ${1:l};",
                                 "r,!i,!i,~{dirflag},~{fpsr},~{flags}"(i32 %0) #1
 14           to label %asm.fallthrough [label %label_true, label %loop], !srcloc !4
 15
 16 asm.fallthrough:                                  ; preds = %entry
 17   store i32 0, i32* %retval, align 4
 18   br label %return
 19
 20 loop:                                             ; preds = %entry
 21   store i32 1, i32* %retval, align 4
 22   br label %return
 23
 24 label_true:                                       ; preds = %entry
 25   store i32 2, i32* %retval, align 4
 26   br label %return
 27
 28 return:                                           ; preds = %label_true, %loop, %asm.fallthrough
 29   %1 = load i32, i32* %retval, align 4
 30   ret i32 %1
 31 }

clang -target x86_64-pc-linux-gnu -O2 -emit-llvm -S
由于loop不会被jump到,所以应该可以被优化,但实际-O2 也没有优化掉:
(不过这是个很好的 PHI多入口例子,见IR 行19)

  7 define dso_local i32 @test1(i32 noundef %cond) local_unnamed_addr #0 {
  8 entry:
  9   callbr void asm sideeffect "testl $0, $0; jne ${1:l};", "r,!i,!i,~{dirflag},~{fpsr},~{flags}"(i32 %cond) #1
 10           to label %return [label %label_true, label %loop], !srcloc !3
 11
 12 loop:                                             ; preds = %entry
 13   br label %return
 14
 15 label_true:                                       ; preds = %entry
 16   br label %return
 17
 18 return:                                           ; preds = %entry, %label_true, %loop
 19   %retval.0 = phi i32 [ 1, %loop ], [ 2, %label_true ], [ 0, %entry ]
 20   ret i32 %retval.0
 21 }

汇编
生成的汇编如下,由于代码不多,我们直接用 O0 生成汇编
clang -target x86_64-pc-linux-gnu -O0 -S

  6 test1:                                  # @test1
  7         .cfi_startproc
  8 # %bb.0:                                # %entry
  9         pushq   %rbp
 10         .cfi_def_cfa_offset 16
 11         .cfi_offset %rbp, -16
 12         movq    %rsp, %rbp
 13         .cfi_def_cfa_register %rbp
 14         movl    %edi, -8(%rbp)
 15         movl    -8(%rbp), %eax
 16         #APP
 17         testl   %eax, %eax
 18         jne     .Ltmp0
 19
 20         #NO_APP
 21         jmp     .LBB0_1
 22 .LBB0_1:                                # %asm.fallthrough
 23         movl    $0, -4(%rbp)
 24         jmp     .LBB0_4
 25 .Ltmp1:                                 # Block address taken
 26 .LBB0_2:                                # %loop
 27         movl    $1, -4(%rbp)
 28         jmp     .LBB0_4
 29 .Ltmp0:                                 # Block address taken
 30 .LBB0_3:                                # %label_true
 31         movl    $2, -4(%rbp)
 32 .LBB0_4:                                # %return
 33         movl    -4(%rbp), %eax
 34         popq    %rbp
 35         .cfi_def_cfa %rsp, 8
 36         retq

完 : )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值