gpt4 book ai didi

gcc - 为什么 GCC for Risc-V 调用后生成 nop 指令

转载 作者:行者123 更新时间:2023-12-04 13:54:35 28 4
gpt4 key购买 nike

Risc-V 的 GCC 生成 nop call 之后的说明默认指令:

$ cat test.c
void g();
void f() {
g();
}
$ riscv64-unknown-elf-gcc -S test.c -o -
[...]
f:
addi sp,sp,-16
sd ra,8(sp)
sd s0,0(sp)
addi s0,sp,16
call g
nop #### <-----------here
ld ra,8(sp)
ld s0,0(sp)
addi sp,sp,16
jr ra
.size f, .-f
.ident "GCC: (GNU) 8.3.0"

我希望在针对具有 branch delay slot 的架构时,但我的理解是,Risc-V 不是这样的架构。实际上, nop-O1 编译时消失或更高。

它只是 GCC 中发出 nop 的“错误”吗?作为具有延迟槽的架构的遗留物,或者是否有实际原因 nop操作说明?

最佳答案

不是一个完整的答案,但至少是尝试深入了解 nop 出现的原因。我坚信这是具有延迟槽的架构的错误/遗留物(因为它是在第一个 RTL channel 中添加的 - 扩展)。

在调查中,GCC 有两种类型的 pass,Tree 和 RTL。要查看它们的运行情况,请准备 2 个文件夹,因为会有很多文件,nooptopt并使用 -fdump-tree-all-raw -fdump-rtl-all查看中间结果。树传递的最后阶段给出(noopt 情况):

$ cat noopt/test.c.232t.optimized

;; Function f (f, funcdef_no=0, decl_uid=1549, cgraph_uid=0, symbol_order=0)

f ()
{
<bb 2> :
gimple_call <g, NULL>
gimple_return <NULL NULL>

}

opt 案例( -O1 )的差异可以忽略不计:
$ diff -u noopt/test.c.232t.optimized opt/test.c.232t.optimized 
--- noopt/test.c.232t.optimized 2019-09-03 14:48:02.874071927 +0200
+++ opt/test.c.232t.optimized 2019-09-03 14:48:29.550278667 +0200
@@ -3,7 +3,7 @@

f ()
{
- <bb 2> :
+ <bb 2> [local count: 1073741825]:
gimple_call <g, NULL>
gimple_return <NULL NULL>

RTL 传递(扩展)的第一阶段是不同的:
$ cat noopt/test.c.234r.expand

;; Function f (f, funcdef_no=0, decl_uid=1549, cgraph_uid=0, symbol_order=0)


;; Generating RTL for gimple basic block 2


try_optimize_cfg iteration 1

Merging block 3 into block 2...
Merged blocks 2 and 3.
Merged 2 and 3 without moving.
Merging block 4 into block 2...
Merged blocks 2 and 4.
Merged 2 and 4 without moving.


try_optimize_cfg iteration 2



;;
;; Full RTL generated for this function:
;;
(note 1 0 3 NOTE_INSN_DELETED)
(note 3 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
(call_insn 5 2 8 2 (parallel [
(call (mem:SI (symbol_ref:DI ("g") [flags 0x41] <function_decl 0x7fbc2827a400 g>) [0 g S4 A32])
(const_int 0 [0]))
(clobber (reg:SI 1 ra))
]) "../test.c":3 -1
(nil)
(nil))
(insn 8 5 0 2 (const_int 0 [0]) "../test.c":4 -1
(nil))

-O1的区别只是删除 const_int 0 [0] ,这最终会导致 nop :
$ diff -u noopt/test.c.234r.expand opt/test.c.234r.expand 
--- noopt/test.c.234r.expand 2019-09-03 14:48:02.874071927 +0200
+++ opt/test.c.234r.expand 2019-09-03 14:48:29.550278667 +0200
@@ -25,12 +25,10 @@
(note 1 0 3 NOTE_INSN_DELETED)
(note 3 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
(note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
-(call_insn 5 2 8 2 (parallel [
- (call (mem:SI (symbol_ref:DI ("g") [flags 0x41] <function_decl 0x7fbc2827a400 g>) [0 g S4 A32])
+(call_insn 5 2 0 2 (parallel [
+ (call (mem:SI (symbol_ref:DI ("g") [flags 0x41] <function_decl 0x7f0bdec1f400 g>) [0 g S4 A32])
(const_int 0 [0]))
(clobber (reg:SI 1 ra))
]) "../test.c":3 -1
(nil)
(nil))
-(insn 8 5 0 2 (const_int 0 [0]) "../test.c":4 -1
- (nil))

关于gcc - 为什么 GCC for Risc-V 调用后生成 nop 指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57695031/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com