[PATCH v2 03/15] unify simplify_lsr_or() & simplify_and_or_mask()

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

 



Doing a LSR(X, N) will drop the N right bits.
So any simplification that can be made when using an AND clearing
the right N bits can also be used on LSR (as if its first operand
would first be implicitly be ANDed with such a mask).

So, in order to not duplicate complex simplifications involving
ANDs & ORs masks, merge these both function in a single one,
using the mask corresponding to the operation.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
---
 simplify.c | 56 ++++++++++++++++++++++--------------------------------
 1 file changed, 23 insertions(+), 33 deletions(-)

diff --git a/simplify.c b/simplify.c
index ef98b205a..ce48b3a91 100644
--- a/simplify.c
+++ b/simplify.c
@@ -546,6 +546,24 @@ undef:
 	return NULL;
 }
 
+static int simplify_mask_or_and(struct instruction *insn, unsigned long long mask,
+	pseudo_t src, pseudo_t other)
+{
+	unsigned long long omask, nmask;
+	pseudo_t src2 = src->def->src2;
+
+	if (!constant(src2))
+		return 0;
+	omask = src2->value;
+	nmask = omask & mask;
+	if (nmask != 0)
+		return 0;
+	// replace OP(((A & M') | B), C)
+	// by      OP(B, C)
+	// when	(M' & M) == 0
+	return replace_pseudo(insn, &insn->src1, other);
+}
+
 static long long check_shift_count(struct instruction *insn, unsigned long long uval)
 {
 	unsigned int size = insn->size;
@@ -575,18 +593,6 @@ static long long check_shift_count(struct instruction *insn, unsigned long long
 	return sval;
 }
 
-static int simplify_or_lsr(struct instruction *insn, pseudo_t src, pseudo_t other, unsigned shift)
-{
-	// src->def->opcode == OP_AND
-	pseudo_t src2 = src->def->src2;
-
-	if (!constant(src2))
-		return 0;
-	if (((unsigned long long) src2->value) >> shift)
-		return 0;
-	return replace_pseudo(insn, &insn->src1, other);
-}
-
 static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long value)
 {
 	struct instruction *def;
@@ -660,15 +666,13 @@ static int simplify_shift(struct instruction *insn, pseudo_t pseudo, long long v
 		case OP_LSR:
 			goto case_shift_shift;
 		case OP_OR:
-			// replace ((A & M) | B) >> S
-			// by      (B >> S)
-			// when	(M >> S) == 0
+			mask = bits_mask(size - value) << value;
 			src = def->src1;
 			if (def_opcode(src) == OP_AND)
-				return simplify_or_lsr(insn, src, def->src2, value);
+				return simplify_mask_or_and(insn, mask, src, def->src2);
 			src = def->src2;
 			if (def_opcode(src) == OP_AND)
-				return simplify_or_lsr(insn, src, def->src1, value);
+				return simplify_mask_or_and(insn, mask, src, def->src1);
 			break;
 		case OP_SHL:
 			// replace (A << S) >> S
@@ -824,17 +828,6 @@ static int simplify_seteq_setne(struct instruction *insn, long long value)
 	return 0;
 }
 
-static int simplify_and_or_mask(struct instruction *insn, pseudo_t and, pseudo_t other, unsigned long long mask)
-{
-	struct instruction *def = and->def;
-
-	if (!constant(def->src2))
-		return 0;
-	if (def->src2->value & mask)
-		return 0;
-	return replace_pseudo(insn, &insn->src1, other);
-}
-
 static int simplify_constant_mask(struct instruction *insn, unsigned long long mask)
 {
 	pseudo_t old = insn->src1;
@@ -849,15 +842,12 @@ static int simplify_constant_mask(struct instruction *insn, unsigned long long m
 		osize = 1;
 		goto oldsize;
 	case OP_OR:
-		// Let's handle ((A & M') | B ) & M
-		// or           (B | (A & M')) & M
-		// when M' & M == 0
 		src1 = def->src1;
 		src2 = def->src2;
 		if (def_opcode(src1) == OP_AND)
-			return simplify_and_or_mask(insn, src1, src2, mask);
+			return simplify_mask_or_and(insn, mask, src1, src2);
 		if (def_opcode(src2) == OP_AND)
-			return simplify_and_or_mask(insn, src2, src1, mask);
+			return simplify_mask_or_and(insn, mask, src2, src1);
 		break;
 	case OP_ZEXT:
 		osize = def->orig_type->bit_size;
-- 
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