diff options
author | Uros Bizjak <ubizjak@gmail.com> | 2024-11-27 20:45:25 +0100 |
---|---|---|
committer | Uros Bizjak <ubizjak@gmail.com> | 2024-11-27 20:46:46 +0100 |
commit | 093584abb854559393e36cd4cdcf9dc4862dd046 (patch) | |
tree | 9a168e1fa9991bdb1bd24d59adaf352a7ca290cd | |
parent | bca515ff1893fe4ca1a9042364af3c43f93a397c (diff) | |
download | gcc-093584abb854559393e36cd4cdcf9dc4862dd046.zip gcc-093584abb854559393e36cd4cdcf9dc4862dd046.tar.gz gcc-093584abb854559393e36cd4cdcf9dc4862dd046.tar.bz2 |
i386: x86 can use x >> y for x >> 32+y [PR36503]
x86 targets mask 32-bit shifts with a 5-bit mask (and 64-bit with 6-bit mask),
so they can use x >> y instead of x >> 32+y.
The optimization converts:
leal 32(%rsi), %ecx
sall %cl, %eax
to:
sall %cl, %eax
PR target/36503
gcc/ChangeLog:
* config/i386/i386.md (*ashl<mode>3_add):
New define_insn_and_split pattern.
(*ashl<mode>3_add_1): Ditto.
(*<insn><mode>3_add): Ditto.
(*<insn><mode>3_add_1): Ditto.
(*ashl<mode>3_sub): Rename from *ashl<mode>3_negcnt.
(*ashl<mode>3_sub_1): Rename from *ashl<mode>3_negcnt_1.
(*<insn><mode>3_sub): Rename from *<insn><mode>3_negcnt.
(*<insn><mode>3_sub_1): Rename from *<insn><mode>3_negcnt_1.
gcc/testsuite/ChangeLog:
* gcc.target/i386/pr36503-3.c: New test.
* gcc.target/i386/pr36503-4.c: New test.
-rw-r--r-- | gcc/config/i386/i386.md | 100 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr36503-3.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr36503-4.c | 19 |
3 files changed, 135 insertions, 4 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index df78e4d..2fc4800 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -15896,7 +15896,53 @@ "" [(set_attr "isa" "*,bmi2")]) -(define_insn_and_split "*ashl<mode>3_negcnt" +(define_insn_and_split "*ashl<mode>3_add" + [(set (match_operand:SWI48 0 "nonimmediate_operand") + (ashift:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand") + (subreg:QI + (plus + (match_operand 2 "int248_register_operand" "c,r") + (match_operand 3 "const_int_operand")) 0))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands) + && (INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT - 1)) == 0 + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(parallel + [(set (match_dup 0) + (ashift:SWI48 (match_dup 1) + (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] +{ + operands[2] = force_reg (GET_MODE (operands[2]), operands[2]); + operands[2] = gen_lowpart (QImode, operands[2]); +} + [(set_attr "isa" "*,bmi2")]) + +(define_insn_and_split "*ashl<mode>3_add_1" + [(set (match_operand:SWI48 0 "nonimmediate_operand") + (ashift:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand") + (plus:QI + (match_operand:QI 2 "register_operand" "c,r") + (match_operand:QI 3 "const_int_operand")))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands) + && (INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT - 1)) == 0 + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(parallel + [(set (match_dup 0) + (ashift:SWI48 (match_dup 1) + (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] + "" + [(set_attr "isa" "*,bmi2")]) + +(define_insn_and_split "*ashl<mode>3_sub" [(set (match_operand:SWI48 0 "nonimmediate_operand") (ashift:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") @@ -15927,7 +15973,7 @@ } [(set_attr "isa" "*,bmi2")]) -(define_insn_and_split "*ashl<mode>3_negcnt_1" +(define_insn_and_split "*ashl<mode>3_sub_1" [(set (match_operand:SWI48 0 "nonimmediate_operand") (ashift:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") @@ -16678,7 +16724,53 @@ "" [(set_attr "isa" "*,bmi2")]) -(define_insn_and_split "*<insn><mode>3_negcnt" +(define_insn_and_split "*<insn><mode>3_add" + [(set (match_operand:SWI48 0 "nonimmediate_operand") + (any_shiftrt:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand") + (subreg:QI + (plus + (match_operand 2 "int248_register_operand" "c,r") + (match_operand 3 "const_int_operand")) 0))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands) + && (INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT - 1)) == 0 + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(parallel + [(set (match_dup 0) + (any_shiftrt:SWI48 (match_dup 1) + (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] +{ + operands[2] = force_reg (GET_MODE (operands[2]), operands[2]); + operands[2] = gen_lowpart (QImode, operands[2]); +} + [(set_attr "isa" "*,bmi2")]) + +(define_insn_and_split "*<insn><mode>3_add_1" + [(set (match_operand:SWI48 0 "nonimmediate_operand") + (any_shiftrt:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand") + (plus:QI + (match_operand:QI 2 "register_operand" "c,r") + (match_operand:QI 3 "const_int_operand")))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands) + && (INTVAL (operands[3]) & (<MODE_SIZE> * BITS_PER_UNIT - 1)) == 0 + && ix86_pre_reload_split ()" + "#" + "&& 1" + [(parallel + [(set (match_dup 0) + (any_shiftrt:SWI48 (match_dup 1) + (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] + "" + [(set_attr "isa" "*,bmi2")]) + +(define_insn_and_split "*<insn><mode>3_sub" [(set (match_operand:SWI48 0 "nonimmediate_operand") (any_shiftrt:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") @@ -16709,7 +16801,7 @@ } [(set_attr "isa" "*,bmi2")]) -(define_insn_and_split "*<insn><mode>3_negcnt_1" +(define_insn_and_split "*<insn><mode>3_sub_1" [(set (match_operand:SWI48 0 "nonimmediate_operand") (any_shiftrt:SWI48 (match_operand:SWI48 1 "nonimmediate_operand") diff --git a/gcc/testsuite/gcc.target/i386/pr36503-3.c b/gcc/testsuite/gcc.target/i386/pr36503-3.c new file mode 100644 index 0000000..6ac4f41 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr36503-3.c @@ -0,0 +1,20 @@ +/* PR target/36503 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-additional-options "-mregparm=3" { target ia32 } } */ +/* { dg-final { scan-assembler-not "leal\[ \\t\]+32" } } */ + +int foo (int i, int n) +{ + return i << (32 + n); +} + +int bar (int i, int n) +{ + return i >> (32 + n); +} + +unsigned int baz (unsigned int i, int n) +{ + return i >> (32 + n); +} diff --git a/gcc/testsuite/gcc.target/i386/pr36503-4.c b/gcc/testsuite/gcc.target/i386/pr36503-4.c new file mode 100644 index 0000000..1fd81f2 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr36503-4.c @@ -0,0 +1,19 @@ +/* PR target/36503 */ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2 -masm=att" } */ +/* { dg-final { scan-assembler-not "leal\[ \\t\]+64" } } */ + +long long foo (long long i, int n) +{ + return i << (64 + n); +} + +long long bar (long long i, int n) +{ + return i >> (64 + n); +} + +unsigned long long baz (unsigned long long i, int n) +{ + return i >> (64 + n); +} |