aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2026-02-19 20:29:16 +0100
committerlemon <lsof@mailbox.org>2026-02-19 20:29:16 +0100
commitad8067a1ab1871cf57936828fb1b40c15cd3349d (patch)
treead86757ae0f84f1fd7dd58373cdb4f50d7f036d6
parent1430f62ebed808458baccbdf0e41b806334ff704 (diff)
IR: just use an array for extended constants
The extra work of using a hashtable to intern them is probably unnecessary.
-rw-r--r--aarch64/emit.c12
-rw-r--r--aarch64/isel.c16
-rw-r--r--ir/dump.c2
-rw-r--r--ir/inliner.c7
-rw-r--r--ir/ir.c36
-rw-r--r--ir/ir.h15
-rw-r--r--ir/ssa.c2
-rw-r--r--x86_64/emit.c22
-rw-r--r--x86_64/isel.c8
9 files changed, 54 insertions, 66 deletions
diff --git a/aarch64/emit.c b/aarch64/emit.c
index d49906e..6db1bd6 100644
--- a/aarch64/emit.c
+++ b/aarch64/emit.c
@@ -86,12 +86,12 @@ ref2oper(union ref r)
case RREG: return reg2oper(r.i);
case RICON: return mkoper(OIMM, .imm = r.i);
case RXCON:
- if (kisint(conht[r.i].cls))
- return mkoper(OIMM, .imm = conht[r.i].i);
- else if (kisflt(conht[r.i].cls)) {
- assert(conht[r.i].f == 0.0);
+ if (kisint(contab.p[r.i].cls))
+ return mkoper(OIMM, .imm = contab.p[r.i].i);
+ else if (kisflt(contab.p[r.i].cls)) {
+ assert(contab.p[r.i].f == 0.0);
return mkoper(OIMM, .imm = 0);
- } else if (!conht[r.i].cls) {
+ } else if (!contab.p[r.i].cls) {
return mkoper(OSYM, .con = r.i);
}
assert(0);
@@ -553,7 +553,7 @@ gencopy(uchar **pcode, enum irclass cls, struct block *blk, int curi, struct ope
Xfmov(pcode, cls, dst, REGZR);
else assert(0);
} else if (isaddrcon(val,0) || (val.t == RADDR && isaddrcon(addrht[val.i].base,0))) {
- if ((ccopt.pic || (conht[val.i].flag & SFUNC)) && !(conht[val.i].flag & SLOCAL)) {
+ if ((ccopt.pic || (contab.p[val.i].flag & SFUNC)) && !(contab.p[val.i].flag & SLOCAL)) {
Xadrp(pcode, KPTR, dst, src);
Xadd(pcode, KPTR, dst, dst, src);
} else {
diff --git a/aarch64/isel.c b/aarch64/isel.c
index 390793b..bcabf2c 100644
--- a/aarch64/isel.c
+++ b/aarch64/isel.c
@@ -108,7 +108,7 @@ fixarg(union ref *r, struct instr *ins, struct block *blk, int *curi)
goto Reg;
} else if (isfltcon(*r)) {
enum irclass k = concls(*r), ki = KI32 + k-KF32;
- if (conht[r->i].f != 0.0) {
+ if (contab.p[r->i].f != 0.0) {
union {
vlong i64;
int i32;
@@ -117,10 +117,10 @@ fixarg(union ref *r, struct instr *ins, struct block *blk, int *curi)
} pun;
vlong i;
if (k == KF32) {
- pun.f32 = conht[r->i].f;
+ pun.f32 = contab.p[r->i].f;
i = pun.i32;
} else {
- pun.f64 = conht[r->i].f;
+ pun.f64 = contab.p[r->i].f;
i = pun.i64;
}
union ref gpr = insertinstr(blk, (*curi)++, mkinstr(Ocopy, ki, mkintcon(ki, i)));
@@ -301,9 +301,9 @@ fuseaddr(union ref *r, struct block *blk, int *curi, uint siz/*1,2,4,8*/)
if (!(addr.disp >= -256 && addr.disp < 256) /* for 9-bit signed unscaled offset */
&& !(!(addr.disp & (siz-1)) && (uvlong)addr.disp < (1<<12)*siz)) /* 12-bit unsigned scaled offset */
return 0;
- if (isaddrcon(addr.base,0) && (!(conht[addr.base.i].flag & SLOCAL) || addr.index.bits)) {
+ if (isaddrcon(addr.base,0) && (!(contab.p[addr.base.i].flag & SLOCAL) || addr.index.bits)) {
/* first load symbol address into a temp register */
- if (addr.disp && (ccopt.pic || (conht[addr.base.i].flag & SFUNC)) && !addr.index.bits) {
+ if (addr.disp && (ccopt.pic || (contab.p[addr.base.i].flag & SFUNC)) && !addr.index.bits) {
addr.base = insertinstr(blk, (*curi)++, mkinstr(Ocopy, KPTR, .l = addr.base));
} else {
addr.base = insertinstr(blk, (*curi)++, mkinstr(Ocopy, KPTR,
@@ -339,7 +339,7 @@ loadstoreaddr(struct block *blk, union ref *r, int *curi, enum op op)
*r = mkaddr((struct addr){.base = *r});
} else if (isaddrcon(*r, 0)) {
bool pcrelok = in_range(op, Oloads32, Oloadi64); /* LDR-LDRSW have PC-relative literal form */
- if (!pcrelok || !(conht[r->i].flag & SLOCAL))
+ if (!pcrelok || !(contab.p[r->i].flag & SLOCAL))
regarg(r, KPTR, blk, curi);
} else if (r->t == RTMP || r->t == RSTACK) {
fuseaddr(r, blk, curi, siz);
@@ -390,7 +390,7 @@ sel(struct function *fn, struct instr *ins, struct block *blk, int *curi)
op = ins->op ^= 1;
ins->r.i = -ins->r.i;
}
- if (!(isaddrcon(ins->l,0) && (conht[ins->l.i].flag & SLOCAL)))
+ if (!(isaddrcon(ins->l,0) && (contab.p[ins->l.i].flag & SLOCAL)))
regarg(&ins->l, ins->cls, blk, curi);
fixarg(&ins->r, ins, blk, curi);
break;
@@ -445,7 +445,7 @@ seljmp(struct function *fn, struct block *blk)
fixarg(&blk->jmp.arg[0], NULL, blk, &curi);
union ref c = blk->jmp.arg[0];
if (c.t != RTMP) {
- enum irclass cls = c.t == RICON ? KI32 : c.t == RXCON && conht[c.i].cls ? conht[c.i].cls : KPTR;
+ enum irclass cls = c.t == RICON ? KI32 : c.t == RXCON && contab.p[c.i].cls ? contab.p[c.i].cls : KPTR;
int curi = blk->ins.n;
c = insertinstr(blk, blk->ins.n, mkinstr(Ocopy, cls, c));
diff --git a/ir/dump.c b/ir/dump.c
index cf8d788..bb6a2fd 100644
--- a/ir/dump.c
+++ b/ir/dump.c
@@ -107,7 +107,7 @@ dumpref(enum op o, union ref ref)
else bfmt(out, "%d", ref.i);
break;
case RXCON:
- con = &conht[ref.i];
+ con = &contab.p[ref.i];
if (con->deref) bfmt(out, "*[");
if (con->issym || con->isdat) {
bfmt(out, "$%y", xcon2sym(ref.i));
diff --git a/ir/inliner.c b/ir/inliner.c
index 0853d26..2ce817b 100644
--- a/ir/inliner.c
+++ b/ir/inliner.c
@@ -4,7 +4,7 @@ struct savedfunc {
int mark;
uint ninstr;
struct instr *instrtab;
- struct xcon *conht;
+ struct xcon *contab;
struct call *calltab;
union ref **phitab;
struct block *entry;
@@ -82,7 +82,7 @@ maybeinlinee(struct function *fn)
} while ((b = b->lnext));
sv->instrtab = alloccopy(&savearena, instrtab, sizeof *instrtab * (sv->ninstr = ninstr), 0);
- sv->conht = alloccopy(&savearena, conht, sizeof *conht * (1<<12), 0); // HACK
+ sv->contab = alloccopy(&savearena, contab.p, sizeof *contab.p * contab.n, 0);
if (calltab.n) {
sv->calltab = alloccopy(&savearena, calltab.p, sizeof *calltab.p * calltab.n, 0);
for (int i = 0; i < calltab.n; ++i) {
@@ -104,9 +104,8 @@ maybeinlinee(struct function *fn)
static union ref
mapref(short *instrmap, struct savedfunc *sv, union ref r)
{
- int newcon(const struct xcon *con);
if (r.t == RTMP) return r.i = instrmap[r.i], r;
- if (r.t == RXCON) return r.i = newcon(&sv->conht[r.i]), r;
+ if (r.t == RXCON) return newxcon(&sv->contab[r.i]);
assert(r.t != RADDR);
assert(r.t != RSTACK);
return r;
diff --git a/ir/ir.c b/ir/ir.c
index 01d8060..b5f9de8 100644
--- a/ir/ir.c
+++ b/ir/ir.c
@@ -35,10 +35,9 @@ static struct arena **usearena;
struct calltab calltab;
struct phitab phitab;
struct dattab dattab;
+struct contab contab;
struct addr addrht[1 << 12];
static int naddrht;
-struct xcon conht[1 << 12];
-static int nconht;
int visitmark;
void
@@ -47,6 +46,7 @@ irinit(struct function *fn)
static struct call callsbuf[64];
static union ref *phisbuf[64];
static struct irdat datsbuf[64];
+ static struct xcon consbuf[64];
assert(fn->arena && !fn->passarena);
@@ -57,11 +57,10 @@ irinit(struct function *fn)
vinit(&calltab, callsbuf, countof(callsbuf));
for (int i = 0; i < phitab.n; ++i) xbfree(phitab.p[i]);
vinit(&phitab, phisbuf, countof(phisbuf));
+ vinit(&contab, consbuf, countof(consbuf));
if (!dattab.p) vinit(&dattab, datsbuf, countof(datsbuf));
if (naddrht >= countof(addrht)/2)
memset(addrht, naddrht = 0, sizeof addrht);
- if (nconht >= countof(conht)/2)
- memset(conht, nconht = 0, sizeof conht);
if (!type2cls[TYINT]) {
for (int i = TYBOOL; i <= TYUVLONG; ++i) {
int siz = targ_primsizes[i];
@@ -100,23 +99,12 @@ newaddr(const struct addr *addr)
}
}
-int
-newcon(const struct xcon *con)
+union ref
+newxcon(const struct xcon *con)
{
- uint h = hashb(0, con, sizeof *con);
- uint i = h, n = countof(conht);
assert((con->issym ^ con->isdat) || con->cls);
- for (;; ++i) {
- i &= countof(conht) - 1;
- if (!conht[i].issym && !conht[i].isdat && !conht[i].cls) {
- conht[i] = *con;
- ++nconht;
- return i;
- } else if (!memcmp(&conht[i], con, sizeof *con)) {
- return i;
- }
- assert(--n > 0 && "conht full");
- }
+ vpush(&contab, *con);
+ return mkref(RXCON, contab.n-1);
}
union irtype
@@ -137,7 +125,7 @@ mkintcon(enum irclass k, vlong i)
struct xcon con = { .cls = k, .i = i };
if (cls2siz[k] == 4) /* check upper half is zero or -1 */
assert(in_range((i >> 32) + 1, 0, 1));
- return mkref(RXCON, newcon(&con));
+ return newxcon(&con);
}
}
@@ -145,14 +133,14 @@ union ref
mkfltcon(enum irclass k, double f)
{
struct xcon con = { .cls = k, .f = k == KF32 ? (float) f : f };
- return mkref(RXCON, newcon(&con));
+ return newxcon(&con);
}
union ref
mksymref(internstr s, enum symflags symflags)
{
struct xcon con = { .issym = 1, .sym = s, .flag = symflags };
- return mkref(RXCON, newcon(&con));
+ return newxcon(&con);
}
union ref
@@ -176,13 +164,13 @@ mkdatref(internstr name, union type ctype, uint siz, uint align, const void *byt
if (n) memcpy(p, bytes, n);
if (dat.section != Stext) memset(p+n, 0, siz - n);
vpush(&dattab, dat);
- return mkref(RXCON, newcon(&(struct xcon){.isdat = 1, .deref = deref, .dat = dattab.n - 1, .flag = SLOCAL}));
+ return newxcon(&(struct xcon){.isdat = 1, .deref = deref, .dat = dattab.n - 1, .flag = SLOCAL});
}
internstr
xcon2sym(int ref)
{
- struct xcon con = conht[ref];
+ struct xcon con = contab.p[ref];
assert(con.issym ^ con.isdat);
return con.issym ? con.sym : dattab.p[con.dat].name;
}
diff --git a/ir/ir.h b/ir/ir.h
index 73a50bd..c7abaa7 100644
--- a/ir/ir.h
+++ b/ir/ir.h
@@ -241,10 +241,10 @@ extern uchar cls2store[];
extern const uchar siz2intcls[];
extern struct instr instrtab[];
extern struct use *instruse[];
-extern struct xcon conht[];
extern struct calltab {vec_of(struct call);} calltab;
extern struct phitab {vec_of(union ref *);} phitab;
extern struct dattab {vec_of(struct irdat);} dattab;
+extern struct contab {vec_of(struct xcon);} contab;
extern struct addr addrht[];
extern int visitmark;
#define mkinstr(O, C, ...) ((struct instr) { .op = (O), .cls = (C), .reg=0, __VA_ARGS__ })
@@ -253,16 +253,17 @@ void irinit(struct function *);
void irfini(struct function *);
#define cls2type(k) ((union irtype){.cls=(k)})
union irtype mkirtype(union type);
+union ref newxcon(const struct xcon *);
union ref mkintcon(enum irclass, vlong);
union ref mkfltcon(enum irclass, double);
#define iscon(r) in_range((r).t, RICON, RXCON)
-#define concls(r) ((r).t == RICON ? KI32 : conht[(r).i].cls)
+#define concls(r) ((r).t == RICON ? KI32 : contab.p[(r).i].cls)
#define isintcon(r) (iscon(r) && kisint(concls(r)))
-#define isfltcon(r) ((r).t == RXCON && kisflt(conht[(r).i].cls))
-#define isnumcon(r) ((r).t == RICON || ((r).t == RXCON && conht[(r).i].cls))
-#define isaddrcon(r,derefok) ((r).t == RXCON && !conht[(r).i].cls && (derefok || !conht[(r).i].deref))
-#define intconval(r) ((r).t == RICON ? (r).i : conht[(r).i].i)
-#define fltconval(r) ((r).t == RICON ? (r).i : conht[(r).i].f)
+#define isfltcon(r) ((r).t == RXCON && kisflt(contab.p[(r).i].cls))
+#define isnumcon(r) ((r).t == RICON || ((r).t == RXCON && contab.p[(r).i].cls))
+#define isaddrcon(r,derefok) ((r).t == RXCON && !contab.p[(r).i].cls && (derefok || !contab.p[(r).i].deref))
+#define intconval(r) ((r).t == RICON ? (r).i : contab.p[(r).i].i)
+#define fltconval(r) ((r).t == RICON ? (r).i : contab.p[(r).i].f)
union ref mksymref(internstr, enum symflags);
union ref mkdatref(internstr name, union type ctype, uint siz, uint align, const void *, uint n, bool deref);
internstr xcon2sym(int ref);
diff --git a/ir/ssa.c b/ir/ssa.c
index 9d248f4..6598fba 100644
--- a/ir/ssa.c
+++ b/ir/ssa.c
@@ -30,7 +30,7 @@ copyopt(struct function *fn)
union ref arg = ins->l;
if (arg.t == RTMP) k = insrescls(instrtab[arg.i]);
else if (arg.t == RICON) k = cls2siz[ins->cls] == 4 ? KI32 : KI64;
- else if (arg.t == RXCON) k = isnumcon(arg) ? conht[arg.i].cls : KPTR;
+ else if (arg.t == RXCON) k = isnumcon(arg) ? concls(arg) : KPTR;
else continue;
if (ins->cls != k) continue;
diff --git a/x86_64/emit.c b/x86_64/emit.c
index 17ea1f3..0d7b77a 100644
--- a/x86_64/emit.c
+++ b/x86_64/emit.c
@@ -46,13 +46,13 @@ ref2oper(union ref r)
case RREG: return reg2oper(r.i);
case RICON: return mkoper(OIMM, .imm = r.i);
case RXCON:
- if (conht[r.i].cls == KI32)
- return mkoper(OIMM, .imm = conht[r.i].i);
- else if (conht[r.i].cls == KI64) {
- vlong i = conht[r.i].i;
+ if (contab.p[r.i].cls == KI32)
+ return mkoper(OIMM, .imm = contab.p[r.i].i);
+ else if (contab.p[r.i].cls == KI64) {
+ vlong i = contab.p[r.i].i;
assert(i == (int)i);
return mkoper(OIMM, .imm = i);
- } else if (!conht[r.i].cls) {
+ } else if (!contab.p[r.i].cls) {
return mkoper(OSYM, .con = r.i, .cindex = NOINDEX);
}
assert(0);
@@ -107,14 +107,14 @@ mkimmregoper(union ref r)
static inline struct oper
mkdatregoper(union ref r)
{
- assert(isregref(r) || (r.t == RXCON && conht[r.i].deref));
+ assert(isregref(r) || (r.t == RXCON && contab.p[r.i].deref));
return ref2oper(r);
}
static inline struct oper
mkimmdatregoper(union ref r)
{
- assert(isregref(r) || r.t == RICON || (r.t == RXCON && (conht[r.i].cls == KI32 || conht[r.i].deref)));
+ assert(isregref(r) || r.t == RICON || (r.t == RXCON && (contab.p[r.i].cls == KI32 || contab.p[r.i].deref)));
return ref2oper(r);
}
@@ -151,7 +151,7 @@ mkmemoper(union ref r)
.disp = addr->disp,
.shift = addr->shift);
} else if (r.t == RXCON) {
- assert(!conht[r.i].cls);
+ assert(!contab.p[r.i].cls);
return mkoper(OSYM, .con = r.i, .cindex = NOINDEX);
} else {
return mkoper(OMEM, .base = isregref(r) ? ref2oper(r).reg : NOBASE,
@@ -869,8 +869,8 @@ gencopy(uchar **pcode, enum irclass cls, struct block *blk, int curi, struct ope
}
/* normal (not 2-address) case */
Lea:
- if (isaddrcon(addr->base,0) && (ccopt.pic || (conht[addr->base.i].flag & SFUNC))
- && !(conht[addr->base.i].flag & SLOCAL)) {
+ if (isaddrcon(addr->base,0) && (ccopt.pic || (contab.p[addr->base.i].flag & SFUNC))
+ && !(contab.p[addr->base.i].flag & SLOCAL)) {
assert(!addr->disp && !addr->index.bits);
val = addr->base;
goto GOTLoad;
@@ -880,7 +880,7 @@ gencopy(uchar **pcode, enum irclass cls, struct block *blk, int curi, struct ope
/* dst = 0 -> xor dst, dst; but only if it is ok to clobber flags */
Xxor(pcode, kisint(cls) ? KI32 : cls, dst, dst);
} else if (isaddrcon(val,0)) {
- if ((ccopt.pic || (conht[val.i].flag & SFUNC)) && !(conht[val.i].flag & SLOCAL)) {
+ if ((ccopt.pic || (contab.p[val.i].flag & SFUNC)) && !(contab.p[val.i].flag & SLOCAL)) {
GOTLoad:
/* for mov reg, [rip(sym@GOTPCREL)] */
Xmov(pcode, cls, dst, mkoper(OSYMGOT, .con = val.i, .cindex = NOINDEX));
diff --git a/x86_64/isel.c b/x86_64/isel.c
index 3faa7fc..7f82984 100644
--- a/x86_64/isel.c
+++ b/x86_64/isel.c
@@ -54,7 +54,7 @@ fixarg(union ref *r, struct instr *ins, struct block *blk, int *curi)
enum op op = ins ? ins->op : 0;
if (r->t == RXCON) {
- struct xcon *con = &conht[r->i];
+ struct xcon *con = &contab.p[r->i];
if (in_range(op, Oshl, Oslr) && r == &ins->r) {
sh = con->i;
goto ShiftImm;
@@ -293,7 +293,7 @@ fuseaddr(union ref *r, struct block *blk, int *curi)
if (r->t != RSTACK && r->t != RTMP) return 0;
if (!aadd(&addr, blk, curi, *r)) return 0;
- if (isaddrcon(addr.base,0) && (ccopt.pic || (ccopt.pie && addr.index.bits) || (conht[addr.base.i].flag & SFUNC))) {
+ if (isaddrcon(addr.base,0) && (ccopt.pic || (ccopt.pie && addr.index.bits) || (contab.p[addr.base.i].flag & SFUNC))) {
/* pic needs to load from GOT */
/* pie cannot encode RIP-relative address with index register */
/* first load symbol address into a temp register */
@@ -318,7 +318,7 @@ static bool
addarg4addrp(union ref r)
{
struct instr *ins;
- if (r.t == RXCON && !conht[r.i].cls && !conht[r.i].deref) return 1; /* sym or dat ref */
+ if (r.t == RXCON && !contab.p[r.i].cls && !contab.p[r.i].deref) return 1; /* sym or dat ref */
if (r.t == RSTACK) return 1;
if (r.t != RTMP) return 0;
ins = &instrtab[r.i];
@@ -574,7 +574,7 @@ seljmp(struct function *fn, struct block *blk)
fixarg(&blk->jmp.arg[0], NULL, blk, &curi);
union ref c = blk->jmp.arg[0];
if (c.t != RTMP) {
- enum irclass cls = c.t == RICON ? KI32 : c.t == RXCON && conht[c.i].cls ? conht[c.i].cls : KPTR;
+ enum irclass cls = c.t == RICON ? KI32 : c.t == RXCON && contab.p[c.i].cls ? contab.p[c.i].cls : KPTR;
int curi = blk->ins.n;
c = insertinstr(blk, blk->ins.n, mkinstr(Ocopy, cls, c));