re PR target/66112 (__builtin_mul_overflow for int16_t emits poor code)
authorJakub Jelinek <jakub@redhat.com>
Wed, 13 May 2015 08:09:01 +0000 (10:09 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 13 May 2015 08:09:01 +0000 (10:09 +0200)
PR target/66112
* config/i386/i386.md (mulv<mode>4, umulv<mode>4, *umulv<mode>4):
Use SWI248 iterator instead of SWI.
(*mulv<mode>4_1): Use SWI48 instead of SWI.  Simplify output template.
Use eq_attr "alternative" "0" instead of match_test in
length_immediate attribute computation.
(*mulvhi4, *mulvhi4_1): New define_insns.

* gcc.target/i386/pr66112-2.c: New test.

From-SVN: r223116

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr66112-2.c [new file with mode: 0644]

index 1199ad7dc2c40a471d52dab11839ce32cab5335d..1906845ed58e024ac6561f02adbc2c39afb4fce4 100644 (file)
@@ -1,5 +1,13 @@
 2015-05-13  Jakub Jelinek  <jakub@redhat.com>
 
+       PR target/66112
+       * config/i386/i386.md (mulv<mode>4, umulv<mode>4, *umulv<mode>4):
+       Use SWI248 iterator instead of SWI.
+       (*mulv<mode>4_1): Use SWI48 instead of SWI.  Simplify output template.
+       Use eq_attr "alternative" "0" instead of match_test in
+       length_immediate attribute computation.
+       (*mulvhi4, *mulvhi4_1): New define_insns.
+
        PR target/66112
        * internal-fn.c (get_min_precision): Use UNSIGNED instead of
        SIGNED to get precision of non-negative value.
index 0959aef7a0d69325437d5250cd4c4fffd89f677f..835e890fac1e5234c9441ba047f2f00b246b2ea5 100644 (file)
   [(parallel [(set (reg:CCO FLAGS_REG)
                   (eq:CCO (mult:<DWI>
                              (sign_extend:<DWI>
-                                (match_operand:SWI48 1 "register_operand"))
+                                (match_operand:SWI248 1 "register_operand"))
                              (match_dup 4))
                           (sign_extend:<DWI>
-                             (mult:SWI48 (match_dup 1)
-                                         (match_operand:SWI48 2
-                                            "<general_operand>")))))
-             (set (match_operand:SWI48 0 "register_operand")
-                  (mult:SWI48 (match_dup 1) (match_dup 2)))])
+                             (mult:SWI248 (match_dup 1)
+                                          (match_operand:SWI248 2
+                                             "<general_operand>")))))
+             (set (match_operand:SWI248 0 "register_operand")
+                  (mult:SWI248 (match_dup 1) (match_dup 2)))])
    (set (pc) (if_then_else
               (eq (reg:CCO FLAGS_REG) (const_int 0))
               (label_ref (match_operand 3))
                   (match_operand:<DWI> 3 "const_int_operand" "K,i"))
                (sign_extend:<DWI>
                   (mult:SWI48 (match_dup 1)
-                              (match_operand:SWI 2 "x86_64_immediate_operand"
-                                                   "K,<i>")))))
+                              (match_operand:SWI48 2
+                                 "x86_64_immediate_operand" "K,<i>")))))
    (set (match_operand:SWI48 0 "register_operand" "=r,r")
        (mult:SWI48 (match_dup 1) (match_dup 2)))]
   "!(MEM_P (operands[1]) && MEM_P (operands[2]))
    && CONST_INT_P (operands[2])
    && INTVAL (operands[2]) == INTVAL (operands[3])"
-  "@
-   imul{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}
-   imul{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
+  "imul{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
   [(set_attr "type" "imul")
    (set (attr "athlon_decode")
        (cond [(eq_attr "cpu" "athlon")
    (set_attr "bdver1_decode" "direct")
    (set_attr "mode" "<MODE>")
    (set (attr "length_immediate")
-       (cond [(match_test "IN_RANGE (INTVAL (operands[2]), -128, 127)")
+       (cond [(eq_attr "alternative" "0")
                  (const_string "1")
               (match_test "<MODE_SIZE> == 8")
                  (const_string "4")]
              (const_string "<MODE_SIZE>")))])
 
+(define_insn "*mulvhi4"
+  [(set (reg:CCO FLAGS_REG)
+       (eq:CCO (mult:SI
+                  (sign_extend:SI
+                     (match_operand:HI 1 "nonimmediate_operand" "0"))
+                  (sign_extend:SI
+                     (match_operand:HI 2 "general_operand" "mr")))
+               (sign_extend:SI
+                  (mult:HI (match_dup 1) (match_dup 2)))))
+   (set (match_operand:HI 0 "register_operand" "=r")
+       (mult:HI (match_dup 1) (match_dup 2)))]
+  "!(MEM_P (operands[1]) && MEM_P (operands[2]))"
+  "imul{w}\t{%2, %0|%0, %2}"
+  [(set_attr "type" "imul")
+   (set_attr "prefix_0f" "1")
+   (set_attr "athlon_decode" "vector")
+   (set_attr "amdfam10_decode" "direct")
+   (set_attr "bdver1_decode" "double")
+   (set_attr "mode" "HI")])
+
+(define_insn "*mulvhi4_1"
+  [(set (reg:CCO FLAGS_REG)
+       (eq:CCO (mult:SI
+                  (sign_extend:SI
+                     (match_operand:HI 1 "nonimmediate_operand" "rm,rm"))
+                  (match_operand:SI 3 "const_int_operand" "K,i"))
+               (sign_extend:SI
+                  (mult:HI (match_dup 1)
+                              (match_operand:HI 2
+                                 "x86_64_immediate_operand" "K,n")))))
+   (set (match_operand:HI 0 "register_operand" "=r,r")
+       (mult:HI (match_dup 1) (match_dup 2)))]
+  "!(MEM_P (operands[1]) && MEM_P (operands[2]))
+   && CONST_INT_P (operands[2])
+   && INTVAL (operands[2]) == INTVAL (operands[3])"
+  "imul{w}\t{%2, %1, %0|%0, %1, %2}"
+  [(set_attr "type" "imul")
+   (set_attr "prefix_0f" "0")
+   (set (attr "athlon_decode")
+       (cond [(eq_attr "cpu" "athlon")
+                 (const_string "vector")
+              (eq_attr "alternative" "1")
+                 (const_string "vector")]
+             (const_string "direct")))
+   (set_attr "amdfam10_decode" "vector")
+   (set_attr "bdver1_decode" "double")
+   (set_attr "mode" "HI")
+   (set (attr "length_immediate")
+       (cond [(eq_attr "alternative" "0")
+                 (const_string "1")]
+             (const_string "2")))])
+
 (define_expand "umulv<mode>4"
   [(parallel [(set (reg:CCO FLAGS_REG)
                   (eq:CCO (mult:<DWI>
                              (zero_extend:<DWI>
-                                (match_operand:SWI48 1
+                                (match_operand:SWI248 1
                                                      "nonimmediate_operand"))
                              (zero_extend:<DWI>
-                                (match_operand:SWI48 2
+                                (match_operand:SWI248 2
                                                      "nonimmediate_operand")))
                           (zero_extend:<DWI>
-                             (mult:SWI48 (match_dup 1) (match_dup 2)))))
-             (set (match_operand:SWI48 0 "register_operand")
-                  (mult:SWI48 (match_dup 1) (match_dup 2)))
-             (clobber (match_scratch:SWI48 4))])
+                             (mult:SWI248 (match_dup 1) (match_dup 2)))))
+             (set (match_operand:SWI248 0 "register_operand")
+                  (mult:SWI248 (match_dup 1) (match_dup 2)))
+             (clobber (match_scratch:SWI248 4))])
    (set (pc) (if_then_else
               (eq (reg:CCO FLAGS_REG) (const_int 0))
               (label_ref (match_operand 3))
   [(set (reg:CCO FLAGS_REG)
        (eq:CCO (mult:<DWI>
                   (zero_extend:<DWI>
-                     (match_operand:SWI48 1 "nonimmediate_operand" "%0"))
+                     (match_operand:SWI248 1 "nonimmediate_operand" "%0"))
                   (zero_extend:<DWI>
-                     (match_operand:SWI48 2 "nonimmediate_operand" "rm")))
+                     (match_operand:SWI248 2 "nonimmediate_operand" "rm")))
                (zero_extend:<DWI>
-                  (mult:SWI48 (match_dup 1) (match_dup 2)))))
-   (set (match_operand:SWI48 0 "register_operand" "=a")
-       (mult:SWI48 (match_dup 1) (match_dup 2)))
-   (clobber (match_scratch:SWI48 3 "=d"))]
+                  (mult:SWI248 (match_dup 1) (match_dup 2)))))
+   (set (match_operand:SWI248 0 "register_operand" "=a")
+       (mult:SWI248 (match_dup 1) (match_dup 2)))
+   (clobber (match_scratch:SWI248 3 "=d"))]
   "!(MEM_P (operands[1]) && MEM_P (operands[2]))"
   "mul{<imodesuffix>}\t%2"
   [(set_attr "type" "imul")
index 4600fe1f8a46ed3e550219f48f9d87decd019ac9..6e394e79fa85105b2901d740c9b5737a9a4f325a 100644 (file)
@@ -1,5 +1,8 @@
 2015-05-13  Jakub Jelinek  <jakub@redhat.com>
 
+       PR target/66112
+       * gcc.target/i386/pr66112-2.c: New test.
+
        PR target/66112
        * gcc.target/i386/pr66112-1.c: New test.
 
diff --git a/gcc/testsuite/gcc.target/i386/pr66112-2.c b/gcc/testsuite/gcc.target/i386/pr66112-2.c
new file mode 100644 (file)
index 0000000..7fc1881
--- /dev/null
@@ -0,0 +1,29 @@
+/* PR target/66112 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+unsigned short int
+foo (int a, int b)
+{
+  unsigned short int res;
+  a &= 0xffff;
+  b &= 0xffff;
+  if (__builtin_mul_overflow (a, b, &res))
+    res = 0x123;
+  return res;
+}
+
+short int
+bar (int a, int b)
+{
+  short int res;
+  a = (short int) a;
+  b = (short int) b;
+  if (__builtin_mul_overflow (a, b, &res))
+    res = 0x123;
+  return res;
+}
+
+/* { dg-final { scan-assembler-times "jn?o\[ \t\]" 2 } } */
+/* { dg-final { scan-assembler-times "mulw\[ \t\]" 2 } } */
+/* { dg-final { scan-assembler-times "imulw\[ \t\]" 1 } } */