问题标签 [register-allocation]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
195 浏览

assembly - 为什么编译器在寄存器分配中构造图?

我一直在研究寄存器分配,想知道为什么他们都从实时寄存器列表中构建图表,而可能有更好的方法来做到这一点。我认为他们可以做到的方式是,当实时寄存器超过可用寄存器的数量时,寄存器可能会溢出。这是一个示例(伪组装):

我已经在汇编代码中列出了实时寄存器。现在,所有的教程和文本都从这里构建干扰图,等等。但不是那样(正如我上面提到的),他们可以查看活动寄存器。例如,如果这是一台单1寄存器机器,那么当活动寄存器为 时{t0, t1},我们将不得不选择一个寄存器进行溢出。我觉得这比构建图表和做所有其他事情来检查我们是否必须溢出寄存器要简单得多。我知道无知不是全球性的(一定有人想到了这一点并认为它不合适),所以我在这里看不到什么?

0 投票
2 回答
284 浏览

x86 - 寄存器分配 --- 如何利用和溢出调用者保存的寄存器

我了解到,如果caller saved registers (rax rdx rcx rsi rdi r8 r9 r10 r11)被调用者使用了任何一个,那么它必须在调用者指令之前保存并call在调用者指令之后恢复。

通过下面的例子,

笔记

  1. 变量a - g应使用所有callee saved registers (rbp rsp rbx r12 r13 r14 r15). 而且我们不能同时使用rbprsp,因为必须使用其中任何一个来寻址堆栈内存。

  2. read来自print一些外部编译单元。main因此,当我们编译当前编译单元时,特别是在为函数分配寄存器期间,我们并不真正了解它们的调用者保存寄存器的使用情况。

godbolt中,-O3它编译为以下

笔记

  1. 变量a溢出到12(%rsp).

  2. 我们不需要溢出任何东西,caller saved registers因为它们根本没有被使用,结果证明在这里更有效。

我的问题

  1. caller saved registers如果我们不使用它们,看起来我们真的不需要处理溢出的问题。因此,我们什么时候应该使用caller saved registers?

  2. 对于像这样的被调用者,read并且print由于我们不知道他们的寄存器使用情况,我们应该如何为caller saved registers?

谢谢

0 投票
0 回答
200 浏览

assembly - “fomit-frame-pointer”有什么好处?

“-fomit-frame-pointer”表示我们不必 pushq %rbp 和移动 %rsp, %rbp 的方式;我们只需要更改 %rsp 的值。据我认为,处理基本指针的堆栈帧和没有它的堆栈帧在好处方面没有差异。你能解释一下“不处理 %ebp 的堆栈帧”有什么好处吗?

0 投票
1 回答
117 浏览

javascript - 如何使用最少的临时变量将 JS 代码解析为每行一个操作?

说我有这个代码

我正在使用meriyah来解析 AST。但是一般来说,由于这涉及到相当多的内容,如果要将每个操作放在一行上,您将如何计算需要多少临时变量?

所以循环的第一行:

它会像这样:

变成这样的东西

但更好的是:

所以我们尽量减少我们创建的变量数量。您如何做到这一点,甚至以编程方式思考它?

我尝试的代码行的 AST 在这里:

您将如何以通用方式处理这种特定情况,以便可以将其推广并在其他地方使用(需要更多工作)?

0 投票
1 回答
209 浏览

compiler-construction - 外循环的寄存器分配

我正在阅读红龙书,在外循环的寄存器分配部分中,我遇到了以下对我来说不太清楚的陈述。

如果外循环L1包含内循环L2,则分配寄存器的名称L2不需要分配寄存器L1 - L2

他们想说什么?他们是在谈论在两者中都使用的变量吗L1L2并且这些名称是在L2. 我不太明白文中的情况。

谁能向我解释一个可能的例子?

框图

0 投票
1 回答
76 浏览

c - 为什么 C 中的这个堆栈变量不在寄存器中?

我对如何执行缓冲区溢出攻击以及寄存器分配在编译器中的工作方式有合理的理解。

让我感到困惑的是,为什么 C 程序的堆栈上有这么多东西。考虑这个易受攻击的程序:

让我们运行它

好的,所以 str 按原样被覆盖int a。但为什么int a甚至在堆栈上?做类似(x86 asm)之类的事情不是最简单的吗

现在我们的内存流量减少了,因为堆栈上没有任何东西,代码也少了很多。

tl;博士为什么int a在堆栈上?

0 投票
2 回答
329 浏览

assembly - 影响 GCC 内联汇编中内存操作数寻址模式的早期破坏行为不正确的具体示例?

以下摘自GCC 手册的 Extended Asm 文档asm,关于使用关键字在 C 中嵌入汇编指令:

如果一个输出参数 ( a ) 允许寄存器约束,而另一个输出参数 ( b ) 允许内存约束,则会出现同样的问题。GCC 生成的用于访问 b中的内存地址的代码可以包含可能由a共享的寄存器,并且 GCC 将这些寄存器视为 asm 的输入。如上所述,GCC 假设在写入任何输出之前消耗了此类输入寄存器。如果 asm 语句在使用 b 之前写入 a,这种假设可能会导致不正确的行为。结合'&' 在a上带有寄存器约束的修饰符确保修改a不会影响b引用的地址. 否则,如果在使用b之前修改a ,则b的位置未定义 。

a斜体句子表示如果 asm 语句在使用之前写入,则可能存在“不正确的行为” b

我想不通这种“不正确的行为”是如何发生的,所以我希望有一个具体的 asm 代码示例来演示“不正确的行为”,以便我对这一段有深刻的理解。

当两个这样的asm代码并行运行时,我可以感知到问题,但是上面这段没有提到多处理场景。

如果我们只有一个 CPU 一个核心,能否请您显示一个可能会产生这种不正确行为的 asm 代码,即修改a会影响所引用的地址,b从而导致位置b未定义。

我唯一熟悉的汇编语言是 Intel x86 汇编,所以请使示例针对该平台。

0 投票
0 回答
209 浏览

timer - 如何在 stm32 微控制器上读取 TIMx CNT 寄存器:等号问题

我一直在玩核板 f411RE,特别是通用定时器 TIM9、TIM10、TIM11。我想使用 TIM10(16 位定时器)通过启用它并让它运行来测量时间,然后使用存储在 TIM10->CNT 中的值通过使用 if 条件来做出决定(是否打开 LED) .

当我使用 <,>, <=, >= 运算符将计数器 (TIM10->CNT) 的值与任何其他数字进行比较时,例如:

甚至:

一切都按我预期的那样工作,我的功能按照我想要的方式运行。

每当我尝试使用等号将定时器计数器寄存器与不为零的数字(表示为“任何值”)进行比较时,就会出现问题,如下所示:

正如上面的评论中所表达的,每当我明确使用等号 ( == ) 且数字不为零时,由该条件定义的块不会被执行。似乎我可以使用和比较 TIM10 计数器的唯一方法是使用不等式运算符(>、<、=>、>=)或将其显式与零进行比较。

到目前为止,我还没有发布实际代码,因为这是唯一困扰我的部分,所有其他组件都像魅力一样工作。无论如何,这是我的代码的一瞥:

伪代码:

--- 程序开始 ---

--- TIM10 -> CNT 初始化为零 ---

---while循环开始---

---读取 TIM10->CNT 寄存器并将其值存储在变量中---

---按下按钮启用 TIM10---

---如果在计数器已经运行时再次按下按钮,则停止计时器并将其值存储在一个变量中以用于下一个函数---

---根据经过时间的值打开或关闭 LED 的功能 TIM10 -> CNT ---

实际的 C++ 代码是:

关于为什么我不能将“==”运算符与定时器计数器寄存器一起使用的帮助和评论将不胜感激。

pd:实际上,任何评论都会受到赞赏。

pd2:有人可能会认为延迟在某种程度上干扰了最后一个 if 条件,但实际上放在那里的指令并不重要,由于“==”的使用,该块将不会执行

pd3:正如我之前所说,问题似乎是明确使用“==”,因为我已经尝试了代码的所有其他部分并且它们完美地工作(时钟配置,定时器配置,GPIO配置以及写入和读取每个相应引脚的方法)

0 投票
0 回答
67 浏览

assembly - 为什么编译器将结果存储到单个寄存器而不是在连续存储到内存之前没有很多不同的寄存器?

例如,看看这个由gcc.

它可以满足我的要求,但我注意到的一件事是,结果总是先存储到内存中,ymm0然后再存储到内存中。我的意思是,我知道vpand不能直接对内存进行操作,但是这不是更有效吗?

这样一来,我认为可以并行完成更多的操作,因为没有通过 ymm0.

它使用了更多的寄存器,但是这个函数无论如何都使用了全部 16 ymms,并且在这部分之后,新的值被加载到每个寄存器中,所以使用更多的寄存器并不是什么问题。

我查了一下clang,它产生了相同的代码,只是寄存器号不同。

如果我使用第二种寄存器分配方式直接在汇编中编写,我可以期待明显的加速吗?

我实际上可以测试并查看,但是直接在汇编中编写对我来说并不是一件容易的事,还有其他部分需要处理,所以我问这个问题是为了首先更好地了解使用不同的寄存器进行连续内存存储是否可以实际提高性能。

0 投票
0 回答
5 浏览

pointers - 我为 HTC 中使用的 pic 文件寄存器名称使用什么 CCS 代码

感谢您接受我。

我将 ccs 编译器用于图片,并希望对数据表中显示的寄存器名称保持“真实”。例如 12f675 数据表中显示的 TRISIO、GPIO 和 ANSEL,这就是我所做的。

在此处输入图像描述

这工作得很好但是,它使用内存,在你知道它之前 50% 的程序内存已经消失了。必须有一种更简单的方法通过代码 preproc 指令来做到这一点。请注意我已经好几年没用过c了,至少18年前在大学里,所以我正在翻阅我以前的大学教科书。我知道 CCS 专家会这样做,但是如何做呢?还有另一种方法吗?下面是工作代码的图片。 在此处输入图像描述