Skip to content
Closed
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
15 changes: 15 additions & 0 deletions llvm/lib/Transforms/Utils/SCCPSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,21 @@ bool SCCPSolver::tryToReplaceWithConstant(Value *V) {
Constant *Const = getConstantOrNull(V);
if (!Const)
return false;

// Don't replace noalias arg or derivatives
if (isa<PointerType>(V->getType())) {
SmallVector<const Value *, 4> Objects;
getUnderlyingObjects(V, Objects, nullptr);

for (const auto Obj : Objects) {
if (const auto *Arg = dyn_cast<Argument>(Obj)) {
if (isa<PointerType>(Arg->getType()) &&
Arg->hasNoAliasAttr())
return false;
}
}
}

// Replacing `musttail` instructions with constant breaks `musttail` invariant
// unless the call itself can be removed.
// Calls with "clang.arc.attachedcall" implicitly use the return value and
Expand Down
47 changes: 47 additions & 0 deletions llvm/test/Transforms/SCCP/ipsccp-noalias-check.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
; RUN: opt < %s -passes='ipsccp,inline' -S | FileCheck %s

; This test looks if the store from callee after inlining gets the alias.scope
; If IPSCCP ignores noalias %p ptr and replaces %add.ptr5's GEP %p with @arr,
; the store will not receive an alias.scope as noalias attribute is lost.
@arr = global [100 x i32] zeroinitializer, align 16

define void @caller(i32 noundef %c, i32 noundef %d) #0 {
; COM: Check that store has both !alias.scope and !noalias
; CHECK-LABEL: for.body.i:
; CHECK: store {{.*}}!alias.scope{{.*}}!noalias
entry:
%idx.ext = sext i32 %d to i64
%add.ptr = getelementptr inbounds i32, ptr @arr, i64 %idx.ext
%add.ptr4 = getelementptr inbounds i32, ptr %add.ptr, i64 %idx.ext
call void @callee(ptr noundef @arr, ptr noundef %add.ptr, ptr noundef %add.ptr4, i32 noundef %d)
ret void
}

define void @callee(ptr noalias noundef %p, ptr noalias noundef %q, ptr noalias noundef %r, i32 noundef %len) #1 align 2 {
Copy link
Contributor

@brunodf-snps brunodf-snps Aug 28, 2025

Choose a reason for hiding this comment

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

I think the function @callee in your test case needs to be "internal" before IPSCCP can transform it. (Also, the alignment on the function is redundant for the test.)

entry:
br label %for.cond
for.cond: ; preds = %for.body, %entry
%i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
%cmp = icmp slt i32 %i.0, %len
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%idx.ext = sext i32 %i.0 to i64
%add.ptr = getelementptr inbounds i32, ptr %q, i64 %idx.ext
%0 = load i32, ptr %add.ptr, align 4
%add.ptr3 = getelementptr inbounds i32, ptr %r, i64 %idx.ext
%1 = load i32, ptr %add.ptr3, align 4
%mul = mul nsw i32 %0, %1
%add = add nsw i32 %mul, %i.0
%add.ptr5 = getelementptr inbounds i32, ptr %p, i64 %idx.ext
store i32 %add, ptr %add.ptr5, align 4
%inc = add nsw i32 %i.0, 1
br label %for.cond

for.end: ; preds = %for.cond
ret void
}

attributes #0 = { mustprogress uwtable}
attributes #1 = { mustprogress nounwind uwtable }


Loading