[PATCH 3/4] simplify AND(SHIFT(a | b, S), M)

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

 



The simplication of AND(SHIFT(a | b, S), M) can be done by combining
the mask M with the effective mask corresponding to SHIFT(_, S).

This intruction pattern is generated when accessing bitfields,
for example, code like:
	struct u {
		unsigned int  :2;
		unsigned int f:3;
	};
	int bfu(struct u s, int a)
	{
		s.f = a;
		return s.f;
	}

is now simplified into the minimal:
	bfu:
		and.32      %r11 <- %arg2, $7
		ret.32      %r11

The simplification is done by introducing a small helper,
simplify_mask_shift(), doing the pattern matching and then calling
simplify_mask_shift_or() with the mask M.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
---
 simplify.c                              | 18 ++++++++++++++++++
 validation/optim/and-or-bfu.c           |  1 -
 validation/optim/bitfield-store-loadu.c |  1 -
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/simplify.c b/simplify.c
index e398d727e..78688c7c3 100644
--- a/simplify.c
+++ b/simplify.c
@@ -686,6 +686,21 @@ static int simplify_mask_shift_or(struct instruction *sh, struct instruction *or
 	return simplify_mask_or(sh, smask & mask, or);
 }
 
+static int simplify_mask_shift(struct instruction *sh, unsigned long long mask)
+{
+	struct instruction *inner;
+
+	if (!constant(sh->src2) || sh->tainted)
+		return 0;
+	switch (DEF_OPCODE(inner, sh->src1)) {
+	case OP_OR:
+		if (!multi_users(sh->target))
+			return simplify_mask_shift_or(sh, inner, mask);
+		break;
+	}
+	return 0;
+}
+
 static long long check_shift_count(struct instruction *insn, unsigned long long uval)
 {
 	unsigned int size = insn->size;
@@ -986,6 +1001,9 @@ static int simplify_constant_mask(struct instruction *insn, unsigned long long m
 		goto oldsize;
 	case OP_OR:
 		return simplify_mask_or(insn, mask, def);
+	case OP_LSR:
+	case OP_SHL:
+		return simplify_mask_shift(def, mask);
 	case OP_ZEXT:
 		osize = def->orig_type->bit_size;
 		/* fall through */
diff --git a/validation/optim/and-or-bfu.c b/validation/optim/and-or-bfu.c
index c9dcfc33e..b6a080bd1 100644
--- a/validation/optim/and-or-bfu.c
+++ b/validation/optim/and-or-bfu.c
@@ -12,7 +12,6 @@ int bfu(struct u s, int a)
 /*
  * check-name: and-or-bfu
  * check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-pattern(1): and\\.
diff --git a/validation/optim/bitfield-store-loadu.c b/validation/optim/bitfield-store-loadu.c
index 4c289504c..7fa1593d9 100644
--- a/validation/optim/bitfield-store-loadu.c
+++ b/validation/optim/bitfield-store-loadu.c
@@ -12,7 +12,6 @@ int foo(struct s s, int a)
 /*
  * check-name: bitfield-store-load unsigned
  * check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-excludes: shl\\.
-- 
2.18.0




[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