middle-end/96369 - fix missed short-circuiting during range folding
authorRichard Biener <rguenther@suse.de>
Fri, 31 Jul 2020 06:41:56 +0000 (08:41 +0200)
committerRichard Biener <rguenther@suse.de>
Fri, 31 Jul 2020 10:05:26 +0000 (12:05 +0200)
This makes the special case of constant evaluated LHS for a
short-circuiting or/and explicit rather than doing range
merging and eventually exposing a side-effect that shouldn't be
evaluated.

2020-07-31  Richard Biener  <rguenther@suse.de>

PR middle-end/96369
* fold-const.c (fold_range_test): Special-case constant
LHS for short-circuiting operations.

* c-c++-common/pr96369.c: New testcase.

gcc/fold-const.c
gcc/testsuite/c-c++-common/pr96369.c [new file with mode: 0644]

index 300d959278b0739eb4f033c5b8dc9e3ba7df2e25..1324a194995a60e8795548b39b8044771decee6f 100644 (file)
@@ -5931,6 +5931,13 @@ fold_range_test (location_t loc, enum tree_code code, tree type,
     return 0;
 
   lhs = make_range (op0, &in0_p, &low0, &high0, &strict_overflow_p);
+  /* If op0 is known true or false and this is a short-circuiting
+     operation we must not merge with op1 since that makes side-effects
+     unconditional.  So special-case this.  */
+  if (!lhs
+      && ((code == TRUTH_ORIF_EXPR && in0_p)
+         || (code == TRUTH_ANDIF_EXPR && !in0_p)))
+    return op0;
   rhs = make_range (op1, &in1_p, &low1, &high1, &strict_overflow_p);
 
   /* If this is an OR operation, invert both sides; we will invert
diff --git a/gcc/testsuite/c-c++-common/pr96369.c b/gcc/testsuite/c-c++-common/pr96369.c
new file mode 100644 (file)
index 0000000..8c468d9
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+int main()
+{
+  const long ONE = 1L;
+  long y = 0L;
+  long x = ((long) (ONE || (y = 1L)) % 8L);
+  if (y != 0)
+    __builtin_abort ();
+  return 0;
+}