Index: llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -428,7 +428,8 @@ void applyUniformRetValOpt(CallSiteInfo &CSInfo, StringRef FnName, uint64_t TheRetVal); bool tryUniformRetValOpt(MutableArrayRef TargetsForSlot, - CallSiteInfo &CSInfo); + CallSiteInfo &CSInfo, + WholeProgramDevirtResolution::ByArg *Res); void applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName, bool IsOne, Constant *UniqueMemberAddr); @@ -439,7 +440,8 @@ void applyVirtualConstProp(CallSiteInfo &CSInfo, StringRef FnName, Constant *Byte, Constant *Bit); bool tryVirtualConstProp(MutableArrayRef TargetsForSlot, - VTableSlotInfo &SlotInfo); + VTableSlotInfo &SlotInfo, + WholeProgramDevirtResolution *Res); void rebuildGlobal(VTableBits &B); @@ -727,10 +729,12 @@ Call.replaceAndErase( "uniform-ret-val", FnName, RemarksEnabled, ConstantInt::get(cast(Call.CS.getType()), TheRetVal)); + CSInfo.TypeCheckedLoadUsers.clear(); } bool DevirtModule::tryUniformRetValOpt( - MutableArrayRef TargetsForSlot, CallSiteInfo &CSInfo) { + MutableArrayRef TargetsForSlot, CallSiteInfo &CSInfo, + WholeProgramDevirtResolution::ByArg *Res) { // Uniform return value optimization. If all functions return the same // constant, replace all calls with that constant. uint64_t TheRetVal = TargetsForSlot[0].RetVal; @@ -738,6 +742,11 @@ if (Target.RetVal != TheRetVal) return false; + if (CSInfo.isExported()) { + Res->TheKind = WholeProgramDevirtResolution::ByArg::UniformRetVal; + Res->Info = TheRetVal; + } + applyUniformRetValOpt(CSInfo, TargetsForSlot[0].Fn->getName(), TheRetVal); if (RemarksEnabled) for (auto &&Target : TargetsForSlot) @@ -824,7 +833,7 @@ bool DevirtModule::tryVirtualConstProp( MutableArrayRef TargetsForSlot, - VTableSlotInfo &SlotInfo) { + VTableSlotInfo &SlotInfo, WholeProgramDevirtResolution *Res) { // This only works if the function returns an integer. auto RetType = dyn_cast(TargetsForSlot[0].Fn->getReturnType()); if (!RetType) @@ -856,7 +865,11 @@ if (!tryEvaluateFunctionsWithArgs(TargetsForSlot, CSByConstantArg.first)) continue; - if (tryUniformRetValOpt(TargetsForSlot, CSByConstantArg.second)) + WholeProgramDevirtResolution::ByArg *ResByArg = nullptr; + if (Res) + ResByArg = &Res->ResByArg[CSByConstantArg.first]; + + if (tryUniformRetValOpt(TargetsForSlot, CSByConstantArg.second, ResByArg)) continue; if (tryUniqueRetValOpt(BitWidth, TargetsForSlot, CSByConstantArg.second)) @@ -1175,7 +1188,7 @@ .WPDRes[S.first.ByteOffset]; if (!trySingleImplDevirt(TargetsForSlot, S.second, Res) && - tryVirtualConstProp(TargetsForSlot, S.second)) + tryVirtualConstProp(TargetsForSlot, S.second, Res)) DidVirtualConstProp = true; // Collect functions devirtualized at least for one call site for stats. Index: llvm/trunk/test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll =================================================================== --- llvm/trunk/test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll +++ llvm/trunk/test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll @@ -0,0 +1,36 @@ +; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -S -o - %s | FileCheck %s +; RUN: FileCheck --check-prefix=SUMMARY %s < %t + +; SUMMARY: - TypeTests: +; SUMMARY-NEXT: TypeTestAssumeVCalls: + +; SUMMARY: TypeIdMap: +; SUMMARY-NEXT: typeid4: +; SUMMARY-NEXT: TTRes: +; SUMMARY-NEXT: Kind: Unsat +; SUMMARY-NEXT: SizeM1BitWidth: 0 +; SUMMARY-NEXT: WPDRes: +; SUMMARY-NEXT: 0: +; SUMMARY-NEXT: Kind: Indir +; SUMMARY-NEXT: SingleImplName: '' +; SUMMARY-NEXT: ResByArg: +; SUMMARY-NEXT: 24,12: +; SUMMARY-NEXT: Kind: UniformRetVal +; SUMMARY-NEXT: Info: 36 + +; CHECK: @vt4a = constant i32 (i8*, i32, i32)* @vf4a +@vt4a = constant i32 (i8*, i32, i32)* @vf4a, !type !0 + +; CHECK: @vt4b = constant i32 (i8*, i32, i32)* @vf4b +@vt4b = constant i32 (i8*, i32, i32)* @vf4b, !type !0 + +define i32 @vf4a(i8*, i32 %x, i32 %y) { + %z = add i32 %x, %y + ret i32 %z +} + +define i32 @vf4b(i8*, i32 %x, i32 %y) { + ret i32 36 +} + +!0 = !{i32 0, !"typeid4"}