通用操作码

注意

本文档尚未完全考虑向量。许多标量/整数/浮点运算也可以使用向量。

常量

G_IMPLICIT_DEF

一个未定义的值。

%0:_(s32) = G_IMPLICIT_DEF

G_CONSTANT

一个整数常量。

%0:_(s32) = G_CONSTANT i32 1

G_FCONSTANT

一个浮点常量。

%0:_(s32) = G_FCONSTANT float 1.0

G_FRAME_INDEX

栈帧中对象的地址。

%1:_(p0) = G_FRAME_INDEX %stack.0.ptr0

G_GLOBAL_VALUE

全局值的地址。

%0(p0) = G_GLOBAL_VALUE @var_local

G_PTRAUTH_GLOBAL_VALUE

全局值的签名地址。操作数:要签名的地址(指针),密钥(32 位立即数),用于地址区分的地址(如果不需要则为零)和一个额外的鉴别器(64 位立即数)。

%0:_(p0) = G_PTRAUTH_GLOBAL_VALUE %1:_(p0), s32, %2:_(p0), s64

G_BLOCK_ADDR

基本块的地址。

%0:_(p0) = G_BLOCK_ADDR blockaddress(@test_blockaddress, %ir-block.block)

G_CONSTANT_POOL

常量池中对象的地址。

%0:_(p0) = G_CONSTANT_POOL %const.0

整数扩展和截断

G_ANYEXT

扩展操作的底层标量类型,将高位保持未指定状态。

%1:_(s32) = G_ANYEXT %0:_(s16)

G_SEXT

符号扩展操作的底层标量类型,将符号位复制到新创建的空间中。

%1:_(s32) = G_SEXT %0:_(s16)

G_SEXT_INREG

从任意位位置进行符号扩展值,将符号位复制到其上方的所有位。这等效于具有适当移位量的 shl + ashr 对。 $sz 是一个立即数 (MachineOperand::isImm() 返回 true),以允许目标具有一些合法的位宽和其他降低的位宽。如果目标具有比构成移位更便宜的符号扩展指令,则此操作码特别有用,因为优化器可以决定是保留 G_SEXT_INREG 还是降低它并优化各个移位。

%1:_(s32) = G_SEXT_INREG %0:_(s32), 16

G_ZEXT

零扩展操作的底层标量类型,将零位放入新创建的空间中。

%1:_(s32) = G_ZEXT %0:_(s16)

G_TRUNC

截断操作的底层标量类型。对于标量类型,这等效于 G_EXTRACT,但对向量按元素执行操作。

%1:_(s16) = G_TRUNC %0:_(s32)

类型转换

G_INTTOPTR

将整数转换为指针。

%1:_(p0) = G_INTTOPTR %0:_(s32)

G_PTRTOINT

将指针转换为整数。

%1:_(s32) = G_PTRTOINT %0:_(p0)

G_BITCAST

将值重新解释为新类型。这通常在不更改任何位的情况下完成,但由于 LLVM-IR Bitcast 指令 定义中的细微之处,情况并非总是如此。允许在大小相同但地址空间不同的指针之间进行位转换。

%1:_(s64) = G_BITCAST %0:_(<2 x s32>)

G_ADDRSPACE_CAST

将指向一个地址空间的指针转换为指向另一个地址空间的指针。

%1:_(p1) = G_ADDRSPACE_CAST %0:_(p0)

注意

‘addrspacecast .. to’ 指令 没有提及如果转换无效(即如果地址空间不相交)会发生什么。

标量运算

G_EXTRACT

从索引给定的块开始,提取指定大小的寄存器。在选择了寄存器组之后,这几乎肯定会映射到子寄存器 COPY。

%3:_(s32) = G_EXTRACT %2:_(s64), 32

G_INSERT

在指定的位索引处将较小的寄存器插入到较大的寄存器中。

%2:_(s64) = G_INSERT %0:(_s64), %1:_(s32), 0

G_MERGE_VALUES

将多个相同大小的寄存器连接成一个更宽的寄存器。输入操作数始终从最低位到最高位排序

%0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
                          %bits_16_23:(s8), %bits_24_31:(s8)

G_UNMERGE_VALUES

从索引给定的块开始,提取多个指定大小的寄存器。在选择了寄存器组之后,这几乎肯定会映射到子寄存器 COPY。输出操作数始终从最低位到最高位排序

%bits_0_7:(s8), %bits_8_15:(s8),
    %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)

G_BSWAP

反转标量中字节的顺序。

%1:_(s32) = G_BSWAP %0:_(s32)

G_BITREVERSE

反转标量中位的顺序。

%1:_(s32) = G_BITREVERSE %0:_(s32)

G_SBFX, G_UBFX

从寄存器中提取一定范围的位。

源操作数是寄存器,如下所示

  • 提取的最低有效位

  • 提取的宽度

最低有效位 (lsb) 和宽度操作数的范围是

0 <= lsb < lsb + width <= source bitwidth, where all values are unsigned

G_SBFX 符号扩展结果,而 G_UBFX 零扩展结果。

; Extract 5 bits starting at bit 1 from %x and store them in %a.
; Sign-extend the result.
;
; Example:
; %x = 0...0000[10110]1 ---> %a = 1...111111[10110]
%lsb_one = G_CONSTANT i32 1
%width_five = G_CONSTANT i32 5
%a:_(s32) = G_SBFX %x, %lsb_one, %width_five

; Extract 3 bits starting at bit 2 from %x and store them in %b. Zero-extend
; the result.
;
; Example:
; %x = 1...11111[100]11 ---> %b = 0...00000[100]
%lsb_two = G_CONSTANT i32 2
%width_three = G_CONSTANT i32 3
%b:_(s32) = G_UBFX %x, %lsb_two, %width_three

整数运算

G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SDIV, G_UDIV, G_SREM, G_UREM

这些操作分别对标量执行各自的整数算术运算。

%dst:_(s32) = G_ADD %src0:_(s32), %src1:_(s32)

上面的示例将 %src1 添加到 %src0,并将结果存储在 %dst 中。

G_SDIVREM, G_UDIVREM

执行整数除法和余数运算,从而产生两个结果。

%div:_(s32), %rem:_(s32) = G_SDIVREM %0:_(s32), %1:_(s32)

G_SADDSAT, G_UADDSAT, G_SSUBSAT, G_USUBSAT, G_SSHLSAT, G_USHLSAT

带饱和的符号和无符号加法、减法和左移。

%2:_(s32) = G_SADDSAT %0:_(s32), %1:_(s32)

G_SHL, G_LSHR, G_ASHR

将标量的位向左或向右移动,插入零(G_ASHR 为符号位)。

G_ROTR, G_ROTL

向右 (G_ROTR) 或向左 (G_ROTL) 旋转位。

G_ICMP

执行整数比较,产生非零值(真)或零值(假)。真值是 1、~0U 还是其他非零值取决于目标。

G_SCMP

执行有符号 3 向整数比较,产生 -1(较小)、0(相等)或 1(较大)。

%5:_(s32) = G_SCMP %6, %2

G_UCMP

执行无符号 3 向整数比较,产生 -1(较小)、0(相等)或 1(较大)。

%7:_(s32) = G_UCMP %2, %6

G_SELECT

根据零/非零值在两个值之间进行选择。

%5:_(s32) = G_SELECT %4(s1), %6, %2

G_PTR_ADD

将可寻址单元中的标量偏移量添加到指针。可寻址单元通常是字节,但这可能因目标而异。

%1:_(p0) = G_PTR_ADD %0:_(p0), %1:_(s32)

注意

目前没有树内目标将此用于可寻址单元不等于 8 位的情况。

G_PTRMASK

将指针的任意位掩码清零。掩码类型必须是整数,并且所有操作数的向量元素数量必须匹配。这对应于 i_intr_llvm_ptrmask

%2:_(p0) = G_PTRMASK %0, %1

G_SMIN, G_SMAX, G_UMIN, G_UMAX

取两个值的最小值/最大值。

%5:_(s32) = G_SMIN %6, %2

G_ABS

取有符号整数的绝对值。最小负值(例如 8 位值 0x80)的绝对值定义为其自身。

%1:_(s32) = G_ABS %0

G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_SMULO, G_UMULO

执行请求的算术运算,并在正常结果之外产生一个进位输出。

%3:_(s32), %4:_(s1) = G_UADDO %0, %1

G_UADDE, G_SADDE, G_USUBE, G_SSUBE

执行请求的算术运算,并在正常输入之外消耗一个进位输入。还在正常结果之外产生一个进位输出。

%4:_(s32), %5:_(s1) = G_UADDE %0, %1, %3:_(s1)

G_UMULH, G_SMULH

将两个数字乘以传入位宽的两倍(无符号或有符号),并返回结果的高半部分。

%3:_(s32) = G_UMULH %0, %1

G_CTLZ, G_CTTZ, G_CTPOP

计数前导零、尾随零或设置位的数量。

%2:_(s33) = G_CTLZ_ZERO_UNDEF %1
%2:_(s33) = G_CTTZ_ZERO_UNDEF %1
%2:_(s33) = G_CTPOP %1

G_CTLZ_ZERO_UNDEF, G_CTTZ_ZERO_UNDEF

计数前导零或尾随零。如果值为零,则结果未定义。

%2:_(s33) = G_CTLZ_ZERO_UNDEF %1
%2:_(s33) = G_CTTZ_ZERO_UNDEF %1

G_ABDS, G_ABDU

计算绝对差值(有符号和无符号),例如 abs(x-y)。

%0:_(s33) = G_ABDS %2, %3
%1:_(s33) = G_ABDU %4, %5

浮点运算

G_FCMP

执行浮点比较,产生非零值(真)或零值(假)。真值是 1、~0U 还是其他非零值取决于目标。

G_FNEG

浮点取反。

G_FPEXT

将浮点值转换为更大的类型。

G_FPTRUNC

将浮点值转换为更窄的类型。

G_FPTOSI, G_FPTOUI, G_SITOFP, G_UITOFP

在整数和浮点之间进行转换。

G_FPTOSI_SAT, G_FPTOUI_SAT

在整数和浮点之间进行饱和转换。

G_FABS

取浮点值的绝对值。

G_FCOPYSIGN

复制第一个操作数的值,并将符号位替换为第二个操作数的符号位。

G_FCANONICALIZE

请参阅 ‘llvm.canonicalize.*’ 内在函数

G_IS_FPCLASS

测试第一个操作数(必须是浮点标量或向量)是否具有第二个操作数指定的浮点类。返回非零值(真)或零值(假)。真值是 1、~0U 还是其他非零值取决于目标。如果第一个操作数是向量,则返回值是相同长度的向量。

G_FMINNUM

对两个值执行浮点最小值运算。

在单个输入为 NaN(信令或静默)的情况下,将返回非 NaN 输入。

(FMINNUM 0.0, -0.0) 的返回值可以是 0.0 或 -0.0。

G_FMAXNUM

对两个值执行浮点最大值运算。

在单个输入为 NaN(信令或静默)的情况下,将返回非 NaN 输入。

(FMAXNUM 0.0, -0.0) 的返回值可以是 0.0 或 -0.0。

G_FMINNUM_IEEE

按照 IEEE-754 定义对两个值执行浮点最小值运算。这与 FMINNUM 在处理信令 NaN 方面有所不同。

如果一个输入是信令 NaN,则返回静默 NaN。这与 IEEE-754 2008 的 minnum/maxnum 对于信令 NaN(与 2019 年不同)相匹配。

这些将 -0 视为小于 +0 的有序值,与 IEEE-754 2019 的 minimumNumber/maximumNumber 的行为相匹配(在 2008 年未指定)。

G_FMAXNUM_IEEE

按照 IEEE-754 定义对两个值执行浮点最大值运算。这与 FMAXNUM 在处理信令 NaN 方面有所不同。

如果一个输入是信令 NaN,则返回静默 NaN。这与 IEEE-754 2008 的 minnum/maxnum 对于信令 NaN(与 2019 年不同)相匹配。

这些将 -0 视为小于 +0 的有序值,与 IEEE-754 2019 的 minimumNumber/maximumNumber 的行为相匹配(在 2008 年未指定)。

G_FMINIMUM

NaN 传播最小值,也将 -0.0 视为小于 0.0。虽然 FMINNUM_IEEE 遵循 IEEE 754-2008 语义,但 FMINIMUM 遵循 IEEE 754-2019 语义。

G_FMAXIMUM

NaN 传播最大值,也将 -0.0 视为小于 0.0。虽然 FMAXNUM_IEEE 遵循 IEEE 754-2008 语义,但 FMAXIMUM 遵循 IEEE 754-2019 语义。

G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FREM

执行指定的浮点算术运算。

G_FMA

执行融合乘加运算(即,不进行中间舍入步骤)。

G_FMAD

执行非融合乘加运算(即,进行中间舍入步骤)。

G_FPOW

将第一个操作数提升为第二个操作数的幂。

G_FEXP, G_FEXP2

计算值的以 e 或 2 为底的指数

G_FLOG, G_FLOG2, G_FLOG10

分别计算以 e、2 或 10 为底的对数。

G_FCEIL, G_FSQRT, G_FFLOOR, G_FRINT, G_FNEARBYINT

这些对应于同名的标准 C 函数。

G_FCOS, G_FSIN, G_FSINCOS, G_FTAN, G_FACOS, G_FASIN, G_FATAN, G_FATAN2, G_FCOSH, G_FSINH, G_FTANH

这些对应于同名的标准 C 三角函数。

G_INTRINSIC_TRUNC

返回操作数四舍五入到最接近的整数,该整数在幅度上不大于操作数。

G_INTRINSIC_ROUND

返回操作数四舍五入到最接近的整数。

G_LROUND, G_LLROUND

返回源操作数四舍五入到最接近的整数,与零方向相反。

有关行为的详细信息,请参阅 LLVM LangRef 中关于 ‘llvm.lround.*' 的条目。

%rounded_32:_(s32) = G_LROUND %round_me:_(s64)
%rounded_64:_(s64) = G_LLROUND %round_me:_(s64)

向量特定运算

G_VSCALE

将运行时 vscale 的值乘以源操作数中的值,并将结果放入目标寄存器中。这在确定向量中元素的实际运行时数量时很有用。

%0:_(s32) = G_VSCALE 4

G_INSERT_SUBVECTOR

将第二个源向量插入到第一个源向量中。索引操作数表示第二个源向量应插入到第一个源向量中的起始索引。

索引必须是第二个源向量的最小向量长度的常数倍数。如果向量是可缩放的,则索引首先按运行时缩放因子缩放。插入到源向量中的索引必须是该向量的有效索引。如果无法静态确定此条件,但在运行时为假,则结果向量未定义。

%2:_(<vscale x 4 x i64>) = G_INSERT_SUBVECTOR %0:_(<vscale x 4 x i64>), %1:_(<vscale x 2 x i64>), 0

G_EXTRACT_SUBVECTOR

从源向量中提取目标类型的向量。索引操作数表示从源向量中提取子向量的起始索引。

索引必须是源向量的最小向量长度的常数倍数。如果源向量是可缩放向量,则索引首先按运行时缩放因子缩放。从源向量中提取的索引必须是该向量的有效索引。如果无法静态确定此条件,但在运行时为假,则结果向量未定义。

不允许混合可缩放向量和固定向量。

%3:_(<vscale x 4 x i64>) = G_EXTRACT_SUBVECTOR %2:_(<vscale x 8 x i64>), 2

G_CONCAT_VECTORS

连接两个向量以形成更长的向量。

G_BUILD_VECTOR, G_BUILD_VECTOR_TRUNC

从多个标量寄存器创建向量。不执行隐式转换(即,结果元素类型必须与所有源操作数相同)

_TRUNC 版本截断较大的操作数类型以适合目标向量 elt 类型。

G_INSERT_VECTOR_ELT

将元素插入向量

G_EXTRACT_VECTOR_ELT

从向量中提取元素

G_SHUFFLE_VECTOR

连接两个向量,并根据掩码操作数对元素进行混洗。掩码操作数应为 IR 常量,该常量与 IR shufflevector 指令的相应掩码完全匹配。

G_SPLAT_VECTOR

创建一个向量,其中所有元素都是来自源操作数的标量。

操作数的类型必须等于或大于向量元素类型。如果操作数大于向量元素类型,则标量会隐式截断为向量元素类型。

G_STEP_VECTOR

创建一个可缩放向量,其中所有通道都是从 0 开始的线性序列,并具有给定的无符号步长。

操作数的类型必须等于向量元素类型。算术运算以元素的位宽为模执行。步长必须 > 0。否则向量为零。

%0:_(<vscale x 2 x s64>) = G_STEP_VECTOR i64 4

%1:_(<vscale x s32>) = G_STEP_VECTOR i32 4

0, 1*Step, 2*Step, 3*Step, 4*Step, ...

G_VECTOR_COMPRESS

给定一个输入向量、一个掩码向量和一个 passthru 向量,连续地将所有选定的(即,其中 mask[i] = true)输入通道放置在输出向量中。输出中的所有剩余通道都取自 passthru,passthru 可能是未定义的。

向量缩减运算

这些操作表示水平向量缩减,产生标量结果。

G_VECREDUCE_SEQ_FADD, G_VECREDUCE_SEQ_FMUL

SEQ 变体按顺序执行缩减。第一个操作数是初始标量累加器值,第二个操作数是要缩减的向量。

G_VECREDUCE_FADD, G_VECREDUCE_FMUL

这些缩减是宽松的变体,可以以任何顺序缩减元素。

G_VECREDUCE_FMAX, G_VECREDUCE_FMIN, G_VECREDUCE_FMAXIMUM, G_VECREDUCE_FMINIMUM

FMIN/FMAX/FMINIMUM/FMAXIMUM 节点可以有标志,用于 NaN/NoNaN 变体。

整数/按位缩减

  • G_VECREDUCE_ADD

  • G_VECREDUCE_MUL

  • G_VECREDUCE_AND

  • G_VECREDUCE_OR

  • G_VECREDUCE_XOR

  • G_VECREDUCE_SMAX

  • G_VECREDUCE_SMIN

  • G_VECREDUCE_UMAX

  • G_VECREDUCE_UMIN

整数缩减的结果类型可能大于向量元素类型。但是,缩减是使用向量元素类型执行的,并且高位中的值未指定。

内存操作

G_LOAD, G_SEXTLOAD, G_ZEXTLOAD

通用加载。除了显式操作数外,还需要一个 MachineMemOperand。如果结果大小大于内存大小,则高位分别是未定义的、符号扩展的或零扩展的。

如果结果是向量类型,则仅 G_LOAD 有效。如果结果大于内存大小,则高元素是未定义的(即,这不是按元素、向量 anyextload)

与 SelectionDAG 不同,原子加载与常规加载使用相同的操作码表示。 G_LOAD、G_SEXTLOAD 和 G_ZEXTLOAD 可能都具有原子内存操作数。

G_INDEXED_LOAD

通用索引加载。将 GEP 与加载结合在一起。 $newaddr 设置为 $base + $offset。如果 $am 为 0(后索引),则从 $base 加载值;如果 $am 为 1(预索引),则从 $newaddr 加载值。

G_INDEXED_SEXTLOAD

与 G_INDEXED_LOAD 相同,但执行的加载操作是带符号扩展,如同 G_SEXTLOAD。

G_INDEXED_ZEXTLOAD

与 G_INDEXED_LOAD 相同,但执行的加载操作是零扩展,如同 G_ZEXTLOAD。

G_STORE

通用存储。除了显式操作数外,还需要一个 MachineMemOperand。如果存储的值大小大于内存大小,则高位将被隐式截断。如果这是向量存储,则高位元素将被丢弃(即,这不像每个通道的向量截断存储那样工作)。

G_INDEXED_STORE

将存储与 GEP 组合。有关索引行为,请参阅 G_INDEXED_LOAD 的描述。

G_ATOMIC_CMPXCHG_WITH_SUCCESS

带有内部成功检查的通用原子 cmpxchg。除了显式操作数外,还需要一个 MachineMemOperand。

G_ATOMIC_CMPXCHG

通用原子 cmpxchg。除了显式操作数外,还需要一个 MachineMemOperand。

G_ATOMICRMW_XCHG, G_ATOMICRMW_ADD, G_ATOMICRMW_SUB, G_ATOMICRMW_AND, G_ATOMICRMW_NAND, G_ATOMICRMW_OR, G_ATOMICRMW_XOR, G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, G_ATOMICRMW_UMAX, G_ATOMICRMW_UMIN, G_ATOMICRMW_FADD, G_ATOMICRMW_FSUB, G_ATOMICRMW_FMAX, G_ATOMICRMW_FMIN, G_ATOMICRMW_UINC_WRAP, G_ATOMICRMW_UDEC_WRAP, G_ATOMICRMW_USUB_COND, G_ATOMICRMW_USUB_SAT

通用 atomicrmw。除了显式操作数外,还需要一个 MachineMemOperand。

G_FENCE

通用 fence。第一个操作数是内存排序。第二个操作数是同步作用域。

有关更多详细信息,请参阅 LLVM LangRef 中关于 ‘fence' 指令的条目。

G_MEMCPY

通用 memcpy。除了显式操作数外,还需要两个 MachineMemOperand,分别涵盖存储和加载。

G_MEMCPY_INLINE

通用内联 memcpy。与 G_MEMCPY 类似,但保证此版本不会被降低为对外部函数的调用。目前,大小操作数需要评估为常量(而不是立即数),尽管当 llvm.memcpy.inline 被教导支持动态大小时,这种情况有望改变。

G_MEMMOVE

通用 memmove。与 G_MEMCPY 类似,但允许源内存范围和目标内存范围重叠。

G_MEMSET

通用 memset。除了显式操作数外,还需要一个 MachineMemOperand。

G_BZERO

通用 bzero。除了显式操作数外,还需要一个 MachineMemOperand。

控制流

G_PHI

实现 SSA 图中表示函数的 φ 节点。

%dst(s8) = G_PHI %src1(s8), %bb.<id1>, %src2(s8), %bb.<id2>

G_BR

无条件分支

G_BR %bb.<id>

G_BRCOND

条件分支

G_BRCOND %condition, %basicblock.<id>

G_BRINDIRECT

间接分支

G_BRINDIRECT %src(p0)

G_BRJT

间接分支到跳转表条目

G_BRJT %ptr(p0), %jti, %idx(s64)

G_JUMP_TABLE

生成指向源操作数指定的跳转表地址的指针。源操作数是跳转表索引。 G_JUMP_TABLE 可以与 G_BRJT 结合使用,以支持使用 GlobalISel 的跳转表代码生成。

%dst:_(p0) = G_JUMP_TABLE %jump-table.0

上面的示例生成指向源跳转表索引的指针。

G_INVOKE_REGION_START

一个标记指令,充当可能抛出异常的代码区域的伪终止符。作为终止符,它可以防止在诸如合法化之类的过程中在其后插入代码。这是必需的,因为对异常抛出例程的调用不会返回,因此任何必须在可执行路径上的代码都不能放置在抛出之后。

G_INTRINSIC, G_INTRINSIC_CONVERGENT

调用没有副作用的 intrinsic。

_CONVERGENT 变体对应于标记为 convergent 的 LLVM IR intrinsic。

注意

与 SelectionDAG 不同,没有 _VOID 变体。这两者都允许有零个、一个或多个结果。

G_INTRINSIC_W_SIDE_EFFECTS, G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS

调用被认为具有未知副作用的 intrinsic,因此不能跨其他具有副作用的指令重新排序。

_CONVERGENT 变体对应于标记为 convergent 的 LLVM IR intrinsic。

注意

与 SelectionDAG 不同,没有 _VOID 变体。这两者都允许有零个、一个或多个结果。

G_TRAP, G_DEBUGTRAP, G_UBSANTRAP

表示 llvm.trapllvm.debugtrapllvm.ubsantrap,它们生成目标相关的 trap 指令。

G_TRAP
G_DEBUGTRAP
G_UBSANTRAP 12

可变参数

G_VASTART

注意

在编写本文档时,我没有找到此指令的文档。

G_VAARG

注意

在编写本文档时,我没有找到此指令的文档。

其他操作

G_DYN_STACKALLOC

动态地将堆栈指针重新对齐到指定的大小和对齐方式。对齐值 01 表示没有特定的对齐方式。

%8:_(p0) = G_DYN_STACKALLOC %7(s64), 32

优化提示

这些指令不对应于任何目标指令。它们充当各种组合的提示。

G_ASSERT_SEXT, G_ASSERT_ZEXT

这表示寄存器的内容先前已从较小的类型扩展而来。

较小的类型使用立即操作数表示。对于标量,这是整个较小类型的宽度。对于向量,这是较小元素类型的宽度。

%x_was_zexted:_(s32) = G_ASSERT_ZEXT %x(s32), 16
%y_was_zexted:_(<2 x s32>) = G_ASSERT_ZEXT %y(<2 x s32>), 16

%z_was_sexted:_(s32) = G_ASSERT_SEXT %z(s32), 8

G_ASSERT_SEXT 和 G_ASSERT_ZEXT 的行为类似于复制,但有一些限制。

源寄存器和目标寄存器必须

  • 是虚拟的

  • 属于同一寄存器类

  • 属于同一寄存器组

始终可以安全地

  • 查看源寄存器

  • 用源寄存器替换目标寄存器

杂项

G_CONSTANT_FOLD_BARRIER

此操作用作防止常量折叠的不透明屏障。组合和其他转换不应穿过它。这些没有其他语义,如果目标选择,可以安全地消除它们。

未列出:G_STACKSAVE, G_STACKRESTORE, G_FSHL, G_FSHR, G_SMULFIX, G_UMULFIX, G_SMULFIXSAT, G_UMULFIXSAT, G_SDIVFIX, G_UDIVFIX, G_SDIVFIXSAT, G_UDIVFIXSAT, G_FPOWI, G_FEXP10, G_FLDEXP, G_FFREXP, G_GET_FPENV, G_SET_FPENV, G_RESET_FPENV, G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE, G_INTRINSIC_FPTRUNC_ROUND, G_INTRINSIC_LRINT, G_INTRINSIC_LLRINT, G_INTRINSIC_ROUNDEVEN, G_READCYCLECOUNTER, G_READSTEADYCOUNTER, G_PREFETCH, G_READ_REGISTER, G_WRITE_REGISTER, G_STRICT_FADD, G_STRICT_FSUB, G_STRICT_FMUL, G_STRICT_FDIV, G_STRICT_FREM, G_STRICT_FMA, G_STRICT_FSQRT, G_STRICT_FLDEXP, G_ASSERT_ALIGN