[PATCH] fix dominance testing of mixed types

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The function dominates() is used to test the dominance of
one instruction over another one. To do this different things
need to be checked, like:
- same symbol or not
- same address & same offset
- partial overlapping

One case is not covered though: when type cohercion is done
via a pointer to an union (IOW when a memory location is used
to store one type and is then read back as another type).
For example, the location is first stored as a float and then is
read back as an integer of the same size. Currently, sparse
will consider that the store effectively dominates the load
which will then allow to simplify away the load and use the
pseudo holding the float value for the expected integer.

There is surely several ways to fix this problem.
The solution used in this patch is to check if both instructions
are of of the same floating-pointness.

Note: this solution is probably incomplete. For example, what
      about compound types?

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
---
 flow.c                                             |  4 +++
 validation/mem2reg/access-union0.c                 | 37 ++++++++++++++++++++++
 validation/mem2reg/access-union1.c                 | 36 +++++++++++++++++++++
 validation/mem2reg/access-union2.c                 | 26 +++++++++++++++
 validation/mem2reg/access-union3.c                 | 24 ++++++++++++++
 .../mem2reg/{init-local.c => init-local-float.c}   | 14 ++------
 validation/mem2reg/init-local-int.c                | 18 +++++++++++
 validation/mem2reg/init-local-union0.c             |  1 +
 8 files changed, 148 insertions(+), 12 deletions(-)
 create mode 100644 validation/mem2reg/access-union0.c
 create mode 100644 validation/mem2reg/access-union1.c
 create mode 100644 validation/mem2reg/access-union2.c
 create mode 100644 validation/mem2reg/access-union3.c
 rename validation/mem2reg/{init-local.c => init-local-float.c} (53%)
 create mode 100644 validation/mem2reg/init-local-int.c

diff --git a/flow.c b/flow.c
index f928c2684..32e30670c 100644
--- a/flow.c
+++ b/flow.c
@@ -367,6 +367,10 @@ int dominates(pseudo_t pseudo, struct instruction *insn, struct instruction *dom
 			return 0;
 		return -1;
 	}
+	if (!insn->type || !dom->type)
+		return -1;
+	if (is_float_type(insn->type) != is_float_type(dom->type))
+		return -1;
 	return 1;
 }
 
diff --git a/validation/mem2reg/access-union0.c b/validation/mem2reg/access-union0.c
new file mode 100644
index 000000000..b04326cea
--- /dev/null
+++ b/validation/mem2reg/access-union0.c
@@ -0,0 +1,37 @@
+typedef unsigned  int u32;
+typedef unsigned long u64;
+
+void use(u32);
+
+u32 f0(void)
+{
+	union {
+		u64 b;
+		u32 a[2];
+	} u;
+
+	u.b = 1;
+	return u.a[0];
+}
+
+
+u32 f1(void)
+{
+	union {
+		u64 b;
+		u32 a[2];
+	} u;
+
+	u.b = 1;
+	return u.a[1];
+}
+
+/*
+ * check-name: access-union0
+ * check-command: test-linearize -m64 -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(2): load\\.
+ * check-output-pattern(2): store\\.
+ * check-output-excludes: ret.32 *\\$1
+ */
diff --git a/validation/mem2reg/access-union1.c b/validation/mem2reg/access-union1.c
new file mode 100644
index 000000000..e6d8c820e
--- /dev/null
+++ b/validation/mem2reg/access-union1.c
@@ -0,0 +1,36 @@
+void use(int);
+
+double foo(void)
+{
+	union {
+		double	d;
+		int	i;
+	} u;
+
+	u.d = 1.0;
+	use(u.i);
+	u.d = 0.0;
+	return u.d;
+}
+
+/*
+ * check-name: access-union1
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-start
+foo:
+.L0:
+	<entry-point>
+	setfval.64  %r1 <- 1.000000
+	store.64    %r1 <- 0[u]
+	load.32     %r2 <- 0[u]
+	call        use, %r2
+	setfval.64  %r3 <- 0.000000
+	ret.64      %r3
+
+
+ * check-output-end
+ * check-output-pattern(1): load\\.
+ * check-output-pattern(1): store\\.
+ */
diff --git a/validation/mem2reg/access-union2.c b/validation/mem2reg/access-union2.c
new file mode 100644
index 000000000..7c119ffbd
--- /dev/null
+++ b/validation/mem2reg/access-union2.c
@@ -0,0 +1,26 @@
+typedef double        dbl;
+typedef unsigned long u64;
+
+void use(u64);
+
+u64 foo(void)
+{
+	union {
+		dbl f;
+		u64 i;
+	} u;
+
+	u.f = 1.0;
+	use(u.i);
+	u.f = 0.0;
+	return u.f;
+}
+
+/*
+ * check-name: access-union2
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(1): load\\.
+ * check-output-pattern(1): store\\.
+ */
diff --git a/validation/mem2reg/access-union3.c b/validation/mem2reg/access-union3.c
new file mode 100644
index 000000000..d977493ab
--- /dev/null
+++ b/validation/mem2reg/access-union3.c
@@ -0,0 +1,24 @@
+typedef double        dbl;
+typedef unsigned long u64;
+
+void use(u64);
+
+static dbl foo(void)
+{
+	union {
+		dbl f;
+		u64 i;
+	} u;
+
+	u.i = 123;
+	return u.f;
+}
+
+/*
+ * check-name: access-union3
+ * check-command: test-linearize -fdump-ir=mem2reg $file
+ *
+ * check-output-ignore
+ * check-output-pattern(1): load\\.
+ * check-output-pattern(1): store\\.
+ */
diff --git a/validation/mem2reg/init-local.c b/validation/mem2reg/init-local-float.c
similarity index 53%
rename from validation/mem2reg/init-local.c
rename to validation/mem2reg/init-local-float.c
index d51c9247a..2642a204a 100644
--- a/validation/mem2reg/init-local.c
+++ b/validation/mem2reg/init-local-float.c
@@ -1,14 +1,4 @@
-int ssimple(void)
-{
-	struct {
-		int a;
-	} s;
-
-	s.a = 1;
-	return s.a;
-}
-
-double sdouble(void)
+static double local_float(void)
 {
 	struct {
 		double a;
@@ -20,7 +10,7 @@ double sdouble(void)
 
 /*
  * check-name: init-local
- * check-command: test-linearize -Wno-decl -fdump-ir=mem2reg $file
+ * check-command: test-linearize $file
  * check-output-ignore
  * check-output-excludes: load\\.
  * check-output-excludes: store\\.
diff --git a/validation/mem2reg/init-local-int.c b/validation/mem2reg/init-local-int.c
new file mode 100644
index 000000000..285f3199f
--- /dev/null
+++ b/validation/mem2reg/init-local-int.c
@@ -0,0 +1,18 @@
+static int local_int(void)
+{
+	struct {
+		int a;
+	} s;
+
+	s.a = 1;
+	return s.a;
+}
+
+/*
+ * check-name: init-local-int
+ * check-command: test-linearize $file
+ * check-output-ignore
+ * check-output-excludes: load\\.
+ * check-output-excludes: store\\.
+ * check-output-contains: ret.32 *\\$1
+ */
diff --git a/validation/mem2reg/init-local-union0.c b/validation/mem2reg/init-local-union0.c
index 3a57e781f..9a3b87d46 100644
--- a/validation/mem2reg/init-local-union0.c
+++ b/validation/mem2reg/init-local-union0.c
@@ -15,4 +15,5 @@ double uintfloat(void)
  * check-output-ignore
  * check-output-pattern(1): store\\.32
  * check-output-pattern(1): load\\.64
+ * check-output-excludes: ret\\.*\\$1
  */
-- 
2.16.2

--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux