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 readonly etc on arguments in that case, 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(); 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/arg-attrs-affect-earlycse.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/PhaseOrdering/arg-attrs-affect-earlycse.ll @@ -0,0 +1,53 @@ +;RUN: opt < %s -O3 -memssa-check-limit=1 -disable-output -debug-only=early-cse 2>&1 | FileCheck %s + +; CHECK: EarlyCSE CSE LOAD + +; Function Attrs: convergent mustprogress norecurse nounwind +define protected amdgpu_kernel void @arg_attrs_affect_earlycse(ptr noalias %arg0) #0 { +bb0: + %alloca0 = alloca ptr, align 8 + %alloca1 = alloca ptr, align 8 + %alloca2 = alloca i32, align 4 + %alloca3 = alloca ptr, align 1 + store ptr %arg0, ptr %alloca0, align 8 + %load0 = load ptr, ptr %alloca0, align 8 + store ptr %load0, ptr %alloca1, align 8 + %add0 = add i64 0, 1 + %mul0 = mul i64 %add0, 8 + %load1 = load ptr, ptr %alloca1, align 8 + %getelementptr0 = getelementptr inbounds i64, ptr %load1, i64 1 + %load2 = load i64, ptr %getelementptr0, align 8 + %icmp0 = icmp ugt i64 %mul0, %load2 + %select = select i1 %icmp0, i1 false, i1 true + %zext = zext i1 %select to i8 + store i8 %zext, ptr %alloca3, align 1 + %udiv0 = udiv i32 undef, 8 + store i32 %udiv0, ptr %alloca2, align 4 + %load3 = load i32, ptr %alloca2, align 4 + %add1 = add i32 %load3, 14 + %icmp1 = icmp ult i32 %add1, 24 + br i1 %icmp1, label %bb1, label %bb2 + + bb1: + %load4 = load i8, ptr %alloca3, align 1 + %trunc0 = trunc i8 %load4 to i1 + %select0 = select i1 %trunc0, i1 true, i1 false + br label %bb2 + +bb2: + %phi0 = phi i1 [ false, %bb0 ], [ %select0, %bb1 ] + call void @snork(i1 zeroext %phi0) + %load5 = load ptr, ptr %alloca1, align 8 + %getelementptr1 = getelementptr inbounds i64, ptr %load5, i64 1 + %load6 = load i64, ptr %getelementptr1, align 8 + %icmp2 = icmp ult i64 0, %load6 + call void @snork(i1 zeroext %icmp2) + ret void +} + +define weak_odr hidden void @snork(i1 %arg) { +bb0: + ret void +} + +attributes #0 = { convergent mustprogress norecurse nounwind "target-features"="+wavefrontsize64"}