From ce451e796d6712a2c954b47b2e1d09787394bba7 Mon Sep 17 00:00:00 2001 From: ZR74 <2401889661@qq.com> Date: Fri, 27 Mar 2026 09:13:47 +0800 Subject: [PATCH 1/2] perf(compiler): optimize EVM BYTE lowering --- .../evm_frontend/evm_mir_compiler.cpp | 138 +++++++++++------- 1 file changed, 87 insertions(+), 51 deletions(-) diff --git a/src/compiler/evm_frontend/evm_mir_compiler.cpp b/src/compiler/evm_frontend/evm_mir_compiler.cpp index cd98f29c..d6b38102 100644 --- a/src/compiler/evm_frontend/evm_mir_compiler.cpp +++ b/src/compiler/evm_frontend/evm_mir_compiler.cpp @@ -2737,68 +2737,104 @@ EVMMirBuilder::handleArithmeticRightShift(const U256Inst &Value, // (value >> (8 × (31 - index))) & 0xFF typename EVMMirBuilder::Operand EVMMirBuilder::handleByte(Operand IndexOp, Operand ValueOp) { - U256Inst IndexComponents = extractU256Operand(IndexOp); - U256Inst ValueComponents = extractU256Operand(ValueOp); - - // Check if index >= 32 (out of bounds) - MInstruction *IsOutOfBounds = isU256GreaterOrEqual(IndexComponents, 32); - MType *MirI64Type = EVMFrontendContext::getMIRTypeFromEVMType(EVMType::UINT64); + MInstruction *Zero = createIntConstInstruction(MirI64Type, 0); + MInstruction *ConstFF = createIntConstInstruction(MirI64Type, 0xFF); - // Calculate bit shift: (31 - index) * 8 - MInstruction *Const31 = createIntConstInstruction(MirI64Type, 31); - MInstruction *ByteIndex = createInstruction( - false, OP_sub, MirI64Type, Const31, IndexComponents[0]); - MInstruction *Const8 = createIntConstInstruction(MirI64Type, 8); - MInstruction *BitShift = createInstruction( - false, OP_mul, MirI64Type, ByteIndex, Const8); - - // Determine which 64-bit component contains the byte - MInstruction *Const64 = createIntConstInstruction(MirI64Type, 64); - MInstruction *ComponentIndex = createInstruction( - false, OP_udiv, MirI64Type, BitShift, Const64); + auto buildByteResult = [&](MInstruction *SelectedComponent, + MInstruction *BitOffset, + MInstruction *IsOutOfBounds = nullptr) { + MInstruction *ShiftedValue = createInstruction( + false, OP_ushr, MirI64Type, SelectedComponent, BitOffset); + MInstruction *ByteValue = createInstruction( + false, OP_and, MirI64Type, ShiftedValue, ConstFF); + MInstruction *Result = IsOutOfBounds + ? createInstruction( + false, MirI64Type, IsOutOfBounds, Zero, + ByteValue) + : ByteValue; + + U256Inst ResultComponents = {}; + ResultComponents[0] = protectUnsafeValue(Result, MirI64Type); + for (size_t I = 1; I < EVM_ELEMENTS_COUNT; ++I) { + ResultComponents[I] = Zero; + } + return Operand(ResultComponents, EVMType::UINT256); + }; - // Calculate the bit offset within the selected 64-bit component - MInstruction *BitOffset = createInstruction( - false, OP_urem, MirI64Type, BitShift, Const64); + if (IndexOp.isConstant() && ValueOp.isConstant()) { + const auto &IndexConst = IndexOp.getConstValue(); + if (IndexConst[1] != 0 || IndexConst[2] != 0 || IndexConst[3] != 0 || + IndexConst[0] >= 32) { + return Operand(U256Value{0, 0, 0, 0}); + } - // Select the appropriate 64-bit component based on component_index - // Example: bit_shift=248 → component_index=3 (248/64=3), bit_offset=56 - // This means target byte is in the highest component (comp3) at bit offset 56 - MInstruction *SelectedComponent = ValueComponents[0]; - for (size_t I = 1; I < EVM_ELEMENTS_COUNT; ++I) { - MInstruction *IsThisComponent = createInstruction( - false, CmpInstruction::Predicate::ICMP_EQ, &Ctx.I64Type, ComponentIndex, - createIntConstInstruction(MirI64Type, I)); - SelectedComponent = createInstruction( - false, MirI64Type, IsThisComponent, ValueComponents[I], - SelectedComponent); + uint64_t Index = IndexConst[0]; + size_t ComponentIndex = 3 - static_cast(Index >> 3); + uint64_t BitOffset = (7 - (Index & 7)) << 3; + uint64_t ByteValue = + (ValueOp.getConstValue()[ComponentIndex] >> BitOffset) & 0xFF; + return Operand(U256Value{ByteValue, 0, 0, 0}); } - // Extract the byte by shifting right and masking - // Shift the selected component right by bit_offset to move target byte to LSB - // Then mask with 0xFF to extract the lowest 8 bits - MInstruction *ShiftedValue = createInstruction( - false, OP_ushr, MirI64Type, SelectedComponent, BitOffset); - MInstruction *ConstFF = createIntConstInstruction(MirI64Type, 0xFF); - MInstruction *ByteValue = createInstruction( - false, OP_and, MirI64Type, ShiftedValue, ConstFF); + U256Inst ValueComponents = extractU256Operand(ValueOp); - MInstruction *Zero = createIntConstInstruction(MirI64Type, 0); - // Return 0 if out of bounds, otherwise return the extracted byte value - MInstruction *Result = createInstruction( - false, MirI64Type, IsOutOfBounds, Zero, ByteValue); + if (IndexOp.isConstant()) { + const auto &IndexConst = IndexOp.getConstValue(); + if (IndexConst[1] != 0 || IndexConst[2] != 0 || IndexConst[3] != 0 || + IndexConst[0] >= 32) { + return Operand(U256Value{0, 0, 0, 0}); + } - // Create U256 result with only the low component set - // High components are zeroed out as per EVM specification - U256Inst ResultComponents = {}; - ResultComponents[0] = protectUnsafeValue(Result, MirI64Type); - for (size_t I = 1; I < EVM_ELEMENTS_COUNT; ++I) { - ResultComponents[I] = Zero; + uint64_t Index = IndexConst[0]; + size_t ComponentIndex = 3 - static_cast(Index >> 3); + uint64_t BitOffset = (7 - (Index & 7)) << 3; + return buildByteResult( + ValueComponents[ComponentIndex], + createIntConstInstruction(MirI64Type, BitOffset)); } - return Operand(ResultComponents, EVMType::UINT256); + U256Inst IndexComponents = extractU256Operand(IndexOp); + + // Check if index >= 32 (out of bounds). + MInstruction *IsOutOfBounds = isU256GreaterOrEqual(IndexComponents, 32); + MInstruction *IndexLow = IndexComponents[0]; + MInstruction *Const1 = createIntConstInstruction(MirI64Type, 1); + MInstruction *Const2 = createIntConstInstruction(MirI64Type, 2); + MInstruction *Const3 = createIntConstInstruction(MirI64Type, 3); + MInstruction *Const7 = createIntConstInstruction(MirI64Type, 7); + + // Use byte-granular arithmetic directly: + // component_index = 3 - (index / 8) + // bit_offset = (7 - (index % 8)) * 8 + MInstruction *GroupIndex = createInstruction( + false, OP_ushr, MirI64Type, IndexLow, Const3); + MInstruction *ByteInGroup = createInstruction( + false, OP_and, MirI64Type, IndexLow, Const7); + MInstruction *ByteShiftInComponent = createInstruction( + false, OP_sub, MirI64Type, Const7, ByteInGroup); + MInstruction *BitOffset = createInstruction( + false, OP_shl, MirI64Type, ByteShiftInComponent, Const3); + + // Pick the source limb with a two-level select tree to shorten live ranges: + // [3,2] and [1,0] are selected independently, then merged. + MInstruction *GroupLowBit = createInstruction( + false, OP_and, MirI64Type, GroupIndex, Const1); + MInstruction *IsSecondInPair = createInstruction( + false, CmpInstruction::Predicate::ICMP_NE, &Ctx.I64Type, GroupLowBit, + Zero); + MInstruction *IsLowerPair = createInstruction( + false, CmpInstruction::Predicate::ICMP_UGE, &Ctx.I64Type, GroupIndex, + Const2); + MInstruction *UpperPair = createInstruction( + false, MirI64Type, IsSecondInPair, ValueComponents[2], ValueComponents[3]); + MInstruction *LowerPair = createInstruction( + false, MirI64Type, IsSecondInPair, ValueComponents[0], ValueComponents[1]); + MInstruction *SelectedComponent = createInstruction( + false, MirI64Type, IsLowerPair, LowerPair, UpperPair); + + return buildByteResult(SelectedComponent, BitOffset, IsOutOfBounds); } // EVM SIGNEXTEND opcode: sign-extends a signed integer from (index+1) bytes to From 5a09425ad51c33eb1ec7dd52220f39dd49ae4482 Mon Sep 17 00:00:00 2001 From: ZR74 <2401889661@qq.com> Date: Fri, 27 Mar 2026 12:42:26 +0800 Subject: [PATCH 2/2] style: format check --- .../evm_frontend/evm_mir_compiler.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/compiler/evm_frontend/evm_mir_compiler.cpp b/src/compiler/evm_frontend/evm_mir_compiler.cpp index d6b38102..5a2ce164 100644 --- a/src/compiler/evm_frontend/evm_mir_compiler.cpp +++ b/src/compiler/evm_frontend/evm_mir_compiler.cpp @@ -2749,11 +2749,10 @@ typename EVMMirBuilder::Operand EVMMirBuilder::handleByte(Operand IndexOp, false, OP_ushr, MirI64Type, SelectedComponent, BitOffset); MInstruction *ByteValue = createInstruction( false, OP_and, MirI64Type, ShiftedValue, ConstFF); - MInstruction *Result = IsOutOfBounds - ? createInstruction( - false, MirI64Type, IsOutOfBounds, Zero, - ByteValue) - : ByteValue; + MInstruction *Result = + IsOutOfBounds ? createInstruction( + false, MirI64Type, IsOutOfBounds, Zero, ByteValue) + : ByteValue; U256Inst ResultComponents = {}; ResultComponents[0] = protectUnsafeValue(Result, MirI64Type); @@ -2790,9 +2789,8 @@ typename EVMMirBuilder::Operand EVMMirBuilder::handleByte(Operand IndexOp, uint64_t Index = IndexConst[0]; size_t ComponentIndex = 3 - static_cast(Index >> 3); uint64_t BitOffset = (7 - (Index & 7)) << 3; - return buildByteResult( - ValueComponents[ComponentIndex], - createIntConstInstruction(MirI64Type, BitOffset)); + return buildByteResult(ValueComponents[ComponentIndex], + createIntConstInstruction(MirI64Type, BitOffset)); } U256Inst IndexComponents = extractU256Operand(IndexOp); @@ -2828,9 +2826,11 @@ typename EVMMirBuilder::Operand EVMMirBuilder::handleByte(Operand IndexOp, false, CmpInstruction::Predicate::ICMP_UGE, &Ctx.I64Type, GroupIndex, Const2); MInstruction *UpperPair = createInstruction( - false, MirI64Type, IsSecondInPair, ValueComponents[2], ValueComponents[3]); + false, MirI64Type, IsSecondInPair, ValueComponents[2], + ValueComponents[3]); MInstruction *LowerPair = createInstruction( - false, MirI64Type, IsSecondInPair, ValueComponents[0], ValueComponents[1]); + false, MirI64Type, IsSecondInPair, ValueComponents[0], + ValueComponents[1]); MInstruction *SelectedComponent = createInstruction( false, MirI64Type, IsLowerPair, LowerPair, UpperPair);