public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 2/2] Add VREL_OTHER for FP unsupported relations.
@ 2023-01-23 17:44 Andrew MacLeod
  2023-01-23 17:45 ` [PATCH 2/2] tree-optimization/108447 - " Andrew MacLeod
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Andrew MacLeod @ 2023-01-23 17:44 UTC (permalink / raw)
  To: gcc-patches; +Cc: hernandez, aldy, Jakub Jelinek, Richard Biener

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

This patch adds VREL_OTHER to represent another relation we do not 
understand.  It is used to represent the class fo relations arising from 
floating point that are currently not represented. IN GCC 14 we will 
determine exactly how to represent them, but for this release, this 
should prevent us from getting things wrong at least.

if intersection produces UNDEFINED and either of the relations feeding 
it were <, <=, >, or >=   then it turns it to VR_OTHER.   the prevents 
false sides of branches from combining to produce  UNDEFINED when they 
end up being a known NAN.

Union is adjusted such that < >, or <= >= also produce VREL_OTHER.   < > 
cannot be properly represented, and <= >= was producing VARYING, which 
is also not correct.

Form the testcase:

     <bb 2> :
     cmp1_10 = x_8(D) <= y_9(D);
     cmp2_11 = x_8(D) >= y_9(D);
     _3 = cmp1_10 & cmp2_11;
     if (_3 != 0)
       goto <bb 3>; [INV]
     else
       goto <bb 4>; [INV]

Relational : (x_8(D) == y_9(D))
     <bb 3> :
     // predicted unlikely by early return (on trees) predictor.
     goto <bb 6>; [INV]


     <bb 4> :
     _4 = ~cmp1_10;
     _5 = ~cmp2_11;
     _1 = cmp1_10 | cmp2_11;
     _6 = ~_1;
     if (_1 != 0)
       goto <bb 6>; [INV]
     else
       goto <bb 5>; [INV]

Relational : (x_8(D) unknown fp y_9(D))
     <bb 5> :
     // predicted unlikely by early return (on trees) predictor.


The intersection "fix" is represented by the relation between x and y in 
BB5.  Without the patch, ti would be UNDEFINED and we do not want that.

The union fix is what prevents us from folding the condition in bb_4.  
Without it, x<=y union x >=y comes out VARYING, when in fact I believe 
it represents everything except a NAN.

So with this fix, all the unrepresentative relations get lumped into 
VREL_OTHER so we at least don't get it wrong.  For next release we can 
take the time to figure out exactly how we want to proceed.

This is currently in testing on x86_64-pc-linux-gnu, and assuming it 
bootstraps with no regressions (a combined patch did before splitting it 
in 2), OK for trunk?   OR does it need more tweaking?

Andrew

[-- Attachment #2: 0002-Add-VREL_OTHER-for-FP-unsupported-relations.patch --]
[-- Type: text/x-patch, Size: 11467 bytes --]

From 6947cfa03098eee46669ec2902e5f6e33c3cbe9a Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Fri, 20 Jan 2023 17:31:26 -0500
Subject: [PATCH 2/2] Add VREL_OTHER for FP unsupported relations.

Add VREL_OTHER to represent floating point relations we do not yet
support.

	PR tree-optimization/108447
	gcc/
	* value-relation.cc (kind_string): Add "unknown fp".
	(rr_negate_table): Add entry for VREL_OTHER.
	(rr_swap_table): Likewise.
	(rr_intersect_table): Likewise.
	(rr_union_table): Likewise.
	(rr_transitive_table): Likewise.
	(relation_to_code): Likewise.
	(value_relation::intersect): Handle floating point differences.
	(value_relation::union_): Likewise.
	* value-relation.h (enum relation_kind_t): Add VREL_OTHER.

	gcc/testsuite/
	* gcc.dg/pr108447.c: New.
---
 gcc/testsuite/gcc.dg/pr108447.c |  33 +++++++++
 gcc/value-relation.cc           | 118 +++++++++++++++++++++-----------
 gcc/value-relation.h            |   1 +
 3 files changed, 113 insertions(+), 39 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr108447.c

diff --git a/gcc/testsuite/gcc.dg/pr108447.c b/gcc/testsuite/gcc.dg/pr108447.c
new file mode 100644
index 00000000000..cfbaba6d0aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr108447.c
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+__attribute__((noipa)) int
+foo (float x, float y)
+{
+  _Bool cmp1 = x <= y;
+  _Bool cmp2 = x >= y;
+  if (cmp1 && cmp2)
+    return 1;
+  else if (!cmp1 && !cmp2)
+    return -1;
+  return 0;
+}
+
+int
+main ()
+{
+  if (foo (0.0f, __builtin_nanf ("")) != -1)
+    __builtin_abort ();
+  if (foo (__builtin_nanf (""), -42.0f) != -1)
+    __builtin_abort ();
+  if (foo (0.0f, -0.0f) != 1)
+    __builtin_abort ();
+  if (foo (42.0f, 42.0f) != 1)
+    __builtin_abort ();
+  if (foo (42.0f, -0.0f) != 0)
+    __builtin_abort ();
+  if (foo (0.0f, -42.0f) != 0)
+    __builtin_abort ();
+  return 0;
+}
+
diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc
index 432828e2b13..299a119827a 100644
--- a/gcc/value-relation.cc
+++ b/gcc/value-relation.cc
@@ -33,8 +33,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "dominance.h"
 
 static const char *kind_string[VREL_LAST] =
-{ "varying", "undefined", "<", "<=", ">", ">=", "==", "!=", "pe8", "pe16",
-  "pe32", "pe64" };
+{ "varying", "undefined", "<", "<=", ">", ">=", "==", "!=", "unknown fp",
+  "pe8", "pe16", "pe32", "pe64" };
 
 // Print a relation_kind REL to file F.
 
@@ -47,7 +47,7 @@ print_relation (FILE *f, relation_kind rel)
 // This table is used to negate the operands.  op1 REL op2 -> !(op1 REL op2).
 relation_kind rr_negate_table[VREL_LAST] = {
   VREL_VARYING, VREL_UNDEFINED, VREL_GE, VREL_GT, VREL_LE, VREL_LT, VREL_NE,
-  VREL_EQ };
+  VREL_EQ, VREL_OTHER };
 
 // Negate the relation, as in logical negation.
 
@@ -60,7 +60,7 @@ relation_negate (relation_kind r)
 // This table is used to swap the operands.  op1 REL op2 -> op2 REL op1.
 relation_kind rr_swap_table[VREL_LAST] = {
   VREL_VARYING, VREL_UNDEFINED, VREL_GT, VREL_GE, VREL_LT, VREL_LE, VREL_EQ,
-  VREL_NE };
+  VREL_NE, VREL_OTHER };
 
 // Return the relation as if the operands were swapped.
 
@@ -75,28 +75,32 @@ relation_swap (relation_kind r)
 relation_kind rr_intersect_table[VREL_LAST][VREL_LAST] = {
 // VREL_VARYING
   { VREL_VARYING, VREL_UNDEFINED, VREL_LT, VREL_LE, VREL_GT, VREL_GE, VREL_EQ,
-    VREL_NE },
+    VREL_NE, VREL_OTHER },
 // VREL_UNDEFINED
   { VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED,
-    VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED },
+    VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED,
+    VREL_UNDEFINED },
 // VREL_LT
   { VREL_LT, VREL_UNDEFINED, VREL_LT, VREL_LT, VREL_UNDEFINED, VREL_UNDEFINED,
-    VREL_UNDEFINED, VREL_LT },
+    VREL_UNDEFINED, VREL_LT, VREL_OTHER },
 // VREL_LE
   { VREL_LE, VREL_UNDEFINED, VREL_LT, VREL_LE, VREL_UNDEFINED, VREL_EQ,
-    VREL_EQ, VREL_LT },
+    VREL_EQ, VREL_LT, VREL_OTHER },
 // VREL_GT
   { VREL_GT, VREL_UNDEFINED, VREL_UNDEFINED, VREL_UNDEFINED, VREL_GT, VREL_GT,
-    VREL_UNDEFINED, VREL_GT },
+    VREL_UNDEFINED, VREL_GT, VREL_OTHER },
 // VREL_GE
   { VREL_GE, VREL_UNDEFINED, VREL_UNDEFINED, VREL_EQ, VREL_GT, VREL_GE,
-    VREL_EQ, VREL_GT },
+    VREL_EQ, VREL_GT, VREL_OTHER },
 // VREL_EQ
   { VREL_EQ, VREL_UNDEFINED, VREL_UNDEFINED, VREL_EQ, VREL_UNDEFINED, VREL_EQ,
-    VREL_EQ, VREL_UNDEFINED },
+    VREL_EQ, VREL_UNDEFINED, VREL_OTHER },
 // VREL_NE
   { VREL_NE, VREL_UNDEFINED, VREL_LT, VREL_LT, VREL_GT, VREL_GT,
-    VREL_UNDEFINED, VREL_NE } };
+    VREL_UNDEFINED, VREL_NE, VREL_OTHER },
+// VREL_OTHER
+  { VREL_OTHER, VREL_UNDEFINED, VREL_OTHER, VREL_OTHER, VREL_OTHER,
+    VREL_OTHER, VREL_OTHER, VREL_OTHER, VREL_OTHER } };
 
 
 // Intersect relation R1 with relation R2 and return the resulting relation.
@@ -113,28 +117,31 @@ relation_intersect (relation_kind r1, relation_kind r2)
 relation_kind rr_union_table[VREL_LAST][VREL_LAST] = {
 // VREL_VARYING
   { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING,
-    VREL_VARYING, VREL_VARYING, VREL_VARYING },
+    VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING },
 // VREL_UNDEFINED
   { VREL_VARYING, VREL_UNDEFINED, VREL_LT, VREL_LE, VREL_GT, VREL_GE,
-    VREL_EQ, VREL_NE },
+    VREL_EQ, VREL_NE, VREL_OTHER },
 // VREL_LT
   { VREL_VARYING, VREL_LT, VREL_LT, VREL_LE, VREL_NE, VREL_VARYING, VREL_LE,
-    VREL_NE },
+    VREL_NE, VREL_OTHER },
 // VREL_LE
   { VREL_VARYING, VREL_LE, VREL_LE, VREL_LE, VREL_VARYING, VREL_VARYING,
-    VREL_LE, VREL_VARYING },
+    VREL_LE, VREL_VARYING, VREL_OTHER },
 // VREL_GT
   { VREL_VARYING, VREL_GT, VREL_NE, VREL_VARYING, VREL_GT, VREL_GE, VREL_GE,
-    VREL_NE },
+    VREL_NE, VREL_OTHER },
 // VREL_GE
   { VREL_VARYING, VREL_GE, VREL_VARYING, VREL_VARYING, VREL_GE, VREL_GE,
-    VREL_GE, VREL_VARYING },
+    VREL_GE, VREL_VARYING, VREL_OTHER },
 // VREL_EQ
   { VREL_VARYING, VREL_EQ, VREL_LE, VREL_LE, VREL_GE, VREL_GE, VREL_EQ,
-    VREL_VARYING },
+    VREL_VARYING, VREL_OTHER },
 // VREL_NE
   { VREL_VARYING, VREL_NE, VREL_NE, VREL_VARYING, VREL_NE, VREL_VARYING,
-    VREL_VARYING, VREL_NE } };
+    VREL_VARYING, VREL_NE, VREL_OTHER },
+// VREL_OTHER
+  { VREL_VARYING, VREL_OTHER, VREL_OTHER, VREL_OTHER, VREL_OTHER,
+    VREL_OTHER, VREL_OTHER, VREL_OTHER, VREL_OTHER } };
 
 // Union relation R1 with relation R2 and return the result.
 
@@ -151,28 +158,31 @@ relation_union (relation_kind r1, relation_kind r2)
 relation_kind rr_transitive_table[VREL_LAST][VREL_LAST] = {
 // VREL_VARYING
   { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING,
-    VREL_VARYING, VREL_VARYING, VREL_VARYING },
+    VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING },
 // VREL_UNDEFINED
   { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING,
-    VREL_VARYING, VREL_VARYING, VREL_VARYING },
+    VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING },
 // VREL_LT
   { VREL_VARYING, VREL_VARYING, VREL_LT, VREL_LT, VREL_VARYING, VREL_VARYING,
-    VREL_LT, VREL_VARYING },
+    VREL_LT, VREL_VARYING, VREL_VARYING },
 // VREL_LE
   { VREL_VARYING, VREL_VARYING, VREL_LT, VREL_LE, VREL_VARYING, VREL_VARYING,
-    VREL_LE, VREL_VARYING },
+    VREL_LE, VREL_VARYING, VREL_VARYING },
 // VREL_GT
   { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_GT, VREL_GT,
-    VREL_GT, VREL_VARYING },
+    VREL_GT, VREL_VARYING, VREL_VARYING },
 // VREL_GE
   { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_GT, VREL_GE,
-    VREL_GE, VREL_VARYING },
+    VREL_GE, VREL_VARYING, VREL_VARYING },
 // VREL_EQ
   { VREL_VARYING, VREL_VARYING, VREL_LT, VREL_LE, VREL_GT, VREL_GE, VREL_EQ,
-    VREL_VARYING },
+    VREL_VARYING, VREL_VARYING },
 // VREL_NE
   { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING,
-    VREL_VARYING, VREL_VARYING, VREL_VARYING } };
+    VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING },
+// VREL_OTHER
+  { VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING,
+    VREL_VARYING, VREL_VARYING, VREL_VARYING, VREL_VARYING } };
 
 // Apply transitive operation between relation R1 and relation R2, and
 // return the resulting relation, if any.
@@ -187,7 +197,7 @@ relation_transitive (relation_kind r1, relation_kind r2)
 
 tree_code relation_to_code [VREL_LAST] = {
   ERROR_MARK, ERROR_MARK, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EQ_EXPR,
-  NE_EXPR };
+  NE_EXPR, ERROR_MARK };
 
 // This routine validates that a relation can be applied to a specific set of
 // ranges.  In particular, floating point x == x may not be true if the NaN bit
@@ -784,17 +794,28 @@ value_relation::negate ()
 bool
 value_relation::intersect (const value_relation &p)
 {
-  // Save previous value
-  relation_kind old = related;
+  relation_kind k;
 
   if (p.op1 () == op1 () && p.op2 () == op2 ())
-    related = relation_intersect (kind (), p.kind ());
+    k = relation_intersect (kind (), p.kind ());
   else if (p.op2 () == op1 () && p.op1 () == op2 ())
-    related = relation_intersect (kind (), relation_swap (p.kind ()));
+    k = relation_intersect (kind (), relation_swap (p.kind ()));
   else
     return false;
 
-  return old != related;
+  if (related == k)
+    return false;
+
+  bool float_p = name1 && FLOAT_TYPE_P (TREE_TYPE (name1));
+  if (float_p && p.kind () != k && k == VREL_UNDEFINED)
+    {
+      if (relation_lt_le_gt_ge_p (kind ())
+	  || relation_lt_le_gt_ge_p (p.kind ()))
+	k = VREL_OTHER;
+    }
+
+  related = k;
+  return true;
 }
 
 // Perform a union between 2 relations. *this ||= p.
@@ -802,17 +823,36 @@ value_relation::intersect (const value_relation &p)
 bool
 value_relation::union_ (const value_relation &p)
 {
-  // Save previous value
-  relation_kind old = related;
+  relation_kind k;
 
   if (p.op1 () == op1 () && p.op2 () == op2 ())
-    related = relation_union (kind(), p.kind());
+    k = relation_union (kind (), p.kind ());
   else if (p.op2 () == op1 () && p.op1 () == op2 ())
-    related = relation_union (kind(), relation_swap (p.kind ()));
+    k = relation_union (kind (), relation_swap (p.kind ()));
   else
     return false;
 
-  return old != related;
+  if (related == k)
+    return false;
+
+  // (x < y) || (x > y) produces x != y, but this is not true with floats.
+  // (x <= y) || (x >= y) produces VARYING, which is also not true for floats.
+  // As they cannot be properly represented, use VREL_OTHER.
+  bool float_p = name1 && FLOAT_TYPE_P (TREE_TYPE (name1));
+  if (float_p && p.kind () != k)
+    {
+      if (kind () == VREL_LT && p.kind () == VREL_GT)
+	k = VREL_OTHER;
+      else if (kind () == VREL_GT && p.kind () == VREL_LT)
+	k = VREL_OTHER;
+      else if (kind () == VREL_LE && p.kind () == VREL_GE)
+	k = VREL_OTHER;
+      else if (kind () == VREL_GE && p.kind () == VREL_LE)
+	k = VREL_OTHER;
+    }
+
+  related = k;
+  return true;
 }
 
 // Identify and apply any transitive relations between REL
diff --git a/gcc/value-relation.h b/gcc/value-relation.h
index 354a0fd4130..c191de292c7 100644
--- a/gcc/value-relation.h
+++ b/gcc/value-relation.h
@@ -70,6 +70,7 @@ typedef enum relation_kind_t
   VREL_GE,		// r1 >= r2
   VREL_EQ,		// r1 == r2
   VREL_NE,		// r1 != r2
+  VREL_OTHER,		// unrepresentatble floating point relation.
   VREL_PE8,		// 8 bit partial equivalency
   VREL_PE16,		// 16 bit partial equivalency
   VREL_PE32,		// 32 bit partial equivalency
-- 
2.39.0


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

end of thread, other threads:[~2023-01-25 23:27 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-23 17:44 [PATCH 2/2] Add VREL_OTHER for FP unsupported relations Andrew MacLeod
2023-01-23 17:45 ` [PATCH 2/2] tree-optimization/108447 - " Andrew MacLeod
2023-01-24  8:55 ` [PATCH 2/2] " Richard Biener
2023-01-24 10:05 ` Jakub Jelinek
2023-01-24 15:57   ` Andrew MacLeod
2023-01-25 11:15     ` Jakub Jelinek
2023-01-25 14:30       ` Andrew MacLeod
2023-01-25 14:48         ` Jakub Jelinek
2023-01-25 16:12           ` Andrew MacLeod
2023-01-25 22:35             ` Jakub Jelinek
2023-01-25 23:23               ` Andrew MacLeod
2023-01-25 23:27                 ` Jakub Jelinek

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).