* [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).