Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 18 additions & 1 deletion llvm/lib/Analysis/VMAliasAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ AliasResult VMAAResult::alias(const MemoryLocation &LocA,
return AAResultBase::alias(LocA, LocB, AAQI, I);

// Don't check unknown memory locations.
if (!LocA.Size.isPrecise() || !LocB.Size.isPrecise())
if (!LocA.Size.isPrecise() && !LocB.Size.isPrecise())
return AAResultBase::alias(LocA, LocB, AAQI, I);

// Only 256-bit keys are valid for storage.
Expand Down Expand Up @@ -166,6 +166,23 @@ AliasResult VMAAResult::alias(const MemoryLocation &LocA,
return AliasResult::PartialAlias;
}

// If one of the locations is imprecise, they don’t alias as long as
// the other location is precise and ends before the first one begins.
if (LocB.Size == LocationSize::afterPointer()) {
Copy link
Collaborator

@akiramenai akiramenai Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainability: I suggest to refactor that code (including DoesOverlap lambda). We have code duplication right below this if, and returning NoAlias, PartialAlias based on a predicate is also become a duplicate.

if (StartBVal.sge(StartAVal + LocA.Size.getValue()))
return AliasResult::NoAlias;
return AliasResult::PartialAlias;
}

if (LocA.Size == LocationSize::afterPointer()) {
if (StartAVal.sge(StartBVal + LocB.Size.getValue()))
return AliasResult::NoAlias;
return AliasResult::PartialAlias;
}

if (!LocA.Size.isPrecise() || !LocB.Size.isPrecise())
return AAResultBase::alias(LocA, LocB, AAQI, I);

auto DoesOverlap = [](const APInt &X, const APInt &XEnd, const APInt &Y) {
return Y.sge(X) && Y.slt(XEnd);
};
Expand Down
17 changes: 17 additions & 0 deletions llvm/test/CodeGen/EVM/aa-eval.ll
Original file line number Diff line number Diff line change
Expand Up @@ -471,3 +471,20 @@ define void @test_as1_alias_extcodecopy() {
call void @llvm.evm.extcodecopy(i256 0, ptr addrspace(1) null, ptr addrspace(4) null, i256 32)
ret void
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant


; CHECK-LABEL: Function: test_as1_alias_return_nonprecise
; CHECK: NoModRef: Ptr: i256* inttoptr (i256 32 to ptr addrspace(1)) <-> call void @llvm.evm.return
define void @test_as1_alias_return_nonprecise(i256 %size) noreturn {
store i256 1, ptr addrspace(1) inttoptr (i256 32 to ptr addrspace(1)), align 32
call void @llvm.evm.return(ptr addrspace(1) inttoptr (i256 128 to ptr addrspace(1)), i256 %size)
unreachable
}

; CHECK-LABEL: Function: test_as1_part_alias_return_nonprecise
; CHECK: Just Ref: Ptr: i256* inttoptr (i256 100 to ptr addrspace(1)) <-> call void @llvm.evm.return
define void @test_as1_part_alias_return_nonprecise(i256 %size) noreturn {
store i256 1, ptr addrspace(1) inttoptr (i256 100 to ptr addrspace(1)), align 32
call void @llvm.evm.return(ptr addrspace(1) inttoptr (i256 128 to ptr addrspace(1)), i256 %size)
unreachable
}
72 changes: 72 additions & 0 deletions llvm/test/CodeGen/EVM/evm-dse-non-precise-memloc.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -O3 -S < %s | FileCheck %s
target datalayout = "E-p:256:256-i256:256:256-S256-a:256:256"
target triple = "evm"

; This test verifies that the dead store to (i256 32 to ptr addrspace(1)) is eliminated.

declare i256 @llvm.evm.datasize(metadata) #0

declare i256 @llvm.evm.dataoffset(metadata) #0

declare i256 @llvm.evm.callvalue() #1

declare void @llvm.evm.return(ptr addrspace(1) readonly, i256) #2

declare void @llvm.evm.revert(ptr addrspace(1) readonly, i256) #3

declare void @llvm.memcpy.p1.p4.i256(ptr addrspace(1) noalias nocapture writeonly, ptr addrspace(4) noalias nocapture readonly, i256, i1 immarg) #4

define void @__entry() local_unnamed_addr #5 {
; CHECK-LABEL: define void @__entry(
; CHECK-SAME: ) local_unnamed_addr #[[ATTR5:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store i256 129, ptr addrspace(1) inttoptr (i256 100 to ptr addrspace(1)), align 64
; CHECK-NEXT: [[CALLVALUE:%.*]] = tail call i256 @llvm.evm.callvalue()
; CHECK-NEXT: [[IF_CONDITION_COMPARED_NOT:%.*]] = icmp eq i256 [[CALLVALUE]], 0
; CHECK-NEXT: br i1 [[IF_CONDITION_COMPARED_NOT]], label %[[IF_JOIN:.*]], label %[[IF_MAIN:.*]]
; CHECK: [[IF_MAIN]]:
; CHECK-NEXT: tail call void @llvm.evm.revert(ptr addrspace(1) noalias nocapture nofree noundef nonnull align 32 null, i256 32)
; CHECK-NEXT: unreachable
; CHECK: [[IF_JOIN]]:
; CHECK-NEXT: store i256 42, ptr addrspace(5) null, align 4294967296
; CHECK-NEXT: [[DATASIZE:%.*]] = tail call i256 @llvm.evm.datasize(metadata [[META0:![0-9]+]])
; CHECK-NEXT: [[DATAOFFSET:%.*]] = tail call i256 @llvm.evm.dataoffset(metadata [[META0]])
; CHECK-NEXT: [[CODECOPY_SOURCE_POINTER:%.*]] = inttoptr i256 [[DATAOFFSET]] to ptr addrspace(4)
; CHECK-NEXT: tail call void @llvm.memcpy.p1.p4.i256(ptr addrspace(1) nonnull align 128 inttoptr (i256 128 to ptr addrspace(1)), ptr addrspace(4) align 1 [[CODECOPY_SOURCE_POINTER]], i256 [[DATASIZE]], i1 false)
; CHECK-NEXT: tail call void @llvm.evm.return(ptr addrspace(1) noalias nocapture nofree noundef nonnull align 32 inttoptr (i256 128 to ptr addrspace(1)), i256 [[DATASIZE]])
; CHECK-NEXT: unreachable
;
entry:
; To be removed
store i256 128, ptr addrspace(1) inttoptr (i256 32 to ptr addrspace(1)), align 64
store i256 129, ptr addrspace(1) inttoptr (i256 100 to ptr addrspace(1)), align 64
%callvalue = tail call i256 @llvm.evm.callvalue()
%if_condition_compared.not = icmp eq i256 %callvalue, 0
br i1 %if_condition_compared.not, label %if_join, label %if_main

if_main:
tail call void @llvm.evm.revert(ptr addrspace(1) noalias nocapture nofree noundef nonnull align 32 null, i256 32)
unreachable

if_join:
store i256 42, ptr addrspace(5) null, align 4294967296
%datasize = tail call i256 @llvm.evm.datasize(metadata !0)
%dataoffset = tail call i256 @llvm.evm.dataoffset(metadata !0)
%codecopy_source_pointer = inttoptr i256 %dataoffset to ptr addrspace(4)
tail call void @llvm.memcpy.p1.p4.i256(ptr addrspace(1) nonnull align 128 inttoptr (i256 128 to ptr addrspace(1)), ptr addrspace(4) align 1 %codecopy_source_pointer, i256 %datasize, i1 false)
tail call void @llvm.evm.return(ptr addrspace(1) noalias nocapture nofree noundef nonnull align 32 inttoptr (i256 128 to ptr addrspace(1)), i256 %datasize)
unreachable
}

attributes #0 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) }
attributes #1 = { mustprogress nofree nosync nounwind willreturn memory(none) }
attributes #2 = { nofree noreturn nounwind memory(read) }
attributes #3 = { nofree noreturn nounwind memory(argmem: read) }
attributes #4 = { mustprogress nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #5 = { nofree noreturn nounwind null_pointer_is_valid memory(readwrite, inaccessiblemem: read) "evm-entry-function" }

!0 = !{!"Test_16_deployed"}
;.
; CHECK: [[META0]] = !{!"Test_16_deployed"}
;.
Loading