Skip to content

Commit

Permalink
Enable split init for sync blocks (chapel-lang#23314)
Browse files Browse the repository at this point in the history
Closes Cray/chapel-private#5375
Closes chapel-lang#20974

This PR enables split init of a variable across a `sync` block. (Note:
sync blocks are typically used with `begin` and split init is still not
allowed across a `begin`). Copy elision was already allowed across
`sync` blocks.

Additionally, this PR
* adjusts the language specification to indicate split init and copy
elision are allowed across `sync` blocks themselves
* adds two tests to lock in split init and copy elision with `sync`
blocks

Reviewed by @DanilaFe - thanks!

- [x] full comm=none testing
  • Loading branch information
mppf authored Sep 12, 2023
2 parents 99e8618 + 7bebbb1 commit abc2232
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 19 deletions.
36 changes: 20 additions & 16 deletions compiler/passes/splitInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -316,22 +316,26 @@ static found_init_t doFindInitPoints(Symbol* sym,
return FOUND_USE;

// if there are any catches, check them for uses;
// also a catch block prevents initialization in the try body
for_alist(elt, tr->_catches) {
if (CatchStmt* ctch = toCatchStmt(elt)) {
std::vector<CallExpr*> inits;
Expr* use = NULL;
Expr* start = ctch->body()->body.first();
found_init_t foundCatch = doFindInitPoints(sym, start, inits,
use, allowReturns,
ignoreFirstEndInBlock);
if (foundCatch == FOUND_USE || foundCatch == FOUND_INIT) {
// Consider even an assignment in a catch block as a use
usePreventingSplitInit = findSymExprFor(ctch, sym);
return FOUND_USE;
} else if (foundCatch != FOUND_RET && foundCatch != FOUND_THROW) {
allCatchesRet = false;
nonReturningCatch = ctch;
// also a catch block prevents initialization in the try body.
// but, don't worry about the compiler-generated catch blocks
// for a sync block's 'try'.
if (!tr->isSyncTry()) {
for_alist(elt, tr->_catches) {
if (CatchStmt* ctch = toCatchStmt(elt)) {
std::vector<CallExpr*> inits;
Expr* use = NULL;
Expr* start = ctch->body()->body.first();
found_init_t foundCatch = doFindInitPoints(sym, start, inits,
use, allowReturns,
ignoreFirstEndInBlock);
if (foundCatch == FOUND_USE || foundCatch == FOUND_INIT) {
// Consider even an assignment in a catch block as a use
usePreventingSplitInit = findSymExprFor(ctch, sym);
return FOUND_USE;
} else if (foundCatch != FOUND_RET && foundCatch != FOUND_THROW) {
allCatchesRet = false;
nonReturningCatch = ctch;
}
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions doc/rst/language/spec/variables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ earliest assignment statement(s) setting that variable that occurs before
the variable is otherwise mentioned. It will consider the variable passed
to an ``out`` intent argument as an assignment statement for this
purpose. It will search only within block statements ``{ }``,
``local`` blocks, ``serial`` blocks, ``try`` blocks, ``try!`` blocks, and
``local`` blocks, ``serial`` blocks, ``sync`` blocks,
``try`` blocks, ``try!`` blocks, and
conditionals. These assignment statements and calls to functions with
``out`` intent are called applicable assignment statements. They perform
initialization, not assignment, of that variable.
Expand Down Expand Up @@ -924,8 +925,8 @@ is not mentioned again, the copy will be elided. Since a ``return`` or
``throw`` exits a function, a copy can be elided if it is followed
immediately by a ``return`` or ``throw``. When searching forward from
variable declarations, copy elision considers eliding copies only within
block statements ``{ }``, ``local`` blocks, ``serial`` blocks, ``try``
blocks, ``try!`` blocks, and conditionals.
block statements ``{ }``, ``local`` blocks, ``serial`` blocks, ``sync`` blocks,
``try`` blocks, ``try!`` blocks, and conditionals.

*Example (copy-elision.chpl)*

Expand Down
57 changes: 57 additions & 0 deletions test/types/records/copy-elision/copy-elision-sync.chpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
class C { }
record R {
var x: int = 0;
var ptr: owned C = new owned C();
proc init() {
this.x = 0;
writeln("init");
}
proc init(arg:int) {
this.x = arg;
writeln("init ", arg);
}
proc init=(other: R) {
this.x = other.x;
writeln("init= ", other.x);
}
}
operator R.=(ref lhs:R, rhs:R) {
writeln("= ", lhs.x, " ", rhs.x);
lhs.x = rhs.x;
}


proc syncSplitInit() {
writeln("syncSplitInit");
var x: R;

sync {
x = new R(1); // split init applies to sync blocks
}
}
syncSplitInit();

proc fOut(out arg: R) {
arg = new R(2);
}

proc syncSplitInitOut() {
writeln("syncSplitInitOut");
var x: R;

sync {
fOut(x);
}
}
syncSplitInitOut();


proc syncCopyElide() {
writeln("syncCopyElide");
var x = new R(1);

sync {
var y = x; // copy elision applies to sync blocks
}
}
syncCopyElide();
6 changes: 6 additions & 0 deletions test/types/records/copy-elision/copy-elision-sync.good
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
syncSplitInit
init 1
syncSplitInitOut
init 2
syncCopyElide
init 1
44 changes: 44 additions & 0 deletions test/types/records/split-init/split-init-sync.chpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
config const cond = false;
config const otherCond = true;

class C { }
record R {
var x: int = 0;
var ptr: owned C = new owned C();
proc init() {
this.x = 0;
writeln("init");
}
proc init(arg:int) {
this.x = arg;
writeln("init ", arg);
}
proc init=(other: R) {
this.x = other.x;
writeln("init= ", other.x);
}
}
operator R.=(ref lhs:R, rhs:R) {
writeln("= ", lhs.x, " ", rhs.x);
lhs.x = rhs.x;
}

proc test100() {
writeln("test100");
var b;
sync {
b = new R(1);
}
writeln(b);
}
test100();

proc test101() {
writeln("test101");
var b: R;
sync {
b = new R(1);
}
writeln(b);
}
test101();
6 changes: 6 additions & 0 deletions test/types/records/split-init/split-init-sync.good
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
test100
init 1
(x = 1, ptr = {})
test101
init 1
(x = 1, ptr = {})

0 comments on commit abc2232

Please sign in to comment.