}
/* Split edge E, and insert_check_and_trap (see above) in the
- newly-created block, using detached copies of LHS's and RHS's
- values (see detach_value above) for the COP compare. */
+ newly-created block, using already-detached copies of LHS's and
+ RHS's values (see detach_value above) for the COP compare. */
static inline void
insert_edge_check_and_trap (location_t loc, edge e,
gimple_stmt_iterator gsik = gsi_after_labels (chk);
- bool same_p = (lhs == rhs);
- lhs = detach_value (loc, &gsik, lhs);
- rhs = same_p ? lhs : detach_value (loc, &gsik, rhs);
-
insert_check_and_trap (loc, &gsik, flags, cop, lhs, rhs);
}
/* ??? Can we do better? */
continue;
+ /* Detach the values before the compares. If we do so later,
+ the compiler may use values inferred from the compares. */
+ bool same_p = (lhs == rhs);
+ lhs = detach_value (loc, &gsi, lhs);
+ rhs = same_p ? lhs : detach_value (loc, &gsi, rhs);
+
insert_edge_check_and_trap (loc, EDGE_SUCC (bb, 0), cop, lhs, rhs);
insert_edge_check_and_trap (loc, EDGE_SUCC (bb, 1), cop, lhs, rhs);
}
tree rhs = copy_ssa_name (lhs);
+ /* Detach the values before the compares, so that the
+ compiler infers nothing from them, not even from a
+ throwing compare that didn't throw. */
+ bool same_p = (op1 == op2);
+ op1 = detach_value (loc, &gsi, op1);
+ op2 = same_p ? op1 : detach_value (loc, &gsi, op2);
+
gimple_stmt_iterator gsi_split = gsi;
/* Don't separate the original assignment from debug stmts
that might be associated with it, and arrange to split the
gimple_bb (asgn)->index, nbb->index);
}
- bool same_p = (op1 == op2);
- op1 = detach_value (loc, &gsi_split, op1);
- op2 = same_p ? op1 : detach_value (loc, &gsi_split, op2);
-
gassign *asgnck = gimple_build_assign (rhs, cop, op1, op2);
gimple_set_location (asgnck, loc);
gsi_insert_before (&gsi_split, asgnck, GSI_SAME_STMT);
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fharden-conditional-branches -fharden-compares -fdump-tree-hardcbr -fdump-tree-hardcmp -ffat-lto-objects" } */
+
+int f(int i, int j) {
+ if (i == 0)
+ return j != 0;
+ else
+ return i * j != 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Splitting edge" 2 "hardcbr" } } */
+/* { dg-final { scan-tree-dump-times "Adding reversed compare" 2 "hardcbr" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_trap" 2 "hardcbr" } } */
+
+/* { dg-final { scan-tree-dump-times "Splitting block" 2 "hardcmp" } } */
+/* { dg-final { scan-tree-dump-times "Adding reversed compare" 2 "hardcmp" } } */
+/* { dg-final { scan-tree-dump-times "__builtin_trap" 4 "hardcmp" } } */
+
+/* Check that the optimization barrier is placed before the original compare. */
+/* { dg-final { scan-tree-dump-times {__asm__[(]"" : "=g" _[0-9]* : "0" i_[0-9]*[(]D[)][)][;][\n][ ]*if [(]i_[0-9]*[(]D[)] == 0[)]} 1 "hardcbr" } } */
+/* { dg-final { scan-tree-dump-times {if [(]_[0-9]* != 0[)]} 2 "hardcbr" } } */
+
+/* { dg-final { scan-tree-dump-times {__asm__[(]"" : "=g" _[0-9]* : "0" j_[0-9]*[(]D[)][)][;][\n][ ]*_[0-9]* = j_[0-9]*[(]D[)] != 0;[\n] *_[0-9]* = _[0-9]* == 0} 1 "hardcmp" } } */
+/* { dg-final { scan-tree-dump-times {__asm__[(]"" : "=g" _[0-9]* : "0" _[0-9]*[)][;][\n][ ]*_[0-9]* = _[0-9]* != 0;[\n] *_[0-9]* = _[0-9]* == 0} 1 "hardcmp" } } */