Richard,
I got the min/max VRP optimization I mentioned working, but it uncovered a bug
in phiopts where that pass is constructing MIN and MAX exprs. (Funnily enough,
I only found that failure due to a broken test of decimal fp).
We start with the following bit of code:
// X has unknown range here
if (X < 0)
X = 0;
if (X > 191)
X = 191;
// X known to be [0,191] here
What's happening is that after mergephi3, (just before phiopt) we have
2: if X_6 < 0 goto 5
3: if X_6 > 191 goto 5
6: <EMPTY>
5: X_2 = PHI<0(2), 191(3), X_6(6)>
X_2 has range info marking it to be [0,191] because of an earlier VRP pass. This
is all good, but notice the PHI on X_2 has 3 incoming edges.
phiopt first converts BB3, BB6 into a MIN_EXPR<X_6,191> which is correct, but
it clones X_2 to hold that result. That cloning duplicates X_2's range
information, which is not correct for the result of the MIN_EXPR. (this
incorrect info causes my new optimization to elide a MAX_EXPR that is actually
needed).
Normally it would be ok, because the PHI on X_2 would usually only have 2
incoming edges (from the conditional and the fall-through).
The code in tree-ssa-phiopt.c (minmax_replacement) is:
result = duplicate_ssa_name (PHI_RESULT (phi), NULL);
new_stmt = gimple_build_assign (result, minmax, arg0, arg1);
gsi = gsi_last_bb (cond_bb);
gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
replace_phi_edge_with_variable (cond_bb, e1, phi, result);
Is the right solution to (a) use make_ssa_name instead of duplicate_ssa_name,
(iff PHI has more than 2 edges?)? Or is it for (b)
replace_phi_edge_with_variable to zap RESULT's range info if the PHI isn't
collapse completely? Or is it something else?
More generally, when is it appropriate to use make_ssa_name and when to use
duplicate_ssa_name?
nathan