diff options
author | Jakub Jelinek <jakub@redhat.com> | 2015-05-13 10:09:01 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2015-05-13 10:09:01 +0200 |
commit | 3d2def23a5bcc445a4dc8f34d90c0bde639b1a05 (patch) | |
tree | 3def4481fc03fdc1cd9a53992f5c5c648076e50e | |
parent | c1ee2e626ea59d8ba14a1d2f36621a2fe525320a (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 98 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr66112-2.c | 29 |
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 } } */ |