Index: llvm/lib/Passes/PassBuilder.cpp =================================================================== --- llvm/lib/Passes/PassBuilder.cpp +++ llvm/lib/Passes/PassBuilder.cpp @@ -693,7 +693,7 @@ } Expected parsePostOrderFunctionAttrsPassOptions(StringRef Params) { - return parseSinglePassOption(Params, "skip-non-recursive", + return parseSinglePassOption(Params, "skip-non-recursive-function-attrs", "PostOrderFunctionAttrs"); } Index: llvm/lib/Passes/PassRegistry.def =================================================================== --- llvm/lib/Passes/PassRegistry.def +++ llvm/lib/Passes/PassRegistry.def @@ -235,7 +235,7 @@ return PostOrderFunctionAttrsPass(SkipNonRecursive); }, parsePostOrderFunctionAttrsPassOptions, - "skip-non-recursive") + "skip-non-recursive-function-attrs") #undef CGSCC_PASS_WITH_PARAMS #ifndef FUNCTION_ANALYSIS Index: llvm/lib/Transforms/IPO/FunctionAttrs.cpp =================================================================== --- llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -1720,7 +1720,8 @@ template static SmallSet -deriveAttrsInPostOrder(ArrayRef Functions, AARGetterT &&AARGetter) { +deriveAttrsInPostOrder(ArrayRef Functions, AARGetterT &&AARGetter, + bool ArgAttrsOnly) { SCCNodesResult Nodes = createSCCNodeSet(Functions); // Bail if the SCC only contains optnone functions. @@ -1728,6 +1729,10 @@ return {}; SmallSet Changed; + if (ArgAttrsOnly) { + addArgumentAttrs(Nodes.SCCNodes, Changed); + return Changed; + } addArgumentReturnedAttrs(Nodes.SCCNodes, Changed); addMemoryAttrs(Nodes.SCCNodes, AARGetter, Changed); @@ -1762,10 +1767,13 @@ LazyCallGraph &CG, CGSCCUpdateResult &) { // Skip non-recursive functions if requested. + // Only infer argument attributes for non-recursive functions, because + // it can affect optimization behavior in conjunction with noalias. + bool ArgAttrsOnly = false; if (C.size() == 1 && SkipNonRecursive) { LazyCallGraph::Node &N = *C.begin(); if (!N->lookup(N)) - return PreservedAnalyses::all(); + ArgAttrsOnly = true; } FunctionAnalysisManager &FAM = @@ -1782,7 +1790,8 @@ Functions.push_back(&N.getFunction()); } - auto ChangedFunctions = deriveAttrsInPostOrder(Functions, AARGetter); + auto ChangedFunctions = + deriveAttrsInPostOrder(Functions, AARGetter, ArgAttrsOnly); if (ChangedFunctions.empty()) return PreservedAnalyses::all(); @@ -1818,7 +1827,7 @@ static_cast *>(this)->printPipeline( OS, MapClassName2PassName); if (SkipNonRecursive) - OS << ""; + OS << ""; } template Index: llvm/test/Other/new-pm-print-pipeline.ll =================================================================== --- llvm/test/Other/new-pm-print-pipeline.ll +++ llvm/test/Other/new-pm-print-pipeline.ll @@ -1,3 +1,4 @@ + ;; Test that the -print-pipeline-passes option correctly prints some explicitly specified pipelines. ; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='function(adce),function(adce)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-0 @@ -99,8 +100,8 @@ ; CHECK-28: function(instcombine,instcombine) ;; Test function-attrs -; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='cgscc(function-attrs)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-29 -; CHECK-29: cgscc(function-attrs) +; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='cgscc(function-attrs)' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-29 +; CHECK-29: cgscc(function-attrs) ;; Test cgscc -> function adaptor ; RUN: opt -disable-output -disable-verify -print-pipeline-passes -passes='cgscc(function(no-op-function))' < %s | FileCheck %s --match-full-lines --check-prefixes=CHECK-30 Index: llvm/test/Transforms/InstCombine/unused-nonnull.ll =================================================================== --- llvm/test/Transforms/InstCombine/unused-nonnull.ll +++ llvm/test/Transforms/InstCombine/unused-nonnull.ll @@ -9,7 +9,7 @@ define i32 @main(i32 %argc, ptr %argv) #0 { ; CHECK-LABEL: define {{[^@]+}}@main -; CHECK-SAME: (i32 [[ARGC:%.*]], ptr nocapture readnone [[ARGV:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +; CHECK-SAME: (i32 [[ARGC:%.*]], ptr nocapture readonly [[ARGV:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[ARGC]], 2 ; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[TMP0]], i32 0, i32 [[ARGC]] Index: llvm/test/Transforms/PhaseOrdering/early-arg-attrs-inference.ll =================================================================== --- llvm/test/Transforms/PhaseOrdering/early-arg-attrs-inference.ll +++ llvm/test/Transforms/PhaseOrdering/early-arg-attrs-inference.ll @@ -4,16 +4,13 @@ define i32 @f(ptr noalias %p, i32 %c) { ; CHECK-LABEL: define i32 @f ; CHECK-SAME: (ptr noalias nocapture readonly [[P:%.*]], i32 [[C:%.*]]) local_unnamed_addr { -; CHECK-NEXT: [[I:%.*]] = load i32, ptr [[P]], align 4 ; CHECK-NEXT: tail call void @g() ; CHECK-NEXT: tail call void @g() ; CHECK-NEXT: tail call void @g() ; CHECK-NEXT: tail call void @g() ; CHECK-NEXT: tail call void @g() ; CHECK-NEXT: tail call void @g() -; CHECK-NEXT: [[I2:%.*]] = load i32, ptr [[P]], align 4 -; CHECK-NEXT: [[R:%.*]] = sub i32 [[I]], [[I2]] -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: ret i32 0 ; %i = load i32, ptr %p call void @g()