aboutsummaryrefslogtreecommitdiffhomepage
path: root/ir/fold.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2025-11-05 13:56:54 +0100
committerlemon <lsof@mailbox.org>2025-11-05 19:02:44 +0100
commit13471741b538baa45cd53a521cf7d52087f3200f (patch)
tree15624e0f3a2e8a11f2c114f8309af6e3207193c0 /ir/fold.c
parent088c3c1ce51de82ef317592bae766ad20f82208d (diff)
amd64: fix aggregate abi stuff;; ir: fold, peephole optimizing constructors
Diffstat (limited to 'ir/fold.c')
-rw-r--r--ir/fold.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/ir/fold.c b/ir/fold.c
new file mode 100644
index 0000000..fd6076e
--- /dev/null
+++ b/ir/fold.c
@@ -0,0 +1,119 @@
+#include "ir.h"
+
+static union ref
+foldint(enum op op, enum irclass k, union ref lr, union ref rr)
+{
+ vlong x;
+ union {
+ vlong s;
+ uvlong u;
+ } l = {.s = intconval(lr)}, r = {.s = intconval(rr)};
+ bool w = cls2siz[k] == 8;
+ if (in_range(op, Odiv, Ourem)) assert(r.u != 0);
+ switch (op) {
+ case Ocopy: x = l.s; break;
+ case Oneg: x = -l.s; break;
+ case Onot: x = ~l.s; break;
+ case Ocvtf4s: x = (int)(float)fltconval(lr); break;
+ case Ocvtf4u: x = (uint)(float)fltconval(lr); break;
+ case Ocvtf8s: x = (vlong)fltconval(lr); break;
+ case Ocvtf8u: x = (uvlong)fltconval(lr); break;
+ case Oexts1: x = (schar)l.s; break;
+ case Oextu1: x = (uchar)l.s; break;
+ case Oexts2: x = (short)l.s; break;
+ case Oextu2: x = (ushort)l.s; break;
+ case Oexts4: x = (int)l.s; break;
+ case Oextu4: x = (uint)l.s; break;
+ case Oadd: x = l.u + r.u; break;
+ case Osub: x = l.u - r.u; break;
+ case Omul: x = l.u * r.u; break;
+ case Oumul: x = l.u * r.u; break;
+ case Odiv: x = w ? l.s / r.s : (int)l.s / (int)r.s; break;
+ case Oudiv: x = w ? l.u / r.u : (uint)l.u / (uint)r.u; break;
+ case Orem: x = w ? l.s % r.s : (int)l.s % (int)r.s; break;
+ case Ourem: x = w ? l.u % r.u : (uint)l.u % (uint)r.u; break;
+ case Oand: x = l.u & r.u; break;
+ case Oior: x = l.u | r.u; break;
+ case Oxor: x = l.u ^ r.u; break;
+ case Oshl: x = l.u << (r.u & (w ? 63 : 31)); break;
+ case Oslr: x = w ? l.u >> (r.u&63) : (int)l.s >> (r.u&31); break;
+ case Osar: x = w ? l.s >> (r.u&63) : (int)l.s >> (r.u&31); break;
+ case Oequ: x = l.s == r.s; break;
+ case Oneq: x = l.s != r.s; break;
+ case Olth: x = l.s < r.s; break;
+ case Ogth: x = l.s > r.s; break;
+ case Olte: x = l.s <= r.s; break;
+ case Ogte: x = l.s >= r.s; break;
+ case Oulth: x = l.u < r.u; break;
+ case Ougth: x = l.u > r.u; break;
+ case Oulte: x = l.u <= r.u; break;
+ case Ougte: x = l.u >= r.u; break;
+ default: assert(0);
+ }
+ return mkintcon(k, x);
+}
+
+static union ref
+foldflt(enum op op, enum irclass k, union ref lr, union ref rr)
+{
+ int xi;
+ double x, l = fltconval(lr), r = fltconval(rr);
+ bool w = k == KF8;
+ if (in_range(op, Odiv, Ourem)) assert(r != 0.0);
+ switch (op) {
+ case Ocopy: x = l; break;
+ case Oneg: x = -l; break;
+ case Ocvtf4f8: x = (float)l; break;
+ case Ocvtf8f4: x = (float)l; break;
+ case Ocvts4f: x = (int)intconval(lr); break;
+ case Ocvtu4f: x = (int)intconval(lr); break;
+ case Ocvts8f: x = (vlong)intconval(lr); break;
+ case Ocvtu8f: x = (uvlong)intconval(lr); break;
+ case Oadd: x = l + r; break;
+ case Osub: x = l - r; break;
+ case Omul: x = l * r; break;
+ case Odiv: x = l / r; break;
+ case Oequ: xi = l == r; break;
+ case Oneq: xi = l != r; break;
+ case Olth: xi = l < r; break;
+ case Ogth: xi = l > r; break;
+ case Olte: xi = l <= r; break;
+ case Ogte: xi = l >= r; break;
+ default: assert(0);
+ }
+ if (oiscmp(op)) return mkref(RICON, xi);
+ if (!w) x = (float)x;
+ return mkfltcon(k, x);
+}
+
+bool
+foldbinop(union ref *to, enum op op, enum irclass k, union ref l, union ref r)
+{
+ if (!iscon(l) || !iscon(r)) return 0;
+ if (in_range(op, Odiv, Ourem) && (kisint(k) ? intconval(r) == 0 : fltconval(r) == 0))
+ return 0;
+ if (!oisarith(op))
+ return 0;
+ to->t = oiscmp(op) ? KI4 : k;
+ if (kisint(k))
+ *to = foldint(op, k, l, r);
+ else
+ *to = foldflt(op, k, l, r);
+ return 1;
+}
+
+bool
+foldunop(union ref *to, enum op op, enum irclass k, union ref a)
+{
+ if (!iscon(a)) return 0;
+ if (op != Ocopy && !oisarith(op))
+ return 0;
+ to->t = k;
+ if (kisint(k))
+ *to = foldint(op, k, a, ZEROREF);
+ else
+ *to = foldflt(op, k, a, ZEROREF);
+ return 1;
+}
+
+/* vim:set ts=3 sw=3 expandtab: */