[PATCH 10/16] cast: preserve the sizes of TRUNC(AND(x,M),N)

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

 



sparse contains some code to simplify an AND masking
followed by a truncating cast.

However, this simplification is problematic because it
doesn't keep the sizes consistent. For example, code like:
	and.32      %r3 <- %r2, $0x7fff
	trunc.16    %r4 <- (32) %r3
will be discarded with %r3 used in place of %r4.
This is correct in the mathematical sense but %r4 had a size
of 16 while %r3 has a size of 32, so using %r3 in place of %r4
will make the sizes inconsistent with unexpected consequences.

We can more or less fix this by using another transformation
that preserve the sizes:
	trunc.16    %r3 <- (32) %r2
	and.16      %r4 <- %r3, $0x7fff
which in itself doesn't optimize anything but:
1) the mask may be smaller
2) may trigger other simplification with the TRUNC or the AND.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
---
 simplify.c                   | 17 +++++++++++------
 validation/optim/and-trunc.c |  1 -
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/simplify.c b/simplify.c
index 0982d9d4b..336339fac 100644
--- a/simplify.c
+++ b/simplify.c
@@ -999,10 +999,18 @@ static int simplify_cast(struct instruction *insn)
 		/* A cast of a AND might be a no-op.. */
 		switch (insn->opcode) {
 		case OP_TRUNC:
+			if (nbr_users(src) > 1)
+				break;
+			def->opcode = OP_TRUNC;
+			def->orig_type = def->type;
+			def->type = insn->type;
+			def->size = size;
+
+			insn->opcode = OP_AND;
 			mask = val->value;
-			if (!(mask >> (size-1)))
-				goto simplify;
-			break;
+			mask &= (1ULL << size) - 1;
+			insn->src2 = value_pseudo(mask);
+			return REPEAT_CSE;
 		}
 		break;
 	case OP_TRUNC:
@@ -1029,9 +1037,6 @@ static int simplify_cast(struct instruction *insn)
 	}
 
 	return 0;
-
-simplify:
-	return replace_with_pseudo(insn, src);
 }
 
 static int simplify_select(struct instruction *insn)
diff --git a/validation/optim/and-trunc.c b/validation/optim/and-trunc.c
index bcb80bbe0..df1e4d03e 100644
--- a/validation/optim/and-trunc.c
+++ b/validation/optim/and-trunc.c
@@ -11,7 +11,6 @@ short umask(unsigned short x)
 /*
  * check-name: and-trunc
  * check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-excludes: sext\\.
-- 
2.18.0

--
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