< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java

Print this page
rev 52889 : 8214023: Update Graal
   1 /*
   2  * Copyright (c) 2015, 2015, 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 
  26 package org.graalvm.compiler.core.aarch64;
  27 
  28 import static jdk.vm.ci.aarch64.AArch64.sp;
  29 import static jdk.vm.ci.aarch64.AArch64Kind.DWORD;
  30 import static jdk.vm.ci.aarch64.AArch64Kind.QWORD;
  31 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
  32 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
  33 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.BSR;
  34 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CLZ;
  35 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CTZ;
  36 
  37 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
  38 import org.graalvm.compiler.core.common.LIRKind;
  39 import org.graalvm.compiler.core.common.NumUtil;
  40 import org.graalvm.compiler.core.common.calc.FloatConvert;
  41 import org.graalvm.compiler.debug.GraalError;
  42 import org.graalvm.compiler.lir.ConstantValue;
  43 import org.graalvm.compiler.lir.LIRFrameState;
  44 import org.graalvm.compiler.lir.Variable;
  45 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
  46 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool;
  47 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
  48 import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp;
  49 import org.graalvm.compiler.lir.aarch64.AArch64Move.LoadOp;
  50 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreConstantOp;
  51 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp;
  52 import org.graalvm.compiler.lir.aarch64.AArch64ReinterpretOp;
  53 import org.graalvm.compiler.lir.aarch64.AArch64SignExtendOp;
  54 import org.graalvm.compiler.lir.aarch64.AArch64Unary;
  55 import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
  56 
  57 import jdk.vm.ci.aarch64.AArch64Kind;
  58 import jdk.vm.ci.code.RegisterValue;
  59 import jdk.vm.ci.meta.AllocatableValue;
  60 import jdk.vm.ci.meta.JavaConstant;
  61 import jdk.vm.ci.meta.PlatformKind;
  62 import jdk.vm.ci.meta.Value;
  63 import jdk.vm.ci.meta.ValueKind;
  64 
  65 public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implements AArch64ArithmeticLIRGeneratorTool {
  66 
  67     @Override
  68     public AArch64LIRGenerator getLIRGen() {
  69         return (AArch64LIRGenerator) super.getLIRGen();
  70     }
  71 
  72     @Override
  73     protected boolean isNumericInteger(PlatformKind kind) {
  74         return ((AArch64Kind) kind).isInteger();
  75     }
  76 
  77     @Override
  78     protected Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) {


 117     }
 118 
 119     @Override
 120     public Value emitMul(Value a, Value b, boolean setFlags) {
 121         AArch64ArithmeticOp intOp = setFlags ? AArch64ArithmeticOp.MULVS : AArch64ArithmeticOp.MUL;
 122         return emitBinary(LIRKind.combine(a, b), getOpCode(a, intOp, AArch64ArithmeticOp.FMUL), true, a, b);
 123     }
 124 
 125     @Override
 126     public Value emitMulHigh(Value a, Value b) {
 127         assert isNumericInteger(a.getPlatformKind());
 128         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.SMULH, true, a, b);
 129     }
 130 
 131     @Override
 132     public Value emitUMulHigh(Value a, Value b) {
 133         assert isNumericInteger(a.getPlatformKind());
 134         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UMULH, true, a, b);
 135     }
 136 





 137     @Override
 138     public Value emitDiv(Value a, Value b, LIRFrameState state) {
 139         return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.DIV, AArch64ArithmeticOp.FDIV), false, asAllocatable(a), asAllocatable(b));
 140     }
 141 
 142     @Override
 143     public Value emitRem(Value a, Value b, LIRFrameState state) {
 144         return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.REM, AArch64ArithmeticOp.FREM), false, asAllocatable(a), asAllocatable(b));
 145     }
 146 
 147     @Override
 148     public Value emitUDiv(Value a, Value b, LIRFrameState state) {
 149         assert isNumericInteger(a.getPlatformKind());
 150         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UDIV, false, asAllocatable(a), asAllocatable(b));
 151     }
 152 
 153     @Override
 154     public Value emitURem(Value a, Value b, LIRFrameState state) {
 155         assert isNumericInteger(a.getPlatformKind());
 156         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UREM, false, asAllocatable(a), asAllocatable(b));


 184     public Value emitShr(Value a, Value b) {
 185         assert isNumericInteger(a.getPlatformKind());
 186         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.ASHR, false, a, b);
 187     }
 188 
 189     @Override
 190     public Value emitUShr(Value a, Value b) {
 191         assert isNumericInteger(a.getPlatformKind());
 192         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.LSHR, false, a, b);
 193     }
 194 
 195     @Override
 196     public Value emitFloatConvert(FloatConvert op, Value inputVal) {
 197         PlatformKind resultPlatformKind = getFloatConvertResultKind(op);
 198         LIRKind resultLirKind = LIRKind.combine(inputVal).changeType(resultPlatformKind);
 199         Variable result = getLIRGen().newVariable(resultLirKind);
 200         getLIRGen().append(new AArch64FloatConvertOp(op, result, asAllocatable(inputVal)));
 201         return result;
 202     }
 203 
 204     public Value emitAddSubShift(AArch64ArithmeticOp op, Value a, Value b, AArch64MacroAssembler.ShiftType shiftType, int shiftAmount) {








 205         assert isNumericInteger(a.getPlatformKind());
 206         assert isNumericInteger(b.getPlatformKind());
 207         Variable result = getLIRGen().newVariable(LIRKind.combine(a, b));


 208         AllocatableValue x = moveSp(asAllocatable(a));
 209         AllocatableValue y = moveSp(asAllocatable(b));
 210         getLIRGen().append(new AArch64ArithmeticOp.AddSubShiftOp(op, result, x, y, shiftType, shiftAmount));

 211         return result;
 212     }
 213 
 214     private static PlatformKind getFloatConvertResultKind(FloatConvert op) {
 215         switch (op) {
 216             case F2I:
 217             case D2I:
 218                 return AArch64Kind.DWORD;
 219             case F2L:
 220             case D2L:
 221                 return AArch64Kind.QWORD;
 222             case I2F:
 223             case L2F:
 224             case D2F:
 225                 return AArch64Kind.SINGLE;
 226             case I2D:
 227             case L2D:
 228             case F2D:
 229                 return AArch64Kind.DOUBLE;
 230             default:


 417     public Value emitCountLeadingZeros(Value value) {
 418         Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
 419         getLIRGen().append(new AArch64BitManipulationOp(CLZ, result, asAllocatable(value)));
 420         return result;
 421     }
 422 
 423     @Override
 424     public Value emitCountTrailingZeros(Value value) {
 425         Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
 426         getLIRGen().append(new AArch64BitManipulationOp(CTZ, result, asAllocatable(value)));
 427         return result;
 428     }
 429 
 430     private Variable emitUnary(AArch64ArithmeticOp op, Value inputVal) {
 431         AllocatableValue input = asAllocatable(inputVal);
 432         Variable result = getLIRGen().newVariable(LIRKind.combine(input));
 433         getLIRGen().append(new AArch64ArithmeticOp.UnaryOp(op, result, input));
 434         return result;
 435     }
 436 
 437     /**
 438      * If val denotes the stackpointer, move it to another location. This is necessary since most
 439      * ops cannot handle the stackpointer as input or output.
 440      */
 441     private AllocatableValue moveSp(AllocatableValue val) {
 442         if (val instanceof RegisterValue && ((RegisterValue) val).getRegister().equals(sp)) {
 443             assert val.getPlatformKind() == AArch64Kind.QWORD : "Stackpointer must be long";
 444             return getLIRGen().emitMove(val);
 445         }
 446         return val;
 447     }
 448 
 449     /**
 450      * Returns the opcode depending on the platform kind of val.
 451      */
 452     private AArch64ArithmeticOp getOpCode(Value val, AArch64ArithmeticOp intOp, AArch64ArithmeticOp floatOp) {
 453         return isNumericInteger(val.getPlatformKind()) ? intOp : floatOp;
 454     }
 455 
 456     @Override
 457     public Variable emitLoad(LIRKind kind, Value address, LIRFrameState state) {
 458         AArch64AddressValue loadAddress = getLIRGen().asAddressValue(address);
 459         Variable result = getLIRGen().newVariable(getLIRGen().toRegisterKind(kind));
 460         getLIRGen().append(new LoadOp((AArch64Kind) kind.getPlatformKind(), result, loadAddress, state));
 461         return result;
 462     }
 463 
 464     @Override
 465     public void emitStore(ValueKind<?> lirKind, Value address, Value inputVal, LIRFrameState state) {
 466         AArch64AddressValue storeAddress = getLIRGen().asAddressValue(address);


   1 /*
   2  * Copyright (c) 2015, 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 
  26 package org.graalvm.compiler.core.aarch64;
  27 

  28 import static jdk.vm.ci.aarch64.AArch64Kind.DWORD;
  29 import static jdk.vm.ci.aarch64.AArch64Kind.QWORD;
  30 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
  31 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
  32 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.BSR;
  33 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CLZ;
  34 import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CTZ;
  35 
  36 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
  37 import org.graalvm.compiler.core.common.LIRKind;
  38 import org.graalvm.compiler.core.common.NumUtil;
  39 import org.graalvm.compiler.core.common.calc.FloatConvert;
  40 import org.graalvm.compiler.debug.GraalError;
  41 import org.graalvm.compiler.lir.ConstantValue;
  42 import org.graalvm.compiler.lir.LIRFrameState;
  43 import org.graalvm.compiler.lir.Variable;
  44 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
  45 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool;
  46 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
  47 import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp;
  48 import org.graalvm.compiler.lir.aarch64.AArch64Move.LoadOp;
  49 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreConstantOp;
  50 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp;
  51 import org.graalvm.compiler.lir.aarch64.AArch64ReinterpretOp;
  52 import org.graalvm.compiler.lir.aarch64.AArch64SignExtendOp;
  53 import org.graalvm.compiler.lir.aarch64.AArch64Unary;
  54 import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
  55 
  56 import jdk.vm.ci.aarch64.AArch64Kind;

  57 import jdk.vm.ci.meta.AllocatableValue;
  58 import jdk.vm.ci.meta.JavaConstant;
  59 import jdk.vm.ci.meta.PlatformKind;
  60 import jdk.vm.ci.meta.Value;
  61 import jdk.vm.ci.meta.ValueKind;
  62 
  63 public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implements AArch64ArithmeticLIRGeneratorTool {
  64 
  65     @Override
  66     public AArch64LIRGenerator getLIRGen() {
  67         return (AArch64LIRGenerator) super.getLIRGen();
  68     }
  69 
  70     @Override
  71     protected boolean isNumericInteger(PlatformKind kind) {
  72         return ((AArch64Kind) kind).isInteger();
  73     }
  74 
  75     @Override
  76     protected Variable emitAdd(LIRKind resultKind, Value a, Value b, boolean setFlags) {


 115     }
 116 
 117     @Override
 118     public Value emitMul(Value a, Value b, boolean setFlags) {
 119         AArch64ArithmeticOp intOp = setFlags ? AArch64ArithmeticOp.MULVS : AArch64ArithmeticOp.MUL;
 120         return emitBinary(LIRKind.combine(a, b), getOpCode(a, intOp, AArch64ArithmeticOp.FMUL), true, a, b);
 121     }
 122 
 123     @Override
 124     public Value emitMulHigh(Value a, Value b) {
 125         assert isNumericInteger(a.getPlatformKind());
 126         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.SMULH, true, a, b);
 127     }
 128 
 129     @Override
 130     public Value emitUMulHigh(Value a, Value b) {
 131         assert isNumericInteger(a.getPlatformKind());
 132         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UMULH, true, a, b);
 133     }
 134 
 135     public Value emitMNeg(Value a, Value b) {
 136         assert isNumericInteger(a.getPlatformKind()) && isNumericInteger(b.getPlatformKind());
 137         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.MNEG, true, a, b);
 138     }
 139 
 140     @Override
 141     public Value emitDiv(Value a, Value b, LIRFrameState state) {
 142         return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.DIV, AArch64ArithmeticOp.FDIV), false, asAllocatable(a), asAllocatable(b));
 143     }
 144 
 145     @Override
 146     public Value emitRem(Value a, Value b, LIRFrameState state) {
 147         return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.REM, AArch64ArithmeticOp.FREM), false, asAllocatable(a), asAllocatable(b));
 148     }
 149 
 150     @Override
 151     public Value emitUDiv(Value a, Value b, LIRFrameState state) {
 152         assert isNumericInteger(a.getPlatformKind());
 153         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UDIV, false, asAllocatable(a), asAllocatable(b));
 154     }
 155 
 156     @Override
 157     public Value emitURem(Value a, Value b, LIRFrameState state) {
 158         assert isNumericInteger(a.getPlatformKind());
 159         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.UREM, false, asAllocatable(a), asAllocatable(b));


 187     public Value emitShr(Value a, Value b) {
 188         assert isNumericInteger(a.getPlatformKind());
 189         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.ASHR, false, a, b);
 190     }
 191 
 192     @Override
 193     public Value emitUShr(Value a, Value b) {
 194         assert isNumericInteger(a.getPlatformKind());
 195         return emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.LSHR, false, a, b);
 196     }
 197 
 198     @Override
 199     public Value emitFloatConvert(FloatConvert op, Value inputVal) {
 200         PlatformKind resultPlatformKind = getFloatConvertResultKind(op);
 201         LIRKind resultLirKind = LIRKind.combine(inputVal).changeType(resultPlatformKind);
 202         Variable result = getLIRGen().newVariable(resultLirKind);
 203         getLIRGen().append(new AArch64FloatConvertOp(op, result, asAllocatable(inputVal)));
 204         return result;
 205     }
 206 
 207     public Value emitMAdd(Value a, Value b, Value c) {
 208         return emitMultiplyAddSub(AArch64ArithmeticOp.ADD, a, b, c);
 209     }
 210 
 211     public Value emitMSub(Value a, Value b, Value c) {
 212         return emitMultiplyAddSub(AArch64ArithmeticOp.SUB, a, b, c);
 213     }
 214 
 215     private Value emitMultiplyAddSub(AArch64ArithmeticOp op, Value a, Value b, Value c) {
 216         assert isNumericInteger(a.getPlatformKind());
 217         assert isNumericInteger(b.getPlatformKind());
 218         assert isNumericInteger(c.getPlatformKind());
 219 
 220         Variable result = getLIRGen().newVariable(LIRKind.combine(a, b, c));
 221         AllocatableValue x = moveSp(asAllocatable(a));
 222         AllocatableValue y = moveSp(asAllocatable(b));
 223         AllocatableValue z = moveSp(asAllocatable(c));
 224         getLIRGen().append(new AArch64ArithmeticOp.MultiplyAddSubOp(op, result, x, y, z));
 225         return result;
 226     }
 227 
 228     private static PlatformKind getFloatConvertResultKind(FloatConvert op) {
 229         switch (op) {
 230             case F2I:
 231             case D2I:
 232                 return AArch64Kind.DWORD;
 233             case F2L:
 234             case D2L:
 235                 return AArch64Kind.QWORD;
 236             case I2F:
 237             case L2F:
 238             case D2F:
 239                 return AArch64Kind.SINGLE;
 240             case I2D:
 241             case L2D:
 242             case F2D:
 243                 return AArch64Kind.DOUBLE;
 244             default:


 431     public Value emitCountLeadingZeros(Value value) {
 432         Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
 433         getLIRGen().append(new AArch64BitManipulationOp(CLZ, result, asAllocatable(value)));
 434         return result;
 435     }
 436 
 437     @Override
 438     public Value emitCountTrailingZeros(Value value) {
 439         Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
 440         getLIRGen().append(new AArch64BitManipulationOp(CTZ, result, asAllocatable(value)));
 441         return result;
 442     }
 443 
 444     private Variable emitUnary(AArch64ArithmeticOp op, Value inputVal) {
 445         AllocatableValue input = asAllocatable(inputVal);
 446         Variable result = getLIRGen().newVariable(LIRKind.combine(input));
 447         getLIRGen().append(new AArch64ArithmeticOp.UnaryOp(op, result, input));
 448         return result;
 449     }
 450 




 451     private AllocatableValue moveSp(AllocatableValue val) {
 452         return getLIRGen().moveSp(val);




 453     }
 454 
 455     /**
 456      * Returns the opcode depending on the platform kind of val.
 457      */
 458     private AArch64ArithmeticOp getOpCode(Value val, AArch64ArithmeticOp intOp, AArch64ArithmeticOp floatOp) {
 459         return isNumericInteger(val.getPlatformKind()) ? intOp : floatOp;
 460     }
 461 
 462     @Override
 463     public Variable emitLoad(LIRKind kind, Value address, LIRFrameState state) {
 464         AArch64AddressValue loadAddress = getLIRGen().asAddressValue(address);
 465         Variable result = getLIRGen().newVariable(getLIRGen().toRegisterKind(kind));
 466         getLIRGen().append(new LoadOp((AArch64Kind) kind.getPlatformKind(), result, loadAddress, state));
 467         return result;
 468     }
 469 
 470     @Override
 471     public void emitStore(ValueKind<?> lirKind, Value address, Value inputVal, LIRFrameState state) {
 472         AArch64AddressValue storeAddress = getLIRGen().asAddressValue(address);


< prev index next >