From: Uros Bizjak Date: Thu, 30 Sep 2021 17:33:49 +0000 (+0200) Subject: i386: Eliminate sign extension after logic operation [PR89954] X-Git-Tag: basepoints/gcc-13~4322 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6f4459c478b1c09e4b5e7d629fbf46d2a4fe4560;p=thirdparty%2Fgcc.git i386: Eliminate sign extension after logic operation [PR89954] Convert (sign_extend:WIDE (any_logic:NARROW (memory, immediate))) to (any_logic:WIDE (sign_extend (memory)), (sign_extend (immediate))). This eliminates sign extension after logic operation. 2021-09-30 Uroš Bizjak gcc/ PR target/89954 * config/i386/i386.md (sign_extend:WIDE (any_logic:NARROW (memory, immediate)) splitters): New splitters. gcc/testsuite/ PR target/89954 * gcc.target/i386/pr89954.c: New test. --- diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 758d7d1e3c0b..04cb3bf6a336 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -10210,6 +10210,40 @@ [(set_attr "type" "alu") (set_attr "mode" "")]) +;; convert (sign_extend:WIDE (any_logic:NARROW (memory, immediate))) +;; to (any_logic:WIDE (sign_extend (memory)), (sign_extend (immediate))). +;; This eliminates sign extension after logic operation. + +(define_split + [(set (match_operand:SWI248 0 "register_operand") + (sign_extend:SWI248 + (any_logic:QI (match_operand:QI 1 "memory_operand") + (match_operand:QI 2 "const_int_operand"))))] + "" + [(set (match_dup 3) (sign_extend:SWI248 (match_dup 1))) + (set (match_dup 0) (any_logic:SWI248 (match_dup 3) (match_dup 2)))] + "operands[3] = gen_reg_rtx (mode);") + +(define_split + [(set (match_operand:SWI48 0 "register_operand") + (sign_extend:SWI48 + (any_logic:HI (match_operand:HI 1 "memory_operand") + (match_operand:HI 2 "const_int_operand"))))] + "" + [(set (match_dup 3) (sign_extend:SWI48 (match_dup 1))) + (set (match_dup 0) (any_logic:SWI48 (match_dup 3) (match_dup 2)))] + "operands[3] = gen_reg_rtx (mode);") + +(define_split + [(set (match_operand:DI 0 "register_operand") + (sign_extend:DI + (any_logic:SI (match_operand:SI 1 "memory_operand") + (match_operand:SI 2 "const_int_operand"))))] + "TARGET_64BIT" + [(set (match_dup 3) (sign_extend:DI (match_dup 1))) + (set (match_dup 0) (any_logic:DI (match_dup 3) (match_dup 2)))] + "operands[3] = gen_reg_rtx (DImode);") + (define_insn "*_2" [(set (reg FLAGS_REG) (compare (any_or:SWI diff --git a/gcc/testsuite/gcc.target/i386/pr89954.c b/gcc/testsuite/gcc.target/i386/pr89954.c new file mode 100644 index 000000000000..c1e9f3a95625 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr89954.c @@ -0,0 +1,45 @@ +/* PR target/89954 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +signed char ab; + +short aw; + +int al; + +short sext_andbw (void) { return ab & -2; } +short sext_orbw (void) { return ab | -3; } +short sext_xorbw (void) { return ab ^ -4; } + +int sext_andbl (void) { return ab & -2; } +int sext_orbl (void) { return ab | -3; } +int sext_xorbl (void) { return ab ^ -4; } + +int sext_andwl (void) { return aw & -2; } +int sext_orwl (void) { return aw | -3; } +int sext_xorwl (void) { return aw ^ -4; } + +#ifdef __x86_64__ + +long long sext_andbq (void) { return ab & -2; } +long long sext_orbq (void) { return ab | -3; } +long long sext_xorbq (void) { return ab ^ -4; } + +long long sext_andwq (void) { return aw & -2; } +long long sext_orwq (void) { return aw | -3; } +long long sext_xorwq (void) { return aw ^ -4; } + +long long sext_andlq (void) { return al & -2; } +long long sext_orlq (void) { return al | -3; } +long long sext_xorlq (void) { return al ^ -4; } + +#endif + +/* { dg-final { scan-assembler-times "movsbw" 3 } } */ +/* { dg-final { scan-assembler-times "movsbl" 3 } } */ +/* { dg-final { scan-assembler-times "movswl" 3 } } */ + +/* { dg-final { scan-assembler-times "movsbq" 3 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "movswq" 3 { target { ! ia32 } } } } */ +/* { dg-final { scan-assembler-times "movslq" 3 { target { ! ia32 } } } } */