]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/go/gofrontend/expressions.cc
compiler: recognize and optimize array range clear
[thirdparty/gcc.git] / gcc / go / gofrontend / expressions.cc
index 0dd869bb9c2f2ed5d8c55861b9b70673dddc8359..efb3d0dae6c874bae58288233c585c6d02fc2664 100644 (file)
@@ -1671,6 +1671,10 @@ class Boolean_expression : public Expression
   do_is_constant() const
   { return true; }
 
+  bool
+  do_is_zero_value() const
+  { return this->val_ == false; }
+
   bool
   do_is_static_initializer() const
   { return true; }
@@ -2054,6 +2058,10 @@ class Integer_expression : public Expression
   do_is_constant() const
   { return true; }
 
+  bool
+  do_is_zero_value() const
+  { return mpz_sgn(this->val_) == 0; }
+
   bool
   do_is_static_initializer() const
   { return true; }
@@ -2474,6 +2482,13 @@ class Float_expression : public Expression
   do_is_constant() const
   { return true; }
 
+  bool
+  do_is_zero_value() const
+  {
+    return mpfr_zero_p(this->val_) != 0
+           && mpfr_signbit(this->val_) == 0;
+  }
+
   bool
   do_is_static_initializer() const
   { return true; }
@@ -2685,6 +2700,15 @@ class Complex_expression : public Expression
   do_is_constant() const
   { return true; }
 
+  bool
+  do_is_zero_value() const
+  {
+    return mpfr_zero_p(mpc_realref(this->val_)) != 0
+           && mpfr_signbit(mpc_realref(this->val_)) == 0
+           && mpfr_zero_p(mpc_imagref(this->val_)) != 0
+           && mpfr_signbit(mpc_imagref(this->val_)) == 0;
+  }
+
   bool
   do_is_static_initializer() const
   { return true; }
@@ -2922,6 +2946,10 @@ class Const_expression : public Expression
   do_is_constant() const
   { return true; }
 
+  bool
+  do_is_zero_value() const
+  { return this->constant_->const_value()->expr()->is_zero_value(); }
+
   bool
   do_is_static_initializer() const
   { return true; }
@@ -3289,6 +3317,10 @@ class Nil_expression : public Expression
   do_is_constant() const
   { return true; }
 
+  bool
+  do_is_zero_value() const
+  { return true; }
+
   bool
   do_is_static_initializer() const
   { return true; }
@@ -3533,6 +3565,28 @@ Type_conversion_expression::do_is_constant() const
   return true;
 }
 
+// Return whether a type conversion is a zero value.
+
+bool
+Type_conversion_expression::do_is_zero_value() const
+{
+  if (!this->expr_->is_zero_value())
+    return false;
+
+  // Some type conversion from zero value is still not zero value.
+  // For example, []byte("") or interface{}(0).
+  // Conservatively, only report true if the RHS is nil.
+  Type* type = this->type_;
+  if (type->integer_type() == NULL
+      && type->float_type() == NULL
+      && type->complex_type() == NULL
+      && !type->is_boolean_type()
+      && !type->is_string_type())
+    return this->expr_->is_nil_expression();
+
+  return true;
+}
+
 // Return whether a type conversion can be used in a constant
 // initializer.
 
@@ -6879,6 +6933,19 @@ String_concat_expression::do_is_constant() const
   return true;
 }
 
+bool
+String_concat_expression::do_is_zero_value() const
+{
+  for (Expression_list::const_iterator pe = this->exprs_->begin();
+       pe != this->exprs_->end();
+       ++pe)
+    {
+      if (!(*pe)->is_zero_value())
+       return false;
+    }
+  return true;
+}
+
 bool
 String_concat_expression::do_is_static_initializer() const
 {
@@ -13007,6 +13074,33 @@ Struct_construction_expression::is_constant_struct() const
   return true;
 }
 
+// Return whether this is a zero value.
+
+bool
+Struct_construction_expression::do_is_zero_value() const
+{
+  if (this->vals() == NULL)
+    return true;
+  for (Expression_list::const_iterator pv = this->vals()->begin();
+       pv != this->vals()->end();
+       ++pv)
+    if (*pv != NULL && !(*pv)->is_zero_value())
+      return false;
+
+  const Struct_field_list* fields = this->type_->struct_type()->fields();
+  for (Struct_field_list::const_iterator pf = fields->begin();
+       pf != fields->end();
+       ++pf)
+    {
+      // Interface conversion may cause a zero value being converted
+      // to a non-zero value, like interface{}(0).  Be conservative.
+      if (pf->type()->interface_type() != NULL)
+        return false;
+    }
+
+  return true;
+}
+
 // Return whether this struct can be used as a constant initializer.
 
 bool
@@ -13288,6 +13382,28 @@ Array_construction_expression::is_constant_array() const
   return true;
 }
 
+// Return whether this is a zero value.
+
+bool
+Array_construction_expression::do_is_zero_value() const
+{
+  if (this->vals() == NULL)
+    return true;
+
+  // Interface conversion may cause a zero value being converted
+  // to a non-zero value, like interface{}(0).  Be conservative.
+  if (this->type_->array_type()->element_type()->interface_type() != NULL)
+    return false;
+
+  for (Expression_list::const_iterator pv = this->vals()->begin();
+       pv != this->vals()->end();
+       ++pv)
+    if (*pv != NULL && !(*pv)->is_zero_value())
+      return false;
+
+  return true;
+}
+
 // Return whether this can be used a constant initializer.
 
 bool