This is an archive of the discontinued LLVM Phabricator instance.

GVN fails to fold constant expression
ClosedPublic

Authored by kromanova on Jul 8 2016, 7:21 PM.

Details

Summary

This is a fix for PR 28418.

opt never finishes compiling test/Transforms/GVN/fold-const-expr.ll when -gvn option is passed.
I added fold-const-expr.ll to the llvm regression test suite.

The problem is caused by the fact that GVN fails to fold a constant expression.
That expression gets expanded multiple times and ends up as a huge, exponentially growing (relative to the number of instructions in the BB) constant expression. This expression is too big for GVN to analyze, so this optimization pass never finishes.

For more details, see the analysis in the PR 28418.
Here is concise version:

The expression (i32 trunc (i128 bitcast (<4 x i32> <i32 234567891, i32 345678912, i32 456789123, i32 0> to i128) to i32) is the result of a GVN expansion, when a previously stored constant vector is partially reloaded (note that the store size does not match the load size).

We have a store of a full <4 x i32> vector;

// (<4 x i32> <i32 234567891, i32 345678912, i32 456789123, i32 0> to i128

later on we reload the first element of the vector.
// i32 234567891

The lack of knowledge about constant expressions currently forces GVN to canonicalize a partial reload into a sequence of `trunc + bitcast`.
The aforementioned expression should be constant folded to i32 234567891 by GVN.

Special thanks to Andrea DiBiagio for his help with the analysis/fix and to Rafael for his help with reducing an immense reproducer.

Diff Detail

Repository
rL LLVM

Event Timeline

kromanova updated this revision to Diff 63370.Jul 8 2016, 7:21 PM
kromanova retitled this revision from to GVN fails to fold constant expression.
kromanova updated this object.
kromanova added reviewers: majnemer, reames, andreadb.
kromanova set the repository for this revision to rL LLVM.
majnemer edited edge metadata.

Seems OK to me. Danny, what do you think?

dberlin edited edge metadata.Jul 11 2016, 12:43 PM

The only question I have is whether it should be folding as you go. This
looks like it calls constant fold on the huge materialized expression,
instead of folding as it is built by the coercion logic.

I expect the latter to be better both memory and time wise.

Hi Daniel and David,
Thank you so much for your feedback. I think what Daniel is suggesting will be more efficient, however that patch might not look as simple and readable. I will work on the new patch and then we could discuss it again.
Katya.

kromanova updated this revision to Diff 63868.Jul 13 2016, 3:22 PM
kromanova edited edge metadata.

Hi Daniel,
I did folding earlier, allowing further folding of const expression as it's being built. It's taking care of the problem and we don't get huge meterialized expression. See the patch.

Andrea noticed that ‘CoerceAvailableValueToLoadType’ can still generate sub-optimal constant expressions, since this function may potentially insert bitcasts, shifts and truncates of the input value. To always simplify constant expressions, we should add some extra folding to simplify the StoredVal before it is returned from the function. I will send a patch for it in a minute.
Katya.

kromanova updated this revision to Diff 63871.Jul 13 2016, 3:34 PM

This patch is better than the previous one, since it does extra folding to simplify the StoredVal before it is returned from the function ‘CoerceAvailableValueToLoadType’ can potentially insert bitcasts, shifts and truncates of the input value, creating though not huge, but still sub-optimal const expression.

dberlin accepted this revision.Jul 14 2016, 12:56 PM
dberlin edited edge metadata.

LGTM.
Thank you so much!

This revision is now accepted and ready to land.Jul 14 2016, 12:56 PM
This revision was automatically updated to reflect the committed changes.