fix(codegen): keep unary constant folding within the operand width

This commit is contained in:
TermiNexus committed 2026-10-27 21:33:48 +08:00
1 parent e63fc34057
commit 8e86eea159
1 file changed
+17 -2
+17 -2
View File
@@ -781,7 +781,15 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
# 触发“隐式窄化禁止”,尽管其数值完全落在 i8 内(隐式窄化的“编译期常量”豁免失效)。
operand_bits: int = self.get_llvm_type_bits(operand.Ty)
if operand_bits != 0 and operand.IsConst == 1:
return mlirlite.const_int(pool, operand_bits, -operand.IntVal)
# Keep the folded value inside the operand's accepted literal range
# [-2^(N-1), 2^N-1]: -1 stays -1, while -(-128) / -200 wrap to the N-bit pattern
# instead of emitting an unparsable wide value.
neg_c: int64 = -operand.IntVal
if operand_bits < 64:
neg_lo: int64 = -(int64(1) << (operand_bits - 1))
neg_hi: int64 = (int64(1) << operand_bits) - 1
if neg_c < neg_lo or neg_c > neg_hi: neg_c = neg_c & neg_hi
return mlirlite.const_int(pool, operand_bits, neg_c)
# Integer: -x = 0 - x;0 常量必须与**当前**操作数同宽(u 类不提升后可能是 i8/i16/i32/i64)
zero: mlirlite.Value* = mlirlite.const_int32(pool, 0)
if operand_bits != 0 and operand_bits != 32: zero = mlirlite.const_int(pool, operand_bits, 0)
@@ -800,7 +808,14 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
operand_bits_inv: int = self.get_llvm_type_bits(operand.Ty)
# 编译期常量折叠:~c 直接产出常量并保持 IsConst(与 -c 相同的窄化豁免口径)
if operand_bits_inv != 0 and operand.IsConst == 1:
return mlirlite.const_int(pool, operand_bits_inv, operand.IntVal ^ -1)
# ~0x80 is -129 in the wide domain; for i8 emit 0x7F (127) instead. Values that
# already fit the literal range (e.g. ~0 = -1) are left untouched.
inv_c: int64 = operand.IntVal ^ -1
if operand_bits_inv < 64:
inv_lo: int64 = -(int64(1) << (operand_bits_inv - 1))
inv_hi: int64 = (int64(1) << operand_bits_inv) - 1
if inv_c < inv_lo or inv_c > inv_hi: inv_c = inv_c & inv_hi
return mlirlite.const_int(pool, operand_bits_inv, inv_c)
# -1 掩码必须与**当前**操作数同宽(u 类不提升后可能是 i8/i16/i32/i64)
neg1: mlirlite.Value* = mlirlite.const_int32(pool, -1)
if operand_bits_inv != 0 and operand_bits_inv != 32: neg1 = mlirlite.const_int(pool, operand_bits_inv, -1)