commit 562164e

hovercats  ·  2024-02-08 23:06:30 +0000 UTC
parent c93044f
qbe: sync with upstream | bump to latest commit
3 files changed,  +85, -2
+83, -0
 1@@ -0,0 +1,83 @@
 2+From 55b93f727cbad62a13dce0136077b0ffb47b90d7 Mon Sep 17 00:00:00 2001
 3+From: =?UTF-8?q?=C3=89rico=20Nogueira?= <erico.erc@gmail.com>
 4+Date: Sun, 11 Jul 2021 19:19:12 -0300
 5+Subject: [PATCH] amd64: optimize loading 0 into registers
 6+
 7+Loading +0 into a floating point register can be done using pxor or
 8+xorps instructions. Per [1], we went with pxor because it can run on all
 9+vector ALU ports, even if it's one byte longer.
10+
11+Similarly, an integer register can be zeroed with xor, which has a
12+smaller encoding than mov with 0 immediate.
13+
14+To implement this, we special case fixarg to allow Ocopy when the
15+value is +0 for floating point, and change emitins to emit pxor/xor
16+when it encounters a copy from 0.
17+
18+Co-authored-by: Michael Forney <mforney@mforney.org>
19+
20+[1] https://stackoverflow.com/questions/39811577/does-using-mix-of-pxor-and-xorps-affect-performance/39828976
21+---
22+ amd64/emit.c | 12 ++++++++++++
23+ amd64/isel.c | 12 +++++++-----
24+ 2 files changed, 19 insertions(+), 5 deletions(-)
25+
26+diff --git a/amd64/emit.c b/amd64/emit.c
27+index 51d1a5c..a3e72e6 100644
28+--- a/amd64/emit.c
29++++ b/amd64/emit.c
30+@@ -458,6 +458,18 @@ emitins(Ins i, Fn *fn, FILE *f)
31+ 		if (req(i.to, i.arg[0]))
32+ 			break;
33+ 		t0 = rtype(i.arg[0]);
34++		if (t0 == RCon
35++		&& fn->con[i.arg[0].val].type == CBits
36++		&& fn->con[i.arg[0].val].bits.i == 0) {
37++			if (isreg(i.to)) {
38++				if (KBASE(i.cls) == 0)
39++					emitf("xor%k %=, %=", &i, fn, f);
40++				else
41++					emitf("pxor %D=, %D=", &i, fn, f);
42++				break;
43++			}
44++			i.cls = KWIDE(i.cls) ? Kl : Kw;
45++		}
46+ 		if (i.cls == Kl
47+ 		&& t0 == RCon
48+ 		&& fn->con[i.arg[0].val].type == CBits) {
49+diff --git a/amd64/isel.c b/amd64/isel.c
50+index e29c8bf..4bec2e1 100644
51+--- a/amd64/isel.c
52++++ b/amd64/isel.c
53+@@ -85,7 +85,7 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn)
54+ 	r1 = r0 = *r;
55+ 	s = rslot(r0, fn);
56+ 	op = i ? i->op : Ocopy;
57+-	if (KBASE(k) == 1 && rtype(r0) == RCon) {
58++	if (KBASE(k) == 1 && rtype(r0) == RCon && fn->con[r0.val].bits.i != 0) {
59+ 		/* load floating points from memory
60+ 		 * slots, they can't be used as
61+ 		 * immediates
62+@@ -99,13 +99,15 @@ fixarg(Ref *r, int k, Ins *i, Fn *fn)
63+ 		a.offset.sym.id = intern(buf);
64+ 		fn->mem[fn->nmem-1] = a;
65+ 	}
66+-	else if (op != Ocopy && k == Kl && noimm(r0, fn)) {
67++	else if (op != Ocopy && ((k == Kl && noimm(r0, fn)) || (KBASE(k) == 1 && rtype(r0) == RCon))) {
68+ 		/* load constants that do not fit in
69+ 		 * a 32bit signed integer into a
70+-		 * long temporary
71++		 * long temporary OR
72++		 * load positive zero into a floating
73++		 * point register
74+ 		 */
75+-		r1 = newtmp("isel", Kl, fn);
76+-		emit(Ocopy, Kl, r1, r0, R);
77++		r1 = newtmp("isel", k, fn);
78++		emit(Ocopy, k, r1, r0, R);
79+ 	}
80+ 	else if (s != -1) {
81+ 		/* load fast locals' addresses into
82+-- 
83+2.42.0
84+
+1, -1
1@@ -1 +1 @@
2-Subproject commit f1b21d145ba03c6052b4b722dc457f8e944e6fca
3+Subproject commit 2d683e0c53907ebca9abde876dd87af70719e42d
+1, -1
1@@ -1 +1 @@
2-1.1 r0
3+1.1-31-g2d683e0c53 r0