gimple-range: implement widen plus range

Message ID 21150fd3-ff31-1188-5876-768e7a5edc84@arm.com
State New
Headers
Series gimple-range: implement widen plus range |

Commit Message

Andre Vieira (lists) June 1, 2023, 4:31 p.m. UTC
  Hi,

This patch adds gimple-range information for the new IFN_VEC_WIDEN_PLUS* 
internal functions, identical to what VEC_WIDEN_PLUS did.

Bootstrapped and regression tested on aarch64-unknown-linux-gnu.

gcc/ChangeLog:

         * gimple-range-op.cc (gimple_range_op_handler::maybe_non_standard):
         Add support for IFN_VEC_WIDEN_PLUS*.
  

Patch

diff --git a/gcc/gimple-range-op.cc b/gcc/gimple-range-op.cc
index 59c47e2074ddc73065468fe92274c260bd5bac48..7a84931d6204a56549cf1563114d8db7a2e26a6a 100644
--- a/gcc/gimple-range-op.cc
+++ b/gcc/gimple-range-op.cc
@@ -1187,6 +1187,7 @@  gimple_range_op_handler::maybe_non_standard ()
 {
   range_operator *signed_op = ptr_op_widen_mult_signed;
   range_operator *unsigned_op = ptr_op_widen_mult_unsigned;
+  bool signed1, signed2, signed_ret;
   if (gimple_code (m_stmt) == GIMPLE_ASSIGN)
     switch (gimple_assign_rhs_code (m_stmt))
       {
@@ -1196,32 +1197,58 @@  gimple_range_op_handler::maybe_non_standard ()
 	  m_op1 = gimple_assign_rhs1 (m_stmt);
 	  m_op2 = gimple_assign_rhs2 (m_stmt);
 	  tree ret = gimple_assign_lhs (m_stmt);
-	  bool signed1 = TYPE_SIGN (TREE_TYPE (m_op1)) == SIGNED;
-	  bool signed2 = TYPE_SIGN (TREE_TYPE (m_op2)) == SIGNED;
-	  bool signed_ret = TYPE_SIGN (TREE_TYPE (ret)) == SIGNED;
-
-	  /* Normally these operands should all have the same sign, but
-	     some passes and violate this by taking mismatched sign args.  At
-	     the moment the only one that's possible is mismatch inputs and
-	     unsigned output.  Once ranger supports signs for the operands we
-	     can properly fix it,  for now only accept the case we can do
-	     correctly.  */
-	  if ((signed1 ^ signed2) && signed_ret)
-	    return;
-
-	  m_valid = true;
-	  if (signed2 && !signed1)
-	    std::swap (m_op1, m_op2);
-
-	  if (signed1 || signed2)
-	    m_int = signed_op;
-	  else
-	    m_int = unsigned_op;
+	  signed1 = TYPE_SIGN (TREE_TYPE (m_op1)) == SIGNED;
+	  signed2 = TYPE_SIGN (TREE_TYPE (m_op2)) == SIGNED;
+	  signed_ret = TYPE_SIGN (TREE_TYPE (ret)) == SIGNED;
 	  break;
 	}
 	default:
-	  break;
+	  return;
+      }
+  else if (gimple_code (m_stmt) == GIMPLE_CALL
+      && gimple_call_internal_p (m_stmt)
+      && gimple_get_lhs (m_stmt) != NULL_TREE)
+    switch (gimple_call_internal_fn (m_stmt))
+      {
+      case IFN_VEC_WIDEN_PLUS:
+      case IFN_VEC_WIDEN_PLUS_LO:
+      case IFN_VEC_WIDEN_PLUS_HI:
+      case IFN_VEC_WIDEN_PLUS_EVEN:
+      case IFN_VEC_WIDEN_PLUS_ODD:
+	  {
+	    signed_op = ptr_op_widen_plus_signed;
+	    unsigned_op = ptr_op_widen_plus_unsigned;
+	    m_valid = false;
+	    m_op1 = gimple_call_arg (m_stmt, 0);
+	    m_op2 = gimple_call_arg (m_stmt, 1);
+	    tree ret = gimple_get_lhs (m_stmt);
+	    signed1 = TYPE_SIGN (TREE_TYPE (m_op1)) == SIGNED;
+	    signed2 = TYPE_SIGN (TREE_TYPE (m_op2)) == SIGNED;
+	    signed_ret = TYPE_SIGN (TREE_TYPE (ret)) == SIGNED;
+	    break;
+	  }
+      default:
+	return;
       }
+  else
+    return;
+
+  /* Normally these operands should all have the same sign, but some passes
+     and violate this by taking mismatched sign args.  At the moment the only
+     one that's possible is mismatch inputs and unsigned output.  Once ranger
+     supports signs for the operands we can properly fix it,  for now only
+     accept the case we can do correctly.  */
+  if ((signed1 ^ signed2) && signed_ret)
+    return;
+
+  m_valid = true;
+  if (signed2 && !signed1)
+    std::swap (m_op1, m_op2);
+
+  if (signed1 || signed2)
+    m_int = signed_op;
+  else
+    m_int = unsigned_op;
 }
 
 // Set up a gimple_range_op_handler for any built in function which can be