From 6754dfa2370c9f28fc7069e872b9a0fcddece8ca Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Sat, 28 Apr 2018 09:37:04 +0200 Subject: [PATCH] re PR target/84431 (Suboptimal code for masked shifts (x86/x86-64)) PR target/84431 * config/i386/i386.md (*ashl3_doubleword_mask): New pattern. (*ashl3_doubleword_mask_1): Ditto. (*3_doubleword_mask): Ditto. (*3_doubleword_mask_1): Ditto. testsuite/ChangeLog: PR target/84431 * gcc.target/i386/pr84431.c: New test. From-SVN: r259739 --- gcc/ChangeLog | 8 ++ gcc/config/i386/i386.md | 142 ++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.target/i386/pr84431.c | 19 ++++ 4 files changed, 174 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/pr84431.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index edc952c18df..1433190f209 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2018-04-28 Uros Bizjak + + PR target/84431 + * config/i386/i386.md (*ashl3_doubleword_mask): New pattern. + (*ashl3_doubleword_mask_1): Ditto. + (*3_doubleword_mask): Ditto. + (*3_doubleword_mask_1): Ditto. + 2018-04-28 Richard Biener * tree-cfg.c (verify_gimple_phi): Take a gphi * argument. diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index eacc3bb6d4e..d85d3467a2f 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -10357,6 +10357,77 @@ "" "ix86_expand_binary_operator (ASHIFT, mode, operands); DONE;") +(define_insn_and_split "*ashl3_doubleword_mask" + [(set (match_operand: 0 "register_operand") + (ashift: + (match_operand: 1 "register_operand") + (subreg:QI + (and:SI + (match_operand:SI 2 "register_operand" "c") + (match_operand:SI 3 "const_int_operand")) 0))) + (clobber (reg:CC FLAGS_REG))] + "INTVAL (operands[3]) <= ( * BITS_PER_UNIT)-1 + && can_create_pseudo_p ()" + "#" + "&& 1" + [(parallel + [(set (match_dup 6) + (ior:DWIH (ashift:DWIH (match_dup 6) (match_dup 2)) + (lshiftrt:DWIH (match_dup 5) + (minus:QI (match_dup 8) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (match_dup 4) + (ashift:DWIH (match_dup 5) (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] +{ + split_double_mode (mode, &operands[0], 2, &operands[4], &operands[6]); + + operands[8] = GEN_INT ( * BITS_PER_UNIT); + + if (INTVAL (operands[3]) < ( * BITS_PER_UNIT)-1) + emit_insn (gen_andsi3 (operands[2], operands[2], operands[3])); + + operands[2] = gen_lowpart (QImode, operands[2]); + + if (!rtx_equal_p (operands[6], operands[7])) + emit_move_insn (operands[6], operands[7]); +}) + +(define_insn_and_split "*ashl3_doubleword_mask_1" + [(set (match_operand: 0 "register_operand") + (ashift: + (match_operand: 1 "register_operand") + (and:QI + (match_operand:QI 2 "register_operand" "c") + (match_operand:QI 3 "const_int_operand")))) + (clobber (reg:CC FLAGS_REG))] + "INTVAL (operands[3]) <= ( * BITS_PER_UNIT)-1 + && can_create_pseudo_p ()" + "#" + "&& 1" + [(parallel + [(set (match_dup 6) + (ior:DWIH (ashift:DWIH (match_dup 6) (match_dup 2)) + (lshiftrt:DWIH (match_dup 5) + (minus:QI (match_dup 8) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (match_dup 4) + (ashift:DWIH (match_dup 5) (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] +{ + split_double_mode (mode, &operands[0], 2, &operands[4], &operands[6]); + + operands[8] = GEN_INT ( * BITS_PER_UNIT); + + if (INTVAL (operands[3]) < ( * BITS_PER_UNIT)-1) + emit_insn (gen_andqi3 (operands[2], operands[2], operands[3])); + + if (!rtx_equal_p (operands[6], operands[7])) + emit_move_insn (operands[6], operands[7]); +}) + (define_insn "*ashl3_doubleword" [(set (match_operand:DWI 0 "register_operand" "=&r") (ashift:DWI (match_operand:DWI 1 "reg_or_pm1_operand" "0n") @@ -11038,6 +11109,77 @@ "" [(set_attr "isa" "*,bmi2")]) +(define_insn_and_split "*3_doubleword_mask" + [(set (match_operand: 0 "register_operand") + (any_shiftrt: + (match_operand: 1 "register_operand") + (subreg:QI + (and:SI + (match_operand:SI 2 "register_operand" "c") + (match_operand:SI 3 "const_int_operand")) 0))) + (clobber (reg:CC FLAGS_REG))] + "INTVAL (operands[3]) <= ( * BITS_PER_UNIT)-1 + && can_create_pseudo_p ()" + "#" + "&& 1" + [(parallel + [(set (match_dup 4) + (ior:DWIH (lshiftrt:DWIH (match_dup 4) (match_dup 2)) + (ashift:DWIH (match_dup 7) + (minus:QI (match_dup 8) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (match_dup 6) + (any_shiftrt:DWIH (match_dup 7) (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] +{ + split_double_mode (mode, &operands[0], 2, &operands[4], &operands[6]); + + operands[8] = GEN_INT ( * BITS_PER_UNIT); + + if (INTVAL (operands[3]) < ( * BITS_PER_UNIT)-1) + emit_insn (gen_andsi3 (operands[2], operands[2], operands[3])); + + operands[2] = gen_lowpart (QImode, operands[2]); + + if (!rtx_equal_p (operands[4], operands[5])) + emit_move_insn (operands[4], operands[5]); +}) + +(define_insn_and_split "*3_doubleword_mask_1" + [(set (match_operand: 0 "register_operand") + (any_shiftrt: + (match_operand: 1 "register_operand") + (and:QI + (match_operand:QI 2 "register_operand" "c") + (match_operand:QI 3 "const_int_operand")))) + (clobber (reg:CC FLAGS_REG))] + "INTVAL (operands[3]) <= ( * BITS_PER_UNIT)-1 + && can_create_pseudo_p ()" + "#" + "&& 1" + [(parallel + [(set (match_dup 4) + (ior:DWIH (lshiftrt:DWIH (match_dup 4) (match_dup 2)) + (ashift:DWIH (match_dup 7) + (minus:QI (match_dup 8) (match_dup 2))))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (match_dup 6) + (any_shiftrt:DWIH (match_dup 7) (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] +{ + split_double_mode (mode, &operands[0], 2, &operands[4], &operands[6]); + + operands[8] = GEN_INT ( * BITS_PER_UNIT); + + if (INTVAL (operands[3]) < ( * BITS_PER_UNIT)-1) + emit_insn (gen_andqi3 (operands[2], operands[2], operands[3])); + + if (!rtx_equal_p (operands[4], operands[5])) + emit_move_insn (operands[4], operands[5]); +}) + (define_insn_and_split "*3_doubleword" [(set (match_operand:DWI 0 "register_operand" "=&r") (any_shiftrt:DWI (match_operand:DWI 1 "register_operand" "0") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 47da0434d8a..ccc4d18cccb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-04-28 Uros Bizjak + + PR target/84431 + * gcc.target/i386/pr84431.c: New test. + 2018-04-27 Martin Jambor PR ipa/85549 diff --git a/gcc/testsuite/gcc.target/i386/pr84431.c b/gcc/testsuite/gcc.target/i386/pr84431.c new file mode 100644 index 00000000000..ee751a7af8e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr84431.c @@ -0,0 +1,19 @@ +/* PR target/84431 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +#ifdef __SIZEOF_INT128__ +typedef unsigned __int128 U; +typedef signed __int128 S; +# define M 63 +#else +typedef unsigned long long U; +typedef signed long long S; +# define M 31 +#endif + +S f1 (S a, int s) { return a >> (s & M); } +U f2 (U a, int s) { return a >> (s & M); } +U f3 (U a, int s) { return a << (s & M); } + +/* { dg-final { scan-assembler-not "and" } } */ -- 2.30.2