Skip to content

Commit 0f6f3d7

Browse files
committed
[GR-63692] X86: Strength reduce test instruction to save code size
PullRequest: graal/20441
2 parents e32c845 + 46fb7b4 commit 0f6f3d7

File tree

5 files changed

+57
-28
lines changed

5 files changed

+57
-28
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64Assembler.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -592,14 +592,15 @@ public void emit(AMD64Assembler asm, OperandSize size, AMD64Address dst) {
592592
*/
593593
public static class AMD64MIOp extends AMD64ImmOp {
594594
// @formatter:off
595-
public static final AMD64MIOp BT = new AMD64MIOp("BT", true, P_0F, 0xBA, 4, true, OpAssertion.WordOrLargerAssertion);
596-
public static final AMD64MIOp BTR = new AMD64MIOp("BTR", true, P_0F, 0xBA, 6, true, OpAssertion.WordOrLargerAssertion);
597-
public static final AMD64MIOp MOVB = new AMD64MIOp("MOVB", true, 0xC6, 0, false, OpAssertion.ByteAssertion);
598-
public static final AMD64MIOp MOV = new AMD64MIOp("MOV", false, 0xC7, 0, false, OpAssertion.WordOrLargerAssertion);
599-
public static final AMD64MIOp SAR = new AMD64MIOp("SAR", true, 0xC1, 7, true, OpAssertion.WordOrLargerAssertion);
600-
public static final AMD64MIOp SHL = new AMD64MIOp("SHL", true, 0xC1, 4, true, OpAssertion.WordOrLargerAssertion);
601-
public static final AMD64MIOp SHR = new AMD64MIOp("SHR", true, 0xC1, 5, true, OpAssertion.WordOrLargerAssertion);
602-
public static final AMD64MIOp TEST = new AMD64MIOp("TEST", false, 0xF7, 0, true);
595+
public static final AMD64MIOp BT = new AMD64MIOp("BT", true, P_0F, 0xBA, 4, true, OpAssertion.WordOrLargerAssertion);
596+
public static final AMD64MIOp BTR = new AMD64MIOp("BTR", true, P_0F, 0xBA, 6, true, OpAssertion.WordOrLargerAssertion);
597+
public static final AMD64MIOp MOVB = new AMD64MIOp("MOVB", true, 0xC6, 0, false, OpAssertion.ByteAssertion);
598+
public static final AMD64MIOp MOV = new AMD64MIOp("MOV", false, 0xC7, 0, false, OpAssertion.WordOrLargerAssertion);
599+
public static final AMD64MIOp SAR = new AMD64MIOp("SAR", true, 0xC1, 7, true, OpAssertion.WordOrLargerAssertion);
600+
public static final AMD64MIOp SHL = new AMD64MIOp("SHL", true, 0xC1, 4, true, OpAssertion.WordOrLargerAssertion);
601+
public static final AMD64MIOp SHR = new AMD64MIOp("SHR", true, 0xC1, 5, true, OpAssertion.WordOrLargerAssertion);
602+
public static final AMD64MIOp TESTB = new AMD64MIOp("TEST", true, 0xF6, 0, true, OpAssertion.ByteAssertion);
603+
public static final AMD64MIOp TEST = new AMD64MIOp("TEST", false, 0xF7, 0, true, OpAssertion.WordOrLargerAssertion);
603604
// @formatter:on
604605

605606
private final int ext;

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64MacroAssembler.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -616,7 +616,8 @@ public int applyMOpAndJcc(AMD64MOp op, OperandSize size, Register dst, Condition
616616
}
617617

618618
public final int testAndJcc(OperandSize size, Register src, int imm32, ConditionFlag cc, Label branchTarget, boolean isShortJmp) {
619-
return applyMIOpAndJcc(AMD64MIOp.TEST, size, src, imm32, cc, branchTarget, isShortJmp, false, null);
619+
AMD64MIOp op = size == OperandSize.BYTE ? AMD64MIOp.TESTB : AMD64MIOp.TEST;
620+
return applyMIOpAndJcc(op, size, src, imm32, cc, branchTarget, isShortJmp, false, null);
620621
}
621622

622623
public final int testlAndJcc(Register src, int imm32, ConditionFlag cc, Label branchTarget, boolean isShortJmp) {
@@ -628,11 +629,13 @@ public final int testqAndJcc(Register src, int imm32, ConditionFlag cc, Label br
628629
}
629630

630631
public final int testAndJcc(OperandSize size, AMD64Address src, int imm32, ConditionFlag cc, Label branchTarget, boolean isShortJmp, IntConsumer applyBeforeFusedPair) {
631-
return applyMIOpAndJcc(AMD64MIOp.TEST, size, src, imm32, cc, branchTarget, isShortJmp, false, applyBeforeFusedPair);
632+
AMD64MIOp op = size == OperandSize.BYTE ? AMD64MIOp.TESTB : AMD64MIOp.TEST;
633+
return applyMIOpAndJcc(op, size, src, imm32, cc, branchTarget, isShortJmp, false, applyBeforeFusedPair);
632634
}
633635

634636
public final int testAndJcc(OperandSize size, Register src1, Register src2, ConditionFlag cc, Label branchTarget, boolean isShortJmp) {
635-
return applyRMOpAndJcc(AMD64RMOp.TEST, size, src1, src2, cc, branchTarget, isShortJmp);
637+
AMD64RMOp op = size == OperandSize.BYTE ? AMD64RMOp.TESTB : AMD64RMOp.TEST;
638+
return applyRMOpAndJcc(op, size, src1, src2, cc, branchTarget, isShortJmp);
636639
}
637640

638641
public final int testlAndJcc(Register src1, Register src2, ConditionFlag cc, Label branchTarget, boolean isShortJmp) {
@@ -644,11 +647,13 @@ public final int testqAndJcc(Register src1, Register src2, ConditionFlag cc, Lab
644647
}
645648

646649
public final int testAndJcc(OperandSize size, Register src1, AMD64Address src2, ConditionFlag cc, Label branchTarget, boolean isShortJmp) {
647-
return applyRMOpAndJcc(AMD64RMOp.TEST, size, src1, src2, cc, branchTarget, isShortJmp, null);
650+
AMD64RMOp op = size == OperandSize.BYTE ? AMD64RMOp.TESTB : AMD64RMOp.TEST;
651+
return applyRMOpAndJcc(op, size, src1, src2, cc, branchTarget, isShortJmp, null);
648652
}
649653

650654
public final int testAndJcc(OperandSize size, Register src1, AMD64Address src2, ConditionFlag cc, Label branchTarget, boolean isShortJmp, IntConsumer applyBeforeFusedPair) {
651-
return applyRMOpAndJcc(AMD64RMOp.TEST, size, src1, src2, cc, branchTarget, isShortJmp, applyBeforeFusedPair);
655+
AMD64RMOp op = size == OperandSize.BYTE ? AMD64RMOp.TESTB : AMD64RMOp.TEST;
656+
return applyRMOpAndJcc(op, size, src1, src2, cc, branchTarget, isShortJmp, applyBeforeFusedPair);
652657
}
653658

654659
public final int testbAndJcc(Register src1, Register src2, ConditionFlag cc, Label branchTarget, boolean isShortJmp) {

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64LIRGenerator.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -446,11 +446,22 @@ public void emitIntegerTestBranch(Value left, Value right, LabelRef trueDestinat
446446
} else {
447447
assert ((AMD64Kind) left.getPlatformKind()).isInteger();
448448
OperandSize size = left.getPlatformKind() == AMD64Kind.QWORD ? QWORD : DWORD;
449-
if (isJavaConstant(right) && NumUtil.is32bit(asJavaConstant(right).asLong())) {
450-
append(new TestConstBranchOp(size, asAllocatable(left), (int) asJavaConstant(right).asLong(), null, Condition.EQ, trueDestination, falseDestination, trueDestinationProbability));
451-
} else if (isJavaConstant(left) && NumUtil.is32bit(asJavaConstant(left).asLong())) {
452-
append(new TestConstBranchOp(size, asAllocatable(right), (int) asJavaConstant(left).asLong(), null, Condition.EQ, trueDestination, falseDestination, trueDestinationProbability));
453-
} else if (isAllocatableValue(right)) {
449+
if (isJavaConstant(left) || isJavaConstant(right)) {
450+
Value x = isJavaConstant(right) ? left : right;
451+
Value y = isJavaConstant(right) ? right : left;
452+
long con = asJavaConstant(y).asLong();
453+
if (NumUtil.isUByte(con)) {
454+
size = BYTE;
455+
} else if (NumUtil.isUInt(con)) {
456+
size = DWORD;
457+
}
458+
if (size != QWORD || NumUtil.isInt(con)) {
459+
append(new TestConstBranchOp(size, asAllocatable(x), (int) con, null, Condition.EQ, trueDestination, falseDestination, trueDestinationProbability));
460+
return;
461+
}
462+
}
463+
464+
if (isAllocatableValue(right)) {
454465
append(new TestBranchOp(size, asAllocatable(right), asAllocatable(left), null, Condition.EQ, trueDestination, falseDestination, trueDestinationProbability));
455466
} else {
456467
append(new TestBranchOp(size, asAllocatable(left), asAllocatable(right), null, Condition.EQ, trueDestination, falseDestination, trueDestinationProbability));
@@ -559,11 +570,23 @@ private void emitIntegerTest(Value a, Value b) {
559570
} else {
560571
assert ((AMD64Kind) a.getPlatformKind()).isInteger();
561572
OperandSize size = a.getPlatformKind() == AMD64Kind.QWORD ? QWORD : DWORD;
562-
if (isJavaConstant(b) && NumUtil.is32bit(asJavaConstant(b).asLong())) {
563-
append(new AMD64BinaryConsumer.ConstOp(AMD64MIOp.TEST, size, asAllocatable(a), (int) asJavaConstant(b).asLong()));
564-
} else if (isJavaConstant(a) && NumUtil.is32bit(asJavaConstant(a).asLong())) {
565-
append(new AMD64BinaryConsumer.ConstOp(AMD64MIOp.TEST, size, asAllocatable(b), (int) asJavaConstant(a).asLong()));
566-
} else if (isAllocatableValue(b)) {
573+
if (isJavaConstant(a) || isJavaConstant(b)) {
574+
Value x = isJavaConstant(b) ? a : b;
575+
Value y = isJavaConstant(b) ? b : a;
576+
long con = asJavaConstant(y).asLong();
577+
if (NumUtil.isUByte(con)) {
578+
size = BYTE;
579+
} else if (NumUtil.isUInt(con)) {
580+
size = DWORD;
581+
}
582+
if (size != QWORD || NumUtil.isInt(con)) {
583+
AMD64MIOp op = size == BYTE ? AMD64MIOp.TESTB : AMD64MIOp.TEST;
584+
append(new AMD64BinaryConsumer.ConstOp(op, size, asAllocatable(x), (int) con));
585+
return;
586+
}
587+
}
588+
589+
if (isAllocatableValue(b)) {
567590
append(new AMD64BinaryConsumer.Op(AMD64RMOp.TEST, size, asAllocatable(b), asAllocatable(a)));
568591
} else {
569592
append(new AMD64BinaryConsumer.Op(AMD64RMOp.TEST, size, asAllocatable(a), asAllocatable(b)));

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64NodeMatchRules.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -377,7 +377,7 @@ public ComplexMatchResult resetLowestSetBit(ValueNode a, ValueNode b) {
377377
@MatchRule("(If (IntegerTest value Constant=a))")
378378
public ComplexMatchResult testBitAndBranch(IfNode root, ValueNode value, ConstantNode a) {
379379
long constant = a.asJavaConstant().asLong();
380-
if (Long.bitCount(constant) == 1) {
380+
if (Long.bitCount(constant) == 1 && !NumUtil.isUByte(constant)) {
381381
return builder -> {
382382
LabelRef trueDestination = getLIRBlock(root.trueSuccessor());
383383
LabelRef falseDestination = getLIRBlock(root.falseSuccessor());

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64ControlFlow.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
import jdk.graal.compiler.asm.Label;
4040
import jdk.graal.compiler.asm.amd64.AMD64Address;
41+
import jdk.graal.compiler.asm.amd64.AMD64Assembler;
4142
import jdk.graal.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
4243
import jdk.graal.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
4344
import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler;
@@ -259,7 +260,6 @@ public static class TestConstBranchOp extends BranchOp implements StandardOp.Imp
259260

260261
public TestConstBranchOp(OperandSize size, Value x, int y, LIRFrameState state, Condition cond, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) {
261262
super(TYPE, intCond(cond), trueDestination, falseDestination, trueDestinationProbability);
262-
assert size == DWORD || size == QWORD : size;
263263
this.size = size;
264264

265265
assert x.getPlatformKind().getVectorLength() == 1 : Assertions.errorMessage(x);
@@ -340,7 +340,7 @@ public BitTestAndBranchOp(LabelRef trueDestination, LabelRef falseDestination, A
340340

341341
@Override
342342
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
343-
masm.btq(asRegister(value), index);
343+
AMD64Assembler.AMD64MIOp.BT.emit(masm, index < Integer.SIZE ? DWORD : QWORD, asRegister(value), index);
344344
super.emitCode(crb, masm);
345345
}
346346
}

0 commit comments

Comments
 (0)