1 class MergeEscaped {
  2     int a;
  3     int b;
  4     int c = 100;
  5 
  6     public MergeEscaped() {}
  7     public MergeEscaped(boolean cond) {
  8         if (cond) {
  9             this.a = 1;
 10             this.b = 20;
 11             this.c = 300;
 12             blackhole(); // kill locals, so LV0 = this is dead here.
 13         } else {
 14             this.a = 100;
 15             this.b = 50;
 16             this.c = 7;
 17             blackhole(); // kill locals.
 18         }
 19         // merge 2 predecessors, but LV0 is not live here.
 20         // we need to merge allocation states, or wrong current allocation state is wrong.
 21     }
 22 
 23     public int sum() {
 24         return a + b + c;
 25     }
 26 
 27     public static MergeEscaped cached;
 28 
 29     void blackhole() {} // not inline this.
 30     static void blackhole(Object obj) {} // not inline this.
 31 
 32     public static MergeEscaped escaped(boolean cond1) {
 33         MergeEscaped obj = new MergeEscaped();
 34 
 35         if (cond1) {
 36             blackhole(obj);
 37             obj.a = 20;
 38         } else {
 39             obj.b = 30;
 40             blackhole(obj);
 41         }
 42         obj.c = 100;
 43         return obj;
 44     }
 45 
 46     static void check_result(boolean cond1, int sum) {
 47         boolean okay = true;
 48 
 49         if (cond1) {
 50             okay = sum == 120;
 51         } else {
 52             okay = sum == 130;
 53         }
 54 
 55         if (!okay) {
 56             throw new RuntimeException("wrong answer: " + cond1 + " " + sum);
 57         }
 58     }
 59     public static MergeEscaped escaped2(boolean cond1) {
 60         MergeEscaped obj = new MergeEscaped();
 61 
 62         for (int i = 0; i < 100; ++i) {
 63             if (cond1) {
 64                 blackhole(obj);
 65                 obj.a = 20;
 66             } else {
 67                 obj.b = 30;
 68             }
 69         }
 70         return obj;
 71     }
 72 
 73     public static MergeEscaped escaped3(boolean cond1, boolean cond2) {
 74         MergeEscaped obj = new MergeEscaped();
 75         if (cond1) {
 76             obj.a = 10; // V
 77         } else {
 78             if (cond2) {
 79                 blackhole(obj); // E1
 80                 obj.a = 20;
 81             } else {
 82                 blackhole(obj); // E2
 83                 obj.b = 30;
 84             }
 85             obj.c = 300;        // PHI(E1, E2),
 86         }                       // PHI'(V, PHI)
 87         return obj;
 88     }
 89 
 90     static void check_result3(boolean cond1, boolean cond2, int sum) {
 91         boolean okay = true;
 92 
 93         if (cond1) {
 94             okay = sum == 110;
 95         } else {
 96             if (cond2) {
 97                 okay = sum == 320;
 98             } else {
 99                 okay = sum == 330;
100             }
101         }
102 
103         if (!okay) {
104             throw new RuntimeException("wrong answer: " + cond1 + " " +  cond2 + " " + sum);
105         }
106     }
107 
108     private static void test4(MergeEscaped obj, int cond) {
109         if (cond == 0) {
110             obj.a = 1;
111         } else if (cond == 1) {
112             obj.a = 2;
113         } else {
114             blackhole(obj);
115         }
116     }
117 
118     public static MergeEscaped escaped4(boolean cond1, boolean cond2) {
119         MergeEscaped obj = new MergeEscaped();
120 
121         int cond = 0;
122         if (cond1) {
123             cond = 2;  // cond1 << 1
124         }
125         if (cond2) {
126             cond = cond + 1;
127         }
128 
129         test4(obj,  cond);
130         blackhole(obj);
131         return obj;
132     }
133 
134     public static void main(String[] args) {
135         long iterations = 0;
136 
137         try {
138             while (true) {
139                 boolean cond = 0 == (iterations & 0xf);
140                 boolean cond2 = 7 == (iterations& 0xf);
141 
142                 int sum = MergeEscaped.escaped(cond).sum();
143                 check_result(cond, sum);
144 
145                 sum = MergeEscaped.escaped2(cond).sum();
146                 check_result(cond, sum);
147 
148                 sum = MergeEscaped.escaped3(cond, cond2).sum();
149                 check_result3(cond, cond2, sum);
150 
151                 escaped4(cond, cond2);
152                 iterations++;
153             }
154         } finally {
155             System.err.println("Epsilon Test: " + iterations);
156         }
157     }
158 }