aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUros Bizjak <ubizjak@gmail.com>2018-04-28 09:37:04 +0200
committerUros Bizjak <uros@gcc.gnu.org>2018-04-28 09:37:04 +0200
commit6754dfa2370c9f28fc7069e872b9a0fcddece8ca (patch)
tree25ff9eb3fe1a664aa508952a38bb03b0bb582259 /gcc
parent782e47649004a0fbc97d0a8d8817577923a5e619 (diff)
downloadgcc-6754dfa2370c9f28fc7069e872b9a0fcddece8ca.zip
gcc-6754dfa2370c9f28fc7069e872b9a0fcddece8ca.tar.gz
gcc-6754dfa2370c9f28fc7069e872b9a0fcddece8ca.tar.bz2
re PR target/84431 (Suboptimal code for masked shifts (x86/x86-64))
PR target/84431 * config/i386/i386.md (*ashl<dwi>3_doubleword_mask): New pattern. (*ashl<dwi>3_doubleword_mask_1): Ditto. (*<shift_insn><dwi>3_doubleword_mask): Ditto. (*<shift_insn><dwi>3_doubleword_mask_1): Ditto. testsuite/ChangeLog: PR target/84431 * gcc.target/i386/pr84431.c: New test. From-SVN: r259739
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/i386/i386.md142
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84431.c19
4 files changed, 174 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index edc952c..1433190 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2018-04-28 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/84431
+ * config/i386/i386.md (*ashl<dwi>3_doubleword_mask): New pattern.
+ (*ashl<dwi>3_doubleword_mask_1): Ditto.
+ (*<shift_insn><dwi>3_doubleword_mask): Ditto.
+ (*<shift_insn><dwi>3_doubleword_mask_1): Ditto.
+
2018-04-28 Richard Biener <rguenther@suse.de>
* 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 eacc3bb..d85d346 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -10357,6 +10357,77 @@
""
"ix86_expand_binary_operator (ASHIFT, <MODE>mode, operands); DONE;")
+(define_insn_and_split "*ashl<dwi>3_doubleword_mask"
+ [(set (match_operand:<DWI> 0 "register_operand")
+ (ashift:<DWI>
+ (match_operand:<DWI> 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]) <= (<MODE_SIZE> * 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 (<DWI>mode, &operands[0], 2, &operands[4], &operands[6]);
+
+ operands[8] = GEN_INT (<MODE_SIZE> * BITS_PER_UNIT);
+
+ if (INTVAL (operands[3]) < (<MODE_SIZE> * 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 "*ashl<dwi>3_doubleword_mask_1"
+ [(set (match_operand:<DWI> 0 "register_operand")
+ (ashift:<DWI>
+ (match_operand:<DWI> 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]) <= (<MODE_SIZE> * 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 (<DWI>mode, &operands[0], 2, &operands[4], &operands[6]);
+
+ operands[8] = GEN_INT (<MODE_SIZE> * BITS_PER_UNIT);
+
+ if (INTVAL (operands[3]) < (<MODE_SIZE> * 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 "*ashl<mode>3_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 "*<shift_insn><dwi>3_doubleword_mask"
+ [(set (match_operand:<DWI> 0 "register_operand")
+ (any_shiftrt:<DWI>
+ (match_operand:<DWI> 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]) <= (<MODE_SIZE> * 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 (<DWI>mode, &operands[0], 2, &operands[4], &operands[6]);
+
+ operands[8] = GEN_INT (<MODE_SIZE> * BITS_PER_UNIT);
+
+ if (INTVAL (operands[3]) < (<MODE_SIZE> * 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 "*<shift_insn><dwi>3_doubleword_mask_1"
+ [(set (match_operand:<DWI> 0 "register_operand")
+ (any_shiftrt:<DWI>
+ (match_operand:<DWI> 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]) <= (<MODE_SIZE> * 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 (<DWI>mode, &operands[0], 2, &operands[4], &operands[6]);
+
+ operands[8] = GEN_INT (<MODE_SIZE> * BITS_PER_UNIT);
+
+ if (INTVAL (operands[3]) < (<MODE_SIZE> * 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 "*<shift_insn><mode>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 47da043..ccc4d18 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-04-28 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/84431
+ * gcc.target/i386/pr84431.c: New test.
+
2018-04-27 Martin Jambor <mjambor@suse.cz>
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 0000000..ee751a7
--- /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" } } */