From dc60bc5f1ef19fc92b2dd9c92655bf5f282106dd Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 17 Dec 2023 17:51:46 +0100 Subject: [PATCH] JitArm64: Improve codegen in ANDI2R and friends The codegen for the functions themselves, not for the emitted code. This seems to save 32 bytes per function. We also get rid of the oddity we had before where ANDI2R would do masking for 32-bit operations but the other functions wouldn't. --- Source/Core/Common/Arm64Emitter.cpp | 67 +++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/Source/Core/Common/Arm64Emitter.cpp b/Source/Core/Common/Arm64Emitter.cpp index 7d7b9fc16f..6f4f42c027 100644 --- a/Source/Core/Common/Arm64Emitter.cpp +++ b/Source/Core/Common/Arm64Emitter.cpp @@ -4039,9 +4039,19 @@ void ARM64FloatEmitter::ABI_PopRegisters(BitSet32 registers, ARM64Reg tmp) void ARM64XEmitter::ANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { if (!Is64Bit(Rn)) - imm &= 0xFFFFFFFF; + { + // To handle 32-bit logical immediates, the very easiest thing is to repeat + // the input value twice to make a 64-bit word. The correct encoding of that + // as a logical immediate will also be the correct encoding of the 32-bit + // value. + // + // Doing this here instead of in the LogicalImm constructor makes it easier + // to check if the input is all ones. - if (imm != (Is64Bit(Rn) ? 0xFFFF'FFFF'FFFF'FFFF : 0xFFFF'FFFF)) + imm = (imm << 32) | (imm & 0xFFFFFFFF); + } + + if ((~imm) == 0) { // Do nothing } @@ -4049,7 +4059,7 @@ void ARM64XEmitter::ANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { MOVZ(Rd, 0); } - else if (const auto result = LogicalImm(imm, Is64Bit(Rn) ? GPRSize::B64 : GPRSize::B32)) + else if (const auto result = LogicalImm(imm, GPRSize::B64)) { AND(Rd, Rn, result); } @@ -4065,15 +4075,28 @@ void ARM64XEmitter::ANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) void ARM64XEmitter::ORRI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { + if (!Is64Bit(Rn)) + { + // To handle 32-bit logical immediates, the very easiest thing is to repeat + // the input value twice to make a 64-bit word. The correct encoding of that + // as a logical immediate will also be the correct encoding of the 32-bit + // value. + // + // Doing this here instead of in the LogicalImm constructor makes it easier + // to check if the input is all ones. + + imm = (imm << 32) | (imm & 0xFFFFFFFF); + } + if (imm == 0) { // Do nothing } - else if (imm == (Is64Bit(Rn) ? 0xFFFF'FFFF'FFFF'FFFF : 0xFFFF'FFFF)) + else if ((~imm) == 0) { MOVN(Rd, 0); } - else if (const auto result = LogicalImm(imm, Is64Bit(Rn) ? GPRSize::B64 : GPRSize::B32)) + else if (const auto result = LogicalImm(imm, GPRSize::B64)) { ORR(Rd, Rn, result); } @@ -4089,15 +4112,28 @@ void ARM64XEmitter::ORRI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) void ARM64XEmitter::EORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { + if (!Is64Bit(Rn)) + { + // To handle 32-bit logical immediates, the very easiest thing is to repeat + // the input value twice to make a 64-bit word. The correct encoding of that + // as a logical immediate will also be the correct encoding of the 32-bit + // value. + // + // Doing this here instead of in the LogicalImm constructor makes it easier + // to check if the input is all ones. + + imm = (imm << 32) | (imm & 0xFFFFFFFF); + } + if (imm == 0) { // Do nothing } - else if (imm == (Is64Bit(Rn) ? 0xFFFF'FFFF'FFFF'FFFF : 0xFFFF'FFFF)) + else if ((~imm) == 0) { MVN(Rd, Rn); } - else if (const auto result = LogicalImm(imm, Is64Bit(Rn) ? GPRSize::B64 : GPRSize::B32)) + else if (const auto result = LogicalImm(imm, GPRSize::B64)) { EOR(Rd, Rn, result); } @@ -4113,16 +4149,29 @@ void ARM64XEmitter::EORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) void ARM64XEmitter::ANDSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { + if (!Is64Bit(Rn)) + { + // To handle 32-bit logical immediates, the very easiest thing is to repeat + // the input value twice to make a 64-bit word. The correct encoding of that + // as a logical immediate will also be the correct encoding of the 32-bit + // value. + // + // Doing this here instead of in the LogicalImm constructor makes it easier + // to check if the input is all ones. + + imm = (imm << 32) | (imm & 0xFFFFFFFF); + } + if (imm == 0) { ANDS(Rd, Is64Bit(Rn) ? ARM64Reg::ZR : ARM64Reg::WZR, Is64Bit(Rn) ? ARM64Reg::ZR : ARM64Reg::WZR); } - else if (imm == (Is64Bit(Rn) ? 0xFFFF'FFFF'FFFF'FFFF : 0xFFFF'FFFF)) + else if ((~imm) == 0) { ANDS(Rd, Rn, Rn); } - else if (const auto result = LogicalImm(imm, Is64Bit(Rn) ? GPRSize::B64 : GPRSize::B32)) + else if (const auto result = LogicalImm(imm, GPRSize::B64)) { ANDS(Rd, Rn, result); }