Hi Richard,

This is the revised patch based on the review and the discussion in
https://gcc.gnu.org/ml/gcc/2018-05/msg00179.html.

In summary:
- I skipped  (element_precision (type) < element_precision (TREE_TYPE
(@0))) in the match.pd pattern as this would prevent transformation
for the case in PR.
that is, I am interested in is something like:
  char t = (char) ABS_EXPR <(int) x>
and I want to generate
char t = (char) ABSU_EXPR <x>

- I also haven't added all the necessary match.pd changes for
ABSU_EXPR. I have a patch for that but will submit separately based on
this reveiw.

- I also tried to add ABSU_EXPRsupport  in the places as necessary by
grepping for ABS_EXPR.

- I also had to add special casing in vectorizer for ABSU_EXP as its
result is unsigned type.

Is this OK. Patch bootstraps and the regression test is ongoing.

Thanks,
Kugan


On 18 May 2018 at 12:36, Kugan Vivekanandarajah
<kugan.vivekanandara...@linaro.org> wrote:
> Hi Richard,
>
> Thanks for the review. I am revising the patch based on Andrew's comments too.
>
> On 17 May 2018 at 20:36, Richard Biener <richard.guent...@gmail.com> wrote:
>> On Thu, May 17, 2018 at 4:56 AM Andrew Pinski <pins...@gmail.com> wrote:
>>
>>> On Wed, May 16, 2018 at 7:14 PM, Kugan Vivekanandarajah
>>> <kugan.vivekanandara...@linaro.org> wrote:
>>> > As mentioned in the PR, I am trying to add ABSU_EXPR to fix this
>>> > issue. In the attached patch, in fold_cond_expr_with_comparison I am
>>> > generating ABSU_EXPR for these cases. As I understand, absu_expr is
>>> > well defined in RTL. So, the issue is generating absu_expr  and
>>> > transferring to RTL in the correct way. I am not sure I am not doing
>>> > all that is needed. I will clean up and add more test-cases based on
>>> > the feedback.
>>
>>
>>> diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
>>> index 71e172c..2b812e5 100644
>>> --- a/gcc/optabs-tree.c
>>> +++ b/gcc/optabs-tree.c
>>> @@ -235,6 +235,7 @@ optab_for_tree_code (enum tree_code code, const_tree
>> type,
>>>         return trapv ? negv_optab : neg_optab;
>>
>>>       case ABS_EXPR:
>>> +    case ABSU_EXPR:
>>>         return trapv ? absv_optab : abs_optab;
>>
>>
>>> This part is not correct, it should something like this:
>>
>>>       case ABS_EXPR:
>>>         return trapv ? absv_optab : abs_optab;
>>> +    case ABSU_EXPR:
>>> +       return abs_optab ;
>>
>>> Because ABSU is not undefined at the TYPE_MAX.
>>
>> Also
>>
>>         /* Unsigned abs is simply the operand.  Testing here means we don't
>>           risk generating incorrect code below.  */
>> -      if (TYPE_UNSIGNED (type))
>> +      if (TYPE_UNSIGNED (type)
>> +         && (code != ABSU_EXPR))
>>          return op0;
>>
>> is wrong.  ABSU of an unsigned number is still just that number.
>>
>> The change to fold_cond_expr_with_comparison looks odd to me
>> (premature optimization).  It should be done separately - it seems
>> you are doing
>
> FE seems to be using this to generate ABS_EXPR from
> c_fully_fold_internal to fold_build3_loc and so on. I changed this to
> generate ABSU_EXPR for the case in the testcase. So the question
> should be, in what cases do we need ABS_EXPR and in what cases do we
> need ABSU_EXPR. It is not very clear to me.
>
>
>>
>> (simplify (abs (convert @0)) (convert (absu @0)))
>>
>> here.
>>
>> You touch one other place in fold-const.c but there seem to be many
>> more that need ABSU_EXPR handling (you touched the one needed
>> for correctness) - esp. you should at least handle constant folding
>> in const_unop and the nonnegative predicate.
>
> OK.
>>
>> @@ -3167,6 +3167,9 @@ verify_expr (tree *tp, int *walk_subtrees, void *data
>> ATTRIBUTE_UNUSED)
>>         CHECK_OP (0, "invalid operand to unary operator");
>>         break;
>>
>> +    case ABSU_EXPR:
>> +      break;
>> +
>>       case REALPART_EXPR:
>>       case IMAGPART_EXPR:
>>
>> verify_expr is no more.  Did you test this recently against trunk?
>
> This patch is against slightly older trunk. I will rebase it.
>
>>
>> @@ -3937,6 +3940,9 @@ verify_gimple_assign_unary (gassign *stmt)
>>       case PAREN_EXPR:
>>       case CONJ_EXPR:
>>         break;
>> +    case ABSU_EXPR:
>> +      /* FIXME.  */
>> +      return false;
>>
>> no - please not!  Please add verification here - ABSU should be only
>> called on INTEGRAL, vector or complex INTEGRAL types and the
>> type of the LHS should be always the unsigned variant of the
>> argument type.
>
> OK.
>>
>>     if (is_gimple_val (cond_expr))
>>       return cond_expr;
>>
>> -  if (TREE_CODE (cond_expr) == ABS_EXPR)
>> +  if (TREE_CODE (cond_expr) == ABS_EXPR
>> +      || TREE_CODE (cond_expr) == ABSU_EXPR)
>>       {
>>         rhs1 = TREE_OPERAND (cond_expr, 1);
>>         STRIP_USELESS_TYPE_CONVERSION (rhs1);
>>
>> err, but the next line just builds a ABS_EXPR ...
>>
>> How did you identify spots that need adjustment?  I would expect that
>> once folding generates ABSU_EXPR that you need to adjust frontends
>> (C++ constexpr handling for example).  Also I miss adjustments
>> to gimple-pretty-print.c and the GIMPLE FE parser.
>
> I will add this.
>>
>> recursively grepping throughout the whole gcc/ tree doesn't reveal too many
>> cases of ABS_EXPR so I think it's reasonable to audit all of them.
>>
>> I also miss some trivial absu simplifications in match.pd.  There are not
>> a lot of abs cases but similar ones would be good to have initially.
>
> I will add them in the next version.
>
> Thanks,
> Kugan
>
>>
>> Thanks for tackling this!
>> Richard.
>>
>>> Thanks,
>>> Andrew
>>
>>> >
>>> > Thanks,
>>> > Kugan
>>> >
>>> >
>>> > gcc/ChangeLog:
>>> >
>>> > 2018-05-13  Kugan Vivekanandarajah  <kugan.vivekanandara...@linaro.org>
>>> >
>>> >     * expr.c (expand_expr_real_2): Handle ABSU_EXPR.
>>> >     * fold-const.c (fold_cond_expr_with_comparison): Generate ABSU_EXPR
>>> >     (fold_unary_loc): Handle ABSU_EXPR.
>>> >     * optabs-tree.c (optab_for_tree_code): Likewise.
>>> >     * tree-cfg.c (verify_expr): Likewise.
>>> >     (verify_gimple_assign_unary):  Likewise.
>>> >     * tree-if-conv.c (fold_build_cond_expr):  Likewise.
>>> >     * tree-inline.c (estimate_operator_cost):  Likewise.
>>> >     * tree-pretty-print.c (dump_generic_node):  Likewise.
>>> >     * tree.def (ABSU_EXPR): New.
>>> >
>>> > gcc/testsuite/ChangeLog:
>>> >
>>> > 2018-05-13  Kugan Vivekanandarajah  <kugan.vivekanandara...@linaro.org>
>>> >
>>> >     * gcc.dg/absu.c: New test.
From 6675f0fe71b1de2c2def5c5d2bd150ae1e707b5c Mon Sep 17 00:00:00 2001
From: Kugan Vivekanandarajah <kugan.vivekanandara...@linaro.org>
Date: Tue, 29 May 2018 10:26:23 +1000
Subject: [PATCH] absu v2

Change-Id: Id34948b4d585fbcdcb8ff6eb3728fd3cc6c41bfa
---
 gcc/c-family/c-common.c            |  1 +
 gcc/c/c-typeck.c                   | 10 ++++++++++
 gcc/c/gimple-parser.c              |  9 ++++++++-
 gcc/cfgexpand.c                    |  1 +
 gcc/config/i386/i386.c             |  1 +
 gcc/cp/constexpr.c                 |  1 +
 gcc/cp/cp-gimplify.c               |  1 +
 gcc/dojump.c                       |  1 +
 gcc/expr.c                         |  3 ++-
 gcc/fold-const.c                   |  6 +++++-
 gcc/gimple-pretty-print.c          |  7 +++++--
 gcc/gimple-ssa-backprop.c          |  2 ++
 gcc/match.pd                       |  8 ++++++++
 gcc/optabs-tree.c                  |  2 ++
 gcc/testsuite/gcc.dg/absu.c        | 41 ++++++++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/gimplefe-29.c | 11 ++++++++++
 gcc/tree-cfg.c                     |  6 ++++++
 gcc/tree-eh.c                      |  1 +
 gcc/tree-inline.c                  |  1 +
 gcc/tree-pretty-print.c            |  6 ++++++
 gcc/tree-vect-patterns.c           |  3 ++-
 gcc/tree-vect-stmts.c              |  6 +++++-
 gcc/tree.def                       |  1 +
 23 files changed, 122 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/absu.c
 create mode 100644 gcc/testsuite/gcc.dg/gimplefe-29.c

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 859eeb4..0e8efb5 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -3312,6 +3312,7 @@ c_common_truthvalue_conversion (location_t location, tree expr)
 
     case NEGATE_EXPR:
     case ABS_EXPR:
+    case ABSU_EXPR:
     case FLOAT_EXPR:
     case EXCESS_PRECISION_EXPR:
       /* These don't change whether an object is nonzero or zero.  */
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 45a4529..5bb6804 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -4314,6 +4314,16 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
 	arg = default_conversion (arg);
       break;
 
+    case ABSU_EXPR:
+      if (!(typecode == INTEGER_TYPE))
+	{
+	  error_at (location, "wrong type argument to absu");
+	  return error_mark_node;
+	}
+      else if (!noconvert)
+	arg = default_conversion (arg);
+      break;
+
     case CONJ_EXPR:
       /* Conjugating a real value is a no-op, but allow it anyway.  */
       if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 8f1c442..1be5d14 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -328,7 +328,8 @@ c_parser_gimple_statement (c_parser *parser, gimple_seq *seq)
     case CPP_NAME:
       {
 	tree id = c_parser_peek_token (parser)->value;
-	if (strcmp (IDENTIFIER_POINTER (id), "__ABS") == 0)
+	if (strcmp (IDENTIFIER_POINTER (id), "__ABS") == 0
+	    || strcmp (IDENTIFIER_POINTER (id), "__ABSU") == 0)
 	  goto build_unary_expr;
 	break;
       }
@@ -638,6 +639,12 @@ c_parser_gimple_unary_expression (c_parser *parser)
 	      op = c_parser_gimple_postfix_expression (parser);
 	      return parser_build_unary_op (op_loc, ABS_EXPR, op);
 	    }
+	  else if (strcmp (IDENTIFIER_POINTER (id), "__ABSU") == 0)
+	    {
+	      c_parser_consume_token (parser);
+	      op = c_parser_gimple_postfix_expression (parser);
+	      return parser_build_unary_op (op_loc, ABSU_EXPR, op);
+	    }
 	  else
 	    return c_parser_gimple_postfix_expression (parser);
 	}
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 5c323be..d06224d 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -4620,6 +4620,7 @@ expand_debug_expr (tree exp)
       }
 
     case ABS_EXPR:
+    case ABSU_EXPR:
       return simplify_gen_unary (ABS, mode, op0, mode);
 
     case NEGATE_EXPR:
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 637c105..f5a4856 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -51232,6 +51232,7 @@ ix86_add_stmt_cost (void *data, int count, enum vect_cost_for_stmt kind,
 
 	case BIT_IOR_EXPR:
 	case ABS_EXPR:
+	case ABSU_EXPR:
 	case MIN_EXPR:
 	case MAX_EXPR:
 	case BIT_XOR_EXPR:
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index a099408..30ea091 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -5759,6 +5759,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
     case FLOAT_EXPR:
     case NEGATE_EXPR:
     case ABS_EXPR:
+    case ABSU_EXPR:
     case TRUTH_NOT_EXPR:
     case FIXED_CONVERT_EXPR:
     case UNARY_PLUS_EXPR:
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index b4e23e2..4567365 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2272,6 +2272,7 @@ cp_fold (tree x)
     case FLOAT_EXPR:
     case NEGATE_EXPR:
     case ABS_EXPR:
+    case ABSU_EXPR:
     case BIT_NOT_EXPR:
     case TRUTH_NOT_EXPR:
     case FIXED_CONVERT_EXPR:
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 9da8a0e..88cc96a 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -467,6 +467,7 @@ do_jump (tree exp, rtx_code_label *if_false_label,
       /* FALLTHRU */
     case NON_LVALUE_EXPR:
     case ABS_EXPR:
+    case ABSU_EXPR:
     case NEGATE_EXPR:
     case LROTATE_EXPR:
     case RROTATE_EXPR:
diff --git a/gcc/expr.c b/gcc/expr.c
index ecc5292..a92c23f 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -9013,6 +9013,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
       return REDUCE_BIT_FIELD (temp);
 
     case ABS_EXPR:
+    case ABSU_EXPR:
       op0 = expand_expr (treeop0, subtarget,
 			 VOIDmode, EXPAND_NORMAL);
       if (modifier == EXPAND_STACK_PARM)
@@ -9024,7 +9025,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
 
       /* Unsigned abs is simply the operand.  Testing here means we don't
 	 risk generating incorrect code below.  */
-      if (TYPE_UNSIGNED (type))
+      if (TYPE_UNSIGNED (TREE_TYPE (treeop0)))
 	return op0;
 
       return expand_abs (mode, op0, target, unsignedp,
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 0f57f07..20b4271 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1723,7 +1723,8 @@ const_unop (enum tree_code code, tree type, tree arg0)
       && HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0)))
       && REAL_VALUE_ISSIGNALING_NAN (TREE_REAL_CST (arg0))
       && code != NEGATE_EXPR
-      && code != ABS_EXPR)
+      && code != ABS_EXPR
+      && code != ABSU_EXPR)
     return NULL_TREE;
 
   switch (code)
@@ -1761,6 +1762,9 @@ const_unop (enum tree_code code, tree type, tree arg0)
       if (TREE_CODE (arg0) == INTEGER_CST || TREE_CODE (arg0) == REAL_CST)
 	return fold_abs_const (arg0, type);
       break;
+    case ABSU_EXPR:
+	return fold_convert (type, fold_abs_const (arg0,
+						   signed_type_for (type)));
 
     case CONJ_EXPR:
       if (TREE_CODE (arg0) == COMPLEX_CST)
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 49e9e12..bb4d259 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -358,14 +358,17 @@ dump_unary_rhs (pretty_printer *buffer, gassign *gs, int spc,
       break;
 
     case ABS_EXPR:
+    case ABSU_EXPR:
       if (flags & TDF_GIMPLE)
 	{
-	  pp_string (buffer, "__ABS ");
+	  pp_string (buffer,
+		     rhs_code == ABS_EXPR ? "__ABS " : "__ABSU ");
 	  dump_generic_node (buffer, rhs, spc, flags, false);
 	}
       else
 	{
-	  pp_string (buffer, "ABS_EXPR <");
+	  pp_string (buffer,
+		     rhs_code == ABS_EXPR ? "ABS_EXPR <" : "ABSU_EXPR <");
 	  dump_generic_node (buffer, rhs, spc, flags, false);
 	  pp_greater (buffer);
 	}
diff --git a/gcc/gimple-ssa-backprop.c b/gcc/gimple-ssa-backprop.c
index 9ab655c..bb378a9 100644
--- a/gcc/gimple-ssa-backprop.c
+++ b/gcc/gimple-ssa-backprop.c
@@ -408,6 +408,7 @@ backprop::process_assign_use (gassign *assign, tree rhs, usage_info *info)
   switch (gimple_assign_rhs_code (assign))
     {
     case ABS_EXPR:
+    case ABSU_EXPR:
       /* The sign of the input doesn't matter.  */
       info->flags.ignore_sign = true;
       break;
@@ -675,6 +676,7 @@ strip_sign_op_1 (tree rhs)
     switch (gimple_assign_rhs_code (assign))
       {
       case ABS_EXPR:
+      case ABSU_EXPR:
       case NEGATE_EXPR:
 	return gimple_assign_rhs1 (assign);
 
diff --git a/gcc/match.pd b/gcc/match.pd
index 14386da..7d7c132 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -102,6 +102,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 (match (nop_convert @0)
  @0) 
 
+(simplify (abs (convert @0))
+ (if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+      && !TYPE_UNSIGNED (TREE_TYPE (@0))
+      && !TYPE_UNSIGNED (type))
+  (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
+   (convert (absu:utype @0)))))
+
+
 /* Simplifications of operations with one constant operand and
    simplifications to constants or single values.  */
 
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index 73e6654..092663b 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -234,6 +234,8 @@ optab_for_tree_code (enum tree_code code, const_tree type,
     case ABS_EXPR:
       return trapv ? absv_optab : abs_optab;
 
+    case ABSU_EXPR:
+      return abs_optab;
     default:
       return unknown_optab;
     }
diff --git a/gcc/testsuite/gcc.dg/absu.c b/gcc/testsuite/gcc.dg/absu.c
new file mode 100644
index 0000000..81e37a4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/absu.c
@@ -0,0 +1,41 @@
+
+/* { dg-do run  } */
+/* { dg-options "-O0" } */
+
+#include <limits.h>
+#define ABS(x)	(((x) >= 0) ? (x) : -(x))
+
+#define DEF_TEST(TYPE)	\
+void foo_##TYPE (signed TYPE x, unsigned TYPE y){	\
+    TYPE t = ABS (x);				\
+    if (t != y)					\
+ 	__builtin_abort ();			\
+}						\
+
+DEF_TEST (char);
+DEF_TEST (short);
+DEF_TEST (int);
+DEF_TEST (long);
+void main ()
+{
+  foo_char (SCHAR_MIN + 1, SCHAR_MAX);
+  foo_char (0, 0);
+  foo_char (-1, 1);
+  foo_char (1, 1);
+  foo_char (SCHAR_MAX, SCHAR_MAX);
+
+  foo_int (-1, 1);
+  foo_int (0, 0);
+  foo_int (INT_MAX, INT_MAX);
+  foo_int (INT_MIN + 1, INT_MAX);
+
+  foo_short (-1, 1);
+  foo_short (0, 0);
+  foo_short (SHRT_MAX, SHRT_MAX);
+  foo_short (SHRT_MIN + 1, SHRT_MAX);
+
+  foo_long (-1, 1);
+  foo_long (0, 0);
+  foo_long (LONG_MAX, LONG_MAX);
+  foo_long (LONG_MIN + 1, LONG_MAX);
+}
diff --git a/gcc/testsuite/gcc.dg/gimplefe-29.c b/gcc/testsuite/gcc.dg/gimplefe-29.c
new file mode 100644
index 0000000..54b86ef
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gimplefe-29.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fgimple -fdump-tree-ssa-gimple" } */
+
+unsigned int __GIMPLE() f(int a)
+{
+  unsigned int t0;
+  t0_1 = __ABSU a;
+  return t0_1;
+}
+
+/* { dg-final { scan-tree-dump "__ABSU a" "ssa" } } */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 68f4fd3..9b62583 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3685,6 +3685,12 @@ verify_gimple_assign_unary (gassign *stmt)
     case PAREN_EXPR:
     case CONJ_EXPR:
       break;
+    case ABSU_EXPR:
+      if (!TYPE_UNSIGNED (lhs_type)
+	  || !ANY_INTEGRAL_TYPE_P (rhs1_type))
+	return true;
+      return false;
+      break;
 
     case VEC_DUPLICATE_EXPR:
       if (TREE_CODE (lhs_type) != VECTOR_TYPE
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 30c6d9e..44b1399 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2465,6 +2465,7 @@ operation_could_trap_helper_p (enum tree_code op,
 
     case NEGATE_EXPR:
     case ABS_EXPR:
+    case ABSU_EXPR:
     case CONJ_EXPR:
       /* These operations don't trap with floating point.  */
       if (honor_trapv)
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 7881131..665e53c 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3865,6 +3865,7 @@ estimate_operator_cost (enum tree_code code, eni_weights *weights,
     case MIN_EXPR:
     case MAX_EXPR:
     case ABS_EXPR:
+    case ABSU_EXPR:
 
     case LSHIFT_EXPR:
     case RSHIFT_EXPR:
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 5a8c8eb..a950a9e 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -2463,6 +2463,12 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
       pp_greater (pp);
       break;
 
+    case ABSU_EXPR:
+      pp_string (pp, "ABSU_EXPR <");
+      dump_generic_node (pp, TREE_OPERAND (node, 0), spc, flags, false);
+      pp_greater (pp);
+      break;
+
     case RANGE_EXPR:
       NIY;
       break;
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 6da784c..af6b9bd 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -615,7 +615,8 @@ vect_recog_sad_pattern (vec<gimple *> *stmts, tree *type_in,
   gcc_assert (abs_stmt_vinfo);
   if (STMT_VINFO_DEF_TYPE (abs_stmt_vinfo) != vect_internal_def)
     return NULL;
-  if (gimple_assign_rhs_code (abs_stmt) != ABS_EXPR)
+  if (gimple_assign_rhs_code (abs_stmt) != ABS_EXPR
+      && gimple_assign_rhs_code (abs_stmt) != ABSU_EXPR)
     return NULL;
 
   tree abs_oprnd = gimple_assign_rhs1 (abs_stmt);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 66c78de..b52d714 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -5995,7 +5995,11 @@ vectorizable_operation (gimple *stmt, gimple_stmt_iterator *gsi,
                      "transform binary/unary operation.\n");
 
   /* Handle def.  */
-  vec_dest = vect_create_destination_var (scalar_dest, vectype);
+  if (code == ABSU_EXPR)
+    vec_dest = vect_create_destination_var (scalar_dest,
+					    unsigned_type_for (vectype));
+  else
+    vec_dest = vect_create_destination_var (scalar_dest, vectype);
 
   /* POINTER_DIFF_EXPR has pointer arguments which are vectorized as
      vectors with unsigned elements, but the result is signed.  So, we
diff --git a/gcc/tree.def b/gcc/tree.def
index c660b2c..5fec781 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -760,6 +760,7 @@ DEFTREECODE (MAX_EXPR, "max_expr", tcc_binary, 2)
    An ABS_EXPR must have either an INTEGER_TYPE or a REAL_TYPE.  The
    operand of the ABS_EXPR must have the same type.  */
 DEFTREECODE (ABS_EXPR, "abs_expr", tcc_unary, 1)
+DEFTREECODE (ABSU_EXPR, "absu_expr", tcc_unary, 1)
 
 /* Shift operations for shift and rotate.
    Shift means logical shift if done on an
-- 
2.7.4

Reply via email to