Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EVM] Improvements #759

Open
wants to merge 42 commits into
base: ef-stackification
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
5023026
[EVM] Fix creation of bundles with terminators
PavelKopyl Nov 16, 2024
608ec16
[EVM] Fix ordering of ARGUMENT instructions
PavelKopyl Nov 15, 2024
6b6acb7
[EVM] Add split critical edges pass
PavelKopyl Nov 15, 2024
09bb760
[EVM] Re-enable inlining
PavelKopyl Nov 15, 2024
135a3ac
[EVM] Add backward propagation (BP) stackification
PavelKopyl Nov 15, 2024
96ed76f
Handle EVM::LINKERSYMBOL after rebasing on '[EVM] Add libraries support'
akiramenai Jan 27, 2025
7dcb3a4
[EVM] Support commutable operations in BP stackification algorithm
PavelKopyl Nov 15, 2024
b8a8976
[EVM] Remove FunctionInfo struct (#742)
vladimirradosavljevic Nov 27, 2024
3c63c6f
[EVM] Introduce pseudo jumps, call and ret instructions
vladimirradosavljevic Dec 4, 2024
4fa5e91
[EVM] Move generation of JUMPDEST to the AsmPrinter phase
vladimirradosavljevic Dec 5, 2024
e39a610
[EVM] Refactor EVMOptimizedCodeTransform
vladimirradosavljevic Dec 13, 2024
d2cd9a6
[EVM] Refactor EVMAssembly
vladimirradosavljevic Dec 13, 2024
21d3983
[EVM] Merge EVMOptimizedCodeTransform and EVMAssembly into one file
vladimirradosavljevic Dec 12, 2024
650fe8d
[EVM] Address comments
vladimirradosavljevic Dec 18, 2024
ae9699d
[EVM] Refactor EVMControlFlowGraph/EVMControlFlowGraphBuilder
PavelKopyl Dec 20, 2024
bcfffd1
[EVM] Replace std::containers/algorithms with the llvm's counterparts
PavelKopyl Dec 20, 2024
313b5f2
[EVM] Refactor EVMStackLayoutGenerator to use LLVM API more broadly
PavelKopyl Jan 16, 2025
026ee9a
[EVM][CMake] Fix unittests shared libs build
akiramenai Jan 13, 2025
2b78f15
[EVM] Refactor StackSlot std::variant -> LLVM style RTTI
akiramenai Jan 16, 2025
e6d46fb
[EVM] Update assert in EVMStackifyCodeEmitter::CodeEmitter::emitSymbol
vladimirradosavljevic Jan 28, 2025
73dcbf0
[SDAG] Read-only intrinsics must have WillReturn and !Throws attribut…
kalxr Aug 16, 2024
9edc16c
[EVM] Add pre-commit test for Update intrinsic attributes
vladimirradosavljevic Nov 6, 2024
63f1d86
[EVM] Update intrinsic attributes
vladimirradosavljevic Oct 31, 2024
3d02e31
Generalize EraVMAAResult and move it to the common part
vladimirradosavljevic Oct 31, 2024
b33c8f8
[EVM] Add pre-commit tests for Add implementation of AliasAnalysis
vladimirradosavljevic Nov 6, 2024
befcbdc
[EVM] Add implementation of AliasAnalysis
vladimirradosavljevic Oct 31, 2024
ecd0c2f
Generalize EraVMSHA3ConstFolding and move it to the common part
vladimirradosavljevic Nov 4, 2024
3687154
[EVM] Add pre-commit test for Add support for constant folding SHA3 c…
vladimirradosavljevic Nov 8, 2024
f74de10
[EVM] Add support for constant folding SHA3 calls
vladimirradosavljevic Nov 6, 2024
cf8d801
[EVM] Remove assert in EVMCodegenPrepare
vladimirradosavljevic Nov 6, 2024
a24684b
[EVM] Add pre-commit test for Don't avoid transformations to shift
vladimirradosavljevic Jan 17, 2025
e9c5785
[EVM] Don't avoid transformations to shift
vladimirradosavljevic Jan 17, 2025
0d9bbc7
[EVM] Add pre-commit test for Set that jumps are expensive
vladimirradosavljevic Jan 17, 2025
4a9cda2
[EVM] Set that jumps are expensive
vladimirradosavljevic Jan 17, 2025
acc82b5
[EVM] Add pre-commit test for Allow rematerialization of some of the …
vladimirradosavljevic Jan 17, 2025
6734faa
[EVM] Allow rematerialization of some of the context instructions
vladimirradosavljevic Jan 17, 2025
a328155
[TTI][RISCV] Unconditionally break critical edges to sink ADDI (#108889)
preames Nov 26, 2024
1a479ca
[EVM] Add pre-commit test for Enable MachineSink to break critical ed…
vladimirradosavljevic Jan 20, 2025
9a8fa98
[EVM] Enable MachineSink to break critical edges for cheap instructions
vladimirradosavljevic Jan 20, 2025
c9bd4ac
[EVM] Add pre-commit test for Implement reverseBranchCondition and ru…
vladimirradosavljevic Jan 28, 2025
c9bdf05
[EVM] Implement reverseBranchCondition and run BranchFolder pass afte…
vladimirradosavljevic Jan 22, 2025
8f52e95
[EVM] Remove MachineBlockPlacement run
vladimirradosavljevic Jan 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions llvm/include/llvm/Analysis/VMAliasAnalysis.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//===-- VMAliasAnalysis.h - VM alias analysis -------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This is the address space based alias analysis pass, that is shared between
// EraVM and EVM backends.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_ANALYSIS_VM_VMALIASANALYSIS_H
#define LLVM_ANALYSIS_VM_VMALIASANALYSIS_H

#include "llvm/Analysis/AliasAnalysis.h"

namespace llvm {

class DataLayout;
class MemoryLocation;

/// A simple AA result that uses address space info to answer queries.
class VMAAResult : public AAResultBase {
const DataLayout &DL;
SmallDenseSet<unsigned> StorageAS;
SmallDenseSet<unsigned> HeapAS;
unsigned MaxAS;

public:
explicit VMAAResult(const DataLayout &DL,
const SmallDenseSet<unsigned> &StorageAS,
const SmallDenseSet<unsigned> &HeapAS, unsigned MaxAS)
: DL(DL), StorageAS(StorageAS), HeapAS(HeapAS), MaxAS(MaxAS) {}

/// Handle invalidation events from the new pass manager.
///
/// By definition, this result is stateless and so remains valid.
bool invalidate(Function &, const PreservedAnalyses &,
FunctionAnalysisManager::Invalidator &) {
return false;
}

AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB,
AAQueryInfo &AAQI, const Instruction *I);
};
} // end namespace llvm

#endif // LLVM_ANALYSIS_VM_ERAVMALIASANALYSIS_H
6 changes: 6 additions & 0 deletions llvm/include/llvm/CodeGen/TargetInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ class TargetInstrInfo : public MCInstrInfo {
return false;
}

/// For a "cheap" instruction which doesn't enable additional sinking,
/// should MachineSink break a critical edge to sink it anyways?
virtual bool shouldBreakCriticalEdgeToSink(MachineInstr &MI) const {
return false;
}

protected:
/// For instructions with opcodes for which the M_REMATERIALIZABLE flag is
/// set, this hook lets the target specify whether the instruction is actually
Expand Down
90 changes: 45 additions & 45 deletions llvm/include/llvm/IR/IntrinsicsEVM.td
Original file line number Diff line number Diff line change
Expand Up @@ -25,134 +25,134 @@ let TargetPrefix = "evm" in {

// Arithmetical operations.
def int_evm_div
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem]>;
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_sdiv
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem]>;
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_mod
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem]>;
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_smod
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem]>;
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_shl
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem]>;
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_shr
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem]>;
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_sar
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem]>;
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_addmod
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty, llvm_i256_ty],
[IntrNoMem]>;
[IntrNoMem, IntrWillReturn]>;

def int_evm_mulmod
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty, llvm_i256_ty],
[IntrNoMem]>;
[IntrNoMem, IntrWillReturn]>;

def int_evm_exp
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem]>;
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_sha3
: Intrinsic<[llvm_i256_ty],
[LLVMQualPointerType<AS.HEAP>, llvm_i256_ty], [IntrReadMem]>;
[LLVMQualPointerType<AS.HEAP>, llvm_i256_ty], [IntrReadMem, IntrWillReturn]>;

def int_evm_signextend
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem]>;
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_byte
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty, llvm_i256_ty],
[IntrNoMem]>;
[IntrNoMem, IntrWillReturn]>;

// Memory operations.
def int_evm_mstore8
: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty], [IntrWriteMem]>;

// TODO: CPR-1555.
// Review system intrinsics attributes taking into account EraVM.
def int_evm_msize : Intrinsic<[llvm_i256_ty], [], []>;
def int_evm_msize : Intrinsic<[llvm_i256_ty], [], [IntrInaccessibleMemOnly, IntrWillReturn]>;

def int_evm_pc : Intrinsic<[llvm_i256_ty], [], []>;
def int_evm_pc : Intrinsic<[llvm_i256_ty], [], [IntrInaccessibleMemOnly, IntrWillReturn]>;

def int_evm_gas : Intrinsic<[llvm_i256_ty], [], []>;
def int_evm_gas : Intrinsic<[llvm_i256_ty], [], [IntrInaccessibleMemOnly, IntrWillReturn]>;


// Getting values from the context.
def int_evm_address : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_address : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_origin : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_origin : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_caller : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_caller : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_balance : Intrinsic<[llvm_i256_ty], [llvm_i256_ty], []>;
def int_evm_balance : Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrInaccessibleMemOnly, IntrWillReturn]>;

def int_evm_callvalue : Intrinsic<[llvm_i256_ty], [], []>;
def int_evm_callvalue : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_calldatasize : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_calldatasize : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_calldataload
: Intrinsic<[llvm_i256_ty], [LLVMQualPointerType<AS.CALL_DATA>], []>;

def int_evm_codesize : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_codesize : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

// TODO: Ensure the gasprice is fixed while a function execution.
def int_evm_gasprice : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_gasprice : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_extcodesize
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrNoMem]>;
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_extcodecopy
: Intrinsic<[], [llvm_i256_ty, LLVMQualPointerType<AS.HEAP>,
LLVMQualPointerType<AS.CODE>, llvm_i256_ty], [IntrWriteMem]>;

def int_evm_returndatasize : Intrinsic<[llvm_i256_ty], [], []>;
def int_evm_returndatasize : Intrinsic<[llvm_i256_ty], [], [IntrInaccessibleMemOnly, IntrWillReturn]>;

def int_evm_extcodehash
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrNoMem]>;
: Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_blockhash : Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrNoMem]>;
def int_evm_blockhash : Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_blobhash : Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrNoMem]>;
def int_evm_blobhash : Intrinsic<[llvm_i256_ty], [llvm_i256_ty], [IntrNoMem, IntrWillReturn]>;

def int_evm_coinbase : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_coinbase : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_timestamp : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_timestamp : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_number : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_number : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_difficulty : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_difficulty : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_gaslimit : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_gaslimit : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_chainid : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_chainid : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_selfbalance : Intrinsic<[llvm_i256_ty], [], []>;
def int_evm_selfbalance : Intrinsic<[llvm_i256_ty], [], [IntrInaccessibleMemOnly]>;

def int_evm_basefee : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_basefee : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

def int_evm_blobbasefee : Intrinsic<[llvm_i256_ty], [], [IntrNoMem]>;
def int_evm_blobbasefee : Intrinsic<[llvm_i256_ty], [], [IntrNoMem, IntrWillReturn]>;

// Logging.
def int_evm_log0
: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty], []>;
: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty], [IntrReadMem]>;

def int_evm_log1
: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty, llvm_i256_ty], []>;
: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty, llvm_i256_ty], [IntrReadMem]>;

def int_evm_log2
: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty, llvm_i256_ty,
llvm_i256_ty], []>;
llvm_i256_ty], [IntrReadMem]>;

def int_evm_log3
: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty, llvm_i256_ty,
llvm_i256_ty, llvm_i256_ty], []>;
llvm_i256_ty, llvm_i256_ty], [IntrReadMem]>;

def int_evm_log4
: Intrinsic<[], [LLVMQualPointerType<AS.HEAP>, llvm_i256_ty, llvm_i256_ty,
llvm_i256_ty, llvm_i256_ty, llvm_i256_ty], []>;
llvm_i256_ty, llvm_i256_ty, llvm_i256_ty], [IntrReadMem]>;

// System calls
def int_evm_create
Expand Down Expand Up @@ -252,14 +252,14 @@ def int_evm_memcpyas1as4
// passed in the metadata.
def int_evm_datasize : DefaultAttrsIntrinsic<
[llvm_i256_ty], [llvm_metadata_ty],
[IntrNoMem, IntrSpeculatable]
[IntrNoMem, IntrWillReturn, IntrSpeculatable]
>;

// Returns a code offset of the Yul object with the name
// passed in the metadata.
def int_evm_dataoffset : DefaultAttrsIntrinsic<
[llvm_i256_ty], [llvm_metadata_ty],
[IntrNoMem, IntrSpeculatable]
[IntrNoMem, IntrWillReturn, IntrSpeculatable]
>;


Expand Down
36 changes: 36 additions & 0 deletions llvm/include/llvm/Transforms/Scalar/SHA3ConstFolding.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===-- SHA3ConstFolding.h - Const fold calls to sha3 -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file provides the interface for the SHA3 const folding pass.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TRANSFORMS_SCALAR_SHA3CONSTFOLDING_H
#define LLVM_TRANSFORMS_SCALAR_SHA3CONSTFOLDING_H

#include "llvm/Analysis/AliasAnalysis.h"

namespace llvm {

class Function;
class AssumptionCache;
class MemorySSA;
class DominatorTree;
class TargetLibraryInfo;
class LoopInfo;
class Instruction;

bool runSHA3ConstFolding(
Function &F, AliasAnalysis &AA, AssumptionCache &AC, MemorySSA &MSSA,
DominatorTree &DT, const TargetLibraryInfo &TLI, const LoopInfo &LI,
const std::function<bool(const Instruction *)> &IsSha3Call,
unsigned HeapAS);

} // end namespace llvm

#endif // LLVM_TRANSFORMS_SCALAR_SHA3CONSTFOLDING_H
3 changes: 3 additions & 0 deletions llvm/lib/Analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ add_llvm_component_library(LLVMAnalysis
ValueTracking.cpp
VectorUtils.cpp
VFABIDemangling.cpp
# EraVM local begin
VMAliasAnalysis.cpp
# EraVM local end
${GeneratedMLSources}

ADDITIONAL_HEADER_DIRS
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/Analysis/MemoryLocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
// EraVM local begin
#include "llvm/IR/IntrinsicsEVM.h"
#include "llvm/TargetParser/Triple.h"
// EraVM local end
#include <optional>
Expand Down Expand Up @@ -190,6 +191,14 @@ MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
case Intrinsic::lifetime_end:
// it is okay to have lifetime intrinsic
break;
case Intrinsic::evm_sha3: {
assert((ArgIdx == 0) && "Invalid argument index for sha3");
const auto *LenCI = dyn_cast<ConstantInt>(Call->getArgOperand(1));
if (LenCI && LenCI->getValue().getActiveBits() <= 64)
return MemoryLocation(
Arg, LocationSize::precise(LenCI->getZExtValue()), AATags);
return MemoryLocation::getAfter(Arg, AATags);
}
default:
llvm_unreachable("Unexpected intrinsic for EraVM/EVM target");
break;
Expand Down
Loading