Re: [PATCH v4 03/63] canonicalize compare instructions

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

 



On Fri, Mar 24, 2017 at 1:11 AM, Luc Van Oostenryck
<luc.vanoostenryck@xxxxxxxxx> wrote:


>
> Yes, indeed.
> In fact, I think it need a name which explain even more
> the purpose. I'll see.

Sure, I am open to suggestion.

BTW, the previous function is call compare_opcode() what
it actually do is invert_compare(). I would just move the inverse
test outside of this function and call it invert_compare() or
invert_compare_opcode()

> Yes, it's kinda ugly.
> OTOH, given that jumps are cheaper and cheaper on modern CPU
> and memory accesses slower and slower, is what you propose
> really an optimization? And even if it would, does it matter?

Well, jump through a indirect table is quit different than jump
to a fix offset. I don't know what modern CPU does now days. It
used to be indirect jump will flush the instruction pipe line.



>
> My preference, if performance mattered here, would be to play
> with the bits of the opcode, something like:
>         #define OP_SET__EQUAL   (1 << ...)
>         #define OP_SET__SIGNED  (1 << ...)
>         #define OP_SET__LTHAN   ...
>         #define OP_SET__GTHAN   ...
>
>         ...
>
>         int swap_compare_opcode(opcode) { return opcode ^= (OP_SET__LTHAN|OP_SET__GTHAN); }

That is ugly. I don't want that.

I cook up an untested patch include here to show what I have in mind.
It should be very close to your case statement way of writing it.  You are
welcome to change it.

Chris
diff --git a/simplify.c b/simplify.c
index 3f39819..6e113d9 100644
--- a/simplify.c
+++ b/simplify.c
@@ -438,22 +438,24 @@ static int compare_opcode(int opcode, int inverse)
 
 static int compare_swap(int opcode)
 {
-	switch (opcode) {
-	case OP_SET_EQ:	return OP_SET_EQ;
-	case OP_SET_NE:	return OP_SET_NE;
-
-	case OP_SET_LT:	return OP_SET_GT;
-	case OP_SET_LE:	return OP_SET_GE;
-	case OP_SET_GT:	return OP_SET_LT;
-	case OP_SET_GE:	return OP_SET_LE;
-
-	case OP_SET_A:	return OP_SET_B;
-	case OP_SET_AE:	return OP_SET_BE;
-	case OP_SET_B:	return OP_SET_A;
-	case OP_SET_BE:	return OP_SET_AE;
-	default:
-		return opcode;
-	}
+
+#define CMP_OFFSET(opcode) ((opcode) - OP_BINCMP)
+	static const int swap_opcodes[CMP_OFFSET(OP_BINCMP_END) + 1] = {
+		[CMP_OFFSET(OP_SET_EQ)] = OP_SET_EQ,
+		[CMP_OFFSET(OP_SET_NE)] = OP_SET_NE,
+
+		[CMP_OFFSET(OP_SET_LT)] = OP_SET_GT,
+		[CMP_OFFSET(OP_SET_GT)] = OP_SET_LT,
+		[CMP_OFFSET(OP_SET_LE)] = OP_SET_GE,
+		[CMP_OFFSET(OP_SET_GE)] = OP_SET_LE,
+
+		[CMP_OFFSET(OP_SET_A)] = OP_SET_B,
+		[CMP_OFFSET(OP_SET_B)] = OP_SET_A,
+		[CMP_OFFSET(OP_SET_AE)] = OP_SET_BE,
+		[CMP_OFFSET(OP_SET_BE)] = OP_SET_AE,
+	};
+	assert(opcode >= OP_BINCMP && opcode <= OP_BINCMP_END);
+	return swap_opcodes[CMP_OFFSET(opcode)];
 }
 
 static int simplify_seteq_setne(struct instruction *insn, long long value)

[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