dead_storage.sol 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // RUN: --target substrate --emit cfg
  2. contract deadstorage {
  3. int a;
  4. // simple test. Two references to "a" must result in a single loadstorage
  5. // BEGIN-CHECK: deadstorage::function::test1
  6. function test1() public view returns (int) {
  7. return a + a;
  8. }
  9. // CHECK: load storage slot(uint256 0) ty:int256
  10. // NOT-CHECK: load storage slot(uint256 0) ty:int256
  11. // Two references to "a" with a write to A in between must result in two loadstorage
  12. // BEGIN-CHECK: deadstorage::function::test2
  13. function test2() public returns (int) {
  14. int x = a;
  15. a = 2;
  16. x += a;
  17. return x;
  18. }
  19. // CHECK: load storage slot(uint256 0) ty:int256
  20. // CHECK: load storage slot(uint256 0) ty:int256
  21. // make sure that reachable stores are not eliminated
  22. // BEGIN-CHECK: deadstorage::function::test3
  23. function test3(bool c) public {
  24. a = 1;
  25. if (c) {
  26. a = 2;
  27. }
  28. }
  29. // CHECK: store storage slot(uint256 0)
  30. // CHECK: store storage slot(uint256 0)
  31. // two successive stores are redundant
  32. // BEGIN-CHECK: deadstorage::function::test4
  33. int b;
  34. function test4() public returns (int) {
  35. b = 511;
  36. b = 512;
  37. return b;
  38. }
  39. // CHECK: store storage slot(uint256 1)
  40. // NOT-CHECK: store storage slot(uint256 1)
  41. // stores in a previous block are always redundant
  42. // BEGIN-CHECK: deadstorage::function::test5
  43. int test5var;
  44. function test5(bool c) public returns (int) {
  45. if (c) {
  46. test5var = 1;
  47. } else {
  48. test5var = 2;
  49. }
  50. test5var = 3;
  51. return test5var;
  52. }
  53. // CHECK: store storage slot(uint256 2)
  54. // NOT-CHECK: store storage slot(uint256 2)
  55. // BEGIN-CHECK: deadstorage::function::test6
  56. // store/load are not merged yet. Make sure that we have a store before a load
  57. int test6var;
  58. function test6() public returns (int) {
  59. test6var = 1;
  60. int f = test6var;
  61. test6var = 2;
  62. return test6var + f;
  63. }
  64. // CHECK: store storage slot(uint256 3)
  65. // CHECK: store storage slot(uint256 3)
  66. // BEGIN-CHECK: deadstorage::function::test7
  67. // storage should be flushed before function call
  68. int test7var;
  69. function test7() public returns (int) {
  70. test7var = 1;
  71. test6();
  72. test7var = 2;
  73. return test7var;
  74. }
  75. // CHECK: store storage slot(uint256 4)
  76. // CHECK: store storage slot(uint256 4)
  77. // BEGIN-CHECK: deadstorage::function::test8
  78. // clear before store is redundant
  79. int test8var;
  80. function test8() public {
  81. delete test8var;
  82. test8var = 2;
  83. }
  84. // NOT-CHECK: clear storage slot(uint256 5)
  85. // CHECK: store storage slot(uint256 5)
  86. // BEGIN-CHECK: deadstorage::function::test9
  87. // push should make both load/stores not redundant
  88. bytes test9var;
  89. function test9() public returns (bytes){
  90. test9var = "a";
  91. bytes f = test9var;
  92. test9var.push(hex"01");
  93. f = test9var;
  94. test9var = "c";
  95. return f;
  96. }
  97. // CHECK: store storage slot(uint256 6)
  98. // CHECK: load storage slot(uint256 6)
  99. // CHECK: push storage ty:bytes1 slot:uint256 6
  100. // CHECK: load storage slot(uint256 6)
  101. // CHECK: store storage slot(uint256 6)
  102. // BEGIN-CHECK: deadstorage::function::test10
  103. // pop should make both load/stores not redundant
  104. bytes test10var;
  105. function test10() public returns (bytes) {
  106. test10var = "a";
  107. bytes f = test10var;
  108. test10var.pop();
  109. f = test10var;
  110. test10var = "c";
  111. return f;
  112. }
  113. // CHECK: store storage slot(uint256 7)
  114. // CHECK: load storage slot(uint256 7)
  115. // CHECK: pop storage ty:bytes1 slot(uint256 7)
  116. // CHECK: load storage slot(uint256 7)
  117. // CHECK: store storage slot(uint256 7)
  118. // BEGIN-CHECK: deadstorage::function::test11
  119. // some array tests
  120. int[11] test11var;
  121. function test11(uint index, uint index2) public view returns (int) {
  122. return test11var[index] + test11var[index2];
  123. }
  124. // CHECK: load storage slot((overflowing uint256 8
  125. // CHECK: load storage slot((overflowing uint256 8
  126. // BEGIN-CHECK: deadstorage::function::test12
  127. // one load needed for this
  128. int[11] test12var;
  129. function test12(uint index) public view returns (int) {
  130. return test12var[index] + test12var[index];
  131. }
  132. // CHECK: load storage slot((overflowing uint256 19
  133. // NOT-CHECK: load storage slot((overflowing uint256 19
  134. }
  135. contract foo {
  136. struct S { int32 f1; }
  137. S[] arr;
  138. function g() private returns (S storage, S storage) {
  139. return (arr[0], arr[1]);
  140. }
  141. // BEGIN-CHECK: foo::foo::function::f
  142. function f() public returns (S, S) {
  143. S[] storage ptrArr = arr;
  144. ptrArr.push(S({f1: 1}));
  145. ptrArr.push(S({f1: 2}));
  146. // CHECK: %.temp.115, %.temp.116 = call foo::foo::function::g
  147. // CHECK: %temp.117 = load storage slot(%.temp.115) ty:struct foo.S
  148. // CHECK: %temp.118 = load storage slot(%.temp.116) ty:struct foo.S
  149. return g();
  150. }
  151. }