re PR rtl-optimization/70467 (Useless "and [esp],-1" emitted on AND with uint64_t...
authorJakub Jelinek <jakub@redhat.com>
Tue, 3 May 2016 11:45:04 +0000 (13:45 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 3 May 2016 11:45:04 +0000 (13:45 +0200)
PR rtl-optimization/70467
* config/i386/predicates.md (x86_64_hilo_int_operand,
x86_64_hilo_general_operand): New predicates.
* config/i386/constraints.md (Wd): New constraint.
* config/i386/i386.md (mode attr di): Use Wd instead of e.
(general_hilo_operand): New mode attr.
(add<mode>3, sub<mode>3): Use <general_hilo_operand>
instead of <general_operand>.
(*add<dwi>3_doubleword, *sub<dwi>3_doubleword): Use
x86_64_hilo_general_operand instead of <general_operand>.

* gcc.target/i386/pr70467-3.c: New test.
* gcc.target/i386/pr70467-4.c: New test.

Co-Authored-By: Uros Bizjak <ubizjak@gmail.com>
From-SVN: r235816

gcc/ChangeLog
gcc/config/i386/constraints.md
gcc/config/i386/i386.md
gcc/config/i386/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr70467-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr70467-4.c [new file with mode: 0644]

index f2952eb9625e644462d913ae7eb1fd4293ecec96..9b1b95b5fff357cc9f0f047779968833db3edd13 100644 (file)
@@ -1,3 +1,17 @@
+2016-05-03  Jakub Jelinek  <jakub@redhat.com>
+           Uros Bizjak  <ubizjak@gmail.com>
+
+       PR rtl-optimization/70467
+       * config/i386/predicates.md (x86_64_hilo_int_operand,
+       x86_64_hilo_general_operand): New predicates.
+       * config/i386/constraints.md (Wd): New constraint.
+       * config/i386/i386.md (mode attr di): Use Wd instead of e.
+       (general_hilo_operand): New mode attr.
+       (add<mode>3, sub<mode>3): Use <general_hilo_operand>
+       instead of <general_operand>.
+       (*add<dwi>3_doubleword, *sub<dwi>3_doubleword): Use
+       x86_64_hilo_general_operand instead of <general_operand>.
+
 2016-05-03  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/70916
index 93d136bc666c640de8b3a65d8e83904316f2dd3c..ccebee775e194edcd061080b0b2adf3b19cfaa73 100644 (file)
   (and (match_operand 0 "x86_64_zext_immediate_operand")
        (match_test "GET_MODE (op) != VOIDmode")))
 
+(define_constraint "Wd"
+  "128-bit integer constant where both the high and low 64-bit word
+   of it satisfies the e constraint."
+  (match_operand 0 "x86_64_hilo_int_operand"))
+
 (define_constraint "Z"
   "32-bit unsigned integer constant, or a symbolic reference known
    to fit that range (for immediate operands in zero-extending x86-64
index c409872a0bec036dc5ce8ad0571604e12a5fd137..940dc204be5cfe401d5cf39f3899dde199baae4a 100644 (file)
 (define_mode_attr g [(QI "qmn") (HI "rmn") (SI "rme") (DI "rme")])
 
 ;; Immediate operand constraint for double integer modes.
-(define_mode_attr di [(SI "nF") (DI "e")])
+(define_mode_attr di [(SI "nF") (DI "Wd")])
 
 ;; Immediate operand constraint for shifts.
 (define_mode_attr S [(QI "I") (HI "I") (SI "I") (DI "J") (TI "O")])
         (DI "x86_64_general_operand")
         (TI "x86_64_general_operand")])
 
+;; General operand predicate for integer modes, where for TImode
+;; we need both words of the operand to be general operands.
+(define_mode_attr general_hilo_operand
+       [(QI "general_operand")
+        (HI "general_operand")
+        (SI "x86_64_general_operand")
+        (DI "x86_64_general_operand")
+        (TI "x86_64_hilo_general_operand")])
+
 ;; General sign extend operand predicate for integer modes,
 ;; which disallows VOIDmode operands and thus it is suitable
 ;; for use inside sign_extend.
 (define_expand "add<mode>3"
   [(set (match_operand:SDWIM 0 "nonimmediate_operand")
        (plus:SDWIM (match_operand:SDWIM 1 "nonimmediate_operand")
-                   (match_operand:SDWIM 2 "<general_operand>")))]
+                   (match_operand:SDWIM 2 "<general_hilo_operand>")))]
   ""
   "ix86_expand_binary_operator (PLUS, <MODE>mode, operands); DONE;")
 
   [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o")
        (plus:<DWI>
          (match_operand:<DWI> 1 "nonimmediate_operand" "%0,0")
-         (match_operand:<DWI> 2 "<general_operand>" "ro<di>,r<di>")))
+         (match_operand:<DWI> 2 "x86_64_hilo_general_operand"
+                                                       "ro<di>,r<di>")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (PLUS, <DWI>mode, operands)"
   "#"
 (define_expand "sub<mode>3"
   [(set (match_operand:SDWIM 0 "nonimmediate_operand")
        (minus:SDWIM (match_operand:SDWIM 1 "nonimmediate_operand")
-                    (match_operand:SDWIM 2 "<general_operand>")))]
+                    (match_operand:SDWIM 2 "<general_hilo_operand>")))]
   ""
   "ix86_expand_binary_operator (MINUS, <MODE>mode, operands); DONE;")
 
   [(set (match_operand:<DWI> 0 "nonimmediate_operand" "=r,o")
        (minus:<DWI>
          (match_operand:<DWI> 1 "nonimmediate_operand" "0,0")
-         (match_operand:<DWI> 2 "<general_operand>" "ro<di>,r<di>")))
+         (match_operand:<DWI> 2 "x86_64_hilo_general_operand"
+                                                       "ro<di>,r<di>")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
   "#"
index c1541b56d133c8ca5f1e95b5d03e26b5c4738f8c..b3a471d8b7669e188acd033b7e2c434d5209542f 100644 (file)
   return false;
 })
 
+;; Return true if VALUE is a constant integer whose low and high words satisfy
+;; x86_64_immediate_operand.
+(define_predicate "x86_64_hilo_int_operand"
+  (match_code "const_int,const_wide_int")
+{
+  switch (GET_CODE (op))
+    {
+    case CONST_INT:
+      return x86_64_immediate_operand (op, mode);
+
+    case CONST_WIDE_INT:
+      gcc_assert (CONST_WIDE_INT_NUNITS (op) == 2);
+      return (x86_64_immediate_operand (GEN_INT (CONST_WIDE_INT_ELT (op, 0)),
+                                       DImode)
+             && x86_64_immediate_operand (GEN_INT (CONST_WIDE_INT_ELT (op,
+                                                                       1)),
+                                          DImode));
+
+    default:
+      gcc_unreachable ();
+    }
+})
+
 ;; Return true if size of VALUE can be stored in a sign
 ;; extended immediate field.
 (define_predicate "x86_64_immediate_size_operand"
         (match_operand 0 "x86_64_immediate_operand"))
     (match_operand 0 "general_operand")))
 
+;; Return true if OP's both words are general operands representable
+;; on x86_64.
+(define_predicate "x86_64_hilo_general_operand"
+  (if_then_else (match_test "TARGET_64BIT")
+    (ior (match_operand 0 "nonimmediate_operand")
+        (match_operand 0 "x86_64_hilo_int_operand"))
+    (match_operand 0 "general_operand")))
+
 ;; Return true if OP is non-VOIDmode general operand representable
 ;; on x86_64.  This predicate is used in sign-extending conversion
 ;; operations that require non-VOIDmode immediate operands.
index 0941f39afa5d7a226d7d63451801c8f583a3370a..7a898688fc582ee9f737d9c13284c73a0b31fee9 100644 (file)
@@ -1,5 +1,9 @@
 2016-05-03  Jakub Jelinek  <jakub@redhat.com>
 
+       PR rtl-optimization/70467
+       * gcc.target/i386/pr70467-3.c: New test.
+       * gcc.target/i386/pr70467-4.c: New test.
+
        PR tree-optimization/70916
        * gcc.c-torture/compile/pr70916.c: New test.
 
diff --git a/gcc/testsuite/gcc.target/i386/pr70467-3.c b/gcc/testsuite/gcc.target/i386/pr70467-3.c
new file mode 100644 (file)
index 0000000..4d2a6cf
--- /dev/null
@@ -0,0 +1,19 @@
+/* PR rtl-optimization/70467 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2" } */
+
+__uint128_t
+foo (__uint128_t x)
+{
+  return x + ((__uint128_t) 123456 << 64);
+}
+
+__uint128_t
+bar (__uint128_t x)
+{
+  return x - ((__uint128_t) 123456 << 64);
+}
+
+/* Make sure there are no unnecessary additions with carry.  */
+/* { dg-final { scan-assembler-not "adcq\[^\n\r\]*%" } } */
+/* { dg-final { scan-assembler-not "sbbq\[^\n\r\]*%" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr70467-4.c b/gcc/testsuite/gcc.target/i386/pr70467-4.c
new file mode 100644 (file)
index 0000000..91f9b6f
--- /dev/null
@@ -0,0 +1,18 @@
+/* PR rtl-optimization/70467 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2" } */
+
+__uint128_t
+foo (__uint128_t x)
+{
+  return x + ((__uint128_t) 123456 << 64) + 0x1234567;
+}
+
+__uint128_t
+bar (__uint128_t x)
+{
+  return x - ((__uint128_t) 123456 << 64) + 0x1234567;
+}
+
+/* Make sure the immediates are not loaded into registers first.  */
+/* { dg-final { scan-assembler-not "mov\[lq\]\[ \t\]*.\[0-9-\]" } } */