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
This commit is contained in:
Jakub Jelinek 2015-05-13 10:09:01 +02:00 committed by Jakub Jelinek
parent c1ee2e626e
commit 3d2def23a5
4 changed files with 114 additions and 24 deletions

View 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.

View File

@ -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")

View 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.

View File

@ -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 } } */