linux-sparse.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] factorization of distributive operations
@ 2020-11-27 16:49 Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 1/8] add testscases for some " Luc Van Oostenryck
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-11-27 16:49 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

This series ad the factorization of distributive operations
involving bitwise operators as well as the more classical
	(x * z) + (y * z) --> (x + y) * z

Luc Van Oostenryck (8):
  add testscases for some factorization of distributive operations
  reassoc: add helper can_move_to()
  add helper make_insn_pair() & swap_insn()
  add helper replace_binop()
  refactor simplify_add() to avoid code duplication (preparation)
  refactor simplify_add() to avoid code duplication
  factorize (x OP1 z) OP2 (y OP1 z) into (x OP2 y) OP1 z
  factorize SHIFT(x, s) OP SHIFT(y, s) into SHIFT((x OP y), s)

 simplify.c                        | 217 +++++++++++++++++++++++++++---
 validation/optim/fact-add-mul.c   |  27 ++++
 validation/optim/fact-and-ior.c   |  27 ++++
 validation/optim/fact-and-shift.c |  26 ++++
 validation/optim/fact-ior-and.c   |  27 ++++
 validation/optim/fact-ior-shift.c |  26 ++++
 validation/optim/fact-xor-and.c   |  27 ++++
 validation/optim/fact-xor-shift.c |  26 ++++
 8 files changed, 386 insertions(+), 17 deletions(-)
 create mode 100644 validation/optim/fact-add-mul.c
 create mode 100644 validation/optim/fact-and-ior.c
 create mode 100644 validation/optim/fact-and-shift.c
 create mode 100644 validation/optim/fact-ior-and.c
 create mode 100644 validation/optim/fact-ior-shift.c
 create mode 100644 validation/optim/fact-xor-and.c
 create mode 100644 validation/optim/fact-xor-shift.c

-- 
2.29.2


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/8] add testscases for some factorization of distributive operations
  2020-11-27 16:49 [PATCH 0/8] factorization of distributive operations Luc Van Oostenryck
@ 2020-11-27 16:49 ` Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 2/8] reassoc: add helper can_move_to() Luc Van Oostenryck
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-11-27 16:49 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Add some testcases for factorizations of:
	(x * z) + (y * z) --> (x + y) * z
	(x | z) & (y | z) --> (x & y) | z
	(x & z) | (y & z) --> (x | y) & z
	(x & z) ^ (y & z) --> (x ^ y) & z
and
	(x << s) | (y << s) --> ((x | y) << s)
	and same for &, ^, LSR and ASR.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 validation/optim/fact-add-mul.c   | 28 ++++++++++++++++++++++++++++
 validation/optim/fact-and-ior.c   | 28 ++++++++++++++++++++++++++++
 validation/optim/fact-and-shift.c | 27 +++++++++++++++++++++++++++
 validation/optim/fact-ior-and.c   | 28 ++++++++++++++++++++++++++++
 validation/optim/fact-ior-shift.c | 27 +++++++++++++++++++++++++++
 validation/optim/fact-xor-and.c   | 28 ++++++++++++++++++++++++++++
 validation/optim/fact-xor-shift.c | 27 +++++++++++++++++++++++++++
 7 files changed, 193 insertions(+)
 create mode 100644 validation/optim/fact-add-mul.c
 create mode 100644 validation/optim/fact-and-ior.c
 create mode 100644 validation/optim/fact-and-shift.c
 create mode 100644 validation/optim/fact-ior-and.c
 create mode 100644 validation/optim/fact-ior-shift.c
 create mode 100644 validation/optim/fact-xor-and.c
 create mode 100644 validation/optim/fact-xor-shift.c

diff --git a/validation/optim/fact-add-mul.c b/validation/optim/fact-add-mul.c
new file mode 100644
index 000000000000..48c3d656accc
--- /dev/null
+++ b/validation/optim/fact-add-mul.c
@@ -0,0 +1,28 @@
+int fr_abx(int a, int b, int x) { return ((a * x) + (b * x)) == ((a + b) * x); }
+int fl_abx(int a, int b, int x) { return ((x * a) + (x * b)) == ((a + b) * x); }
+int fm_abx(int a, int b, int x) { return ((a * x) + (x * b)) == ((a + b) * x); }
+int fn_abx(int a, int b, int x) { return ((x * a) + (b * x)) == ((a + b) * x); }
+
+int fr_bax(int b, int a, int x) { return ((a * x) + (b * x)) == ((b + a) * x); }
+int fl_bax(int b, int a, int x) { return ((x * a) + (x * b)) == ((b + a) * x); }
+int fm_bax(int b, int a, int x) { return ((a * x) + (x * b)) == ((b + a) * x); }
+int fn_bax(int b, int a, int x) { return ((x * a) + (b * x)) == ((b + a) * x); }
+
+int fr_axb(int a, int x, int b) { return ((a * x) + (b * x)) == ((a + b) * x); }
+int fl_axb(int a, int x, int b) { return ((x * a) + (x * b)) == ((a + b) * x); }
+int fm_axb(int a, int x, int b) { return ((a * x) + (x * b)) == ((a + b) * x); }
+int fn_axb(int a, int x, int b) { return ((x * a) + (b * x)) == ((a + b) * x); }
+
+int fr_bxa(int b, int x, int a) { return ((b * x) + (a * x)) == ((b + a) * x); }
+int fl_bxa(int b, int x, int a) { return ((x * b) + (x * a)) == ((b + a) * x); }
+int fm_bxa(int b, int x, int a) { return ((b * x) + (x * a)) == ((b + a) * x); }
+int fn_bxa(int b, int x, int a) { return ((x * b) + (a * x)) == ((b + a) * x); }
+
+/*
+ * check-name: fact-add-mul
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/fact-and-ior.c b/validation/optim/fact-and-ior.c
new file mode 100644
index 000000000000..f2a78eddf41d
--- /dev/null
+++ b/validation/optim/fact-and-ior.c
@@ -0,0 +1,28 @@
+int fr_abx(int a, int b, int x) { return ((a | x) & (b | x)) == ((a & b) | x); }
+int fl_abx(int a, int b, int x) { return ((x | a) & (x | b)) == ((a & b) | x); }
+int fm_abx(int a, int b, int x) { return ((a | x) & (x | b)) == ((a & b) | x); }
+int fn_abx(int a, int b, int x) { return ((x | a) & (b | x)) == ((a & b) | x); }
+
+int fr_bax(int b, int a, int x) { return ((a | x) & (b | x)) == ((b & a) | x); }
+int fl_bax(int b, int a, int x) { return ((x | a) & (x | b)) == ((b & a) | x); }
+int fm_bax(int b, int a, int x) { return ((a | x) & (x | b)) == ((b & a) | x); }
+int fn_bax(int b, int a, int x) { return ((x | a) & (b | x)) == ((b & a) | x); }
+
+int fr_axb(int a, int x, int b) { return ((a | x) & (b | x)) == ((a & b) | x); }
+int fl_axb(int a, int x, int b) { return ((x | a) & (x | b)) == ((a & b) | x); }
+int fm_axb(int a, int x, int b) { return ((a | x) & (x | b)) == ((a & b) | x); }
+int fn_axb(int a, int x, int b) { return ((x | a) & (b | x)) == ((a & b) | x); }
+
+int fr_bxa(int b, int x, int a) { return ((b | x) & (a | x)) == ((b & a) | x); }
+int fl_bxa(int b, int x, int a) { return ((x | b) & (x | a)) == ((b & a) | x); }
+int fm_bxa(int b, int x, int a) { return ((b | x) & (x | a)) == ((b & a) | x); }
+int fn_bxa(int b, int x, int a) { return ((x | b) & (a | x)) == ((b & a) | x); }
+
+/*
+ * check-name: fact-and-ior
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/fact-and-shift.c b/validation/optim/fact-and-shift.c
new file mode 100644
index 000000000000..401750216b44
--- /dev/null
+++ b/validation/optim/fact-and-shift.c
@@ -0,0 +1,27 @@
+typedef unsigned int uint;
+typedef   signed int sint;
+
+
+uint fact_and_shl(uint a, uint b, uint s)
+{
+	return ((a << s) & (b << s)) == ((a & b) << s);
+}
+
+uint fact_and_lsr(uint a, uint b, uint s)
+{
+	return ((a >> s) & (b >> s)) == ((a & b) >> s);
+}
+
+sint fact_and_asr(sint a, sint b, sint s)
+{
+	return ((a >> s) & (b >> s)) == ((a & b) >> s);
+}
+
+/*
+ * check-name: fact-and-shift
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/fact-ior-and.c b/validation/optim/fact-ior-and.c
new file mode 100644
index 000000000000..7af89df1e1f0
--- /dev/null
+++ b/validation/optim/fact-ior-and.c
@@ -0,0 +1,28 @@
+int fr_abx(int a, int b, int x) { return ((a & x) | (b & x)) == ((a | b) & x); }
+int fl_abx(int a, int b, int x) { return ((x & a) | (x & b)) == ((a | b) & x); }
+int fm_abx(int a, int b, int x) { return ((a & x) | (x & b)) == ((a | b) & x); }
+int fn_abx(int a, int b, int x) { return ((x & a) | (b & x)) == ((a | b) & x); }
+
+int fr_bax(int b, int a, int x) { return ((a & x) | (b & x)) == ((b | a) & x); }
+int fl_bax(int b, int a, int x) { return ((x & a) | (x & b)) == ((b | a) & x); }
+int fm_bax(int b, int a, int x) { return ((a & x) | (x & b)) == ((b | a) & x); }
+int fn_bax(int b, int a, int x) { return ((x & a) | (b & x)) == ((b | a) & x); }
+
+int fr_axb(int a, int x, int b) { return ((a & x) | (b & x)) == ((a | b) & x); }
+int fl_axb(int a, int x, int b) { return ((x & a) | (x & b)) == ((a | b) & x); }
+int fm_axb(int a, int x, int b) { return ((a & x) | (x & b)) == ((a | b) & x); }
+int fn_axb(int a, int x, int b) { return ((x & a) | (b & x)) == ((a | b) & x); }
+
+int fr_bxa(int b, int x, int a) { return ((b & x) | (a & x)) == ((b | a) & x); }
+int fl_bxa(int b, int x, int a) { return ((x & b) | (x & a)) == ((b | a) & x); }
+int fm_bxa(int b, int x, int a) { return ((b & x) | (x & a)) == ((b | a) & x); }
+int fn_bxa(int b, int x, int a) { return ((x & b) | (a & x)) == ((b | a) & x); }
+
+/*
+ * check-name: fact-ior-and
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/fact-ior-shift.c b/validation/optim/fact-ior-shift.c
new file mode 100644
index 000000000000..07fdf80604dc
--- /dev/null
+++ b/validation/optim/fact-ior-shift.c
@@ -0,0 +1,27 @@
+typedef unsigned int uint;
+typedef   signed int sint;
+
+
+uint fact_ior_shl(uint a, uint b, uint s)
+{
+	return ((a << s) | (b << s)) == ((a | b) << s);
+}
+
+uint fact_ior_lsr(uint a, uint b, uint s)
+{
+	return ((a >> s) | (b >> s)) == ((a | b) >> s);
+}
+
+sint fact_ior_asr(sint a, sint b, sint s)
+{
+	return ((a >> s) | (b >> s)) == ((a | b) >> s);
+}
+
+/*
+ * check-name: fact-ior-shift
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/fact-xor-and.c b/validation/optim/fact-xor-and.c
new file mode 100644
index 000000000000..905cbf4ab659
--- /dev/null
+++ b/validation/optim/fact-xor-and.c
@@ -0,0 +1,28 @@
+int fr_abx(int a, int b, int x) { return ((a & x) ^ (b & x)) == ((a ^ b) & x); }
+int fl_abx(int a, int b, int x) { return ((x & a) ^ (x & b)) == ((a ^ b) & x); }
+int fm_abx(int a, int b, int x) { return ((a & x) ^ (x & b)) == ((a ^ b) & x); }
+int fn_abx(int a, int b, int x) { return ((x & a) ^ (b & x)) == ((a ^ b) & x); }
+
+int fr_bax(int b, int a, int x) { return ((a & x) ^ (b & x)) == ((b ^ a) & x); }
+int fl_bax(int b, int a, int x) { return ((x & a) ^ (x & b)) == ((b ^ a) & x); }
+int fm_bax(int b, int a, int x) { return ((a & x) ^ (x & b)) == ((b ^ a) & x); }
+int fn_bax(int b, int a, int x) { return ((x & a) ^ (b & x)) == ((b ^ a) & x); }
+
+int fr_axb(int a, int x, int b) { return ((a & x) ^ (b & x)) == ((a ^ b) & x); }
+int fl_axb(int a, int x, int b) { return ((x & a) ^ (x & b)) == ((a ^ b) & x); }
+int fm_axb(int a, int x, int b) { return ((a & x) ^ (x & b)) == ((a ^ b) & x); }
+int fn_axb(int a, int x, int b) { return ((x & a) ^ (b & x)) == ((a ^ b) & x); }
+
+int fr_bxa(int b, int x, int a) { return ((b & x) ^ (a & x)) == ((b ^ a) & x); }
+int fl_bxa(int b, int x, int a) { return ((x & b) ^ (x & a)) == ((b ^ a) & x); }
+int fm_bxa(int b, int x, int a) { return ((b & x) ^ (x & a)) == ((b ^ a) & x); }
+int fn_bxa(int b, int x, int a) { return ((x & b) ^ (a & x)) == ((b ^ a) & x); }
+
+/*
+ * check-name: fact-xor-and
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/fact-xor-shift.c b/validation/optim/fact-xor-shift.c
new file mode 100644
index 000000000000..81fcda851400
--- /dev/null
+++ b/validation/optim/fact-xor-shift.c
@@ -0,0 +1,27 @@
+typedef unsigned int uint;
+typedef   signed int sint;
+
+
+uint fact_xor_shl(uint a, uint b, uint s)
+{
+	return ((a << s) ^ (b << s)) == ((a ^ b) << s);
+}
+
+uint fact_xor_lsr(uint a, uint b, uint s)
+{
+	return ((a >> s) ^ (b >> s)) == ((a ^ b) >> s);
+}
+
+sint fact_xor_asr(sint a, sint b, sint s)
+{
+	return ((a >> s) ^ (b >> s)) == ((a ^ b) >> s);
+}
+
+/*
+ * check-name: fact-xor-shift
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/8] reassoc: add helper can_move_to()
  2020-11-27 16:49 [PATCH 0/8] factorization of distributive operations Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 1/8] add testscases for some " Luc Van Oostenryck
@ 2020-11-27 16:49 ` Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 3/8] add helper make_insn_pair() & swap_insn() Luc Van Oostenryck
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-11-27 16:49 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

When transforming IR expressions, it may happen that we want to
reuse an instruction and move a pseudo into it but that this pseudo
is only defined later.

Add a small help to check this: can_move_to().

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 simplify.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/simplify.c b/simplify.c
index de03d315ec33..d16390caed49 100644
--- a/simplify.c
+++ b/simplify.c
@@ -46,6 +46,7 @@
 #include "linearize.h"
 #include "flow.h"
 #include "symbol.h"
+#include "flowgraph.h"
 
 ///
 // Utilities
@@ -1508,6 +1509,42 @@ static inline int simple_pseudo(pseudo_t pseudo)
 	return pseudo->type == PSEUDO_VAL || pseudo->type == PSEUDO_SYM;
 }
 
+///
+// test if, in the given BB, the ordering of 2 instructions
+static bool insn_before(struct basic_block *bb, struct instruction *x, struct instruction *y)
+{
+	struct instruction *insn;
+
+	FOR_EACH_PTR(bb->insns, insn) {
+		if (insn == x)
+			return true;
+		if (insn == y)
+			return false;
+	} END_FOR_EACH_PTR(insn);
+	return false;
+}
+
+///
+// check if it safe for a pseudo to be used by an instruction
+static inline bool can_move_to(pseudo_t src, struct instruction *dst)
+{
+	struct basic_block *bbs, *bbd;
+	struct instruction *def;
+
+	if (!one_use(dst->target))
+		return false;
+	if (src->type != PSEUDO_REG)
+		return true;
+
+	def = src->def;
+	bbs = def->bb;
+	bbd = dst->bb;
+	if (bbs == bbd)
+		return insn_before(bbs, def, dst);
+	else
+		return domtree_dominates(bbs, bbd);
+}
+
 static int simplify_associative_binop(struct instruction *insn)
 {
 	struct instruction *def;
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/8] add helper make_insn_pair() & swap_insn()
  2020-11-27 16:49 [PATCH 0/8] factorization of distributive operations Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 1/8] add testscases for some " Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 2/8] reassoc: add helper can_move_to() Luc Van Oostenryck
@ 2020-11-27 16:49 ` Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 4/8] add helper replace_binop() Luc Van Oostenryck
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-11-27 16:49 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Add two helpers to create instruction pair OUT(IN(a, b), c).

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 simplify.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/simplify.c b/simplify.c
index d16390caed49..24b3dcb52428 100644
--- a/simplify.c
+++ b/simplify.c
@@ -506,6 +506,37 @@ static inline int replace_opcode(struct instruction *insn, int op)
 	return REPEAT_CSE;
 }
 
+///
+// create an instruction pair OUT(IN(a, b), c)
+static int replace_insn_pair(struct instruction *out, int op_out, struct instruction *in, int op_in, pseudo_t a, pseudo_t b, pseudo_t c)
+{
+	pseudo_t old_a = in->src1;
+	pseudo_t old_b = in->src2;
+	pseudo_t old_1 = out->src1;
+	pseudo_t old_2 = out->src2;
+
+	use_pseudo(in, a, &in->src1);
+	use_pseudo(in, b, &in->src2);
+	use_pseudo(out, in->target, &out->src1);
+	use_pseudo(out, c, &out->src2);
+
+	remove_usage(old_a, &in->src1);
+	remove_usage(old_b, &in->src2);
+	remove_usage(old_1, &out->src1);
+	remove_usage(old_2, &out->src2);
+
+	out->opcode = op_out;
+	in->opcode = op_in;
+	return REPEAT_CSE;
+}
+
+///
+// create an instruction pair OUT(IN(a, b), c) with swapped opcodes
+static inline int swap_insn(struct instruction *out, struct instruction *in, pseudo_t a, pseudo_t b, pseudo_t c)
+{
+	return replace_insn_pair(out, in->opcode, in, out->opcode, a, b, c);
+}
+
 static inline int def_opcode(pseudo_t p)
 {
 	if (p->type != PSEUDO_REG)
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/8] add helper replace_binop()
  2020-11-27 16:49 [PATCH 0/8] factorization of distributive operations Luc Van Oostenryck
                   ` (2 preceding siblings ...)
  2020-11-27 16:49 ` [PATCH 3/8] add helper make_insn_pair() & swap_insn() Luc Van Oostenryck
@ 2020-11-27 16:49 ` Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 5/8] refactor simplify_add() to avoid code duplication (preparation) Luc Van Oostenryck
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-11-27 16:49 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Add an helper to replace a binop OP(a, b) and taking care to
drop the usage of the previous operands.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 simplify.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/simplify.c b/simplify.c
index 24b3dcb52428..046bf02c6d36 100644
--- a/simplify.c
+++ b/simplify.c
@@ -497,6 +497,23 @@ static inline int replace_binop_value(struct instruction *insn, int op, long lon
 	return REPEAT_CSE;
 }
 
+///
+// replace binop's opcode and values
+// @insn: the instruction to be replaced
+// @op: the instruction's new opcode
+// @return: REPEAT_CSE
+static inline int replace_binop(struct instruction *insn, int op, pseudo_t *pa, pseudo_t a, pseudo_t *pb, pseudo_t b)
+{
+	pseudo_t olda = *pa;
+	pseudo_t oldb = *pb;
+	insn->opcode = op;
+	use_pseudo(insn, a, pa);
+	use_pseudo(insn, b, pb);
+	remove_usage(olda, pa);
+	remove_usage(oldb, pb);
+	return REPEAT_CSE;
+}
+
 ///
 // replace the opcode of an instruction
 // @return: REPEAT_CSE
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/8] refactor simplify_add() to avoid code duplication (preparation)
  2020-11-27 16:49 [PATCH 0/8] factorization of distributive operations Luc Van Oostenryck
                   ` (3 preceding siblings ...)
  2020-11-27 16:49 ` [PATCH 4/8] add helper replace_binop() Luc Van Oostenryck
@ 2020-11-27 16:49 ` Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 6/8] refactor simplify_add() to avoid code duplication Luc Van Oostenryck
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-11-27 16:49 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Do some refactoring in simplify_add() to prepare the next patch
which will avoid some code duplication there.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 simplify.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/simplify.c b/simplify.c
index 046bf02c6d36..82ff1242bb0e 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1628,9 +1628,7 @@ static int simplify_add(struct instruction *insn)
 
 	switch (DEF_OPCODE(def, src1)) {
 	case OP_NEG:				// (-x + y) --> (y - x)
-		switch_pseudo(insn, &insn->src1, insn, &insn->src2);
-		insn->opcode = OP_SUB;
-		return replace_pseudo(insn, &insn->src2, def->src);
+		return replace_binop(insn, OP_SUB, &insn->src1, src2, &insn->src2, def->src);
 
 	case OP_SUB:
 		if (def->src2 == src2)		// (x - y) + y --> x
@@ -1640,8 +1638,7 @@ static int simplify_add(struct instruction *insn)
 
 	switch (DEF_OPCODE(def, src2)) {
 	case OP_NEG:				// (x + -y) --> (x - y)
-		insn->opcode = OP_SUB;
-		return replace_pseudo(insn, &insn->src2, def->src);
+		return replace_binop(insn, OP_SUB, &insn->src1, src1, &insn->src2, def->src);
 	case OP_SUB:
 		if (src1 == def->src2)		// x + (y - x) --> y
 			return replace_with_pseudo(insn, def->src1);
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/8] refactor simplify_add() to avoid code duplication
  2020-11-27 16:49 [PATCH 0/8] factorization of distributive operations Luc Van Oostenryck
                   ` (4 preceding siblings ...)
  2020-11-27 16:49 ` [PATCH 5/8] refactor simplify_add() to avoid code duplication (preparation) Luc Van Oostenryck
@ 2020-11-27 16:49 ` Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 7/8] factorize (x OP1 z) OP2 (y OP1 z) into (x OP2 y) OP1 z Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 8/8] factorize SHIFT(x, s) OP SHIFT(y, s) into SHIFT((x OP y), s) Luc Van Oostenryck
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-11-27 16:49 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Do some refactoring in simplify_add() to avoid some code
duplication there and better handle generic transforms
that need to be applied on both operands.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 simplify.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/simplify.c b/simplify.c
index 82ff1242bb0e..5174a903dfd6 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1620,11 +1620,11 @@ static int simplify_associative_binop(struct instruction *insn)
 	return REPEAT_CSE;
 }
 
-static int simplify_add(struct instruction *insn)
+static int simplify_add_one_side(struct instruction *insn, pseudo_t *p1, pseudo_t *p2)
 {
-	pseudo_t src1 = insn->src1;
-	pseudo_t src2 = insn->src2;
 	struct instruction *def;
+	pseudo_t src1 = *p1;
+	pseudo_t src2 = *p2;
 
 	switch (DEF_OPCODE(def, src1)) {
 	case OP_NEG:				// (-x + y) --> (y - x)
@@ -1635,19 +1635,15 @@ static int simplify_add(struct instruction *insn)
 			return replace_with_pseudo(insn, def->src1);
 		break;
 	}
-
-	switch (DEF_OPCODE(def, src2)) {
-	case OP_NEG:				// (x + -y) --> (x - y)
-		return replace_binop(insn, OP_SUB, &insn->src1, src1, &insn->src2, def->src);
-	case OP_SUB:
-		if (src1 == def->src2)		// x + (y - x) --> y
-			return replace_with_pseudo(insn, def->src1);
-		break;
-	}
-
 	return 0;
 }
 
+static int simplify_add(struct instruction *insn)
+{
+	return simplify_add_one_side(insn, &insn->src1, &insn->src2) ||
+	       simplify_add_one_side(insn, &insn->src2, &insn->src1);
+}
+
 static int simplify_sub(struct instruction *insn)
 {
 	pseudo_t src1 = insn->src1;
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 7/8] factorize (x OP1 z) OP2 (y OP1 z) into (x OP2 y) OP1 z
  2020-11-27 16:49 [PATCH 0/8] factorization of distributive operations Luc Van Oostenryck
                   ` (5 preceding siblings ...)
  2020-11-27 16:49 ` [PATCH 6/8] refactor simplify_add() to avoid code duplication Luc Van Oostenryck
@ 2020-11-27 16:49 ` Luc Van Oostenryck
  2020-11-27 16:49 ` [PATCH 8/8] factorize SHIFT(x, s) OP SHIFT(y, s) into SHIFT((x OP y), s) Luc Van Oostenryck
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-11-27 16:49 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Factorize common distributive operations:
	(x * z) + (y * z) --> (x + y) * z
	(x | z) & (y | z) --> (x & y) | z
	(x & z) | (y & z) --> (x | y) & z
	(x & z) ^ (y & z) --> (x ^ y) & z

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 simplify.c                      | 78 +++++++++++++++++++++++++++++++++
 validation/optim/fact-add-mul.c |  1 -
 validation/optim/fact-and-ior.c |  1 -
 validation/optim/fact-ior-and.c |  1 -
 validation/optim/fact-xor-and.c |  1 -
 5 files changed, 78 insertions(+), 4 deletions(-)

diff --git a/simplify.c b/simplify.c
index 5174a903dfd6..319112a90b7b 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1622,11 +1622,32 @@ static int simplify_associative_binop(struct instruction *insn)
 
 static int simplify_add_one_side(struct instruction *insn, pseudo_t *p1, pseudo_t *p2)
 {
+	struct instruction *defr = NULL;
 	struct instruction *def;
 	pseudo_t src1 = *p1;
 	pseudo_t src2 = *p2;
 
 	switch (DEF_OPCODE(def, src1)) {
+	case OP_MUL:
+		if (DEF_OPCODE(defr, *p2) == OP_MUL) {
+			if (defr->src2 == def->src2 && can_move_to(def->src2, defr)) {
+				// ((x * z) + (y * z)) into ((x + y) * z)
+				swap_insn(insn, defr, def->src1, defr->src1, def->src2);
+				return REPEAT_CSE;
+			}
+			if (defr->src1 == def->src1 && can_move_to(def->src1, defr)) {
+				// ((z * x) + (z * y)) into ((x + y) * z)
+				swap_insn(insn, defr, def->src2, defr->src2, def->src1);
+				return REPEAT_CSE;
+			}
+			if (defr->src1 == def->src2 && can_move_to(def->src1, defr)) {
+				// ((x * z) + (z * y)) into ((x + y) * z)
+				swap_insn(insn, defr, def->src1, defr->src2, def->src2);
+				return REPEAT_CSE;
+			}
+		}
+		break;
+
 	case OP_NEG:				// (-x + y) --> (y - x)
 		return replace_binop(insn, OP_SUB, &insn->src1, src2, &insn->src2, def->src);
 
@@ -1714,6 +1735,25 @@ static int simplify_and_one_side(struct instruction *insn, pseudo_t *p1, pseudo_
 				return replace_with_value(insn, 0);
 		}
 		break;
+	case OP_OR:
+		if (DEF_OPCODE(defr, *p2) == OP_OR) {
+			if (defr->src2 == def->src2 && can_move_to(def->src2, defr)) {
+				// ((x | z) & (y | z)) into ((x & y) | z)
+				swap_insn(insn, defr, def->src1, defr->src1, def->src2);
+				return REPEAT_CSE;
+			}
+			if (defr->src1 == def->src1 && can_move_to(def->src1, defr)) {
+				// ((z | x) & (z | y)) into ((x & y) | z)
+				swap_insn(insn, defr, def->src2, defr->src2, def->src1);
+				return REPEAT_CSE;
+			}
+			if (defr->src1 == def->src2 && can_move_to(def->src1, defr)) {
+				// ((x | z) & (z | y)) into ((x & y) | z)
+				swap_insn(insn, defr, def->src1, defr->src2, def->src2);
+				return REPEAT_CSE;
+			}
+		}
+		break;
 	}
 	return 0;
 }
@@ -1730,6 +1770,25 @@ static int simplify_ior_one_side(struct instruction *insn, pseudo_t *p1, pseudo_
 	pseudo_t src1 = *p1;
 
 	switch (DEF_OPCODE(def, src1)) {
+	case OP_AND:
+		if (DEF_OPCODE(defr, *p2) == OP_AND) {
+			if (defr->src2 == def->src2 && can_move_to(def->src2, defr)) {
+				// ((x & z) | (y & z)) into ((x | y) & z)
+				swap_insn(insn, defr, def->src1, defr->src1, def->src2);
+				return REPEAT_CSE;
+			}
+			if (defr->src1 == def->src1 && can_move_to(def->src1, defr)) {
+				// ((z & x) | (z & y)) into ((x | y) & z)
+				swap_insn(insn, defr, def->src2, defr->src2, def->src1);
+				return REPEAT_CSE;
+			}
+			if (defr->src1 == def->src2 && can_move_to(def->src1, defr)) {
+				// ((x & z) | (z & y)) into ((x | y) & z)
+				swap_insn(insn, defr, def->src1, defr->src2, def->src2);
+				return REPEAT_CSE;
+			}
+		}
+		break;
 	case OP_NOT:
 		if (def->src == *p2)
 			return replace_with_value(insn, bits_mask(insn->size));
@@ -1756,6 +1815,25 @@ static int simplify_xor_one_side(struct instruction *insn, pseudo_t *p1, pseudo_
 	pseudo_t src1 = *p1;
 
 	switch (DEF_OPCODE(def, src1)) {
+	case OP_AND:
+		if (DEF_OPCODE(defr, *p2) == OP_AND) {
+			if (defr->src2 == def->src2 && can_move_to(def->src2, defr)) {
+				// ((x & z) ^ (y & z)) into ((x ^ y) & z)
+				swap_insn(insn, defr, def->src1, defr->src1, def->src2);
+				return REPEAT_CSE;
+			}
+			if (defr->src1 == def->src1 && can_move_to(def->src1, defr)) {
+				// ((z & x) ^ (z & y)) into ((x ^ y) & z)
+				swap_insn(insn, defr, def->src2, defr->src2, def->src1);
+				return REPEAT_CSE;
+			}
+			if (defr->src1 == def->src2 && can_move_to(def->src1, defr)) {
+				// ((x & z) ^ (z & y)) into ((x ^ y) & z)
+				swap_insn(insn, defr, def->src1, defr->src2, def->src2);
+				return REPEAT_CSE;
+			}
+		}
+		break;
 	case OP_NOT:
 		if (def->src == *p2)
 			return replace_with_value(insn, bits_mask(insn->size));
diff --git a/validation/optim/fact-add-mul.c b/validation/optim/fact-add-mul.c
index 48c3d656accc..9da6d71c9a7d 100644
--- a/validation/optim/fact-add-mul.c
+++ b/validation/optim/fact-add-mul.c
@@ -21,7 +21,6 @@ int fn_bxa(int b, int x, int a) { return ((x * b) + (a * x)) == ((b + a) * x); }
 /*
  * check-name: fact-add-mul
  * check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-returns: 1
diff --git a/validation/optim/fact-and-ior.c b/validation/optim/fact-and-ior.c
index f2a78eddf41d..96466616d877 100644
--- a/validation/optim/fact-and-ior.c
+++ b/validation/optim/fact-and-ior.c
@@ -21,7 +21,6 @@ int fn_bxa(int b, int x, int a) { return ((x | b) & (a | x)) == ((b & a) | x); }
 /*
  * check-name: fact-and-ior
  * check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-returns: 1
diff --git a/validation/optim/fact-ior-and.c b/validation/optim/fact-ior-and.c
index 7af89df1e1f0..a6ad3c45515d 100644
--- a/validation/optim/fact-ior-and.c
+++ b/validation/optim/fact-ior-and.c
@@ -21,7 +21,6 @@ int fn_bxa(int b, int x, int a) { return ((x & b) | (a & x)) == ((b | a) & x); }
 /*
  * check-name: fact-ior-and
  * check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-returns: 1
diff --git a/validation/optim/fact-xor-and.c b/validation/optim/fact-xor-and.c
index 905cbf4ab659..62232b29da40 100644
--- a/validation/optim/fact-xor-and.c
+++ b/validation/optim/fact-xor-and.c
@@ -21,7 +21,6 @@ int fn_bxa(int b, int x, int a) { return ((x & b) ^ (a & x)) == ((b ^ a) & x); }
 /*
  * check-name: fact-xor-and
  * check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-returns: 1
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 8/8] factorize SHIFT(x, s) OP SHIFT(y, s) into SHIFT((x OP y), s)
  2020-11-27 16:49 [PATCH 0/8] factorization of distributive operations Luc Van Oostenryck
                   ` (6 preceding siblings ...)
  2020-11-27 16:49 ` [PATCH 7/8] factorize (x OP1 z) OP2 (y OP1 z) into (x OP2 y) OP1 z Luc Van Oostenryck
@ 2020-11-27 16:49 ` Luc Van Oostenryck
  7 siblings, 0 replies; 9+ messages in thread
From: Luc Van Oostenryck @ 2020-11-27 16:49 UTC (permalink / raw)
  To: linux-sparse; +Cc: Luc Van Oostenryck

Factorize bitwise OPs of shifts with identical counts.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 simplify.c                        | 27 +++++++++++++++++++++++++++
 validation/optim/fact-and-shift.c |  1 -
 validation/optim/fact-ior-shift.c |  1 -
 validation/optim/fact-xor-shift.c |  1 -
 4 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/simplify.c b/simplify.c
index 319112a90b7b..89a064b93e85 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1754,6 +1754,15 @@ static int simplify_and_one_side(struct instruction *insn, pseudo_t *p1, pseudo_
 			}
 		}
 		break;
+	case OP_SHL: case OP_LSR: case OP_ASR:
+		if (DEF_OPCODE(defr, *p2) == def->opcode && defr->src2 == def->src2) {
+			if (can_move_to(def->src1, defr)) {
+				// SHIFT(x, s) & SHIFT(y, s) --> SHIFT((x & y), s)
+				swap_insn(insn, defr, def->src1, defr->src1, def->src2);
+				return REPEAT_CSE;
+			}
+		}
+		break;
 	}
 	return 0;
 }
@@ -1799,6 +1808,15 @@ static int simplify_ior_one_side(struct instruction *insn, pseudo_t *p1, pseudo_
 				return replace_with_value(insn, 1);
 		}
 		break;
+	case OP_SHL: case OP_LSR: case OP_ASR:
+		if (DEF_OPCODE(defr, *p2) == def->opcode && defr->src2 == def->src2) {
+			if (can_move_to(def->src1, defr)) {
+				// SHIFT(x, s) | SHIFT(y, s) --> SHIFT((x | y), s)
+				swap_insn(insn, defr, def->src1, defr->src1, def->src2);
+				return REPEAT_CSE;
+			}
+		}
+		break;
 	}
 	return 0;
 }
@@ -1844,6 +1862,15 @@ static int simplify_xor_one_side(struct instruction *insn, pseudo_t *p1, pseudo_
 				return replace_with_value(insn, 1);
 		}
 		break;
+	case OP_SHL: case OP_LSR: case OP_ASR:
+		if (DEF_OPCODE(defr, *p2) == def->opcode && defr->src2 == def->src2) {
+			if (can_move_to(def->src1, defr)) {
+				// SHIFT(x, s) ^ SHIFT(y, s) --> SHIFT((x ^ y), s)
+				swap_insn(insn, defr, def->src1, defr->src1, def->src2);
+				return REPEAT_CSE;
+			}
+		}
+		break;
 	}
 	return 0;
 }
diff --git a/validation/optim/fact-and-shift.c b/validation/optim/fact-and-shift.c
index 401750216b44..e9eb9cceef95 100644
--- a/validation/optim/fact-and-shift.c
+++ b/validation/optim/fact-and-shift.c
@@ -20,7 +20,6 @@ sint fact_and_asr(sint a, sint b, sint s)
 /*
  * check-name: fact-and-shift
  * check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-returns: 1
diff --git a/validation/optim/fact-ior-shift.c b/validation/optim/fact-ior-shift.c
index 07fdf80604dc..5fa91eb5cfc2 100644
--- a/validation/optim/fact-ior-shift.c
+++ b/validation/optim/fact-ior-shift.c
@@ -20,7 +20,6 @@ sint fact_ior_asr(sint a, sint b, sint s)
 /*
  * check-name: fact-ior-shift
  * check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-returns: 1
diff --git a/validation/optim/fact-xor-shift.c b/validation/optim/fact-xor-shift.c
index 81fcda851400..5fb228bd80a1 100644
--- a/validation/optim/fact-xor-shift.c
+++ b/validation/optim/fact-xor-shift.c
@@ -20,7 +20,6 @@ sint fact_xor_asr(sint a, sint b, sint s)
 /*
  * check-name: fact-xor-shift
  * check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-returns: 1
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2020-11-27 16:52 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-27 16:49 [PATCH 0/8] factorization of distributive operations Luc Van Oostenryck
2020-11-27 16:49 ` [PATCH 1/8] add testscases for some " Luc Van Oostenryck
2020-11-27 16:49 ` [PATCH 2/8] reassoc: add helper can_move_to() Luc Van Oostenryck
2020-11-27 16:49 ` [PATCH 3/8] add helper make_insn_pair() & swap_insn() Luc Van Oostenryck
2020-11-27 16:49 ` [PATCH 4/8] add helper replace_binop() Luc Van Oostenryck
2020-11-27 16:49 ` [PATCH 5/8] refactor simplify_add() to avoid code duplication (preparation) Luc Van Oostenryck
2020-11-27 16:49 ` [PATCH 6/8] refactor simplify_add() to avoid code duplication Luc Van Oostenryck
2020-11-27 16:49 ` [PATCH 7/8] factorize (x OP1 z) OP2 (y OP1 z) into (x OP2 y) OP1 z Luc Van Oostenryck
2020-11-27 16:49 ` [PATCH 8/8] factorize SHIFT(x, s) OP SHIFT(y, s) into SHIFT((x OP y), s) Luc Van Oostenryck

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).