This is an archive of the discontinued LLVM Phabricator instance.

Don't assume cleanup emission preserves dominance in expr evaluation
ClosedPublic

Authored by rnk on Mar 3 2017, 1:21 PM.

Details

Summary

Because of the existence branches out of GNU statement expressions, it
is possible that emitting cleanups for a full expression may cause the
new insertion point to not be dominated by the result of the inner
expression. Consider this example:

struct Foo { Foo(); ~Foo(); int x; };
int g(Foo, int);
int f(bool cond) {
  int n = g(Foo(), ({ if (cond) return 0; 42; }));
  return n;
}

Before this change, result of the call to 'g' did not dominate its use
in the store to 'n'. The early return exit from the statement expression
branches to a shared cleanup block, which ends in a switch between the
fallthrough destination (the assignment to 'n') or the function exit
block.

This change solves the problem by spilling and reloading expression
evaluation results when any of the active cleanups have branches.

I audited the other call sites of enterFullExpression, and they don't
appear to keep and Values live across the site of the cleanup, except in
ARC code. I wasn't able to create a test case for ARC that exhibits this
problem, though.

Diff Detail

Repository
rL LLVM

Event Timeline

rnk created this revision.Mar 3 2017, 1:21 PM
rsmith accepted this revision.Mar 6 2017, 1:09 PM

Hal and I discussed exactly the same problem (in the context of coroutines) on Saturday and came up with exactly the same approach :) I think this is the right direction.

lib/CodeGen/CGExprComplex.cpp
204–206 ↗(On Diff #90528)

I'm a little concerned about the loose connection between ensureDominatingValue and ForrceCleanup here -- if you forget the ForceCleanup, you get silent misbehavior. How about removing ensureDominatingValue and instead passing a std::initializer_list<Value**> to ForceCleanup?

lib/CodeGen/CodeGenFunction.h
539 ↗(On Diff #90528)

If you keep a SmallVector here, set its inline size to 2 to avoid allocations for the _Complex case.

This revision is now accepted and ready to land.Mar 6 2017, 1:09 PM
rnk added inline comments.Mar 6 2017, 2:00 PM
lib/CodeGen/CGExprComplex.cpp
204–206 ↗(On Diff #90528)

Done.

lib/CodeGen/CodeGenFunction.h
539 ↗(On Diff #90528)

I removed it. Also, who wants to waste a whole pointer of stack space for _Complex expression evaluation. ;)

rnk updated this revision to Diff 90743.Mar 6 2017, 2:00 PM
  • comments
This revision was automatically updated to reflect the committed changes.