< prev index next >

test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java

Print this page

 64 /*
 65  * @test id=StoreNSerial
 66  * @bug 8020282
 67  * @summary Test that we do not generate redundant leas on x86 when storing narrow oops to object arrays.
 68  * @requires os.simpleArch == "x64" & vm.gc.Serial
 69  * @modules jdk.compiler/com.sun.tools.javac.util
 70  * @library /test/lib /
 71  * @run driver compiler.codegen.TestRedundantLea StoreNSerial
 72  */
 73 
 74 /*
 75  * @test id=StoreNParallel
 76  * @bug 8020282
 77  * @summary Test that we do not generate redundant leas on x86 when storing narrow oops to object arrays.
 78  * @requires os.simpleArch == "x64" & vm.gc.Parallel
 79  * @modules jdk.compiler/com.sun.tools.javac.util
 80  * @library /test/lib /
 81  * @run driver compiler.codegen.TestRedundantLea StoreNParallel
 82  */
 83 










 84 
 85 package compiler.codegen;
 86 
 87 import java.util.concurrent.atomic.*;
 88 import java.util.regex.Matcher;
 89 import java.util.regex.Pattern;
 90 
 91 import com.sun.tools.javac.util.*;
 92 
 93 import compiler.lib.ir_framework.*;
 94 
 95 // The following tests ensure that we do not generate a redundant lea instruction on x86.
 96 // These get generated on chained dereferences for the rules leaPCompressedOopOffset,
 97 // leaP8Narrow, and leaP32Narrow and stem from a decodeHeapOopNotNull that is not needed
 98 // unless the derived oop is added to an oop map. The redundant lea is removed with an
 99 // opto assembly peephole optimization. Hence, all tests below feature a negative test
100 // run with -XX:-OptoPeephole to detect changes that obsolete that peephole.
101 // Further, all tests are run with different max heap sizes to trigger the generation of
102 // different lea match rules: -XX:MaxHeapSize=32m generates leaP(8|32)Narrow and
103 // -XX:MaxHeapSize=4g generates leaPCompressedOopOffset, since the address computation

112             }
113             case "StringEquals" -> {
114                 framework = new TestFramework(StringEqualsTest.class);
115                 framework.addHelperClasses(StringEqualsTestHelper.class);
116             }
117             case "StringInflate" -> {
118                 framework = new TestFramework(StringInflateTest.class);
119                 framework.addFlags("--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED");
120             }
121             case "RegexFind" -> {
122                 framework = new TestFramework(RegexFindTest.class);
123             }
124             case "StoreNSerial" -> {
125                 framework = new TestFramework(StoreNTest.class);
126                 framework.addFlags("-XX:+UseSerialGC");
127             }
128             case "StoreNParallel" -> {
129                 framework = new TestFramework(StoreNTest.class);
130                 framework.addFlags("-XX:+UseParallelGC");
131             }



132             default -> {
133                 throw new IllegalArgumentException("Unknown test name \"" + testName +"\"");
134             }
135         }
136 
137         Scenario[] scenarios = new Scenario[2];
138         // Scenario for the negative test without peephole optimizations.
139         scenarios[0] = new Scenario(0, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-OptoPeephole");
140         // Scenario for the positive test with +OptoPeephole (the default on x64).
141         scenarios[1] = new Scenario(1);
142         framework.addScenarios(scenarios).start();
143     }
144 }
145 
146 // This generates a leaP* rule for the chained dereference of obj.value that
147 // gets passed to the get and set VM intrinsic.
148 class GetAndSetTest {
149     private static final Object CURRENT = new Object();
150     private final AtomicReference<Object> obj = new AtomicReference<Object>();
151 

257     @IR(counts = {IRNode.LEA_P, "=1"},
258         phase = {CompilePhase.FINAL_CODE},
259         applyIfPlatform = {"mac", "false"})
260     // Due to unpredictable code generation, we cannot match the exact number of decodes below.
261     // Negative test
262     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, ">=7"},
263         phase = {CompilePhase.FINAL_CODE},
264         applyIfAnd = {"OptoPeephole", "false", "UseAVX", "=3"})
265     // Test that the peephole worked for leaPCompressedOopOffset
266     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, ">=6"},
267         phase = {CompilePhase.FINAL_CODE},
268         applyIfAnd = {"OptoPeephole", "true", "UseAVX", "=3"})
269     @Arguments(setup = "setup")
270     public boolean test(Matcher m) {
271         return m.find();
272     }
273 }
274 
275 // The matcher generates leaP* rules for storing an object in an array of objects
276 // at a constant offset, but only when using the Serial or Parallel GC.
277 // Here, we can also manipulate the offset such that we get a leaP32Narrow rule
278 // and we can demonstrate that the peephole also removes simple cases of unneeded
279 // spills.
280 class StoreNTest {
281     private static final int SOME_SIZE = 42;
282     private static final int OFFSET8BIT_IDX = 3;
283     private static final int OFFSET32BIT_IDX = 33;
284 
285     private static final Object CURRENT = new Object();
286     private static final Object OTHER = new Object();
287 
288     private StoreNTestHelper[] classArr8bit = new StoreNTestHelper[SOME_SIZE];
289     private StoreNTestHelper[] classArr32bit = new StoreNTestHelper[SOME_SIZE];
290     private Object[] objArr8bit = new Object[SOME_SIZE];
291     private Object[] objArr32bit = new Object[SOME_SIZE];
292 
293     @Test
294     @IR(counts = {IRNode.LEA_P, "=2"},
295         phase = {CompilePhase.FINAL_CODE},
296         applyIfPlatform = {"mac", "false"})
297     // Negative test
298     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=2"},
299         phase = {CompilePhase.FINAL_CODE},
300         applyIf = {"OptoPeephole", "false"})
301     // Test that the peephole worked for leaPCompressedOopOffset
302     @IR(failOn = {IRNode.DECODE_HEAP_OOP_NOT_NULL},
303         phase = {CompilePhase.FINAL_CODE},
304         applyIf = {"OptoPeephole", "true"})
305     // Test that the peephole removes a spill.
306     @IR(counts = {IRNode.MEM_TO_REG_SPILL_COPY, "=4"},
307         phase = {CompilePhase.FINAL_CODE},
308         applyIfAnd ={"OptoPeephole", "false", "UseCompactObjectHeaders", "false"})
309     @IR(counts = {IRNode.MEM_TO_REG_SPILL_COPY, "=3"},
310         phase = {CompilePhase.FINAL_CODE},
311         applyIfAnd ={"OptoPeephole", "true", "UseCompactObjectHeaders", "false"})
312     public void testRemoveSpill() {
313         this.classArr8bit[OFFSET8BIT_IDX] = new StoreNTestHelper(CURRENT, OTHER);
314         this.classArr32bit[OFFSET32BIT_IDX] = new StoreNTestHelper(OTHER, CURRENT);
315     }
316 
317     // This variation of the test above generates a split spill register path.
318     // Due to the complicated graph structure with the phis, the peephole
319     // cannot remove the redundant decode shared by both leaP*s.
320     @Test
321     @IR(counts = {IRNode.LEA_P, "=2"},
322         phase = {CompilePhase.FINAL_CODE},
323         applyIfPlatform = {"mac", "false"})
324     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=1"},
325         phase = {CompilePhase.FINAL_CODE},
326         applyIf = {"OptoPeephole", "false"})
327     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=1"},
328         phase = {CompilePhase.FINAL_CODE},
329         applyIf = {"OptoPeephole", "true"})
330     public void testPhiSpill() {
331         this.classArr8bit[OFFSET8BIT_IDX] = new StoreNTestHelper(CURRENT, OTHER);
332         this.classArr8bit[OFFSET32BIT_IDX] = new StoreNTestHelper(CURRENT, OTHER);
333     }































334 
335     @Test

336     @IR(counts = {IRNode.LEA_P, "=2"},
337         phase = {CompilePhase.FINAL_CODE},
338         applyIfPlatform = {"mac", "false"})
339     // Negative test
340     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=2"},
341         phase = {CompilePhase.FINAL_CODE},
342         applyIf = {"OptoPeephole", "false"})
343     // Test that the peephole worked for leaPCompressedOopOffset
344     @IR(failOn = {IRNode.DECODE_HEAP_OOP_NOT_NULL},
345         phase = {CompilePhase.FINAL_CODE},
346         applyIf = {"OptoPeephole", "true"})
347     public void testNoAlloc() {
348         this.objArr8bit[OFFSET8BIT_IDX] = CURRENT;
349         this.objArr32bit[OFFSET32BIT_IDX] = OTHER;
350     }
351 
352     @Test
353     @IR(counts = {IRNode.LEA_P, "=2"},
354         phase = {CompilePhase.FINAL_CODE},
355         applyIfPlatform = {"mac", "false"})
356     // Negative test
357     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=1"},
358         phase = {CompilePhase.FINAL_CODE},
359         applyIf = {"OptoPeephole", "false"})
360     // Test that the peephole worked for leaPCompressedOopOffset
361     @IR(failOn = {IRNode.DECODE_HEAP_OOP_NOT_NULL},
362         phase = {CompilePhase.FINAL_CODE},
363         applyIf = {"OptoPeephole", "true"})
364     public void testNoAllocSameArray() {
365         this.objArr8bit[OFFSET8BIT_IDX] = CURRENT;
366         this.objArr8bit[OFFSET32BIT_IDX] = OTHER;
367     }
368 }
369 
370 class StoreNTestHelper {
371     Object o1;
372     Object o2;
373 
374     public StoreNTestHelper(Object o1, Object o2) {
375         this.o1 = o1;
376         this.o2 = o2;
377     }
378 }

 64 /*
 65  * @test id=StoreNSerial
 66  * @bug 8020282
 67  * @summary Test that we do not generate redundant leas on x86 when storing narrow oops to object arrays.
 68  * @requires os.simpleArch == "x64" & vm.gc.Serial
 69  * @modules jdk.compiler/com.sun.tools.javac.util
 70  * @library /test/lib /
 71  * @run driver compiler.codegen.TestRedundantLea StoreNSerial
 72  */
 73 
 74 /*
 75  * @test id=StoreNParallel
 76  * @bug 8020282
 77  * @summary Test that we do not generate redundant leas on x86 when storing narrow oops to object arrays.
 78  * @requires os.simpleArch == "x64" & vm.gc.Parallel
 79  * @modules jdk.compiler/com.sun.tools.javac.util
 80  * @library /test/lib /
 81  * @run driver compiler.codegen.TestRedundantLea StoreNParallel
 82  */
 83 
 84 /*
 85  * @test id=Spill
 86  * @bug 8020282
 87  * @summary Test that we do not generate redundant leas and remove related spills on x86.
 88  * @requires os.simpleArch == "x64"
 89  * @modules jdk.compiler/com.sun.tools.javac.util
 90  * @library /test/lib /
 91  * @run driver compiler.codegen.TestRedundantLea Spill
 92  */
 93 
 94 
 95 package compiler.codegen;
 96 
 97 import java.util.concurrent.atomic.*;
 98 import java.util.regex.Matcher;
 99 import java.util.regex.Pattern;
100 
101 import com.sun.tools.javac.util.*;
102 
103 import compiler.lib.ir_framework.*;
104 
105 // The following tests ensure that we do not generate a redundant lea instruction on x86.
106 // These get generated on chained dereferences for the rules leaPCompressedOopOffset,
107 // leaP8Narrow, and leaP32Narrow and stem from a decodeHeapOopNotNull that is not needed
108 // unless the derived oop is added to an oop map. The redundant lea is removed with an
109 // opto assembly peephole optimization. Hence, all tests below feature a negative test
110 // run with -XX:-OptoPeephole to detect changes that obsolete that peephole.
111 // Further, all tests are run with different max heap sizes to trigger the generation of
112 // different lea match rules: -XX:MaxHeapSize=32m generates leaP(8|32)Narrow and
113 // -XX:MaxHeapSize=4g generates leaPCompressedOopOffset, since the address computation

122             }
123             case "StringEquals" -> {
124                 framework = new TestFramework(StringEqualsTest.class);
125                 framework.addHelperClasses(StringEqualsTestHelper.class);
126             }
127             case "StringInflate" -> {
128                 framework = new TestFramework(StringInflateTest.class);
129                 framework.addFlags("--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED");
130             }
131             case "RegexFind" -> {
132                 framework = new TestFramework(RegexFindTest.class);
133             }
134             case "StoreNSerial" -> {
135                 framework = new TestFramework(StoreNTest.class);
136                 framework.addFlags("-XX:+UseSerialGC");
137             }
138             case "StoreNParallel" -> {
139                 framework = new TestFramework(StoreNTest.class);
140                 framework.addFlags("-XX:+UseParallelGC");
141             }
142             case "Spill" -> {
143                 framework = new TestFramework(SpillTest.class);
144             }
145             default -> {
146                 throw new IllegalArgumentException("Unknown test name \"" + testName +"\"");
147             }
148         }
149 
150         Scenario[] scenarios = new Scenario[2];
151         // Scenario for the negative test without peephole optimizations.
152         scenarios[0] = new Scenario(0, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-OptoPeephole");
153         // Scenario for the positive test with +OptoPeephole (the default on x64).
154         scenarios[1] = new Scenario(1);
155         framework.addScenarios(scenarios).start();
156     }
157 }
158 
159 // This generates a leaP* rule for the chained dereference of obj.value that
160 // gets passed to the get and set VM intrinsic.
161 class GetAndSetTest {
162     private static final Object CURRENT = new Object();
163     private final AtomicReference<Object> obj = new AtomicReference<Object>();
164 

270     @IR(counts = {IRNode.LEA_P, "=1"},
271         phase = {CompilePhase.FINAL_CODE},
272         applyIfPlatform = {"mac", "false"})
273     // Due to unpredictable code generation, we cannot match the exact number of decodes below.
274     // Negative test
275     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, ">=7"},
276         phase = {CompilePhase.FINAL_CODE},
277         applyIfAnd = {"OptoPeephole", "false", "UseAVX", "=3"})
278     // Test that the peephole worked for leaPCompressedOopOffset
279     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, ">=6"},
280         phase = {CompilePhase.FINAL_CODE},
281         applyIfAnd = {"OptoPeephole", "true", "UseAVX", "=3"})
282     @Arguments(setup = "setup")
283     public boolean test(Matcher m) {
284         return m.find();
285     }
286 }
287 
288 // The matcher generates leaP* rules for storing an object in an array of objects
289 // at a constant offset, but only when using the Serial or Parallel GC.
290 // Here, we can also manipulate the offset such that we get a leaP32Narrow rule.


291 class StoreNTest {
292     private static final int SOME_SIZE = 42;
293     private static final int OFFSET8BIT_IDX = 3;
294     private static final int OFFSET32BIT_IDX = 33;
295 
296     private static final Object CURRENT = new Object();
297     private static final Object OTHER = new Object();
298 
299     private StoreNTestHelper[] classArr8bit = new StoreNTestHelper[SOME_SIZE];
300     private StoreNTestHelper[] classArr32bit = new StoreNTestHelper[SOME_SIZE];


301 
302     @Test
303     @IR(counts = {IRNode.LEA_P, "=2"},
304         phase = {CompilePhase.FINAL_CODE},
305         applyIfPlatform = {"mac", "false"})
306     // Negative test
307     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=2"},
308         phase = {CompilePhase.FINAL_CODE},
309         applyIf = {"OptoPeephole", "false"})
310     // Test that the peephole worked for leaPCompressedOopOffset
311     @IR(failOn = {IRNode.DECODE_HEAP_OOP_NOT_NULL},
312         phase = {CompilePhase.FINAL_CODE},
313         applyIf = {"OptoPeephole", "true"})







314     public void testRemoveSpill() {
315         this.classArr8bit[OFFSET8BIT_IDX] = new StoreNTestHelper(CURRENT, OTHER);
316         this.classArr32bit[OFFSET32BIT_IDX] = new StoreNTestHelper(OTHER, CURRENT);
317     }
318 
319     // This variation of the test above generates a split spill register path.
320     // Due to the complicated graph structure with the phis, the peephole
321     // cannot remove the redundant decode shared by both leaP*s.
322     @Test
323     @IR(counts = {IRNode.LEA_P, "=2"},
324         phase = {CompilePhase.FINAL_CODE},
325         applyIfPlatform = {"mac", "false"})
326     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=1"},
327         phase = {CompilePhase.FINAL_CODE},
328         applyIf = {"OptoPeephole", "false"})
329     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=1"},
330         phase = {CompilePhase.FINAL_CODE},
331         applyIf = {"OptoPeephole", "true"})
332     public void testPhiSpill() {
333         this.classArr8bit[OFFSET8BIT_IDX] = new StoreNTestHelper(CURRENT, OTHER);
334         this.classArr8bit[OFFSET32BIT_IDX] = new StoreNTestHelper(CURRENT, OTHER);
335     }
336 }
337 
338 class StoreNTestHelper {
339     Object o1;
340     Object o2;
341 
342     public StoreNTestHelper(Object o1, Object o2) {
343         this.o1 = o1;
344         this.o2 = o2;
345     }
346 }
347 
348 // This test validates that the peephole removes simple spills.
349 // The code for the test originates from compiler/escapeAnalysis/Test6775880.java.
350 class SpillTest {
351     int cnt;
352     int b[];
353     String s;
354 
355     @Run(test = "test")
356     public static void run() {
357         SpillTest t = new SpillTest();
358         t.cnt = 3;
359         t.b = new int[3];
360         t.b[0] = 0;
361         t.b[1] = 1;
362         t.b[2] = 2;
363         int j = 0;
364         t.s = "";
365         t.test();
366     }
367 
368     @Test
369     // TODO: Make tests more precise
370     @IR(counts = {IRNode.LEA_P, "=2"},
371         phase = {CompilePhase.FINAL_CODE},
372         applyIfPlatform = {"mac", "false"})
373     // Negative test
374     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, ">=2"},
375         phase = {CompilePhase.FINAL_CODE},
376         applyIf = {"OptoPeephole", "false"})
377     @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "<=2"},

378         phase = {CompilePhase.FINAL_CODE},
379         applyIf = {"OptoPeephole", "true"})
380     // Test that the peephole removes a spill.
381     @IR(counts = {IRNode.MEM_TO_REG_SPILL_COPY, ">=18"},









382         phase = {CompilePhase.FINAL_CODE},
383         applyIf = {"OptoPeephole", "false"})
384     @IR(counts = {IRNode.MEM_TO_REG_SPILL_COPY, ">=16"},

385         phase = {CompilePhase.FINAL_CODE},
386         applyIf = {"OptoPeephole", "true"})
387     String test() {
388         String res = "";
389         for (int i = 0; i < cnt; i++) {
390             if (i != 0) {
391                 res = res + ".";
392             }
393             res = res + b[i];
394         }
395         return res;




396     }
397 }
< prev index next >