fix(mlirlite): 常量表与自动常量名空间(%c<seq>)按需扩容
原实现三处都钉死在 MLIR_CONST_CAP(512):常量表满 → MlirFail("constant table overflow")、%c0..%c511 用尽 → MlirFail、_MlirMarkUsedCName 里"更大的后缀不可能冲突"的假设。这些只是资源限制,不该中断编译。
- 新增 _MLIR_ConstCap 活容量与 _MlirConstGrow(池内翻倍扩容常量表 + 已用名表并拷贝旧内容)
- 常量表满、名字空间用尽改为扩容后重试;_MlirMarkUsedCName 记录任意 c<digits> 并先扩容再置位
- _MlirTablesInit 按活容量分配/清零,复用分支保留已扩容容量
This commit is contained in:
1 parent
cc7cfdb4af
commit
4914311014
1 file changed
+61
-23
+61
-23
@@ -1210,9 +1210,11 @@ _MlirTablesValid: int = 0
|
||||
_MlirTablesPool: memhub.MemBuddy* = None
|
||||
|
||||
# Live capacities of the constant/alias tables: start at the define defaults and grow on demand
|
||||
# (_MlirAliasGrow / const table), instead of hard-failing the whole compile when a big function
|
||||
# needs more entries than the fixed caps allow.
|
||||
# (_MlirAliasGrow / _MlirConstGrow), instead of hard-failing the whole compile when a big function
|
||||
# needs more entries than the fixed caps allow. _MLIR_ConstCap also bounds the auto constant name
|
||||
# space (%c<seq>) and the used-name table, which used to be nailed to MLIR_CONST_CAP.
|
||||
_MLIR_AliasCap: int = MLIR_ALIAS_CAP
|
||||
_MLIR_ConstCap: int = MLIR_CONST_CAP
|
||||
|
||||
|
||||
def MlirTablesReset():
|
||||
@@ -1254,7 +1256,7 @@ def _MlirTablesInit(pool: memhub.MemBuddy*):
|
||||
function-heavy modules; the equivalent global-region scratch (MlirGvEnsureScratch) already reuses
|
||||
this way. Callers that may reset the pool between prints must call MlirTablesReset first.
|
||||
"""
|
||||
global _MLIR_Pool, _MLIR_Pass, _MLIR_ConstTy, _MLIR_ConstVal, _MLIR_ConstName, _MLIR_ConstCount, _MLIR_ConstNameSeq, _MLIR_UsedC, _MLIR_AliasFrom, _MLIR_AliasTo, _MLIR_AliasCount, _MLIR_AliasCap, _SC_Op, _SC_Tb, _SC_Ty, _SC_Ty2, _SC_V1, _SC_V2, _SC_V3, _SC_Callee, _SC_Args, _SC_ArgTs, _SC_IdxV, _SC_IdxT, _SC_Mt, _SC_Tmp, _SC_Tmp2, _SC_P1, _SC_P2, _SC_B1, _SC_B2, _SC_Buf, _MlirTablesValid, _MlirTablesPool
|
||||
global _MLIR_Pool, _MLIR_Pass, _MLIR_ConstTy, _MLIR_ConstVal, _MLIR_ConstName, _MLIR_ConstCount, _MLIR_ConstNameSeq, _MLIR_UsedC, _MLIR_ConstCap, _MLIR_AliasFrom, _MLIR_AliasTo, _MLIR_AliasCount, _MLIR_AliasCap, _SC_Op, _SC_Tb, _SC_Ty, _SC_Ty2, _SC_V1, _SC_V2, _SC_V3, _SC_Callee, _SC_Args, _SC_ArgTs, _SC_IdxV, _SC_IdxT, _SC_Mt, _SC_Tmp, _SC_Tmp2, _SC_P1, _SC_P2, _SC_B1, _SC_B2, _SC_Buf, _MlirTablesValid, _MlirTablesPool
|
||||
if pool is None:
|
||||
MlirFail("MLIR render: memory pool is null")
|
||||
if _MlirTablesValid != 0 and _MlirTablesPool == pool:
|
||||
@@ -1266,27 +1268,28 @@ def _MlirTablesInit(pool: memhub.MemBuddy*):
|
||||
_MLIR_ConstCount = 0
|
||||
_MLIR_ConstNameSeq = 0
|
||||
_MLIR_AliasCount = 0
|
||||
string.memset(_MLIR_UsedC, 0, MLIR_CONST_CAP * 4)
|
||||
string.memset(_MLIR_UsedC, 0, _MLIR_ConstCap * 4)
|
||||
return
|
||||
_MLIR_Pool = pool
|
||||
_MLIR_Pass = 0
|
||||
_MLIR_ConstCount = 0
|
||||
_MLIR_ConstNameSeq = 0
|
||||
_MLIR_AliasCount = 0
|
||||
_MLIR_ConstTy = pool.alloc(MLIR_CONST_CAP * 8)
|
||||
_MLIR_ConstVal = pool.alloc(MLIR_CONST_CAP * 8)
|
||||
_MLIR_ConstName = pool.alloc(MLIR_CONST_CAP * 8)
|
||||
_MLIR_UsedC = pool.alloc(MLIR_CONST_CAP * 4)
|
||||
_MLIR_ConstCap = MLIR_CONST_CAP
|
||||
_MLIR_ConstTy = pool.alloc(_MLIR_ConstCap * 8)
|
||||
_MLIR_ConstVal = pool.alloc(_MLIR_ConstCap * 8)
|
||||
_MLIR_ConstName = pool.alloc(_MLIR_ConstCap * 8)
|
||||
_MLIR_UsedC = pool.alloc(_MLIR_ConstCap * 4)
|
||||
_MLIR_AliasCap = MLIR_ALIAS_CAP
|
||||
_MLIR_AliasFrom = pool.alloc(_MLIR_AliasCap * 8)
|
||||
_MLIR_AliasTo = pool.alloc(_MLIR_AliasCap * 8)
|
||||
if _MLIR_ConstTy is None or _MLIR_ConstVal is None or _MLIR_ConstName is None \
|
||||
or _MLIR_UsedC is None or _MLIR_AliasFrom is None or _MLIR_AliasTo is None:
|
||||
MlirFail("MLIR render: constant/alias table allocation failed")
|
||||
string.memset(_MLIR_ConstTy, 0, MLIR_CONST_CAP * 8)
|
||||
string.memset(_MLIR_ConstVal, 0, MLIR_CONST_CAP * 8)
|
||||
string.memset(_MLIR_ConstName, 0, MLIR_CONST_CAP * 8)
|
||||
string.memset(_MLIR_UsedC, 0, MLIR_CONST_CAP * 4)
|
||||
string.memset(_MLIR_ConstTy, 0, _MLIR_ConstCap * 8)
|
||||
string.memset(_MLIR_ConstVal, 0, _MLIR_ConstCap * 8)
|
||||
string.memset(_MLIR_ConstName, 0, _MLIR_ConstCap * 8)
|
||||
string.memset(_MLIR_UsedC, 0, _MLIR_ConstCap * 4)
|
||||
string.memset(_MLIR_AliasFrom, 0, _MLIR_AliasCap * 8)
|
||||
string.memset(_MLIR_AliasTo, 0, _MLIR_AliasCap * 8)
|
||||
_SC_Op = pool.alloc(64)
|
||||
@@ -1355,6 +1358,36 @@ def _MlirAliasGrow():
|
||||
_MLIR_AliasCap = old_cap * 2
|
||||
|
||||
|
||||
def _MlirConstGrow():
|
||||
"""扩容常量表 + 自动常量名空间(%c<seq>)+ 已用名表:池内分配翻倍新块并拷贝旧内容。
|
||||
|
||||
原实现三处都钉死在 MLIR_CONST_CAP(512):常量表满 → MlirFail("constant table overflow")、
|
||||
%c0..%c511 用尽 → MlirFail、以及 _MlirMarkUsedCName 里"更大的后缀不可能冲突"的假设。
|
||||
这些只是资源限制,不该中断编译,故统一按需扩容。
|
||||
"""
|
||||
global _MLIR_ConstTy, _MLIR_ConstVal, _MLIR_ConstName, _MLIR_UsedC, _MLIR_ConstCap
|
||||
old_cap: int = _MLIR_ConstCap
|
||||
nb_ty: bytes = _MLIR_Pool.alloc(old_cap * 16)
|
||||
nb_val: bytes = _MLIR_Pool.alloc(old_cap * 16)
|
||||
nb_nm: bytes = _MLIR_Pool.alloc(old_cap * 16)
|
||||
nb_used: bytes = _MLIR_Pool.alloc(old_cap * 8)
|
||||
if nb_ty is None or nb_val is None or nb_nm is None or nb_used is None:
|
||||
MlirFail("MLIR render: constant table growth allocation failed")
|
||||
string.memcpy(nb_ty, _MLIR_ConstTy, old_cap * 8)
|
||||
string.memcpy(nb_val, _MLIR_ConstVal, old_cap * 8)
|
||||
string.memcpy(nb_nm, _MLIR_ConstName, old_cap * 8)
|
||||
string.memcpy(nb_used, _MLIR_UsedC, old_cap * 4)
|
||||
string.memset(nb_ty + old_cap * 8, 0, old_cap * 8)
|
||||
string.memset(nb_val + old_cap * 8, 0, old_cap * 8)
|
||||
string.memset(nb_nm + old_cap * 8, 0, old_cap * 8)
|
||||
string.memset(nb_used + old_cap * 4, 0, old_cap * 4)
|
||||
_MLIR_ConstTy = nb_ty
|
||||
_MLIR_ConstVal = nb_val
|
||||
_MLIR_ConstName = nb_nm
|
||||
_MLIR_UsedC = nb_used
|
||||
_MLIR_ConstCap = old_cap * 2
|
||||
|
||||
|
||||
def _MlirAliasAdd(from_name: str, to_name: str):
|
||||
"""Register a no-op bitcast alias (from is replaced by to)"""
|
||||
global _MLIR_AliasCount
|
||||
@@ -1410,9 +1443,8 @@ def _usedc_get(idx: int) -> int:
|
||||
def _MlirMarkUsedCName(name: str):
|
||||
"""Mark name (an SSA name, with or without a leading '%') as used iff it is exactly c<digits>.
|
||||
|
||||
Only numbers in [0, MLIR_CONST_CAP) can ever be produced by the constant namer (it fails before
|
||||
reaching MLIR_CONST_CAP), so larger suffixes cannot collide and are ignored. A longer name like
|
||||
`c1x` is not c<digits> and is ignored too (its token would not match `%c1`).
|
||||
自动常量名 %c<seq> 的编号空间会按需扩容(见 _MlirConstGrow),所以这里记录**任意** c<digits>
|
||||
后缀:越界的编号先扩容已用名表再置位,否则扩出来的编号可能与该函数自带的 c<N> 撞名。
|
||||
"""
|
||||
if name is None:
|
||||
return
|
||||
@@ -1450,13 +1482,16 @@ def _MlirScanUsedCText(text: str):
|
||||
d: int = 0
|
||||
nd: int = 0
|
||||
while _is_digit_ch(e[0]) != 0:
|
||||
if d < MLIR_CONST_CAP:
|
||||
# 上限只用于防溢出:记录任何 c<digits>(名字空间会按需扩容,
|
||||
# 不能再假设"更大的后缀不会与自动名冲突")
|
||||
if d < 100000000:
|
||||
d = d * 10 + (int(e[0]) - 48)
|
||||
nd += 1
|
||||
e = e + 1
|
||||
if nd > 0 and _MlirIsSsaNameChar(e[0]) == 0:
|
||||
if d < MLIR_CONST_CAP:
|
||||
_usedc_set(d, 1)
|
||||
if d >= _MLIR_ConstCap:
|
||||
_MlirConstGrow()
|
||||
_usedc_set(d, 1)
|
||||
p = e
|
||||
continue
|
||||
p = p + 1
|
||||
@@ -1517,8 +1552,8 @@ def _MlirConstGet(tytext: str, valtext: str) -> str:
|
||||
if _MLIR_Pass == 2:
|
||||
# pass1 already scanned all instruction lines; no new constant should appear here
|
||||
MlirFail("MLIR render: unmaterialized constant in emit pass (scan missed it)")
|
||||
if _MLIR_ConstCount >= MLIR_CONST_CAP:
|
||||
MlirFail("MLIR render: constant table overflow")
|
||||
if _MLIR_ConstCount >= _MLIR_ConstCap:
|
||||
_MlirConstGrow()
|
||||
nm: str = _MLIR_Pool.alloc(32)
|
||||
if nm is None:
|
||||
MlirFail("MLIR render: constant name allocation failed")
|
||||
@@ -1526,10 +1561,13 @@ def _MlirConstGet(tytext: str, valtext: str) -> str:
|
||||
# seq is strictly increasing, so names stay unique; it is decoupled from the table index, and the
|
||||
# (type,value) cache above still makes identical constants reuse the same name.
|
||||
seq: int = _MLIR_ConstNameSeq
|
||||
while seq < MLIR_CONST_CAP and _usedc_get(seq) != 0:
|
||||
while seq < _MLIR_ConstCap and _usedc_get(seq) != 0:
|
||||
seq += 1
|
||||
if seq >= MLIR_CONST_CAP:
|
||||
MlirFail("MLIR render: no free constant SSA name (%c0..%c511 all used by the function)")
|
||||
if seq >= _MLIR_ConstCap:
|
||||
# 名字空间同样按需扩容:原来钉死在 %c0..%c511,用尽就 MlirFail
|
||||
_MlirConstGrow()
|
||||
while seq < _MLIR_ConstCap and _usedc_get(seq) != 0:
|
||||
seq += 1
|
||||
_MLIR_ConstNameSeq = seq + 1
|
||||
viperlib.snprintf(nm, 32, "%%c%d", seq)
|
||||
sp2: str* = _mlir_slotp(_MLIR_ConstTy, _MLIR_ConstCount)
|
||||
|
||||
Reference in new issue
Block a user