* [PATCH 0/5] simplify SEL(SEL, ...), ...)
@ 2020-11-07 11:42 Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 1/5] select: add some testcases for select simplification Luc Van Oostenryck
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Luc Van Oostenryck @ 2020-11-07 11:42 UTC (permalink / raw)
To: linux-sparse; +Cc: Linus Torvalds, Luc Van Oostenryck
These patch add a few simplifications when the condition of a
select is another select and have constants as operands.
@Linus,
The patch you wanted is patch #3.
Luc Van Oostenryck (5):
select: add some testcases for select simplification
select: simplify SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z) and its dual
select: simplify SEL(SEL(x, C, 0), C, 0) --> SEL(x, C, 0) == cond
select: simplify SEL(SEL(x, C1, C2), y, z) --> y (with C1, C2 != 0)
select: simplify handling of constant cond or src1 == src2
simplify.c | 40 ++++++++++++++++----
validation/optim/select-constant-cond.c | 10 +++++
validation/optim/select-same-args.c | 9 +++++
validation/optim/select-select-true-false0.c | 10 +++++
validation/optim/select-select-true-false1.c | 13 +++++++
validation/optim/select-select-true-true.c | 9 +++++
6 files changed, 83 insertions(+), 8 deletions(-)
create mode 100644 validation/optim/select-constant-cond.c
create mode 100644 validation/optim/select-same-args.c
create mode 100644 validation/optim/select-select-true-false0.c
create mode 100644 validation/optim/select-select-true-false1.c
create mode 100644 validation/optim/select-select-true-true.c
--
2.29.2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/5] select: add some testcases for select simplification
2020-11-07 11:42 [PATCH 0/5] simplify SEL(SEL, ...), ...) Luc Van Oostenryck
@ 2020-11-07 11:42 ` Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 2/5] select: simplify SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z) and its dual Luc Van Oostenryck
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Luc Van Oostenryck @ 2020-11-07 11:42 UTC (permalink / raw)
To: linux-sparse; +Cc: Linus Torvalds, Luc Van Oostenryck
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
validation/optim/select-constant-cond.c | 10 ++++++++++
validation/optim/select-same-args.c | 9 +++++++++
validation/optim/select-select-true-false0.c | 11 +++++++++++
validation/optim/select-select-true-false1.c | 14 ++++++++++++++
validation/optim/select-select-true-true.c | 10 ++++++++++
5 files changed, 54 insertions(+)
create mode 100644 validation/optim/select-constant-cond.c
create mode 100644 validation/optim/select-same-args.c
create mode 100644 validation/optim/select-select-true-false0.c
create mode 100644 validation/optim/select-select-true-false1.c
create mode 100644 validation/optim/select-select-true-true.c
diff --git a/validation/optim/select-constant-cond.c b/validation/optim/select-constant-cond.c
new file mode 100644
index 000000000000..a9337e2ceaee
--- /dev/null
+++ b/validation/optim/select-constant-cond.c
@@ -0,0 +1,10 @@
+int t(int p, int a, int b) { return ((p == p) ? a : b) == a; }
+int f(int p, int a, int b) { return ((p != p) ? a : b) == b; }
+
+/*
+ * check-name: select-constant-cond
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/select-same-args.c b/validation/optim/select-same-args.c
new file mode 100644
index 000000000000..403af47169c3
--- /dev/null
+++ b/validation/optim/select-same-args.c
@@ -0,0 +1,9 @@
+int foo(int p, int a) { return (p ? a : a) == a; }
+
+/*
+ * check-name: select-same-args
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/select-select-true-false0.c b/validation/optim/select-select-true-false0.c
new file mode 100644
index 000000000000..46bd7667400d
--- /dev/null
+++ b/validation/optim/select-select-true-false0.c
@@ -0,0 +1,11 @@
+int fw(int p, int a, int b) { return ((p ? 42 : 0) ? a : b) == ( p ? a : b); }
+int bw(int p, int a, int b) { return ((p ? 0 : 42) ? a : b) == ( p ? b : a); }
+
+/*
+ * check-name: select-select-true-false0
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/select-select-true-false1.c b/validation/optim/select-select-true-false1.c
new file mode 100644
index 000000000000..00ffdcd1bc9b
--- /dev/null
+++ b/validation/optim/select-select-true-false1.c
@@ -0,0 +1,14 @@
+int foo(int p)
+{
+ int t = (p ? 42 : 0);
+ return (t ? 42 : 0) == ( p ? 42 : 0);
+}
+
+/*
+ * check-name: select-select-true-false1
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-returns: 1
+ */
diff --git a/validation/optim/select-select-true-true.c b/validation/optim/select-select-true-true.c
new file mode 100644
index 000000000000..e6fa2c89febb
--- /dev/null
+++ b/validation/optim/select-select-true-true.c
@@ -0,0 +1,10 @@
+int foo(int p, int a, int b) { return ((p ? 42 : 43) ? a : b) == a ; }
+
+/*
+ * check-name: select-select-true-true
+ * 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] 8+ messages in thread
* [PATCH 2/5] select: simplify SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z) and its dual
2020-11-07 11:42 [PATCH 0/5] simplify SEL(SEL, ...), ...) Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 1/5] select: add some testcases for select simplification Luc Van Oostenryck
@ 2020-11-07 11:42 ` Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 3/5] select: simplify SEL(SEL(x, C, 0), C, 0) --> SEL(x, C, 0) == cond Luc Van Oostenryck
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Luc Van Oostenryck @ 2020-11-07 11:42 UTC (permalink / raw)
To: linux-sparse; +Cc: Linus Torvalds, Luc Van Oostenryck
If the condition of a select is also a select but with constant
operands, some simplification can be done:
* if the second operand is 0, the original condition can be used,
* idem if the first operand is 0s but the operand must be swapped.
Originally-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
simplify.c | 20 ++++++++++++++++++++
validation/optim/select-select-true-false0.c | 1 -
validation/optim/select-select-true-false1.c | 1 -
3 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/simplify.c b/simplify.c
index f2aaa52de84b..6b44d447c0a9 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1748,6 +1748,7 @@ static int simplify_cast(struct instruction *insn)
static int simplify_select(struct instruction *insn)
{
pseudo_t cond, src1, src2;
+ struct instruction *def;
cond = insn->src1;
src1 = insn->src2;
@@ -1782,6 +1783,25 @@ static int simplify_select(struct instruction *insn)
kill_use(&insn->src3);
return replace_with_value(insn, 0);
}
+
+ switch (DEF_OPCODE(def, cond)) {
+ case OP_SEL:
+ if (constant(def->src2) && constant(def->src3)) {
+ // Is the def of the conditional another select?
+ // And if that one results in a "zero or not", use the
+ // original conditional instead.
+ // SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z)
+ // SEL(SEL(x, 0, C), y, z) --> SEL(x, z, y)
+ if (!def->src3->value) {
+ return replace_pseudo(insn, &insn->cond, def->cond);
+ }
+ if (!def->src2->value) {
+ switch_pseudo(insn, &insn->src2, insn, &insn->src3);
+ return replace_pseudo(insn, &insn->cond, def->cond);
+ }
+ }
+ break;
+ }
return 0;
}
diff --git a/validation/optim/select-select-true-false0.c b/validation/optim/select-select-true-false0.c
index 46bd7667400d..4066c2dad6fc 100644
--- a/validation/optim/select-select-true-false0.c
+++ b/validation/optim/select-select-true-false0.c
@@ -4,7 +4,6 @@ int bw(int p, int a, int b) { return ((p ? 0 : 42) ? a : b) == ( p ? b : a); }
/*
* check-name: select-select-true-false0
* check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
*
* check-output-ignore
* check-output-returns: 1
diff --git a/validation/optim/select-select-true-false1.c b/validation/optim/select-select-true-false1.c
index 00ffdcd1bc9b..32c0364de2ba 100644
--- a/validation/optim/select-select-true-false1.c
+++ b/validation/optim/select-select-true-false1.c
@@ -7,7 +7,6 @@ int foo(int p)
/*
* check-name: select-select-true-false1
* 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] 8+ messages in thread
* [PATCH 3/5] select: simplify SEL(SEL(x, C, 0), C, 0) --> SEL(x, C, 0) == cond
2020-11-07 11:42 [PATCH 0/5] simplify SEL(SEL, ...), ...) Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 1/5] select: add some testcases for select simplification Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 2/5] select: simplify SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z) and its dual Luc Van Oostenryck
@ 2020-11-07 11:42 ` Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 4/5] select: simplify SEL(SEL(x, C1, C2), y, z) --> y (with C1, C2 != 0) Luc Van Oostenryck
` (2 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Luc Van Oostenryck @ 2020-11-07 11:42 UTC (permalink / raw)
To: linux-sparse; +Cc: Linus Torvalds, Luc Van Oostenryck
If the condition of a select is also a select, both with the same
arguments: first a non-zero constant, then a zero constant, then
the outer select is equivalent to the inner one and can thus
be replaced by the result of the inner select (which is its own
condition).
Note: this is a special case of:
SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z)
and without this patch we'll have:
t = SEL(x, C, 0)
r = SEL(t, C, 0)
simplified into:
t = SEL(x, C, 0) // possibly unused now
r = SEL(x, C, 0)
but the present patch do
t = SEL(x, C, 0)
r = t
In other words, functionally, the result is the same but
now the result is taken from the first instruction.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
simplify.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/simplify.c b/simplify.c
index 6b44d447c0a9..1fcfc691579a 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1791,8 +1791,11 @@ static int simplify_select(struct instruction *insn)
// And if that one results in a "zero or not", use the
// original conditional instead.
// SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z)
+ // SEL(SEL(x, C, 0), C, 0) --> SEL(x, C, 0) == cond
// SEL(SEL(x, 0, C), y, z) --> SEL(x, z, y)
if (!def->src3->value) {
+ if ((src1 == def->src2) && (src2 == def->src3))
+ return replace_with_pseudo(insn, cond);
return replace_pseudo(insn, &insn->cond, def->cond);
}
if (!def->src2->value) {
--
2.29.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/5] select: simplify SEL(SEL(x, C1, C2), y, z) --> y (with C1, C2 != 0)
2020-11-07 11:42 [PATCH 0/5] simplify SEL(SEL, ...), ...) Luc Van Oostenryck
` (2 preceding siblings ...)
2020-11-07 11:42 ` [PATCH 3/5] select: simplify SEL(SEL(x, C, 0), C, 0) --> SEL(x, C, 0) == cond Luc Van Oostenryck
@ 2020-11-07 11:42 ` Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 5/5] select: simplify handling of constant cond or src1 == src2 Luc Van Oostenryck
2020-11-07 18:38 ` [PATCH 0/5] simplify SEL(SEL, ...), ...) Linus Torvalds
5 siblings, 0 replies; 8+ messages in thread
From: Luc Van Oostenryck @ 2020-11-07 11:42 UTC (permalink / raw)
To: linux-sparse; +Cc: Linus Torvalds, Luc Van Oostenryck
If the condition of a select is also a select, with constant
but non-zero operands, then the result of this inner select
is always true and the outer select can be replaced by its
second operand.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
simplify.c | 3 +++
validation/optim/select-select-true-true.c | 1 -
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/simplify.c b/simplify.c
index 1fcfc691579a..20ea5f1be71a 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1793,6 +1793,7 @@ static int simplify_select(struct instruction *insn)
// SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z)
// SEL(SEL(x, C, 0), C, 0) --> SEL(x, C, 0) == cond
// SEL(SEL(x, 0, C), y, z) --> SEL(x, z, y)
+ // SEL(SEL(x, C1, C2), y, z) --> y
if (!def->src3->value) {
if ((src1 == def->src2) && (src2 == def->src3))
return replace_with_pseudo(insn, cond);
@@ -1802,6 +1803,8 @@ static int simplify_select(struct instruction *insn)
switch_pseudo(insn, &insn->src2, insn, &insn->src3);
return replace_pseudo(insn, &insn->cond, def->cond);
}
+ // both values must be non-zero
+ return replace_with_pseudo(insn, src1);
}
break;
}
diff --git a/validation/optim/select-select-true-true.c b/validation/optim/select-select-true-true.c
index e6fa2c89febb..c0c26fdd199a 100644
--- a/validation/optim/select-select-true-true.c
+++ b/validation/optim/select-select-true-true.c
@@ -3,7 +3,6 @@ int foo(int p, int a, int b) { return ((p ? 42 : 43) ? a : b) == a ; }
/*
* check-name: select-select-true-true
* 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] 8+ messages in thread
* [PATCH 5/5] select: simplify handling of constant cond or src1 == src2
2020-11-07 11:42 [PATCH 0/5] simplify SEL(SEL, ...), ...) Luc Van Oostenryck
` (3 preceding siblings ...)
2020-11-07 11:42 ` [PATCH 4/5] select: simplify SEL(SEL(x, C1, C2), y, z) --> y (with C1, C2 != 0) Luc Van Oostenryck
@ 2020-11-07 11:42 ` Luc Van Oostenryck
2020-11-07 18:38 ` [PATCH 0/5] simplify SEL(SEL, ...), ...) Linus Torvalds
5 siblings, 0 replies; 8+ messages in thread
From: Luc Van Oostenryck @ 2020-11-07 11:42 UTC (permalink / raw)
To: linux-sparse; +Cc: Linus Torvalds, Luc Van Oostenryck
If the operands of a select instruction are identical, then
this select can be replaced by its operand.
If the condition of a select is a constant, the this select
can be replaced by one of its condition, depending on the
truth value of the condition.
This simplification is already done but:
* when src1 == src2, the condition's value is tested although
it may not be a constant. It's kinda OK because in all case
one of the operand will be selected and both are identical
but it's a bit weird and unclean.
* since the instruction will be replaced, the usage of its
condition and operands must be removed. This is done here but
the kill_instruction() inside replace_with_pseudo() take
already care of this.
So, separate the two cases and simply use replace_with_pseudo()
for both without bothering killing the operands.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
simplify.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/simplify.c b/simplify.c
index 20ea5f1be71a..20ab9b3b3ecf 100644
--- a/simplify.c
+++ b/simplify.c
@@ -1753,14 +1753,12 @@ static int simplify_select(struct instruction *insn)
cond = insn->src1;
src1 = insn->src2;
src2 = insn->src3;
- if (constant(cond) || src1 == src2) {
- pseudo_t *kill, take;
- kill_use(&insn->src1);
- take = cond->value ? src1 : src2;
- kill = cond->value ? &insn->src3 : &insn->src2;
- kill_use(kill);
- return replace_with_pseudo(insn, take);
- }
+
+ if (constant(cond))
+ return replace_with_pseudo(insn, cond->value ? src1 : src2);
+ if (src1 == src2)
+ return replace_with_pseudo(insn, src1);
+
if (constant(src1) && constant(src2)) {
long long val1 = src1->value;
long long val2 = src2->value;
--
2.29.2
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 0/5] simplify SEL(SEL, ...), ...)
2020-11-07 11:42 [PATCH 0/5] simplify SEL(SEL, ...), ...) Luc Van Oostenryck
` (4 preceding siblings ...)
2020-11-07 11:42 ` [PATCH 5/5] select: simplify handling of constant cond or src1 == src2 Luc Van Oostenryck
@ 2020-11-07 18:38 ` Linus Torvalds
2020-11-07 19:12 ` Linus Torvalds
5 siblings, 1 reply; 8+ messages in thread
From: Linus Torvalds @ 2020-11-07 18:38 UTC (permalink / raw)
To: Luc Van Oostenryck; +Cc: Sparse Mailing-list
On Sat, Nov 7, 2020 at 3:42 AM Luc Van Oostenryck
<luc.vanoostenryck@gmail.com> wrote:
>
> These patch add a few simplifications when the condition of a
> select is another select and have constants as operands.
Looks good to me.
I think there's a couple of others, like
SEL(x, x, 0) -> x
which looks insane, but I think these are the kinds of things that end
up showing up when you inline things that return errors, and then you
test them for zero etc.
I haven't thought them all through, and didn't check your cases deeply
and just took your word for them, but it looked all sane to me.
Linus
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/5] simplify SEL(SEL, ...), ...)
2020-11-07 18:38 ` [PATCH 0/5] simplify SEL(SEL, ...), ...) Linus Torvalds
@ 2020-11-07 19:12 ` Linus Torvalds
0 siblings, 0 replies; 8+ messages in thread
From: Linus Torvalds @ 2020-11-07 19:12 UTC (permalink / raw)
To: Luc Van Oostenryck; +Cc: Sparse Mailing-list
On Sat, Nov 7, 2020 at 10:38 AM Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> I think there's a couple of others, like
>
> SEL(x, x, 0) -> x
>
> which looks insane, but I think these are the kinds of things that end
> up showing up when you inline things that return errors, and then you
> test them for zero etc.
Made-up crazy example:
extern int fn(int);
int t(int x)
{
int err = fn(x);
if (err)
return err;
return 0;
}
which is the kind of thing that can happen when you have various
config options and code goes away. It *should* just result in a no-op
(ie just call 'fn()' and return its value), but currently sparse
generates
call.32 %r2 <- fn, %arg1
select.32 %r6 <- %r2, %r2, $0
ret.32 %r6
instead of
call.32 %r2 <- fn, %arg1
ret.32 %r2
but I hadn't actually applied your patches when I did that test, so
maybe you had caught this case already without me realizing it.
Linus
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2020-11-07 19:13 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-07 11:42 [PATCH 0/5] simplify SEL(SEL, ...), ...) Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 1/5] select: add some testcases for select simplification Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 2/5] select: simplify SEL(SEL(x, C, 0), y, z) --> SEL(x, y, z) and its dual Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 3/5] select: simplify SEL(SEL(x, C, 0), C, 0) --> SEL(x, C, 0) == cond Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 4/5] select: simplify SEL(SEL(x, C1, C2), y, z) --> y (with C1, C2 != 0) Luc Van Oostenryck
2020-11-07 11:42 ` [PATCH 5/5] select: simplify handling of constant cond or src1 == src2 Luc Van Oostenryck
2020-11-07 18:38 ` [PATCH 0/5] simplify SEL(SEL, ...), ...) Linus Torvalds
2020-11-07 19:12 ` Linus Torvalds
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).