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.

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.
diff --git a/gcc/expr.c b/gcc/expr.c
index 5e3d9a5..67f8dd1 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -9063,6 +9063,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)
@@ -9074,7 +9075,8 @@ 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 (type)
+         && (code != ABSU_EXPR))
        return op0;
 
       return expand_abs (mode, op0, target, unsignedp,
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 3a99b66..6e80178 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -5324,8 +5324,17 @@ fold_cond_expr_with_comparison (location_t loc, tree 
type,
       case GT_EXPR:
        if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
          break;
-       tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
-       return fold_convert_loc (loc, type, tem);
+       if (TREE_CODE (arg1) == NOP_EXPR)
+         {
+           arg1 = TREE_OPERAND (arg1, 0);
+           tem = fold_build1_loc (loc, ABSU_EXPR, unsigned_type_for 
(arg1_type), arg1);
+           return fold_convert_loc (loc, type, tem);
+         }
+       else
+         {
+           tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
+           return fold_convert_loc (loc, type, tem);
+         }
       case UNLE_EXPR:
       case UNLT_EXPR:
        if (flag_trapping_math)
@@ -7698,7 +7707,8 @@ fold_unary_loc (location_t loc, enum tree_code code, tree 
type, tree op0)
   if (arg0)
     {
       if (CONVERT_EXPR_CODE_P (code)
-         || code == FLOAT_EXPR || code == ABS_EXPR || code == NEGATE_EXPR)
+         || code == FLOAT_EXPR || code == ABS_EXPR
+         || code == ABSU_EXPR || code == NEGATE_EXPR)
        {
          /* Don't use STRIP_NOPS, because signedness of argument type
             matters.  */
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;
 
     default:
diff --git a/gcc/testsuite/gcc.dg/absu.c b/gcc/testsuite/gcc.dg/absu.c
index e69de29..43e651b 100644
--- a/gcc/testsuite/gcc.dg/absu.c
+++ b/gcc/testsuite/gcc.dg/absu.c
@@ -0,0 +1,39 @@
+
+/* { 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 (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/tree-cfg.c b/gcc/tree-cfg.c
index 9485f73..59a115c 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -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:
     case BIT_FIELD_REF:
@@ -3937,6 +3940,9 @@ verify_gimple_assign_unary (gassign *stmt)
     case PAREN_EXPR:
     case CONJ_EXPR:
       break;
+    case ABSU_EXPR:
+      /* FIXME.  */
+      return false;
 
     case VEC_DUPLICATE_EXPR:
       if (TREE_CODE (lhs_type) != VECTOR_TYPE
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 71dac4f..13d4c25 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -466,7 +466,8 @@ fold_build_cond_expr (tree type, tree cond, tree rhs, tree 
lhs)
   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);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 5a0a252..d272974 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3866,6 +3866,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 276ad00..b74d8c9 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -2460,6 +2460,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.def b/gcc/tree.def
index 31de6c0..768167b 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

Reply via email to