public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [RFA/RFC] [PR tree-optimization/80635] Optimize some V_C_Es with limited ranges into NOP_EXPRs
@ 2020-04-05 15:25 Jeff Law
  2020-04-05 18:48 ` Richard Biener
  2020-04-06  9:14 ` Richard Biener
  0 siblings, 2 replies; 6+ messages in thread
From: Jeff Law @ 2020-04-05 15:25 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 2570 bytes --]


So here's an approach to try and address PR80635.

In this BZ we're getting a false positive uninitialized warning using
std::optional.

As outlined in the BZ this stems from SRA using a VIEW_CONVERT_EXPR  which isn't
handled terribly well by the various optimizers/analysis passes.

We have these key blocks:

;;   basic block 5, loop depth 0
;;    pred:       3
;;                2
  # maybe_a$m_6 = PHI <_5(3), maybe_a$m_4(D)(2)>
  # maybe_a$4_7 = PHI <1(3), 0(2)>
<L0>:
  _8 = maybe_b.live;
  if (_8 != 0)
    goto <bb 6>; [0.00%]
  else
    goto <bb 7>; [0.00%]
;;    succ:       6
;;                7

;;   basic block 6, loop depth 0
;;    pred:       5
  B::~B (&maybe_b.D.2512.m_item);
;;    succ:       7

;;   basic block 7, loop depth 0
;;    pred:       5
;;                6
  maybe_b ={v} {CLOBBER};
  resx 3
;;    succ:       8

;;   basic block 8, loop depth 0
;;    pred:       7
<L1>:
  _9 = VIEW_CONVERT_EXPR<bool>(maybe_a$4_7);
  if (_9 != 0)
    goto <bb 9>; [0.00%]
  else
    goto <bb 10>; [0.00%]
;;    succ:       9
;;                10

Where there is a use of maybe_a$m_6 in block #9.

Of course maybe_a$m_6 only takes the value of maybe_a$m_4(D) when we traverse the
edge 2->5 but in that case maybe_a$4_7 will always have the value zero and thus
we can not reach bb #9..  But the V_C_E gets in the way of the analysis and we
issue the false positive warning.  Martin Jambor has indicated that he doesn't
see a way to avoid the V_C_E from SRA without reintroducing PR52244.

This patch optimizes the V_C_E into a NOP_EXPR by verifying that the V_C_E folds
to a constant value for the min & max values of the range of the input operand
and the result of folding is equal to the original input.  We do some additional
checking beyond just that original value and converted value are equal according
to operand_equal_p.

Eventually the NOP_EXPR also gets removed as well and the conditional in bb8
tests maybe_a$4_7 against 0 directly.

That in turn allows the uninit analysis to determine the use of maybe_a$_m_6 in
block #9 is properly guarded and the false positive is avoided.

The optimization of a V_C_E into a NOP_EXPR via this patch occurs a couple
hundred times during a bootstrap, so this isn't a horribly narrow change just to
fix a false positive warning.

Bootstrapped and regression tested on x86_64.  I've also put it through its paces
in the tester.  The tester's current failures (aarch64, mips, h8) are unrelated
to this patch.


Thoughts?  OK for the trunk?  Alternately I wouldn't lose sleep moving this to
gcc-11.

jeff



[-- Attachment #2: P --]
[-- Type: text/plain, Size: 3266 bytes --]

	PR tree-optimization/90635
	* vr-values.c (simplify_stmt_using_ranges): Simplify V_C_E into
	NOP_EXPR in some cases.

	* g++.dg/warn/Wuninitialized-11.C: New test.


diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-11.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-11.C
new file mode 100644
index 00000000000..8e3782264bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-11.C
@@ -0,0 +1,46 @@
+// { dg-do compile { target c++11 } } 
+// { dg-options "-O2 -Wuninitialized" }
+
+using size_t = decltype(sizeof(1));
+inline void *operator new (size_t, void *p) { return p; }
+template<typename T>
+struct optional
+{
+  optional () : m_dummy (), live (false) {}
+  void emplace () { new (&m_item) T (); live = true; }
+  ~optional () { if (live) m_item.~T (); }
+
+  union
+  {
+    struct {} m_dummy;
+    T m_item;
+  };
+  bool live;
+};
+
+
+extern int get ();
+extern void set (int);
+
+struct A
+{
+  A () : m (get ()) {}
+  ~A () { set (m); }
+
+  int m;
+};
+
+struct B
+{
+  B ();
+  ~B ();
+};
+
+void func ()
+{
+  optional<A> maybe_a;
+  optional<B> maybe_b;
+
+  maybe_a.emplace ();
+  maybe_b.emplace ();
+}
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index 2e3a0788710..bfd3f4f2cea 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -4308,6 +4308,54 @@ vr_values::simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
 	    return simplify_bit_ops_using_ranges (gsi, stmt);
 	  break;
 
+
+	case VIEW_CONVERT_EXPR:
+	  /* If we're converting an object with a range which is
+	     directly representable in the final type, then just
+	     turn the VIEW_CONVERT_EXPR into a NOP_EXPR.
+
+	     Various optimizers/analyzers handle the NOP_EXPR
+	     better than VIEW_CONVERT_EXPR.  */
+	  if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == SSA_NAME)
+	    {
+	      const value_range_equiv *vr
+		= get_value_range (TREE_OPERAND (rhs1, 0));
+	      if (vr->kind () == VR_RANGE)
+		{
+		  /* See if the min and max values convert to themselves.  */
+		  tree min = vr->min ();
+		  tree max = vr->min ();
+		  tree min_converted = const_unop (VIEW_CONVERT_EXPR,
+						   TREE_TYPE (lhs),
+						   min);
+		  tree max_converted = const_unop (VIEW_CONVERT_EXPR,
+						   TREE_TYPE (lhs),
+						   max);
+		  if (TREE_CODE (min) == INTEGER_CST
+		      && TREE_CODE (max) == INTEGER_CST
+		      && min_converted
+		      && max_converted
+		      && TREE_CODE (min_converted) == INTEGER_CST
+		      && TREE_CODE (max_converted) == INTEGER_CST
+		      /* These may not be strictly necessary, but to be safe
+			 do not do this optimization if the original or
+			 converted min/max have their sign bit set.  */
+		      && tree_int_cst_sgn (min) != -1
+		      && tree_int_cst_sgn (min_converted) != -1
+		      && tree_int_cst_sgn (max) != -1
+		      && tree_int_cst_sgn (max_converted) != -1
+		      && operand_equal_p (min, min_converted, OEP_ONLY_CONST)
+		      && operand_equal_p (max, max_converted, OEP_ONLY_CONST))
+		    {
+		      gimple_assign_set_rhs_code (stmt, NOP_EXPR);
+		      gimple_assign_set_rhs1 (stmt, TREE_OPERAND (rhs1, 0));
+		      update_stmt (stmt);
+		      return true;
+		    }
+		}
+	    }
+	  break;
+
 	CASE_CONVERT:
 	  if (TREE_CODE (rhs1) == SSA_NAME
 	      && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-04-06  9:15 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-05 15:25 [RFA/RFC] [PR tree-optimization/80635] Optimize some V_C_Es with limited ranges into NOP_EXPRs Jeff Law
2020-04-05 18:48 ` Richard Biener
2020-04-05 18:52   ` Jeff Law
2020-04-05 20:12   ` Eric Botcazou
2020-04-05 20:21     ` Eric Botcazou
2020-04-06  9:14 ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).