[PATCH 10/16] cmp: simplify sext(x) cmp C --> x cmp C

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

 



When doing a compare of a sign-extended value against a constant
the, sign-extension can be dropped and the comparison done on the
original type if the constant is within the original range.

Simplify away these sign-extensions.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx>
---
 simplify.c                  | 24 ++++++++++++++++++++++++
 validation/optim/cmp-sext.c |  1 -
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/simplify.c b/simplify.c
index 2176f90dc133..eb2c724f6307 100644
--- a/simplify.c
+++ b/simplify.c
@@ -415,6 +415,13 @@ static inline int constant(pseudo_t pseudo)
 	return pseudo->type == PSEUDO_VAL;
 }
 
+///
+// is this same signed value when interpreted with both size?
+static inline bool is_signed_constant(long long val, unsigned osize, unsigned nsize)
+{
+	return bits_extend(val, osize, 1) == bits_extend(val, nsize, 1);
+}
+
 ///
 // replace the operand of an instruction
 // @insn: the instruction
@@ -1082,6 +1089,9 @@ static int simplify_seteq_setne(struct instruction *insn, long long value)
 static int simplify_compare_constant(struct instruction *insn, long long value)
 {
 	unsigned long long bits = bits_mask(insn->itype->bit_size);
+	struct instruction *def;
+	pseudo_t src1, src2;
+	unsigned int osize;
 	int changed = 0;
 
 	switch (insn->opcode) {
@@ -1126,6 +1136,20 @@ static int simplify_compare_constant(struct instruction *insn, long long value)
 			changed |= replace_binop_value(insn, OP_SET_LT, 0);
 		break;
 	}
+
+	src1 = insn->src1;
+	src2 = insn->src2;
+	value = src2->value;
+	switch (DEF_OPCODE(def, src1)) {
+	case OP_SEXT:				// sext(x) cmp C --> x cmp trunc(C)
+		osize = def->orig_type->bit_size;
+		if (is_signed_constant(value, osize, def->size)) {
+			insn->itype = def->orig_type;
+			insn->src2 = value_pseudo(zero_extend(value, osize));
+			return replace_pseudo(insn, &insn->src1, def->src);
+		}
+		break;
+	}
 	return changed;
 }
 
diff --git a/validation/optim/cmp-sext.c b/validation/optim/cmp-sext.c
index 2dd60fff064c..13f4fbdfad77 100644
--- a/validation/optim/cmp-sext.c
+++ b/validation/optim/cmp-sext.c
@@ -17,7 +17,6 @@ _Bool cmpgtu_sext(int a) { return (a >= 0x80000000ULL) == (a <  0); }
 /*
  * check-name: cmp-sext
  * check-command: test-linearize -Wno-decl $file
- * check-known-to-fail
  *
  * check-output-ignore
  * check-output-returns: 1
-- 
2.29.2




[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