[RFC PATCH] implement volatile load/store
Export this patch
This is an attempt to implement volatile load/store. Currently they are
unimplemented for arm64 and rv64, but right now I just want to make
sure people more familiar with qbe think the approach is reasonable.
Thanks, it looks okay to me but I have mixed feelings about
adding it to qbe. Frontends that want to make sure store/loads
are not eliminated and reordered can just issue function
calls to small stubs that read/write memory. This clearly
does not generate the best code, but it should work. If we
want to venture into these kind of subtle memory model
considerations, I'd rather we tackle directly the elephant
in the room: atomics. That'd be more helpful than 'volatile'
which only C has.
Just to be clear here, C atomics could similarly be implemented with
function calls?
I'm guessing you're looking for a useful QBE IL abstraction for memory
barriers and/or cache "locking" instructions?
Nonetheless, thanks for your contribution.
Essentially I took all of the existing load/store instructions, and
made duplicates which don't go through any of the optimization passes.
Nice, and seems reasonable to me.
---
all.h | 2 ++
amd64/isel.c | 12 ++++++++++++
ops.h | 15 +++++++++++++++
parse.c | 16 ++++++++++++++ --
ssa.c | 2 ++
tools/lexh.c | 11 +++++++ ----
6 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/all.h b/all.h
index bb6f096..9679fd2 100644
--- a/all.h
+++ b/all.h
@@ -190,7 +190,9 @@ enum {
#define INRANGE(x, l, u) ((unsigned)(x) - l <= u - l) /* linear in x */
#define isstore(o) INRANGE(o, Ostoreb, Ostored)
+ #define isvstore(o) INRANGE(o, Ovstoreb, Ovstored)
#define isload(o) INRANGE(o, Oloadsb, Oload)
+ #define isvload(o) INRANGE(o, Ovloadsb, Ovload)
#define isext(o) INRANGE(o, Oextsb, Oextuw)
#define ispar(o) INRANGE(o, Opar, Opare)
#define isarg(o) INRANGE(o, Oarg, Oargv)
diff --git a/amd64/isel.c b/amd64/isel.c
index ed0ba66..0db4f8f 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -385,6 +385,14 @@ sel(Ins i, Num *tn, Fn *fn)
break;
case Onop:
break;
+ case Ovstored:
+ case Ovstores:
+ case Ovstorel:
+ case Ovstorew:
+ case Ovstoreh:
+ case Ovstoreb:
+ i.op = i.op - Ovstoreb + Ostoreb;
+ /* fallthrough */
case Ostored:
case Ostores:
case Ostorel:
@@ -438,6 +446,10 @@ Emit:
goto case_OExt;
if (isload(i.op))
goto case_Oload;
+ if (isvload(i.op)) {
+ i.op = i.op - Ovloadsb + Oloadsb;
+ goto case_Oload;
+ }
if (iscmp(i.op, &kc, &x)) {
switch (x) {
case NCmpI+Cfeq:
diff --git a/ops.h b/ops.h
index 8ccf80d..ed4bac8 100644
--- a/ops.h
+++ b/ops.h
@@ -82,6 +82,13 @@ O(storel, T(l,e,e,e, m,e,e,e), 0) X(0, 0, 1) V(0)
O(stores, T(s,e,e,e, m,e,e,e), 0) X(0, 0, 1) V(0)
O(stored, T(d,e,e,e, m,e,e,e), 0) X(0, 0, 1) V(0)
+ O(vstoreb, T(w,e,e,e, m,e,e,e), 0) X(0, 0, 1) V(0)
+ O(vstoreh, T(w,e,e,e, m,e,e,e), 0) X(0, 0, 1) V(0)
+ O(vstorew, T(w,e,e,e, m,e,e,e), 0) X(0, 0, 1) V(0)
+ O(vstorel, T(l,e,e,e, m,e,e,e), 0) X(0, 0, 1) V(0)
+ O(vstores, T(s,e,e,e, m,e,e,e), 0) X(0, 0, 1) V(0)
+ O(vstored, T(d,e,e,e, m,e,e,e), 0) X(0, 0, 1) V(0)
+
O(loadsb, T(m,m,e,e, x,x,e,e), 0) X(0, 0, 1) V(0)
O(loadub, T(m,m,e,e, x,x,e,e), 0) X(0, 0, 1) V(0)
O(loadsh, T(m,m,e,e, x,x,e,e), 0) X(0, 0, 1) V(0)
@@ -90,6 +97,14 @@ O(loadsw, T(m,m,e,e, x,x,e,e), 0) X(0, 0, 1) V(0)
O(loaduw, T(m,m,e,e, x,x,e,e), 0) X(0, 0, 1) V(0)
O(load, T(m,m,m,m, x,x,x,x), 0) X(0, 0, 1) V(0)
+ O(vloadsb, T(m,m,e,e, x,x,e,e), 0) X(0, 0, 1) V(0)
+ O(vloadub, T(m,m,e,e, x,x,e,e), 0) X(0, 0, 1) V(0)
+ O(vloadsh, T(m,m,e,e, x,x,e,e), 0) X(0, 0, 1) V(0)
+ O(vloaduh, T(m,m,e,e, x,x,e,e), 0) X(0, 0, 1) V(0)
+ O(vloadsw, T(m,m,e,e, x,x,e,e), 0) X(0, 0, 1) V(0)
+ O(vloaduw, T(m,m,e,e, x,x,e,e), 0) X(0, 0, 1) V(0)
+ O(vload, T(m,m,m,m, x,x,x,x), 0) X(0, 0, 1) V(0)
+
/* Extensions and Truncations */
O(extsb, T(w,w,e,e, x,x,e,e), 1) X(0, 0, 1) V(0)
O(extub, T(w,w,e,e, x,x,e,e), 1) X(0, 0, 1) V(0)
diff --git a/parse.c b/parse.c
index 6dee38f..b2417ef 100644
--- a/parse.c
+++ b/parse.c
@@ -35,6 +35,10 @@ enum Token {
Tloadl,
Tloads,
Tloadd,
+ Tvloadw,
+ Tvloadl,
+ Tvloads,
+ Tvloadd,
Talloc1,
Talloc2,
@@ -95,6 +99,10 @@ static char *kwmap[Ntok] = {
[Tloadl] = "loadl",
[Tloads] = "loads",
[Tloadd] = "loadd",
+ [Tvloadw] = "vloadw",
+ [Tvloadl] = "vloadl",
+ [Tvloads] = "vloads",
+ [Tvloadd] = "vloadd",
[Talloc1] = "alloc1",
[Talloc2] = "alloc2",
[Tblit] = "blit",
@@ -134,7 +142,7 @@ enum {
TMask = 16383, /* for temps hash */
BMask = 8191, /* for blocks hash */
- K = 11183273, /* found using tools/lexh.c */
+ K = 913725585, /* found using tools/lexh.c */
M = 23,
};
@@ -607,7 +615,7 @@ parseline(PState ps)
op = next();
break;
default:
- if (isstore(t)) {
+ if (isstore(t) || isvstore(t)) {
case Tblit:
case Tcall:
case Ovastart:
@@ -707,6 +715,10 @@ parseline(PState ps)
op = Oloadsw;
if (op >= Tloadl && op <= Tloadd)
op = Oload;
+ if (op == Tvloadw)
+ op = Ovloadsw;
+ if (op >= Tvloadl && op <= Tvloadd)
+ op = Ovload;
if (op == Talloc1 || op == Talloc2)
op = Oalloc;
if (op == Ovastart && !curf->vararg)
diff --git a/ssa.c b/ssa.c
index 356135b..172e9fa 100644
--- a/ssa.c
+++ b/ssa.c
@@ -82,6 +82,8 @@ filluse(Fn *fn)
w = Wsb + (i->op - Oparsb);
if (isload(i->op) && i->op != Oload)
w = Wsb + (i->op - Oloadsb);
+ if (isvload(i->op) && i->op != Ovload)
+ w = Wsb + (i->op - Ovloadsb);
if (isext(i->op))
w = Wsb + (i->op - Oextsb);
if (w == Wsw || w == Wuw)
diff --git a/tools/lexh.c b/tools/lexh.c
index efc30fe..319b1fb 100644
--- a/tools/lexh.c
+++ b/tools/lexh.c
@@ -9,10 +9,12 @@
char *tok[] = {
"add", "sub", "neg", "div", "rem", "udiv", "urem", "mul",
- "and", "or", "xor", "sar", "shr", "shl", "stored",
- "stores", "storel", "storew", "storeh", "storeb",
- "load", "loadsw", "loaduw", "loadsh", "loaduh",
- "loadsb", "loadub", "extsw", "extuw", "extsh",
+ "and", "or", "xor", "sar", "shr", "shl",
+ "stored", "stores", "storel", "storew", "storeh", "storeb",
+ "load", "loadsw", "loaduw", "loadsh", "loaduh", "loadsb", "loadub",
+ "vstored", "vstores", "vstorel", "vstorew", "vstoreh", "vstoreb",
+ "vload", "vloadsw", "vloaduw", "vloadsh", "vloaduh", "vloadsb", "vloadub",
+ "extsw", "extuw", "extsh",
"extuh", "extsb", "extub", "exts", "truncd",
"stosi", "dtosi", "stoui", "dtoui", "uwtof",
"ultof", "swtof", "sltof", "cast", "copy",
@@ -29,6 +31,7 @@ char *tok[] = {
"function", "type", "data", "section", "align", "dbgfile",
"blit", "l", "w", "sh", "uh", "h", "sb", "ub", "b",
"d", "s", "z", "loadw", "loadl", "loads", "loadd",
+ "vloadw", "vloadl", "vloads", "vloadd",
"alloc1", "alloc2", "thread", "common",
};
--
2.43.0
https://todo.sr.ht/~mcf/cproc/7