From 3d2def23a5bcc445a4dc8f34d90c0bde639b1a05 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 13 May 2015 10:09:01 +0200 Subject: [PATCH] re PR target/66112 (__builtin_mul_overflow for int16_t emits poor code) PR target/66112 * config/i386/i386.md (mulv4, umulv4, *umulv4): Use SWI248 iterator instead of SWI. (*mulv4_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 | 8 ++ gcc/config/i386/i386.md | 98 +++++++++++++++++------ gcc/testsuite/ChangeLog | 3 + gcc/testsuite/gcc.target/i386/pr66112-2.c | 29 +++++++ 4 files changed, 114 insertions(+), 24 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr66112-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1199ad7dc2c..1906845ed58 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2015-05-13 Jakub Jelinek + PR target/66112 + * config/i386/i386.md (mulv4, umulv4, *umulv4): + Use SWI248 iterator instead of SWI. + (*mulv4_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: (sign_extend: - (match_operand:SWI48 1 "register_operand")) + (match_operand:SWI248 1 "register_operand")) (match_dup 4)) (sign_extend: - (mult:SWI48 (match_dup 1) - (match_operand:SWI48 2 - ""))))) - (set (match_operand:SWI48 0 "register_operand") - (mult:SWI48 (match_dup 1) (match_dup 2)))]) + (mult:SWI248 (match_dup 1) + (match_operand:SWI248 2 + ""))))) + (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: 3 "const_int_operand" "K,i")) (sign_extend: (mult:SWI48 (match_dup 1) - (match_operand:SWI 2 "x86_64_immediate_operand" - "K,"))))) + (match_operand:SWI48 2 + "x86_64_immediate_operand" "K,"))))) (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{}\t{%2, %1, %0|%0, %1, %2} - imul{}\t{%2, %1, %0|%0, %1, %2}" + "imul{}\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" "") (set (attr "length_immediate") - (cond [(match_test "IN_RANGE (INTVAL (operands[2]), -128, 127)") + (cond [(eq_attr "alternative" "0") (const_string "1") (match_test " == 8") (const_string "4")] (const_string "")))]) +(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 "umulv4" [(parallel [(set (reg:CCO FLAGS_REG) (eq:CCO (mult: (zero_extend: - (match_operand:SWI48 1 + (match_operand:SWI248 1 "nonimmediate_operand")) (zero_extend: - (match_operand:SWI48 2 + (match_operand:SWI248 2 "nonimmediate_operand"))) (zero_extend: - (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: (zero_extend: - (match_operand:SWI48 1 "nonimmediate_operand" "%0")) + (match_operand:SWI248 1 "nonimmediate_operand" "%0")) (zero_extend: - (match_operand:SWI48 2 "nonimmediate_operand" "rm"))) + (match_operand:SWI248 2 "nonimmediate_operand" "rm"))) (zero_extend: - (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{}\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,5 +1,8 @@ 2015-05-13 Jakub Jelinek + 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 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 } } */