Index: llvm/trunk/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/Attributor.cpp +++ llvm/trunk/lib/Transforms/IPO/Attributor.cpp @@ -807,10 +807,34 @@ STATS_DECLTRACK(UniqueReturnValue, FunctionReturn, "Number of function with unique return"); + // Callback to replace the uses of CB with the constant C. + auto ReplaceCallSiteUsersWith = [](CallBase &CB, Constant &C) { + if (CB.getNumUses() == 0) + return ChangeStatus::UNCHANGED; + CB.replaceAllUsesWith(&C); + return ChangeStatus::CHANGED; + }; + // If the assumed unique return value is an argument, annotate it. if (auto *UniqueRVArg = dyn_cast(UniqueRV.getValue())) { getIRPosition() = IRPosition::argument(*UniqueRVArg); - Changed = IRAttribute::manifest(A) | Changed; + Changed = IRAttribute::manifest(A); + } else if (auto *RVC = dyn_cast(UniqueRV.getValue())) { + // We can replace the returned value with the unique returned constant. + Value &AnchorValue = getAnchorValue(); + if (Function *F = dyn_cast(&AnchorValue)) { + for (const Use &U : F->uses()) + if (CallBase *CB = dyn_cast(U.getUser())) + if (CB->isCallee(&U)) + Changed = ReplaceCallSiteUsersWith(*CB, *RVC) | Changed; + } else { + assert(isa(AnchorValue) && + "Expcected a function or call base anchor!"); + Changed = ReplaceCallSiteUsersWith(cast(AnchorValue), *RVC); + } + if (Changed == ChangeStatus::CHANGED) + STATS_DECLTRACK(UniqueConstantReturnValue, FunctionReturn, + "Number of function returns replaced by constant return"); } return Changed; Index: llvm/trunk/test/Transforms/FunctionAttrs/nounwind.ll =================================================================== --- llvm/trunk/test/Transforms/FunctionAttrs/nounwind.ll +++ llvm/trunk/test/Transforms/FunctionAttrs/nounwind.ll @@ -92,6 +92,15 @@ ret i32 -1 } +define i32 @catch_thing_user() { +; ATTRIBUTOR: define i32 @catch_thing_user +; ATTRIBUTOR-NEXT: %catch_thing_call = call +; ATTRIBUTOR-NEXT: ret i32 -1 + %catch_thing_call = call i32 @catch_thing() + ret i32 %catch_thing_call +} + + declare i32 @__gxx_personality_v0(...) declare i8* @__cxa_begin_catch(i8*)