aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-i386.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2019-07-01 08:35:08 +0200
committerJan Beulich <jbeulich@suse.com>2019-07-01 08:35:08 +0200
commit5641ec015a191e0584fd4cae57bb3262f7a51735 (patch)
tree4a0364a281bb459f742a431a19448ef0e76d2083 /gas/config/tc-i386.c
parent79dec6b7baa243a4ada018a082491990adb6aec1 (diff)
downloadgdb-5641ec015a191e0584fd4cae57bb3262f7a51735.zip
gdb-5641ec015a191e0584fd4cae57bb3262f7a51735.tar.gz
gdb-5641ec015a191e0584fd4cae57bb3262f7a51735.tar.bz2
x86: optimize AND/OR with twice the same register
It seems to be not uncommon for people to use AND or OR in this form for just setting the status flags. TEST, which doesn't write to any register other than EFLAGS, ought to be preferred. Make the change only for -O2 and above though, at least for now.
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r--gas/config/tc-i386.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 28dd540..56ccd12 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -4040,6 +4040,29 @@ optimize_encoding (void)
}
}
}
+ else if (optimize > 1
+ && !optimize_for_space
+ && i.reg_operands == 2
+ && i.op[0].regs == i.op[1].regs
+ && ((i.tm.base_opcode & ~(Opcode_D | 1)) == 0x8
+ || (i.tm.base_opcode & ~(Opcode_D | 1)) == 0x20)
+ && (flag_code != CODE_64BIT || !i.types[0].bitfield.dword))
+ {
+ /* Optimize: -O2:
+ andb %rN, %rN -> testb %rN, %rN
+ andw %rN, %rN -> testw %rN, %rN
+ andq %rN, %rN -> testq %rN, %rN
+ orb %rN, %rN -> testb %rN, %rN
+ orw %rN, %rN -> testw %rN, %rN
+ orq %rN, %rN -> testq %rN, %rN
+
+ and outside of 64-bit mode
+
+ andl %rN, %rN -> testl %rN, %rN
+ orl %rN, %rN -> testl %rN, %rN
+ */
+ i.tm.base_opcode = 0x84 | (i.tm.base_opcode & 1);
+ }
else if (i.reg_operands == 3
&& i.op[0].regs == i.op[1].regs
&& !i.types[2].bitfield.xmmword