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 22 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
22 commits
Select commit Hold shift + click to select a range
f306c40
[SDAG] Read-only intrinsics must have WillReturn and !Throws attribut…
kalxr Aug 16, 2024
64a80a4
[EVM] Add pre-commit test for Update intrinsic attributes
vladimirradosavljevic Nov 6, 2024
a67786e
[EVM] Update intrinsic attributes
vladimirradosavljevic Oct 31, 2024
bb6c791
Generalize EraVMAAResult and move it to the common part
vladimirradosavljevic Oct 31, 2024
9d199fd
[EVM] Add pre-commit tests for Add implementation of AliasAnalysis
vladimirradosavljevic Nov 6, 2024
f08cd89
[EVM] Add implementation of AliasAnalysis
vladimirradosavljevic Oct 31, 2024
bd9e879
Generalize EraVMSHA3ConstFolding and move it to the common part
vladimirradosavljevic Nov 4, 2024
beb1dc3
[EVM] Add pre-commit test for Add support for constant folding SHA3 c…
vladimirradosavljevic Nov 8, 2024
6d93783
[EVM] Add support for constant folding SHA3 calls
vladimirradosavljevic Nov 6, 2024
5cade09
[EVM] Remove assert in EVMCodegenPrepare
vladimirradosavljevic Nov 6, 2024
0d77fdb
[EVM] Add pre-commit test for Don't avoid transformations to shift
vladimirradosavljevic Jan 17, 2025
95784a2
[EVM] Don't avoid transformations to shift
vladimirradosavljevic Jan 17, 2025
8f56291
[EVM] Add pre-commit test for Set that jumps are expensive
vladimirradosavljevic Jan 17, 2025
1d1c9bc
[EVM] Set that jumps are expensive
vladimirradosavljevic Jan 17, 2025
ed88355
[EVM] Add pre-commit test for Allow rematerialization of some of the …
vladimirradosavljevic Jan 17, 2025
dd9b886
[EVM] Allow rematerialization of some of the context instructions
vladimirradosavljevic Jan 17, 2025
3757dc5
[TTI][RISCV] Unconditionally break critical edges to sink ADDI (#108889)
preames Nov 26, 2024
b356009
[EVM] Add pre-commit test for Enable MachineSink to break critical ed…
vladimirradosavljevic Jan 20, 2025
83f8bc7
[EVM] Enable MachineSink to break critical edges for cheap instructions
vladimirradosavljevic Jan 20, 2025
494fb41
[EVM] Add pre-commit test for Implement reverseBranchCondition and ru…
vladimirradosavljevic Jan 28, 2025
366f4ca
[EVM] Implement reverseBranchCondition and run BranchFolder pass afte…
vladimirradosavljevic Jan 22, 2025
c825686
[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