Skip to content

Commit

Permalink
[GR-52402] Use correct compare size in AMD64NormalizedUnsignedCompareOp
Browse files Browse the repository at this point in the history
PullRequest: graal/17138
  • Loading branch information
gergo- committed Mar 2, 2024
2 parents 795ba9a + 2a2d7bb commit 7d01e1a
Show file tree
Hide file tree
Showing 7 changed files with 208 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. 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
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package jdk.graal.compiler.replacements.test;

import org.junit.Assume;
import org.junit.Test;

import jdk.graal.compiler.core.test.GraalCompilerTest;
import jdk.graal.compiler.nodes.ConstantNode;
import jdk.graal.compiler.nodes.NodeView;
import jdk.graal.compiler.nodes.ValueNode;
import jdk.graal.compiler.nodes.calc.AndNode;
import jdk.graal.compiler.nodes.calc.IntegerNormalizeCompareNode;
import jdk.graal.compiler.nodes.calc.NarrowNode;
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext;
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin;
import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaMethod;

/**
* Tests for {@link IntegerNormalizeCompareNode} applied to subword integers.
*/
public class NarrowCompareUnsignedTest extends GraalCompilerTest {

public static int narrowCompareUnsignedByte(int x, int y) {
/*
* This expression doesn't quite produce the graph shape we want: The narrows feed into sign
* extensions that feed into the actual compare. We want to test the compare when applied to
* the actual narrows. It's possible but fairly difficult to produce that graph shape in
* practice. Therefore we intrinsify this method to get what we want.
*/
return Integer.compareUnsigned((byte) x, (byte) y);
}

public static int narrowCompareUnsignedShort(int x, int y) {
return Integer.compareUnsigned((short) x, (short) y);
}

public static int narrowCompareUnsignedChar(int x, int y) {
return Integer.compareUnsigned((char) x, (char) y);
}

@Override
protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
InvocationPlugins.Registration r = new InvocationPlugins.Registration(invocationPlugins, NarrowCompareUnsignedTest.class);
r.register(new InvocationPlugin.InlineOnlyInvocationPlugin("narrowCompareUnsignedByte", int.class, int.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
ValueNode narrowX = NarrowNode.create(x, Byte.SIZE, NodeView.DEFAULT);
ValueNode narrowY = NarrowNode.create(y, Byte.SIZE, NodeView.DEFAULT);
b.addPush(JavaKind.Int, IntegerNormalizeCompareNode.create(narrowX, narrowY, true, JavaKind.Int, b.getConstantReflection()));
return true;
}
});
r.register(new InvocationPlugin.InlineOnlyInvocationPlugin("narrowCompareUnsignedShort", int.class, int.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
ValueNode narrowX = NarrowNode.create(x, Short.SIZE, NodeView.DEFAULT);
ValueNode narrowY = NarrowNode.create(y, Short.SIZE, NodeView.DEFAULT);
b.addPush(JavaKind.Int, IntegerNormalizeCompareNode.create(narrowX, narrowY, true, JavaKind.Int, b.getConstantReflection()));
return true;
}
});
r.register(new InvocationPlugin.InlineOnlyInvocationPlugin("narrowCompareUnsignedChar", int.class, int.class) {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) {
int unsignedMask = 0xffff;
ValueNode maskedX = AndNode.create(x, ConstantNode.forInt(unsignedMask), NodeView.DEFAULT);
ValueNode maskedY = AndNode.create(y, ConstantNode.forInt(unsignedMask), NodeView.DEFAULT);
ValueNode narrowX = NarrowNode.create(maskedX, Character.SIZE, NodeView.DEFAULT);
ValueNode narrowY = NarrowNode.create(maskedY, Character.SIZE, NodeView.DEFAULT);
b.addPush(JavaKind.Int, IntegerNormalizeCompareNode.create(narrowX, narrowY, true, JavaKind.Int, b.getConstantReflection()));
return true;
}
});
super.registerInvocationPlugins(invocationPlugins);
}

private static final int[] TEST_VALUES = new int[]{0, 40, Byte.MAX_VALUE, Byte.MAX_VALUE + 40, Short.MAX_VALUE, Short.MAX_VALUE + 40, Character.MAX_VALUE, Character.MAX_VALUE + 40};

public static int byteVariableSnippet(int x, int y) {
return narrowCompareUnsignedByte(x, y);
}

@Test
public void byteVariable() {
Assume.assumeTrue("only test byte compare when supported on target", getLowerer().smallestCompareWidth() <= Byte.SIZE);
for (int x : TEST_VALUES) {
for (int y : TEST_VALUES) {
test("byteVariableSnippet", x, y);
}
}
}

public static int byteConstantSnippet(int x) {
return narrowCompareUnsignedByte(x, Byte.MAX_VALUE);
}

@Test
public void byteConstant() {
Assume.assumeTrue("only test byte compare when supported on target", getLowerer().smallestCompareWidth() <= Byte.SIZE);
for (int x : TEST_VALUES) {
test("byteConstantSnippet", x);
}
}

public static int shortVariableSnippet(int x, int y) {
return narrowCompareUnsignedShort(x, y);
}

@Test
public void shortVariable() {
Assume.assumeTrue("only test short compare when supported on target", getLowerer().smallestCompareWidth() <= Short.SIZE);
for (int x : TEST_VALUES) {
for (int y : TEST_VALUES) {
test("shortVariableSnippet", x, y);
}
}
}

public static int shortConstantSnippet(int x) {
return narrowCompareUnsignedShort(x, Short.MAX_VALUE);
}

@Test
public void shortConstant() {
Assume.assumeTrue("only test short compare when supported on target", getLowerer().smallestCompareWidth() <= Short.SIZE);
for (int x : TEST_VALUES) {
test("shortConstantSnippet", x);
}
}

public static int charVariableSnippet(int x, int y) {
return narrowCompareUnsignedChar(x, y);
}

@Test
public void charVariable() {
Assume.assumeTrue("only test char compare when supported on target", getLowerer().smallestCompareWidth() <= Character.SIZE);
for (int x : TEST_VALUES) {
for (int y : TEST_VALUES) {
test("charVariableSnippet", x, y);
}
}
}

public static int charConstantSnippet(int x) {
return narrowCompareUnsignedChar(x, Character.MAX_VALUE);
}

@Test
public void charConstant() {
Assume.assumeTrue("only test char compare when supported on target", getLowerer().smallestCompareWidth() <= Character.SIZE);
for (int x : TEST_VALUES) {
test("charConstantSnippet", x);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. 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
Expand Down Expand Up @@ -686,7 +686,8 @@ public Variable emitFloatToHalfFloat(Value input) {
}

@Override
public Variable emitNormalizedUnsignedCompare(Value x, Value y) {
public Variable emitNormalizedUnsignedCompare(LIRKind compareKind, Value x, Value y) {
GraalError.guarantee(compareKind.getPlatformKind() == AArch64Kind.DWORD || compareKind.getPlatformKind() == AArch64Kind.QWORD, "unsupported subword comparison: %s", compareKind);
Variable result = getLIRGen().newVariable(LIRKind.value(AArch64Kind.DWORD));
getLIRGen().append(new AArch64NormalizedUnsignedCompareOp(result, asAllocatable(x), asAllocatable(y)));
return result;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. 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
Expand Down Expand Up @@ -911,7 +911,8 @@ public final ComplexMatchResult floatSqrt(FloatConvertNode a, FloatConvertNode b
public ComplexMatchResult normalizedIntegerCompare(ValueNode x, ValueNode y, ConstantNode cm1, ConstantNode c0, ConstantNode c1) {
if (cm1.getStackKind() == JavaKind.Int && cm1.asJavaConstant().asInt() == -1 && c0.getStackKind() == JavaKind.Int && c0.asJavaConstant().asInt() == 0 && c1.getStackKind() == JavaKind.Int &&
c1.asJavaConstant().asInt() == 1) {
return builder -> getArithmeticLIRGenerator().emitNormalizedUnsignedCompare(operand(x), operand(y));
LIRKind compareKind = gen.getLIRKind(x.stamp(NodeView.DEFAULT));
return builder -> getArithmeticLIRGenerator().emitNormalizedUnsignedCompare(compareKind, operand(x), operand(y));
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1738,9 +1738,9 @@ public Variable emitFloatToHalfFloat(Value input) {
}

@Override
public Variable emitNormalizedUnsignedCompare(Value x, Value y) {
public Variable emitNormalizedUnsignedCompare(LIRKind compareKind, Value x, Value y) {
Variable result = getLIRGen().newVariable(LIRKind.value(AMD64Kind.DWORD));
getLIRGen().append(new AMD64NormalizedUnsignedCompareOp(result, asAllocatable(x), asAllocatable(y)));
getLIRGen().append(new AMD64NormalizedUnsignedCompareOp(result, compareKind, asAllocatable(x), asAllocatable(y)));
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
import jdk.graal.compiler.core.common.calc.FloatConvertCategory;
import jdk.graal.compiler.core.common.memory.MemoryExtendKind;
import jdk.graal.compiler.core.common.memory.MemoryOrderMode;
import jdk.graal.compiler.core.common.type.PrimitiveStamp;
import jdk.graal.compiler.core.gen.NodeLIRBuilder;
import jdk.graal.compiler.core.gen.NodeMatchRules;
import jdk.graal.compiler.core.match.ComplexMatchResult;
Expand Down Expand Up @@ -738,7 +739,11 @@ public ComplexMatchResult writeReinterpret(WriteNode root, ReinterpretNode reint
public ComplexMatchResult normalizedIntegerCompare(ValueNode x, ValueNode y, ConstantNode cm1, ConstantNode c0, ConstantNode c1) {
if (cm1.getStackKind() == JavaKind.Int && cm1.asJavaConstant().asInt() == -1 && c0.getStackKind() == JavaKind.Int && c0.asJavaConstant().asInt() == 0 && c1.getStackKind() == JavaKind.Int &&
c1.asJavaConstant().asInt() == 1) {
return builder -> getArithmeticLIRGenerator().emitNormalizedUnsignedCompare(operand(x), operand(y));
GraalError.guarantee(PrimitiveStamp.getBits(x.stamp(NodeView.DEFAULT)) == PrimitiveStamp.getBits(y.stamp(NodeView.DEFAULT)), "need compatible inputs: %s, %s", x, y);
return builder -> {
LIRKind compareKind = gen.getLIRKind(x.stamp(NodeView.DEFAULT));
return getArithmeticLIRGenerator().emitNormalizedUnsignedCompare(compareKind, operand(x), operand(y));
};
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. 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
Expand All @@ -24,17 +24,17 @@
*/
package jdk.graal.compiler.lir.amd64;

import static jdk.graal.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP;
import static jdk.vm.ci.code.ValueUtil.asRegister;

import jdk.graal.compiler.asm.Label;
import jdk.graal.compiler.asm.amd64.AMD64Assembler;
import jdk.graal.compiler.asm.amd64.AMD64BaseAssembler;
import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler;
import jdk.graal.compiler.debug.GraalError;
import jdk.graal.compiler.core.common.LIRKind;
import jdk.graal.compiler.lir.LIRInstructionClass;
import jdk.graal.compiler.lir.SyncPort;
import jdk.graal.compiler.lir.asm.CompilationResultBuilder;

import jdk.vm.ci.amd64.AMD64Kind;
import jdk.vm.ci.meta.AllocatableValue;

/**
Expand All @@ -53,23 +53,22 @@ public class AMD64NormalizedUnsignedCompareOp extends AMD64LIRInstruction {
@Use({OperandFlag.REG}) protected AllocatableValue x;
@Use({OperandFlag.REG}) protected AllocatableValue y;

public AMD64NormalizedUnsignedCompareOp(AllocatableValue result, AllocatableValue x, AllocatableValue y) {
private final LIRKind compareKind;

public AMD64NormalizedUnsignedCompareOp(AllocatableValue result, LIRKind compareKind, AllocatableValue x, AllocatableValue y) {
super(TYPE);

this.result = result;
this.x = x;
this.y = y;
this.compareKind = compareKind;
}

@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
Label done = new Label();
if (x.getPlatformKind() == AMD64Kind.DWORD) {
masm.cmpl(asRegister(x), asRegister(y));
} else {
GraalError.guarantee(x.getPlatformKind() == AMD64Kind.QWORD, "unsupported value kind %s", x.getPlatformKind());
masm.cmpq(asRegister(x), asRegister(y));
}
AMD64BaseAssembler.OperandSize size = AMD64BaseAssembler.OperandSize.get(compareKind.getPlatformKind());
CMP.getRMOpcode(size).emit(masm, size, asRegister(x), asRegister(y));
masm.movl(asRegister(result), -1);
masm.jccb(AMD64Assembler.ConditionFlag.Below, done);
masm.setl(AMD64Assembler.ConditionFlag.NotEqual, asRegister(result));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2024, Oracle and/or its affiliates. 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
Expand Down Expand Up @@ -216,7 +216,7 @@ default Variable emitFloatToHalfFloat(Value operand) {
}

@SuppressWarnings("unused")
default Variable emitNormalizedUnsignedCompare(Value x, Value y) {
default Variable emitNormalizedUnsignedCompare(LIRKind compareKind, Value x, Value y) {
throw GraalError.unimplemented("No specialized implementation available");
}

Expand Down

0 comments on commit 7d01e1a

Please sign in to comment.