Do not allocate memory objects if they will be assigned directly.

This commit is contained in:
chriseth
2020-11-24 14:11:01 +01:00
parent 6f8435301e
commit 409e92580f
9 changed files with 126 additions and 5 deletions
@@ -0,0 +1,14 @@
contract C {
function f() public pure {
uint[] memory x;
uint y;
assembly {
y := x
}
assert(y != 0);
}
}
// ====
// compileViaYul: also
// ----
// f() ->
@@ -0,0 +1,30 @@
contract C {
function memorySize() internal pure returns (uint s) {
assembly { s := mload(0x40) }
}
function f() public returns (uint, uint, uint) {
uint a = memorySize();
g();
uint b = memorySize();
h();
uint c = memorySize();
i();
uint d = memorySize();
return (b - a, c - b, d - c);
}
// In these functions, we do allocate memory in both cases.
// In `i()`, this could be avoided but we would have to check
// that all code paths return explicitly and provide a value.
function g() internal returns (uint[40] memory) {
}
function h() internal returns (uint[40] memory t) {
}
function i() internal returns (uint[40] memory) {
uint[40] memory x;
return x;
}
}
// ====
// compileViaYul: also
// ----
// f() -> 0x0500, 0x0500, 0x0a00
@@ -0,0 +1,24 @@
contract C {
function memorySize() internal pure returns (uint s) {
assembly { s := mload(0x40) }
}
function withValue() public pure returns (uint) {
uint[20] memory x;
uint memorySizeBefore = memorySize();
uint[20] memory t = x;
uint memorySizeAfter = memorySize();
return memorySizeAfter - memorySizeBefore;
}
function withoutValue() public pure returns (uint) {
uint[20] memory x;
uint memorySizeBefore = memorySize();
uint[20] memory t;
uint memorySizeAfter = memorySize();
return memorySizeAfter - memorySizeBefore;
}
}
// ====
// compileViaYul: also
// ----
// withValue() -> 0x00
// withoutValue() -> 0x0280
@@ -0,0 +1,24 @@
contract C {
struct S { uint x; uint y; uint z; }
function memorySize() internal pure returns (uint s) {
assembly { s := mload(0x40) }
}
function withValue() public pure returns (uint) {
S memory x = S(1, 2, 3);
uint memorySizeBefore = memorySize();
S memory t = x;
uint memorySizeAfter = memorySize();
return memorySizeAfter - memorySizeBefore;
}
function withoutValue() public pure returns (uint) {
uint memorySizeBefore = memorySize();
S memory t;
uint memorySizeAfter = memorySize();
return memorySizeAfter - memorySizeBefore;
}
}
// ====
// compileViaYul: also
// ----
// withValue() -> 0x00
// withoutValue() -> 0x60
@@ -0,0 +1,7 @@
contract C {
function f() public pure {
uint[] memory x = x[0];
}
}
// ----
// DeclarationError 7576: (70-71): Undeclared identifier. "x" is not (or not yet) visible at this point.
@@ -0,0 +1,8 @@
contract C {
struct S { uint y; }
function f() public pure {
S memory x = x.y;
}
}
// ----
// DeclarationError 7576: (90-91): Undeclared identifier. "x" is not (or not yet) visible at this point.