summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2015-05-13 10:09:01 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2015-05-13 10:09:01 +0200
commit3d2def23a5bcc445a4dc8f34d90c0bde639b1a05 (patch)
tree3def4481fc03fdc1cd9a53992f5c5c648076e50e
parentc1ee2e626ea59d8ba14a1d2f36621a2fe525320a (diff)
downloadgcc-3d2def23a5bcc445a4dc8f34d90c0bde639b1a05.tar.gz
re PR target/66112 (__builtin_mul_overflow for int16_t emits poor code)
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
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/i386/i386.md98
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr66112-2.c29
4 files changed, 114 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1199ad7dc2c..1906845ed58 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,14 @@
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.
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 0959aef7a0d..835e890fac1 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -6602,14 +6602,14 @@
[(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))
@@ -6665,16 +6665,14 @@
(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")
@@ -6689,26 +6687,78 @@
(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))
@@ -6723,14 +6773,14 @@
[(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")
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4600fe1f8a4..6e394e79fa8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,9 @@
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.
2015-05-13 Ilya Enkovich <ilya.enkovich@intel.com>
diff --git a/gcc/testsuite/gcc.target/i386/pr66112-2.c b/gcc/testsuite/gcc.target/i386/pr66112-2.c
new file mode 100644
index 00000000000..7fc18811638
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr66112-2.c
@@ -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 } } */