< prev index next >
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java
Print this page
rev 56282 : [mq]: graal
*** 1,7 ****
/*
! * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
--- 1,7 ----
/*
! * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
*** 36,55 ****
--- 36,57 ----
import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.LOAD_COUNTERS;
import static org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction.RESOLVE;
import static org.graalvm.compiler.lir.LIRValueUtil.asConstant;
import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
+ import java.util.EnumSet;
import java.util.function.Function;
import org.graalvm.compiler.asm.Label;
import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode;
import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator;
import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator;
import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool;
import org.graalvm.compiler.core.common.CompressEncoding;
+ import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.calc.Condition;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
import org.graalvm.compiler.core.common.spi.LIRKindTool;
*** 66,76 ****
import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
import org.graalvm.compiler.hotspot.stubs.Stub;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.LabelRef;
! import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
import org.graalvm.compiler.lir.SwitchStrategy;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.VirtualStackSlot;
import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
import org.graalvm.compiler.lir.aarch64.AArch64CCall;
--- 68,78 ----
import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider;
import org.graalvm.compiler.hotspot.stubs.Stub;
import org.graalvm.compiler.lir.LIRFrameState;
import org.graalvm.compiler.lir.LIRInstruction;
import org.graalvm.compiler.lir.LabelRef;
! import org.graalvm.compiler.lir.StandardOp.ZapRegistersOp;
import org.graalvm.compiler.lir.SwitchStrategy;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.lir.VirtualStackSlot;
import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
import org.graalvm.compiler.lir.aarch64.AArch64CCall;
*** 80,89 ****
--- 82,92 ----
import org.graalvm.compiler.lir.aarch64.AArch64Move;
import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp;
import org.graalvm.compiler.lir.aarch64.AArch64PrefetchOp;
import org.graalvm.compiler.lir.aarch64.AArch64RestoreRegistersOp;
import org.graalvm.compiler.lir.aarch64.AArch64SaveRegistersOp;
+ import org.graalvm.compiler.lir.aarch64.AArch64ZeroMemoryOp;
import org.graalvm.compiler.lir.gen.LIRGenerationResult;
import org.graalvm.compiler.options.OptionValues;
import jdk.vm.ci.aarch64.AArch64;
import jdk.vm.ci.aarch64.AArch64Kind;
*** 165,178 ****
}
/**
* @param savedRegisters the registers saved by this operation which may be subject to pruning
* @param savedRegisterLocations the slots to which the registers are saved
- * @param supportsRemove determines if registers can be pruned
*/
! protected AArch64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) {
! AArch64SaveRegistersOp save = new AArch64SaveRegistersOp(savedRegisters, savedRegisterLocations, supportsRemove);
append(save);
return save;
}
/**
--- 168,180 ----
}
/**
* @param savedRegisters the registers saved by this operation which may be subject to pruning
* @param savedRegisterLocations the slots to which the registers are saved
*/
! protected AArch64SaveRegistersOp emitSaveRegisters(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations) {
! AArch64SaveRegistersOp save = new AArch64SaveRegistersOp(savedRegisters, savedRegisterLocations);
append(save);
return save;
}
/**
*** 180,206 ****
*/
protected VirtualStackSlot allocateSaveRegisterLocation(Register register) {
PlatformKind kind = target().arch.getLargestStorableKind(register.getRegisterCategory());
if (kind.getVectorLength() > 1) {
// we don't use vector registers, so there is no need to save them
! kind = AArch64Kind.QWORD;
}
return getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind));
}
/**
* Adds a node to the graph that saves all allocatable registers to the stack.
*
- * @param supportsRemove determines if registers can be pruned
* @return the register save node
*/
! private AArch64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters, boolean supportsRemove) {
AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length];
for (int i = 0; i < savedRegisters.length; i++) {
savedRegisterLocations[i] = allocateSaveRegisterLocation(savedRegisters[i]);
}
! return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove);
}
protected void emitRestoreRegisters(AArch64SaveRegistersOp save) {
append(new AArch64RestoreRegistersOp(save.getSlots().clone(), save));
}
--- 182,207 ----
*/
protected VirtualStackSlot allocateSaveRegisterLocation(Register register) {
PlatformKind kind = target().arch.getLargestStorableKind(register.getRegisterCategory());
if (kind.getVectorLength() > 1) {
// we don't use vector registers, so there is no need to save them
! kind = AArch64Kind.DOUBLE;
}
return getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind));
}
/**
* Adds a node to the graph that saves all allocatable registers to the stack.
*
* @return the register save node
*/
! private AArch64SaveRegistersOp emitSaveAllRegisters(Register[] savedRegisters) {
AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length];
for (int i = 0; i < savedRegisters.length; i++) {
savedRegisterLocations[i] = allocateSaveRegisterLocation(savedRegisters[i]);
}
! return emitSaveRegisters(savedRegisters, savedRegisterLocations);
}
protected void emitRestoreRegisters(AArch64SaveRegistersOp save) {
append(new AArch64RestoreRegistersOp(save.getSlots().clone(), save));
}
*** 345,359 ****
HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage;
boolean destroysRegisters = hotspotLinkage.destroysRegisters();
AArch64SaveRegistersOp save = null;
Stub stub = getStub();
! if (destroysRegisters) {
! if (stub != null && stub.preservesRegisters()) {
Register[] savedRegisters = getRegisterConfig().getAllocatableRegisters().toArray();
! save = emitSaveAllRegisters(savedRegisters, true);
! }
}
Variable result;
LIRFrameState debugInfo = null;
if (hotspotLinkage.needsDebugInfo()) {
--- 346,358 ----
HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage;
boolean destroysRegisters = hotspotLinkage.destroysRegisters();
AArch64SaveRegistersOp save = null;
Stub stub = getStub();
! if (destroysRegisters && stub != null && stub.shouldSaveRegistersAroundCalls()) {
Register[] savedRegisters = getRegisterConfig().getAllocatableRegisters().toArray();
! save = emitSaveAllRegisters(savedRegisters);
}
Variable result;
LIRFrameState debugInfo = null;
if (hotspotLinkage.needsDebugInfo()) {
*** 377,400 ****
label = null;
} else {
result = super.emitForeignCall(hotspotLinkage, debugInfo, args);
}
! if (destroysRegisters) {
! if (stub != null) {
! if (stub.preservesRegisters()) {
HotSpotLIRGenerationResult generationResult = getResult();
LIRFrameState key = currentRuntimeCallInfo;
if (key == null) {
key = LIRFrameState.NO_STATE;
}
assert !generationResult.getCalleeSaveInfo().containsKey(key);
generationResult.getCalleeSaveInfo().put(key, save);
emitRestoreRegisters(save);
}
- }
- }
return result;
}
@Override
--- 376,395 ----
label = null;
} else {
result = super.emitForeignCall(hotspotLinkage, debugInfo, args);
}
! if (save != null) {
HotSpotLIRGenerationResult generationResult = getResult();
LIRFrameState key = currentRuntimeCallInfo;
if (key == null) {
key = LIRFrameState.NO_STATE;
}
assert !generationResult.getCalleeSaveInfo().containsKey(key);
generationResult.getCalleeSaveInfo().put(key, save);
emitRestoreRegisters(save);
}
return result;
}
@Override
*** 537,550 ****
public void setDebugInfoBuilder(HotSpotDebugInfoBuilder debugInfoBuilder) {
this.debugInfoBuilder = debugInfoBuilder;
}
@Override
! public SaveRegistersOp createZapRegisters(Register[] zappedRegisters, JavaConstant[] zapValues) {
throw GraalError.unimplemented();
}
@Override
public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) {
throw GraalError.unimplemented();
}
}
--- 532,569 ----
public void setDebugInfoBuilder(HotSpotDebugInfoBuilder debugInfoBuilder) {
this.debugInfoBuilder = debugInfoBuilder;
}
@Override
! public ZapRegistersOp createZapRegisters(Register[] zappedRegisters, JavaConstant[] zapValues) {
throw GraalError.unimplemented();
}
@Override
public LIRInstruction createZapArgumentSpace(StackSlot[] zappedStack, JavaConstant[] zapValues) {
throw GraalError.unimplemented();
}
+
+ @Override
+ public void emitZeroMemory(Value address, Value length) {
+ int dczidValue = config.psrInfoDczidValue;
+ EnumSet<AArch64.Flag> flags = ((AArch64) target().arch).getFlags();
+
+ // ARMv8-A architecture reference manual D12.2.35 Data Cache Zero ID register says:
+ // * BS, bits [3:0] indicate log2 of the DC ZVA block size in (4-byte) words.
+ // * DZP, bit [4] of indicates whether use of DC ZVA instruction is prohibited.
+ int zvaLength = 4 << (dczidValue & 0xF);
+ boolean isDcZvaProhibited = ((dczidValue & 0x10) != 0);
+
+ // Use DC ZVA if it's not prohibited and AArch64 HotSpot flag UseBlockZeroing is on.
+ boolean useDcZva = !isDcZvaProhibited && flags.contains(AArch64.Flag.UseBlockZeroing);
+
+ // Set zva length negative (unknown at compile-time) for AOT compilation, since the value
+ // could be different on different AArch64 CPU implementations.
+ if (GraalOptions.ImmutableCode.getValue(getResult().getLIR().getOptions())) {
+ useDcZva = false;
+ }
+
+ // Value address is 8-byte aligned; Value length is multiple of 8.
+ append(new AArch64ZeroMemoryOp(asAllocatable(address), asAllocatable(length), useDcZva, zvaLength));
+ }
}
< prev index next >