This patch utilizes the new check_operands_p() routine in range-ops to verify the operands are compatible before IPA tries to call fold_range().   I do not know if there are other places in IPA that should be checking this, but we have a bug report for this place at least.

The other option would be to have fold_range simply return false when operands don't match, but then we lose the compile time checking that everything is as it should be and bugs may sneak thru.

Bootstraps on x86_64-pc-linux-gnu with  no regressions. Committed.

Andrew


From 5f0c0f02702eba568374a7d82ec9463edd1a905c Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Tue, 28 Nov 2023 13:02:35 -0500
Subject: [PATCH 2/2] Check operands before invoking fold_range.

Call check_operands_p before fold_range to make sure it is a valid operation.

	PR tree-optimization/111922
	gcc/
	* ipa-cp.cc (ipa_vr_operation_and_type_effects): Check the
	operands are valid before calling fold_range.

	gcc/testsuite/
	* gcc.dg/pr111922.c: New.
---
 gcc/ipa-cp.cc                   |  3 ++-
 gcc/testsuite/gcc.dg/pr111922.c | 29 +++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr111922.c

diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index 34fae065454..649ad536161 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -1926,7 +1926,8 @@ ipa_vr_operation_and_type_effects (vrange &dst_vr,
   Value_Range varying (dst_type);
   varying.set_varying (dst_type);
 
-  return (handler.fold_range (dst_vr, dst_type, src_vr, varying)
+  return (handler.operand_check_p (dst_type, src_type, dst_type)
+	  && handler.fold_range (dst_vr, dst_type, src_vr, varying)
 	  && !dst_vr.varying_p ()
 	  && !dst_vr.undefined_p ());
 }
diff --git a/gcc/testsuite/gcc.dg/pr111922.c b/gcc/testsuite/gcc.dg/pr111922.c
new file mode 100644
index 00000000000..4f429d741c7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr111922.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-fre" } */
+
+void f2 (void);
+void f4 (int, int, int);
+struct A { int a; };
+struct B { struct A *b; int c; } v;
+
+static int
+f1 (x, y)
+  struct C *x;
+  struct A *y;
+{
+  (v.c = v.b->a) || (v.c = v.b->a);
+  f2 ();
+}
+
+static void
+f3 (int x, int y)
+{
+  int b = f1 (0, ~x);
+  f4 (0, 0, v.c);
+}
+
+void
+f5 (void)
+{
+  f3 (0, 0);
+}
-- 
2.41.0

Reply via email to