Index: llvm/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/lib/Transforms/IPO/Attributor.cpp +++ llvm/lib/Transforms/IPO/Attributor.cpp @@ -1526,6 +1526,12 @@ struct AANoAliasFloating final : AANoAliasImpl { AANoAliasFloating(const IRPosition &IRP) : AANoAliasImpl(IRP) {} + /// See AbstractAttribute::initialize(...). + void initialize(Attributor &A) override { + // TODO: It isn't sound to initialize as the same with `AANoAliasImpl` + // because `noalias` may not be valid in the current position. + } + /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A) override { // TODO: Implement this. @@ -1539,14 +1545,10 @@ }; /// NoAlias attribute for an argument. -struct AANoAliasArgument final : AANoAliasImpl { - AANoAliasArgument(const IRPosition &IRP) : AANoAliasImpl(IRP) {} - - /// See AbstractAttribute::updateImpl(...). - ChangeStatus updateImpl(Attributor &A) override { - // TODO: Implement this. - return indicatePessimisticFixpoint(); - } +struct AANoAliasArgument final + : AAArgumentFromCallSiteArguments { + AANoAliasArgument(const IRPosition &IRP) + : AAArgumentFromCallSiteArguments(IRP) {} /// See AbstractAttribute::trackStatistics() void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) } @@ -1555,6 +1557,12 @@ struct AANoAliasCallSiteArgument final : AANoAliasImpl { AANoAliasCallSiteArgument(const IRPosition &IRP) : AANoAliasImpl(IRP) {} + /// See AbstractAttribute::initialize(...). + void initialize(Attributor &A) override { + // TODO: It isn't sound to initialize as the same with `AANoAliasImpl` + // because `noalias` may not be valid in the current position. + } + /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A) override { // TODO: Implement this. @@ -2738,6 +2746,9 @@ // Every argument with pointer type might be marked nonnull. checkAndRegisterAA(ArgPos, *this, Whitelist); + // Every argument with pointer type might be marked noalias. + checkAndRegisterAA(ArgPos, *this, Whitelist); + // Every argument with pointer type might be marked dereferenceable. checkAndRegisterAA(ArgPos, *this, Whitelist); @@ -2803,6 +2814,10 @@ checkAndRegisterAA(CSArgPos, *this, Whitelist); + // Call site argument attribute "no-alias". + checkAndRegisterAA(CSArgPos, *this, + Whitelist); + // Call site argument attribute "dereferenceable". checkAndRegisterAA(CSArgPos, *this, Whitelist); Index: llvm/test/Transforms/FunctionAttrs/internal-noalias.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/FunctionAttrs/internal-noalias.ll @@ -0,0 +1,49 @@ +; RUN: opt -S -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=11 < %s | FileCheck %s + +define dso_local i32 @visible(i32* noalias %A, i32* noalias %B) #0 { +entry: + %call1 = call i32 @noalias_args(i32* %A, i32* %B) + %call2 = call i32 @noalias_args_argmem(i32* %A, i32* %B) + %add = add nsw i32 %call1, %call2 + ret i32 %add +} + +; FIXME: Should be something like this. +; define internal i32 @noalias_args(i32* nocapture readonly %A, i32* noalias nocapture readonly %B) +; CHECK: define internal i32 @noalias_args(i32* %A, i32* %B) + +define internal i32 @noalias_args(i32* %A, i32* %B) #0 { +entry: + %0 = load i32, i32* %A, align 4 + %1 = load i32, i32* %B, align 4 + %add = add nsw i32 %0, %1 + %call = call i32 @noalias_args_argmem(i32* %A, i32* %B) + %add2 = add nsw i32 %add, %call + ret i32 %add2 +} + + +; FIXME: Should be something like this. +; define internal i32 @noalias_args_argmem(i32* noalias nocapture readonly %A, i32* noalias nocapture readonly %B) +; CHECK: define internal i32 @noalias_args_argmem(i32* %A, i32* %B) +; +define internal i32 @noalias_args_argmem(i32* %A, i32* %B) #1 { +entry: + %0 = load i32, i32* %A, align 4 + %1 = load i32, i32* %B, align 4 + %add = add nsw i32 %0, %1 + ret i32 %add +} + +define dso_local i32 @visible_local(i32* %A) #0 { +entry: + %B = alloca i32, align 4 + store i32 5, i32* %B, align 4 + %call1 = call i32 @noalias_args(i32* %A, i32* nonnull %B) + %call2 = call i32 @noalias_args_argmem(i32* %A, i32* nonnull %B) + %add = add nsw i32 %call1, %call2 + ret i32 %add +} + +attributes #0 = { noinline nounwind uwtable willreturn } +attributes #1 = { argmemonly noinline nounwind uwtable willreturn} Index: llvm/test/Transforms/FunctionAttrs/noalias_returned.ll =================================================================== --- llvm/test/Transforms/FunctionAttrs/noalias_returned.ll +++ llvm/test/Transforms/FunctionAttrs/noalias_returned.ll @@ -138,3 +138,41 @@ 5: ; preds = %1, %4 ret i8* %2 } + +; TEST 9 +; Simple Argument Test +define internal void @test9(i8* %a, i8* %b) { +; FIXME: missing noalias +; CHECK: define internal void @test9(i8* %a, i8* %b) + ret void +} +define void @test9_helper(i8* %a, i8* %b) { + tail call void @test9(i8* noalias %a, i8* %b) + tail call void @test9(i8* noalias %b, i8* noalias %a) + ret void +} + + +; TEST 10 +; Simple CallSite Test + +declare void @test10_helper(i8* %a) +define void @test10(i8* noalias %a) { +; CHECK: define void @test10(i8* noalias %a) +; FIXME: missing noalias +; CHECK-NEXT: tail call void @test10_helper(i8* %a) + tail call void @test10_helper(i8* %a) + ret void +} + +; TEST 11 +; CallSite Test + +declare void @test11_helper(i8* %a, i8 *%b) +define void @test11(i8* noalias %a) { +; CHECK: define void @test11(i8* noalias %a) +; CHECK-NEXT: tail call void @test11_helper(i8* %a, i8* %a) + tail call void @test11_helper(i8* %a, i8* %a) + ret void +} +