You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 lines
5.9 KiB

/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class HoistIndirect {
public static int svar = 0;
public int x = 0;
int[] array;
class Test {
int a = 0;
int[] test_array;
int foo(int x) {
return x + 10;
}
void set_test(Test test) {
test.a = 5;
}
int get_test(Test test) {
return test.a;
}
int get_sum_test(Test test, int x) {
return test.a + x;
}
Test return_only(Test t) {
return t;
}
int indirect_modification_dont_hoist(int size, Test t) {
int d = 0;
for (int i = 0; i < size; i++) {
set_test(t);
d = get_test(t); // don't hoist since t changes
}
return d;
}
void variant_arg_dont_hoist(int size, Test t) {
for (int i = 0; i < size; i++) {
set_test(t); // t is invalidated
get_sum_test(return_only(t), size); // return_only's argument is variant, hence don't hoist
}
}
// t changes deep in the call stack
int deep_modification_dont_hoist(int size) {
int d = 0;
Test t = new Test();
for (int i = 0; i < size; i++) {
indirect_modification_dont_hoist(size, t);
}
return d;
}
// foo(3) is ok to hoist
int indirect_modification_hoist(int size) {
int d = 0;
Test t = new Test();
for (int i = 0; i < size; i++) {
set_test(t); // t is invalidated here
d = foo(3); // foo is still invariant so it is ok to hoist
}
return d;
}
void set_only_first_param(Test test, Test no_mod) {
test.a = 5;
}
int indirect_modification_only_second_call_hoist(int size, Test t, Test no_mod_t) {
int d = 0;
for (int i = 0; i < size; i++) {
set_only_first_param(t, no_mod_t);
d = get_test(t); // don't hoist since t changes
d = get_test(no_mod_t); // hoist since no_mod_t doesn't change
}
return d;
}
}
void set() {
svar = 5;
}
int get() {
return svar;
}
//
int indirect_this_modification_dont_hoist(int size) {
int d = 0;
for (int i = 0; i < size; i++) {
d = get(); // don't hoist since HoistIndirect.svar changes in the loop
set();
}
return d;
}
int direct_this_modification_dont_hoist_FP(int size) {
int d = 0;
for (int i = 0; i < size; i++) {
d += get(); // don't hoist since this.svar changes in the loop
svar = i;
}
return d;
}
int this_modification_outside_hoist(int size) {
int d = 0;
set();
for (int i = 0; i < size; i++) {
d += get(); // ok to hoist since set is outside
}
return d;
}
int arg_modification_hoist(int size, Test t) {
int d = 0;
for (int i = 0; i < size; i++) {
d += get(); // ok to hoist since set_test doesn't modify this
t.set_test(t);
}
return d;
}
void set_ith(int i, int[] array) {
array[i] = 0;
}
int get_ith(int i, int[] array) {
return array[i];
}
int modified_array_dont_hoist(int size, Test t) {
int d = 0;
for (int i = 0; i < size; i++) {
set_ith(i, array);
d += get_ith(size, array); // don't hoist since array changes
}
return d;
}
int independent_hoist(int size, Test t) {
int d = 0;
for (int i = 0; i < size; i++) {
set_ith(i, array);
t.foo(size); // hoist call to foo
d += get_ith(size, array); // don't hoist since array changes
}
return d;
}
int modified_inner_array_dont_hoist(int size, Test t) {
int d = 0;
for (int i = 0; i < size; i++) {
set_ith(i, t.test_array);
d += t.foo(t.test_array[0]); // don't hoist since t.test_array changes
}
return d;
}
static int regionFirst(int[] region) {
return region[0];
}
static void incrDest(int[] source, int[] dest) {
dest[0] = source[0] + 1;
}
static void sumDest(int[] source, int[] dest, int x) {
dest[0] = source[0] + x;
}
void irvar_change_dont_hoist(int[][] nextRegionM, int p, int[] tempRegion) {
for (int i = 0; i < 10; i++) {
if (i < regionFirst(nextRegionM[p])) {
incrDest(tempRegion, nextRegionM[p]); // invalidate nextRegionM
}
}
}
void tmp_irvar_change_dont_hoist(int[][] nextRegionM, int p, int[] tempRegion) {
for (int i = 0; i < 10; i++) {
if (i < regionFirst(nextRegionM[p])) {
int[] arr = nextRegionM[p];
incrDest(tempRegion, arr); // invalidate nextRegionM
}
}
}
int double_me(int p) {
return 2 * p;
}
void irvar_independent_hoist(int[][] nextRegionM, int p, int[] tempRegion) {
for (int i = 0; i < 10; i++) {
if (i < regionFirst(nextRegionM[p]) + double_me(p)) { // double_me(p) can be hoisted
sumDest(tempRegion, nextRegionM[p], i); // invalidate nextRegionM
}
}
}
void unmodified_arg_hoist(int[][] nextRegionM, int p, int[] tempRegion) {
for (int i = 0; i < 10; i++) {
if (i
< regionFirst(nextRegionM[p])
+ regionFirst(tempRegion)) { // regionFirst(tempRegion) can be hoisted
sumDest(tempRegion, nextRegionM[p], i); // invalidate nextRegionM
}
}
}
// arr is modified via aliasing
void alias(int[] arr) {
int[] new_arr = arr;
new_arr[0] = 4;
}
void alias_dont_hoist(int[] arr) {
for (int i = 0; i < 10; i++) {
alias(arr); // alias modifies arr
get_ith(0, arr); // don't hoist
}
}
int return_zero() {
return 0;
}
void set_x() {
x = 0;
}
// Since we don't keep track of what values are read in purity
// analysis, when we call set_x, we add implicit arg. "this" to
// modified arguments which prevents any other call in the loop to
// be hoisted
int indirect_this_modification_hoist_FN(int size) {
int d = 0;
for (int i = 0; i < size; i++) {
d = return_zero(); // OK to hoist
set_x();
}
return d;
}
}