1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 package org.graalvm.compiler.core.aarch64.test; 26 27 import static org.junit.Assume.assumeTrue; 28 29 import java.util.function.Predicate; 30 31 import org.graalvm.compiler.api.directives.GraalDirectives; 32 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; 33 import org.graalvm.compiler.lir.LIR; 34 import org.graalvm.compiler.lir.LIRInstruction; 35 import org.graalvm.compiler.lir.LIRInstructionClass; 36 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow; 37 import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; 38 import org.graalvm.compiler.lir.asm.CompilationResultBuilder; 39 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 40 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 41 import org.graalvm.compiler.lir.jtt.LIRTest; 42 import org.graalvm.compiler.lir.jtt.LIRTestSpecification; 43 import org.graalvm.compiler.lir.phases.LIRPhase; 44 import org.graalvm.compiler.lir.phases.LIRSuites; 45 import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; 46 import org.graalvm.compiler.options.OptionValues; 47 import org.junit.Assert; 48 import org.junit.Before; 49 import org.junit.Test; 50 51 import jdk.vm.ci.aarch64.AArch64; 52 import jdk.vm.ci.code.TargetDescription; 53 import jdk.vm.ci.meta.Value; 54 55 public class AArch64TestBitAndBranchTest extends LIRTest { 56 private static final Predicate<LIRInstruction> checkForBitTestAndBranchOp = op -> (op instanceof AArch64ControlFlow.BitTestAndBranchOp); 57 private LIR lir; 58 59 @Before 60 public void checkAArch64() { 61 assumeTrue("skipping AArch64 specific test", getTarget().arch instanceof AArch64); 62 } 63 64 public static long testBit42Snippet(long a, long b, long c) { 65 if ((a & (1 << 42)) == 0) { 66 return b; 67 } else { 68 return c; 69 } 70 } 71 72 @Test 73 public void testBit42() { 74 test("testBit42Snippet", 1L << 42L, Long.MAX_VALUE, Long.MIN_VALUE); 75 test("testBit42Snippet", ~(1L << 42L), Long.MAX_VALUE, Long.MIN_VALUE); 76 checkLIR("testBit42Snippet", checkForBitTestAndBranchOp, 1); 77 } 78 79 private static final LargeOpSpec largeOpSingleNop = new LargeOpSpec((1 << 14 - 2), 2); 80 81 /** 82 * Tests the graceful case, where the estimation for 83 * {@link CompilationResultBuilder#labelWithinRange(LIRInstruction, org.graalvm.compiler.asm.Label, int)} 84 * holds. 85 */ 86 public static int testBitTestAndBranchSingleSnippet(int a) { 87 int res; 88 if (a % 2 == 0) { 89 res = fillOps(largeOpSingleNop, 1); 90 } else { 91 res = fillOps(largeOpSingleNop, 2); 92 } 93 return GraalDirectives.opaque(res); 94 } 95 96 @Test 97 public void testBitTestAndBranchSingle() { 98 runTest("testBitTestAndBranchSingleSnippet", 1); 99 checkLIR("testBitTestAndBranchSingleSnippet", checkForBitTestAndBranchOp, 1); 100 } 101 102 private static final LargeOpSpec largeOpFourNop = new LargeOpSpec((1 << 14 - 2), 8); 103 104 /** 105 * Tests the case, where the estimation for 106 * {@link CompilationResultBuilder#labelWithinRange(LIRInstruction, org.graalvm.compiler.asm.Label, int)} 107 * does not hold and the code generation must be redone with large branches. 108 */ 109 public static int testBitTestAndBranchFourSnippet(int a) { 110 int res; 111 if (a % 2 == 0) { 112 res = fillOps(largeOpFourNop, 1); 113 } else { 114 res = fillOps(largeOpFourNop, 2); 115 } 116 return GraalDirectives.opaque(res); 117 } 118 119 @Test 120 public void testBitTestAndBranchFour() { 121 runTest("testBitTestAndBranchFourSnippet", 1); 122 checkLIR("testBitTestAndBranchFourSnippet", checkForBitTestAndBranchOp, 1); 123 } 124 125 private static class LargeOpSpec extends LIRTestSpecification { 126 private final int n; 127 private final int nopCount; 128 129 LargeOpSpec(int n, int nopCount) { 130 super(); 131 this.n = n; 132 this.nopCount = nopCount; 133 } 134 135 @Override 136 public void generate(LIRGeneratorTool gen, Value a) { 137 for (int i = 0; i < n; i++) { 138 gen.append(new NoOp(nopCount)); 139 } 140 setResult(a); 141 } 142 } 143 144 public static class NoOp extends AArch64LIRInstruction { 145 private static final LIRInstructionClass<NoOp> TYPE = LIRInstructionClass.create(NoOp.class); 146 private final int nopCount; 147 148 public NoOp(int nopCount) { 149 super(TYPE); 150 this.nopCount = nopCount; 151 } 152 153 @Override 154 protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { 155 for (int i = 0; i < nopCount; i++) { 156 masm.nop(); 157 } 158 } 159 } 160 161 @LIRIntrinsic 162 public static int fillOps(@SuppressWarnings("unused") LargeOpSpec s, int a) { 163 return a; 164 } 165 166 @Override 167 protected LIRSuites createLIRSuites(OptionValues options) { 168 LIRSuites suites = super.createLIRSuites(options); 169 suites.getPreAllocationOptimizationStage().appendPhase(new CheckPhase()); 170 return suites; 171 } 172 173 public class CheckPhase extends LIRPhase<PreAllocationOptimizationContext> { 174 @Override 175 protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreAllocationOptimizationContext context) { 176 lir = lirGenRes.getLIR(); 177 } 178 } 179 180 protected void checkLIR(String methodName, Predicate<LIRInstruction> predicate, int expected) { 181 compile(getResolvedJavaMethod(methodName), null); 182 int actualOpNum = 0; 183 for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { 184 if (predicate.test(ins)) { 185 actualOpNum++; 186 } 187 } 188 Assert.assertEquals(expected, actualOpNum); 189 } 190 }