summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-02-08 18:41:21 +0100
committerJakub Jelinek <jakub@redhat.com>2023-02-08 18:41:21 +0100
commit6ad1c1027628f094260037536f6b6fcdb63b5add (patch)
tree7d80dfa11b4b9e29f2968858e34b61df7e272e24
parentaarch64: Fix return_address_sign_ab_exception.C regression (diff)
vect-patterns: Fix up vect_widened_op_tree [PR108692]
The following testcase is miscompiled on aarch64-linux since r11-5160. Given <bb 3> [local count: 955630225]: # i_22 = PHI <i_20(6), 0(5)> # r_23 = PHI <r_19(6), 0(5)> ... a.0_5 = (unsigned char) a_15; _6 = (int) a.0_5; b.1_7 = (unsigned char) b_17; _8 = (int) b.1_7; c_18 = _6 - _8; _9 = ABS_EXPR <c_18>; r_19 = _9 + r_23; ... where SSA_NAMEs 15/17 have signed char, 5/7 unsigned char and rest is int we first pattern recognize c_18 as patt_34 = (a.0_5) w- (b.1_7); which is still correct, 5/7 are unsigned char subtracted in wider type, but then vect_recog_sad_pattern turns it into SAD_EXPR <a_15, b_17, r_23> which is incorrect, because 15/17 are signed char and so it is sum of absolute signed differences rather than unsigned sum of absolute unsigned differences. The reason why this happens is that vect_recog_sad_pattern calls vect_widened_op_tree with MINUS_EXPR, WIDEN_MINUS_EXPR on the patt_34 = (a.0_5) w- (b.1_7); statement's vinfo and vect_widened_op_tree calls vect_look_through_possible_promotion on the operands of the WIDEN_MINUS_EXPR, which looks through the further casts. vect_look_through_possible_promotion has careful code to stop when there would be nested casts that need to be preserved, but the problem here is that the WIDEN_*_EXPR operation itself has an implicit cast on the operands already - in this case of WIDEN_MINUS_EXPR the unsigned char 5/7 SSA_NAMEs are widened to unsigned short before the subtraction, and vect_look_through_possible_promotion obviously isn't told about that. Now, I think when we see those WIDEN_{MULT,MINUS,PLUS}_EXPR codes, we had to look through possible promotions already when creating those and so vect_look_through_possible_promotion again isn't really needed, all we need to do is arrange what that function will do if the operand isn't result of any cast. Other option would be let vect_look_through_possible_promotion know about the implicit promotion from the WIDEN_*_EXPR, but I'm afraid that would be much harder. 2023-02-08 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/108692 * tree-vect-patterns.cc (vect_widened_op_tree): If rhs_code is widened_code which is different from code, don't call vect_look_through_possible_promotion but instead just check op is SSA_NAME with integral type for which vect_is_simple_use is true and call set_op on this_unprom. * gcc.dg/pr108692.c: New test.
-rw-r--r--gcc/testsuite/gcc.dg/pr108692.c31
-rw-r--r--gcc/tree-vect-patterns.cc20
2 files changed, 50 insertions, 1 deletions
diff --git a/gcc/testsuite/gcc.dg/pr108692.c b/gcc/testsuite/gcc.dg/pr108692.c
new file mode 100644
index 000000000000..fc25bf54e45d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr108692.c
@@ -0,0 +1,31 @@
1/* PR tree-optimization/108692 */
2/* { dg-do compile } */
3/* { dg-options "-O2 -ftree-vectorize" } */
4
5__attribute__((noipa)) int
6foo (signed char *x, signed char *y, int n)
7{
8 int i, r = 0;
9 signed char a, b;
10 for (i = 0; i < n; i++)
11 {
12 a = x[i];
13 b = y[i];
14 int c = (unsigned char) a - (unsigned char) b;
15 r = r + (c < 0 ? -c : c);
16 }
17 return r;
18}
19
20int
21main ()
22{
23 signed char x[64] = {}, y[64] = {};
24 if (__CHAR_BIT__ != 8 || __SIZEOF_INT__ != 4)
25 return 0;
26 x[32] = -128;
27 y[32] = 1;
28 if (foo (x, y, 64) != 127)
29 __builtin_abort ();
30 return 0;
31}
diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
index 6934aebc69f2..cefe331620f7 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -601,7 +601,25 @@ vect_widened_op_tree (vec_info *vinfo, stmt_vec_info stmt_info, tree_code code,
601 if (shift_p && i == 1) 601 if (shift_p && i == 1)
602 return 0; 602 return 0;
603 603
604 if (!vect_look_through_possible_promotion (vinfo, op, this_unprom)) 604 if (rhs_code != code)
605 {
606 /* If rhs_code is widened_code, don't look through further
607 possible promotions, there is a promotion already embedded
608 in the WIDEN_*_EXPR. */
609 if (TREE_CODE (op) != SSA_NAME
610 || !INTEGRAL_TYPE_P (TREE_TYPE (op)))
611 return 0;
612
613 stmt_vec_info def_stmt_info;
614 gimple *def_stmt;
615 vect_def_type dt;
616 if (!vect_is_simple_use (op, vinfo, &dt, &def_stmt_info,
617 &def_stmt))
618 return 0;
619 this_unprom->set_op (op, dt, NULL);
620 }
621 else if (!vect_look_through_possible_promotion (vinfo, op,
622 this_unprom))
605 return 0; 623 return 0;
606 624
607 if (TYPE_PRECISION (this_unprom->type) == TYPE_PRECISION (type)) 625 if (TYPE_PRECISION (this_unprom->type) == TYPE_PRECISION (type))