src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java
changeset 58299 6df94ce3ab2f
parent 54328 37648a9c4a6a
child 58533 46b0b7fe255c
equal deleted inserted replaced
58298:0152ad7b38b8 58299:6df94ce3ab2f
     1 /*
     1 /*
     2  * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * Copyright (c) 2018, Red Hat Inc. All rights reserved.
     3  * Copyright (c) 2018, Red Hat Inc. All rights reserved.
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5  *
     5  *
     6  * This code is free software; you can redistribute it and/or modify it
     6  * This code is free software; you can redistribute it and/or modify it
     7  * under the terms of the GNU General Public License version 2 only, as
     7  * under the terms of the GNU General Public License version 2 only, as
    36 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.LOAD_COUNTERS;
    36 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.LOAD_COUNTERS;
    37 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.RESOLVE;
    37 import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.RESOLVE;
    38 import static org.graalvm.compiler.lir.LIRValueUtil.asConstant;
    38 import static org.graalvm.compiler.lir.LIRValueUtil.asConstant;
    39 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
    39 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
    40 
    40 
       
    41 import java.util.EnumSet;
    41 import java.util.function.Function;
    42 import java.util.function.Function;
    42 
    43 
    43 import org.graalvm.compiler.asm.Label;
    44 import org.graalvm.compiler.asm.Label;
    44 import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
    45 import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
    45 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
    46 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
    46 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode;
    47 import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode;
    47 import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator;
    48 import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator;
    48 import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator;
    49 import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator;
    49 import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool;
    50 import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool;
    50 import org.graalvm.compiler.core.common.CompressEncoding;
    51 import org.graalvm.compiler.core.common.CompressEncoding;
       
    52 import org.graalvm.compiler.core.common.GraalOptions;
    51 import org.graalvm.compiler.core.common.LIRKind;
    53 import org.graalvm.compiler.core.common.LIRKind;
    52 import org.graalvm.compiler.core.common.calc.Condition;
    54 import org.graalvm.compiler.core.common.calc.Condition;
    53 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
    55 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
    54 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
    56 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
    55 import org.graalvm.compiler.core.common.spi.LIRKindTool;
    57 import org.graalvm.compiler.core.common.spi.LIRKindTool;
    66 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
    68 import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
    67 import org.graalvm.compiler.hotspot.stubs.Stub;
    69 import org.graalvm.compiler.hotspot.stubs.Stub;
    68 import org.graalvm.compiler.lir.LIRFrameState;
    70 import org.graalvm.compiler.lir.LIRFrameState;
    69 import org.graalvm.compiler.lir.LIRInstruction;
    71 import org.graalvm.compiler.lir.LIRInstruction;
    70 import org.graalvm.compiler.lir.LabelRef;
    72 import org.graalvm.compiler.lir.LabelRef;
    71 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
    73 import org.graalvm.compiler.lir.StandardOp.ZapRegistersOp;
    72 import org.graalvm.compiler.lir.SwitchStrategy;
    74 import org.graalvm.compiler.lir.SwitchStrategy;
    73 import org.graalvm.compiler.lir.Variable;
    75 import org.graalvm.compiler.lir.Variable;
    74 import org.graalvm.compiler.lir.VirtualStackSlot;
    76 import org.graalvm.compiler.lir.VirtualStackSlot;
    75 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
    77 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
    76 import org.graalvm.compiler.lir.aarch64.AArch64CCall;
    78 import org.graalvm.compiler.lir.aarch64.AArch64CCall;
    80 import org.graalvm.compiler.lir.aarch64.AArch64Move;
    82 import org.graalvm.compiler.lir.aarch64.AArch64Move;
    81 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp;
    83 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp;
    82 import org.graalvm.compiler.lir.aarch64.AArch64PrefetchOp;
    84 import org.graalvm.compiler.lir.aarch64.AArch64PrefetchOp;
    83 import org.graalvm.compiler.lir.aarch64.AArch64RestoreRegistersOp;
    85 import org.graalvm.compiler.lir.aarch64.AArch64RestoreRegistersOp;
    84 import org.graalvm.compiler.lir.aarch64.AArch64SaveRegistersOp;
    86 import org.graalvm.compiler.lir.aarch64.AArch64SaveRegistersOp;
       
    87 import org.graalvm.compiler.lir.aarch64.AArch64ZeroMemoryOp;
    85 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
    88 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
    86 import org.graalvm.compiler.options.OptionValues;
    89 import org.graalvm.compiler.options.OptionValues;
    87 
    90 
    88 import jdk.vm.ci.aarch64.AArch64;
    91 import jdk.vm.ci.aarch64.AArch64;
    89 import jdk.vm.ci.aarch64.AArch64Kind;
    92 import jdk.vm.ci.aarch64.AArch64Kind;
   165     }
   168     }
   166 
   169 
   167     /**
   170     /**
   168      * @param savedRegisters the registers saved by this operation which may be subject to pruning
   171      * @param savedRegisters the registers saved by this operation which may be subject to pruning
   169      * @param savedRegisterLocations the slots to which the registers are saved
   172      * @param savedRegisterLocations the slots to which the registers are saved
   170      * @param supportsRemove determines if registers can be pruned
       
   171      */
   173      */
   172     protected AArch64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) {
   174     protected AArch64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations) {
   173         AArch64SaveRegistersOp save = new AArch64SaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove);
   175         AArch64SaveRegistersOp save = new AArch64SaveRegistersOp(savedRegisters, savedRegisterLocations);
   174         append(save);
   176         append(save);
   175         return save;
   177         return save;
   176     }
   178     }
   177 
   179 
   178     /**
   180     /**
   180      */
   182      */
   181     protected VirtualStackSlot allocateSaveRegisterLocation(Register register) {
   183     protected VirtualStackSlot allocateSaveRegisterLocation(Register register) {
   182         PlatformKind kind = target().arch.getLargestStorableKind(register.getRegisterCategory());
   184         PlatformKind kind = target().arch.getLargestStorableKind(register.getRegisterCategory());
   183         if (kind.getVectorLength() > 1) {
   185         if (kind.getVectorLength() > 1) {
   184             // we don't use vector registers, so there is no need to save them
   186             // we don't use vector registers, so there is no need to save them
   185             kind = AArch64Kind.QWORD;
   187             kind = AArch64Kind.DOUBLE;
   186         }
   188         }
   187         return getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind));
   189         return getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind));
   188     }
   190     }
   189 
   191 
   190     /**
   192     /**
   191      * Adds a node to the graph that saves all allocatable registers to the stack.
   193      * Adds a node to the graph that saves all allocatable registers to the stack.
   192      *
   194      *
   193      * @param supportsRemove determines if registers can be pruned
       
   194      * @return the register save node
   195      * @return the register save node
   195      */
   196      */
   196     private AArch64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters, boolean supportsRemove) {
   197     private AArch64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters) {
   197         AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length];
   198         AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length];
   198         for (int i = 0; i < savedRegisters.length; i++) {
   199         for (int i = 0; i < savedRegisters.length; i++) {
   199             savedRegisterLocations[i] = allocateSaveRegisterLocation(savedRegisters[i]);
   200             savedRegisterLocations[i] = allocateSaveRegisterLocation(savedRegisters[i]);
   200         }
   201         }
   201         return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove);
   202         return emitSaveRegisters(savedRegisters, savedRegisterLocations);
   202     }
   203     }
   203 
   204 
   204     protected void emitRestoreRegisters(AArch64SaveRegistersOp save) {
   205     protected void emitRestoreRegisters(AArch64SaveRegistersOp save) {
   205         append(new AArch64RestoreRegistersOp(save.getSlots().clone(), save));
   206         append(new AArch64RestoreRegistersOp(save.getSlots().clone(), save));
   206     }
   207     }
   345         HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage;
   346         HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage;
   346         boolean destroysRegisters = hotspotLinkage.destroysRegisters();
   347         boolean destroysRegisters = hotspotLinkage.destroysRegisters();
   347 
   348 
   348         AArch64SaveRegistersOp save = null;
   349         AArch64SaveRegistersOp save = null;
   349         Stub stub = getStub();
   350         Stub stub = getStub();
   350         if (destroysRegisters) {
   351         if (destroysRegisters && stub != null && stub.shouldSaveRegistersAroundCalls()) {
   351             if (stub != null && stub.preservesRegisters()) {
   352             Register[] savedRegisters = getRegisterConfig().getAllocatableRegisters().toArray();
   352                 Register[] savedRegisters = getRegisterConfig().getAllocatableRegisters().toArray();
   353             save = emitSaveAllRegisters(savedRegisters);
   353                 save = emitSaveAllRegisters(savedRegisters, true);
       
   354             }
       
   355         }
   354         }
   356 
   355 
   357         Variable result;
   356         Variable result;
   358         LIRFrameState debugInfo = null;
   357         LIRFrameState debugInfo = null;
   359         if (hotspotLinkage.needsDebugInfo()) {
   358         if (hotspotLinkage.needsDebugInfo()) {
   377             label = null;
   376             label = null;
   378         } else {
   377         } else {
   379             result = super.emitForeignCall(hotspotLinkage, debugInfo, args);
   378             result = super.emitForeignCall(hotspotLinkage, debugInfo, args);
   380         }
   379         }
   381 
   380 
   382         if (destroysRegisters) {
   381         if (save != null) {
   383             if (stub != null) {
   382             HotSpotLIRGenerationResult generationResult = getResult();
   384                 if (stub.preservesRegisters()) {
   383             LIRFrameState key = currentRuntimeCallInfo;
   385                     HotSpotLIRGenerationResult generationResult = getResult();
   384             if (key == null) {
   386                     LIRFrameState key = currentRuntimeCallInfo;
   385                 key = LIRFrameState.NO_STATE;
   387                     if (key == null) {
       
   388                         key = LIRFrameState.NO_STATE;
       
   389                     }
       
   390                     assert !generationResult.getCalleeSaveInfo().containsKey(key);
       
   391                     generationResult.getCalleeSaveInfo().put(key, save);
       
   392                     emitRestoreRegisters(save);
       
   393                 }
       
   394             }
   386             }
       
   387             assert !generationResult.getCalleeSaveInfo().containsKey(key);
       
   388             generationResult.getCalleeSaveInfo().put(key, save);
       
   389             emitRestoreRegisters(save);
   395         }
   390         }
   396 
   391 
   397         return result;
   392         return result;
   398     }
   393     }
   399 
   394 
   537     public void setDebugInfoBuilder(HotSpotDebugInfoBuilder debugInfoBuilder) {
   532     public void setDebugInfoBuilder(HotSpotDebugInfoBuilder debugInfoBuilder) {
   538         this.debugInfoBuilder = debugInfoBuilder;
   533         this.debugInfoBuilder = debugInfoBuilder;
   539     }
   534     }
   540 
   535 
   541     @Override
   536     @Override
   542     public SaveRegistersOp createZapRegisters(Register[] zappedRegisters, JavaConstant[] zapValues) {
   537     public ZapRegistersOp createZapRegisters(Register[] zappedRegisters, JavaConstant[] zapValues) {
   543         throw GraalError.unimplemented();
   538         throw GraalError.unimplemented();
   544     }
   539     }
   545 
   540 
   546     @Override
   541     @Override
   547     public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) {
   542     public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) {
   548         throw GraalError.unimplemented();
   543         throw GraalError.unimplemented();
   549     }
   544     }
       
   545 
       
   546     @Override
       
   547     public void emitZeroMemory(Value address, Value length) {
       
   548         int dczidValue = config.psrInfoDczidValue;
       
   549         EnumSet<AArch64.Flag> flags = ((AArch64) target().arch).getFlags();
       
   550 
       
   551         // ARMv8-A architecture reference manual D12.2.35 Data Cache Zero ID register says:
       
   552         // * BS, bits [3:0] indicate log2 of the DC ZVA block size in (4-byte) words.
       
   553         // * DZP, bit [4] of indicates whether use of DC ZVA instruction is prohibited.
       
   554         int zvaLength = 4 << (dczidValue & 0xF);
       
   555         boolean isDcZvaProhibited = ((dczidValue & 0x10) != 0);
       
   556 
       
   557         // Use DC ZVA if it's not prohibited and AArch64 HotSpot flag UseBlockZeroing is on.
       
   558         boolean useDcZva = !isDcZvaProhibited && flags.contains(AArch64.Flag.UseBlockZeroing);
       
   559 
       
   560         // Set zva length negative (unknown at compile-time) for AOT compilation, since the value
       
   561         // could be different on different AArch64 CPU implementations.
       
   562         if (GraalOptions.ImmutableCode.getValue(getResult().getLIR().getOptions())) {
       
   563             useDcZva = false;
       
   564         }
       
   565 
       
   566         // Value address is 8-byte aligned; Value length is multiple of 8.
       
   567         append(new AArch64ZeroMemoryOp(asAllocatable(address), asAllocatable(length), useDcZva, zvaLength));
       
   568     }
   550 }
   569 }