[llvm] r371584 - clang-misexpect: Profile Guided Validation of Performance Annotations in LLVM
Petr Hosek via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 10 18:09:17 PDT 2019
Author: phosek
Date: Tue Sep 10 18:09:16 2019
New Revision: 371584
URL: http://llvm.org/viewvc/llvm-project?rev=371584&view=rev
Log:
clang-misexpect: Profile Guided Validation of Performance Annotations in LLVM
This patch contains the basic functionality for reporting potentially
incorrect usage of __builtin_expect() by comparing the developer's
annotation against a collected PGO profile. A more detailed proposal and
discussion appears on the CFE-dev mailing list
(http://lists.llvm.org/pipermail/cfe-dev/2019-July/062971.html) and a
prototype of the initial frontend changes appear here in D65300
We revised the work in D65300 by moving the misexpect check into the
LLVM backend, and adding support for IR and sampling based profiles, in
addition to frontend instrumentation.
We add new misexpect metadata tags to those instructions directly
influenced by the llvm.expect intrinsic (branch, switch, and select)
when lowering the intrinsics. The misexpect metadata contains
information about the expected target of the intrinsic so that we can
check against the correct PGO counter when emitting diagnostics, and the
compiler's values for the LikelyBranchWeight and UnlikelyBranchWeight.
We use these branch weight values to determine when to emit the
diagnostic to the user.
A future patch should address the comment at the top of
LowerExpectIntrisic.cpp to hoist the LikelyBranchWeight and
UnlikelyBranchWeight values into a shared space that can be accessed
outside of the LowerExpectIntrinsic pass. Once that is done, the
misexpect metadata can be updated to be smaller.
In the long term, it is possible to reconstruct portions of the
misexpect metadata from the existing profile data. However, we have
avoided this to keep the code simple, and because some kind of metadata
tag will be required to identify which branch/switch/select instructions
are influenced by the use of llvm.expect
Patch By: paulkirth
Differential Revision: https://reviews.llvm.org/D66324
Added:
llvm/trunk/include/llvm/Transforms/Utils/MisExpect.h
llvm/trunk/lib/Transforms/Utils/MisExpect.cpp
llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-branch-correct.proftext
llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-branch.proftext
llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-switch-correct.proftext
llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-switch.proftext
llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-correct.ll
llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-stripped.ll
llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-unpredictable.ll
llvm/trunk/test/Transforms/PGOProfile/misexpect-branch.ll
llvm/trunk/test/Transforms/PGOProfile/misexpect-switch-default.ll
llvm/trunk/test/Transforms/PGOProfile/misexpect-switch.ll
Modified:
llvm/trunk/include/llvm/IR/DiagnosticInfo.h
llvm/trunk/include/llvm/IR/FixedMetadataKinds.def
llvm/trunk/include/llvm/IR/MDBuilder.h
llvm/trunk/lib/IR/DiagnosticInfo.cpp
llvm/trunk/lib/IR/MDBuilder.cpp
llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp
llvm/trunk/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
llvm/trunk/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp
llvm/trunk/lib/Transforms/Utils/CMakeLists.txt
llvm/trunk/test/ThinLTO/X86/lazyload_metadata.ll
llvm/trunk/test/Transforms/LowerExpectIntrinsic/basic.ll
Modified: llvm/trunk/include/llvm/IR/DiagnosticInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DiagnosticInfo.h?rev=371584&r1=371583&r2=371584&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/DiagnosticInfo.h (original)
+++ llvm/trunk/include/llvm/IR/DiagnosticInfo.h Tue Sep 10 18:09:16 2019
@@ -75,7 +75,8 @@ enum DiagnosticKind {
DK_MIRParser,
DK_PGOProfile,
DK_Unsupported,
- DK_FirstPluginKind
+ DK_FirstPluginKind,
+ DK_MisExpect
};
/// Get the next available kind ID for a plugin diagnostic.
@@ -1002,6 +1003,25 @@ public:
void print(DiagnosticPrinter &DP) const override;
};
+/// Diagnostic information for MisExpect analysis.
+class DiagnosticInfoMisExpect : public DiagnosticInfoWithLocationBase {
+public:
+ DiagnosticInfoMisExpect(const Instruction *Inst, Twine &Msg);
+
+ /// \see DiagnosticInfo::print.
+ void print(DiagnosticPrinter &DP) const override;
+
+ static bool classof(const DiagnosticInfo *DI) {
+ return DI->getKind() == DK_MisExpect;
+ }
+
+ const Twine &getMsg() const { return Msg; }
+
+private:
+ /// Message to report.
+ const Twine &Msg;
+};
+
} // end namespace llvm
#endif // LLVM_IR_DIAGNOSTICINFO_H
Modified: llvm/trunk/include/llvm/IR/FixedMetadataKinds.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/FixedMetadataKinds.def?rev=371584&r1=371583&r2=371584&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/FixedMetadataKinds.def (original)
+++ llvm/trunk/include/llvm/IR/FixedMetadataKinds.def Tue Sep 10 18:09:16 2019
@@ -39,3 +39,4 @@ LLVM_FIXED_MD_KIND(MD_irr_loop, "irr_loo
LLVM_FIXED_MD_KIND(MD_access_group, "llvm.access.group", 25)
LLVM_FIXED_MD_KIND(MD_callback, "callback", 26)
LLVM_FIXED_MD_KIND(MD_preserve_access_index, "llvm.preserve.access.index", 27)
+LLVM_FIXED_MD_KIND(MD_misexpect, "misexpect", 28)
Modified: llvm/trunk/include/llvm/IR/MDBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/MDBuilder.h?rev=371584&r1=371583&r2=371584&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/MDBuilder.h (original)
+++ llvm/trunk/include/llvm/IR/MDBuilder.h Tue Sep 10 18:09:16 2019
@@ -16,6 +16,7 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/Support/DataTypes.h"
#include <utility>
@@ -75,6 +76,10 @@ public:
/// Return metadata containing the section prefix for a function.
MDNode *createFunctionSectionPrefix(StringRef Prefix);
+ /// return metadata containing expected value
+ MDNode *createMisExpect(uint64_t Index, uint64_t LikelyWeight,
+ uint64_t UnlikelyWeight);
+
//===------------------------------------------------------------------===//
// Range metadata.
//===------------------------------------------------------------------===//
Added: llvm/trunk/include/llvm/Transforms/Utils/MisExpect.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/MisExpect.h?rev=371584&view=auto
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/MisExpect.h (added)
+++ llvm/trunk/include/llvm/Transforms/Utils/MisExpect.h Tue Sep 10 18:09:16 2019
@@ -0,0 +1,43 @@
+//===--- MisExpect.h - Check the use of llvm.expect with PGO data ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit warnings for potentially incorrect usage of the
+// llvm.expect intrinsic. This utility extracts the threshold values from
+// metadata associated with the instrumented Branch or Switch instruction. The
+// threshold values are then used to determine if a warning should be emmited.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+
+namespace llvm {
+namespace misexpect {
+
+/// verifyMisExpect - compares PGO counters to the thresholds used for
+/// llvm.expect and warns if the PGO counters are outside of the expected
+/// range.
+/// \param I The Instruction being checked
+/// \param Weights A vector of profile weights for each target block
+/// \param Ctx The current LLVM context
+void verifyMisExpect(llvm::Instruction *I,
+ const llvm::SmallVector<uint32_t, 4> &Weights,
+ llvm::LLVMContext &Ctx);
+
+/// checkClangInstrumentation - verify if llvm.expect matches PGO profile
+/// This function checks the frontend instrumentation in the backend when
+/// lowering llvm.expect intrinsics. It checks for existing metadata, and
+/// then validates the use of llvm.expect against the assigned branch weights.
+//
+/// \param I the Instruction being checked
+void checkFrontendInstrumentation(Instruction &I);
+
+} // namespace misexpect
+} // namespace llvm
Modified: llvm/trunk/lib/IR/DiagnosticInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DiagnosticInfo.cpp?rev=371584&r1=371583&r2=371584&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DiagnosticInfo.cpp (original)
+++ llvm/trunk/lib/IR/DiagnosticInfo.cpp Tue Sep 10 18:09:16 2019
@@ -370,5 +370,16 @@ std::string DiagnosticInfoOptimizationBa
return OS.str();
}
+DiagnosticInfoMisExpect::DiagnosticInfoMisExpect(const Instruction *Inst,
+ Twine &Msg)
+ : DiagnosticInfoWithLocationBase(DK_MisExpect, DS_Warning,
+ *Inst->getParent()->getParent(),
+ Inst->getDebugLoc()),
+ Msg(Msg) {}
+
+void DiagnosticInfoMisExpect::print(DiagnosticPrinter &DP) const {
+ DP << getLocationStr() << ": " << getMsg();
+}
+
void OptimizationRemarkAnalysisFPCommute::anchor() {}
void OptimizationRemarkAnalysisAliasing::anchor() {}
Modified: llvm/trunk/lib/IR/MDBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/MDBuilder.cpp?rev=371584&r1=371583&r2=371584&view=diff
==============================================================================
--- llvm/trunk/lib/IR/MDBuilder.cpp (original)
+++ llvm/trunk/lib/IR/MDBuilder.cpp Tue Sep 10 18:09:16 2019
@@ -309,3 +309,15 @@ MDNode *MDBuilder::createIrrLoopHeaderWe
};
return MDNode::get(Context, Vals);
}
+
+MDNode *MDBuilder::createMisExpect(uint64_t Index, uint64_t LikleyWeight,
+ uint64_t UnlikleyWeight) {
+ auto *IntType = Type::getInt64Ty(Context);
+ Metadata *Vals[] = {
+ createString("misexpect"),
+ createConstant(ConstantInt::get(IntType, Index)),
+ createConstant(ConstantInt::get(IntType, LikleyWeight)),
+ createConstant(ConstantInt::get(IntType, UnlikleyWeight)),
+ };
+ return MDNode::get(Context, Vals);
+}
Modified: llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp?rev=371584&r1=371583&r2=371584&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/SampleProfile.cpp Tue Sep 10 18:09:16 2019
@@ -72,6 +72,7 @@
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Utils/CallPromotionUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/MisExpect.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
@@ -1446,6 +1447,8 @@ void SampleProfileLoader::propagateWeigh
}
}
+ misexpect::verifyMisExpect(TI, Weights, TI->getContext());
+
uint64_t TempWeight;
// Only set weights if there is at least one non-zero weight.
// In any other case, let the analyzer set weights.
Modified: llvm/trunk/lib/Transforms/Instrumentation/PGOInstrumentation.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/PGOInstrumentation.cpp?rev=371584&r1=371583&r2=371584&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/PGOInstrumentation.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/PGOInstrumentation.cpp Tue Sep 10 18:09:16 2019
@@ -108,6 +108,7 @@
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/MisExpect.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
@@ -1776,6 +1777,9 @@ void llvm::setProfMetadata(Module *M, In
: Weights) {
dbgs() << W << " ";
} dbgs() << "\n";);
+
+ misexpect::verifyMisExpect(TI, Weights, TI->getContext());
+
TI->setMetadata(LLVMContext::MD_prof, MDB.createBranchWeights(Weights));
if (EmitBranchProbability) {
std::string BrCondStr = getBranchCondString(TI);
Modified: llvm/trunk/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp?rev=371584&r1=371583&r2=371584&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LowerExpectIntrinsic.cpp Tue Sep 10 18:09:16 2019
@@ -26,6 +26,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/MisExpect.h"
using namespace llvm;
@@ -71,15 +72,20 @@ static bool handleSwitchExpect(SwitchIns
unsigned n = SI.getNumCases(); // +1 for default case.
SmallVector<uint32_t, 16> Weights(n + 1, UnlikelyBranchWeight);
- if (Case == *SI.case_default())
- Weights[0] = LikelyBranchWeight;
- else
- Weights[Case.getCaseIndex() + 1] = LikelyBranchWeight;
+ uint64_t Index = (Case == *SI.case_default()) ? 0 : Case.getCaseIndex() + 1;
+ Weights[Index] = LikelyBranchWeight;
+
+ SI.setMetadata(
+ LLVMContext::MD_misexpect,
+ MDBuilder(CI->getContext())
+ .createMisExpect(Index, LikelyBranchWeight, UnlikelyBranchWeight));
+
+ SI.setCondition(ArgValue);
+ misexpect::checkFrontendInstrumentation(SI);
SI.setMetadata(LLVMContext::MD_prof,
MDBuilder(CI->getContext()).createBranchWeights(Weights));
- SI.setCondition(ArgValue);
return true;
}
@@ -280,19 +286,28 @@ template <class BrSelInst> static bool h
MDBuilder MDB(CI->getContext());
MDNode *Node;
+ MDNode *ExpNode;
if ((ExpectedValue->getZExtValue() == ValueComparedTo) ==
- (Predicate == CmpInst::ICMP_EQ))
+ (Predicate == CmpInst::ICMP_EQ)) {
Node = MDB.createBranchWeights(LikelyBranchWeight, UnlikelyBranchWeight);
- else
+ ExpNode = MDB.createMisExpect(0, LikelyBranchWeight, UnlikelyBranchWeight);
+ } else {
Node = MDB.createBranchWeights(UnlikelyBranchWeight, LikelyBranchWeight);
+ ExpNode = MDB.createMisExpect(1, LikelyBranchWeight, UnlikelyBranchWeight);
+ }
- BSI.setMetadata(LLVMContext::MD_prof, Node);
+ BSI.setMetadata(LLVMContext::MD_misexpect, ExpNode);
if (CmpI)
CmpI->setOperand(0, ArgValue);
else
BSI.setCondition(ArgValue);
+
+ misexpect::checkFrontendInstrumentation(BSI);
+
+ BSI.setMetadata(LLVMContext::MD_prof, Node);
+
return true;
}
Modified: llvm/trunk/lib/Transforms/Utils/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CMakeLists.txt?rev=371584&r1=371583&r2=371584&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/CMakeLists.txt (original)
+++ llvm/trunk/lib/Transforms/Utils/CMakeLists.txt Tue Sep 10 18:09:16 2019
@@ -40,6 +40,7 @@ add_llvm_library(LLVMTransformUtils
LowerSwitch.cpp
Mem2Reg.cpp
MetaRenamer.cpp
+ MisExpect.cpp
ModuleUtils.cpp
NameAnonGlobals.cpp
PredicateInfo.cpp
Added: llvm/trunk/lib/Transforms/Utils/MisExpect.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/MisExpect.cpp?rev=371584&view=auto
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/MisExpect.cpp (added)
+++ llvm/trunk/lib/Transforms/Utils/MisExpect.cpp Tue Sep 10 18:09:16 2019
@@ -0,0 +1,177 @@
+//===--- MisExpect.cpp - Check the use of llvm.expect with PGO data -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit warnings for potentially incorrect usage of the
+// llvm.expect intrinsic. This utility extracts the threshold values from
+// metadata associated with the instrumented Branch or Switch instruction. The
+// threshold values are then used to determine if a warning should be emmited.
+//
+// MisExpect metadata is generated when llvm.expect intrinsics are lowered see
+// LowerExpectIntrinsic.cpp
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/MisExpect.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Analysis/OptimizationRemarkEmitter.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/Support/BranchProbability.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/FormatVariadic.h"
+#include <cstdint>
+#include <functional>
+#include <numeric>
+
+#define DEBUG_TYPE "misexpect"
+
+using namespace llvm;
+using namespace misexpect;
+
+namespace llvm {
+
+// Command line option to enable/disable the warning when profile data suggests
+// a mismatch with the use of the llvm.expect intrinsic
+static cl::opt<bool> PGOWarnMisExpect(
+ "pgo-warn-misexpect", cl::init(false), cl::Hidden,
+ cl::desc("Use this option to turn on/off "
+ "warnings about incorrect usage of llvm.expect intrinsics."));
+
+} // namespace llvm
+
+namespace {
+
+Instruction *getOprndOrInst(Instruction *I) {
+ assert(I != nullptr && "MisExpect target Instruction cannot be nullptr");
+ Instruction *Ret = nullptr;
+ if (auto *B = dyn_cast<BranchInst>(I)) {
+ Ret = dyn_cast<Instruction>(B->getCondition());
+ }
+ // TODO: Find a way to resolve condition location for switches
+ // Using the condition of the switch seems to often resolve to an earlier
+ // point in the program, i.e. the calculation of the switch condition, rather
+ // than the switches location in the source code. Thus, we should use the
+ // instruction to get source code locations rather than the condition to
+ // improve diagnostic output, such as the caret. If the same problem exists
+ // for branch instructions, then we should remove this function and directly
+ // use the instruction
+ //
+ // else if (auto S = dyn_cast<SwitchInst>(I)) {
+ // Ret = I;
+ //}
+ return Ret ? Ret : I;
+}
+
+void emitMisexpectDiagnostic(Instruction *I, LLVMContext &Ctx,
+ uint64_t ProfCount, uint64_t TotalCount) {
+ double PercentageCorrect = (double)ProfCount / TotalCount;
+ auto PerString =
+ formatv("{0:P} ({1} / {2})", PercentageCorrect, ProfCount, TotalCount);
+ auto RemStr = formatv(
+ "Potential performance regression from use of the llvm.expect intrinsic: "
+ "Annotation was correct on {0} of profiled executions.",
+ PerString);
+ Twine Msg(PerString);
+ Instruction *Cond = getOprndOrInst(I);
+ if (PGOWarnMisExpect)
+ Ctx.diagnose(DiagnosticInfoMisExpect(Cond, Msg));
+ OptimizationRemarkEmitter ORE(I->getParent()->getParent());
+ ORE.emit(OptimizationRemark(DEBUG_TYPE, "misexpect", Cond) << RemStr.str());
+}
+
+} // namespace
+
+namespace llvm {
+namespace misexpect {
+
+void verifyMisExpect(Instruction *I, const SmallVector<uint32_t, 4> &Weights,
+ LLVMContext &Ctx) {
+ if (auto *MisExpectData = I->getMetadata(LLVMContext::MD_misexpect)) {
+ auto *MisExpectDataName = dyn_cast<MDString>(MisExpectData->getOperand(0));
+ if (MisExpectDataName &&
+ MisExpectDataName->getString().equals("misexpect")) {
+ LLVM_DEBUG(llvm::dbgs() << "------------------\n");
+ LLVM_DEBUG(llvm::dbgs()
+ << "Function: " << I->getFunction()->getName() << "\n");
+ LLVM_DEBUG(llvm::dbgs() << "Instruction: " << *I << ":\n");
+ LLVM_DEBUG(for (int Idx = 0, Size = Weights.size(); Idx < Size; ++Idx) {
+ llvm::dbgs() << "Weights[" << Idx << "] = " << Weights[Idx] << "\n";
+ });
+
+ // extract values from misexpect metadata
+ const auto *IndexCint =
+ mdconst::dyn_extract<ConstantInt>(MisExpectData->getOperand(1));
+ const auto *LikelyCInt =
+ mdconst::dyn_extract<ConstantInt>(MisExpectData->getOperand(2));
+ const auto *UnlikelyCInt =
+ mdconst::dyn_extract<ConstantInt>(MisExpectData->getOperand(3));
+
+ if (!IndexCint || !LikelyCInt || !UnlikelyCInt)
+ return;
+
+ const uint64_t Index = IndexCint->getZExtValue();
+ const uint64_t LikelyBranchWeight = LikelyCInt->getZExtValue();
+ const uint64_t UnlikelyBranchWeight = UnlikelyCInt->getZExtValue();
+ const uint64_t ProfileCount = Weights[Index];
+ const uint64_t CaseTotal = std::accumulate(
+ Weights.begin(), Weights.end(), (uint64_t)0, std::plus<uint64_t>());
+ const uint64_t NumUnlikelyTargets = Weights.size() - 1;
+
+ const uint64_t TotalBranchWeight =
+ LikelyBranchWeight + (UnlikelyBranchWeight * NumUnlikelyTargets);
+
+ const llvm::BranchProbability LikelyThreshold(LikelyBranchWeight,
+ TotalBranchWeight);
+ uint64_t ScaledThreshold = LikelyThreshold.scale(CaseTotal);
+
+ LLVM_DEBUG(llvm::dbgs()
+ << "Unlikely Targets: " << NumUnlikelyTargets << ":\n");
+ LLVM_DEBUG(llvm::dbgs() << "Profile Count: " << ProfileCount << ":\n");
+ LLVM_DEBUG(llvm::dbgs()
+ << "Scaled Threshold: " << ScaledThreshold << ":\n");
+ LLVM_DEBUG(llvm::dbgs() << "------------------\n");
+ if (ProfileCount < ScaledThreshold)
+ emitMisexpectDiagnostic(I, Ctx, ProfileCount, CaseTotal);
+ }
+ }
+}
+
+void checkFrontendInstrumentation(Instruction &I) {
+ if (auto *MD = I.getMetadata(LLVMContext::MD_prof)) {
+ unsigned NOps = MD->getNumOperands();
+
+ // Only emit misexpect diagnostics if at least 2 branch weights are present.
+ // Less than 2 branch weights means that the profiling metadata is:
+ // 1) incorrect/corrupted
+ // 2) not branch weight metadata
+ // 3) completely deterministic
+ // In these cases we should not emit any diagnostic related to misexpect.
+ if (NOps < 3)
+ return;
+
+ // Operand 0 is a string tag "branch_weights"
+ if (MDString *Tag = cast<MDString>(MD->getOperand(0))) {
+ if (Tag->getString().equals("branch_weights")) {
+ SmallVector<uint32_t, 4> RealWeights(NOps - 1);
+ for (unsigned i = 1; i < NOps; i++) {
+ ConstantInt *Value =
+ mdconst::dyn_extract<ConstantInt>(MD->getOperand(i));
+ RealWeights[i - 1] = Value->getZExtValue();
+ }
+ verifyMisExpect(&I, RealWeights, I.getContext());
+ }
+ }
+ }
+}
+
+} // namespace misexpect
+} // namespace llvm
+#undef DEBUG_TYPE
Modified: llvm/trunk/test/ThinLTO/X86/lazyload_metadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ThinLTO/X86/lazyload_metadata.ll?rev=371584&r1=371583&r2=371584&view=diff
==============================================================================
--- llvm/trunk/test/ThinLTO/X86/lazyload_metadata.ll (original)
+++ llvm/trunk/test/ThinLTO/X86/lazyload_metadata.ll Tue Sep 10 18:09:16 2019
@@ -10,13 +10,13 @@
; RUN: llvm-lto -thinlto-action=import %t2.bc -thinlto-index=%t3.bc \
; RUN: -o /dev/null -stats \
; RUN: 2>&1 | FileCheck %s -check-prefix=LAZY
-; LAZY: 61 bitcode-reader - Number of Metadata records loaded
+; LAZY: 63 bitcode-reader - Number of Metadata records loaded
; LAZY: 2 bitcode-reader - Number of MDStrings loaded
; RUN: llvm-lto -thinlto-action=import %t2.bc -thinlto-index=%t3.bc \
; RUN: -o /dev/null -disable-ondemand-mds-loading -stats \
; RUN: 2>&1 | FileCheck %s -check-prefix=NOTLAZY
-; NOTLAZY: 70 bitcode-reader - Number of Metadata records loaded
+; NOTLAZY: 72 bitcode-reader - Number of Metadata records loaded
; NOTLAZY: 7 bitcode-reader - Number of MDStrings loaded
Modified: llvm/trunk/test/Transforms/LowerExpectIntrinsic/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LowerExpectIntrinsic/basic.ll?rev=371584&r1=371583&r2=371584&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LowerExpectIntrinsic/basic.ll (original)
+++ llvm/trunk/test/Transforms/LowerExpectIntrinsic/basic.ll Tue Sep 10 18:09:16 2019
@@ -13,7 +13,7 @@ entry:
%conv1 = sext i32 %conv to i64
%expval = call i64 @llvm.expect.i64(i64 %conv1, i64 1)
%tobool = icmp ne i64 %expval, 0
-; CHECK: !prof !0
+; CHECK: !prof !0, !misexpect !1
; CHECK-NOT: @llvm.expect
br i1 %tobool, label %if.then, label %if.end
@@ -45,7 +45,7 @@ entry:
%conv = sext i32 %tmp to i64
%expval = call i64 @llvm.expect.i64(i64 %conv, i64 1)
%tobool = icmp ne i64 %expval, 0
-; CHECK: !prof !0
+; CHECK: !prof !0, !misexpect !1
; CHECK-NOT: @llvm.expect
br i1 %tobool, label %if.then, label %if.end
@@ -76,7 +76,7 @@ entry:
%conv = sext i32 %lnot.ext to i64
%expval = call i64 @llvm.expect.i64(i64 %conv, i64 1)
%tobool1 = icmp ne i64 %expval, 0
-; CHECK: !prof !0
+; CHECK: !prof !0, !misexpect !1
; CHECK-NOT: @llvm.expect
br i1 %tobool1, label %if.then, label %if.end
@@ -108,7 +108,7 @@ entry:
%conv = sext i32 %lnot.ext to i64
%expval = call i64 @llvm.expect.i64(i64 %conv, i64 1)
%tobool2 = icmp ne i64 %expval, 0
-; CHECK: !prof !0
+; CHECK: !prof !0, !misexpect !1
; CHECK-NOT: @llvm.expect
br i1 %tobool2, label %if.then, label %if.end
@@ -138,7 +138,7 @@ entry:
%conv1 = sext i32 %conv to i64
%expval = call i64 @llvm.expect.i64(i64 %conv1, i64 0)
%tobool = icmp ne i64 %expval, 0
-; CHECK: !prof !1
+; CHECK: !prof !2, !misexpect !3
; CHECK-NOT: @llvm.expect
br i1 %tobool, label %if.then, label %if.end
@@ -164,8 +164,8 @@ entry:
store i32 %x, i32* %x.addr, align 4
%tmp = load i32, i32* %x.addr, align 4
%conv = sext i32 %tmp to i64
- %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1)
-; CHECK: !prof !2
+ %expval = call i64 @llvm.expect.i64(i64 %conv, i64 2)
+; CHECK: !prof !4, !misexpect !5
; CHECK-NOT: @llvm.expect
switch i64 %expval, label %sw.epilog [
i64 1, label %sw.bb
@@ -194,7 +194,7 @@ entry:
%tmp = load i32, i32* %x.addr, align 4
%conv = sext i32 %tmp to i64
%expval = call i64 @llvm.expect.i64(i64 %conv, i64 1)
-; CHECK: !prof !3
+; CHECK: !prof !6, !misexpect !1
; CHECK-NOT: @llvm.expect
switch i64 %expval, label %sw.epilog [
i64 2, label %sw.bb
@@ -226,7 +226,7 @@ entry:
%conv = zext i1 %cmp to i32
%expval = call i32 @llvm.expect.i32(i32 %conv, i32 1)
%tobool = icmp ne i32 %expval, 0
-; CHECK: !prof !0
+; CHECK: !prof !0, !misexpect !1
; CHECK-NOT: @llvm.expect
br i1 %tobool, label %if.then, label %if.end
@@ -255,7 +255,7 @@ entry:
%tmp = load i32, i32* %x.addr, align 4
%cmp = icmp sgt i32 %tmp, 1
%expval = call i1 @llvm.expect.i1(i1 %cmp, i1 1)
-; CHECK: !prof !0
+; CHECK: !prof !0, !misexpect !1
; CHECK-NOT: @llvm.expect
br i1 %expval, label %if.then, label %if.end
@@ -278,7 +278,7 @@ define i32 @test10(i64 %t6) {
%t7 = call i64 @llvm.expect.i64(i64 %t6, i64 0)
%t8 = icmp ne i64 %t7, 0
%t9 = select i1 %t8, i32 1, i32 2
-; CHECK: select{{.*}}, !prof !1
+; CHECK: select{{.*}}, !prof !2, !misexpect !3
ret i32 %t9
}
@@ -286,6 +286,9 @@ define i32 @test10(i64 %t6) {
declare i1 @llvm.expect.i1(i1, i1) nounwind readnone
; CHECK: !0 = !{!"branch_weights", i32 2000, i32 1}
-; CHECK: !1 = !{!"branch_weights", i32 1, i32 2000}
-; CHECK: !2 = !{!"branch_weights", i32 1, i32 2000, i32 1}
-; CHECK: !3 = !{!"branch_weights", i32 2000, i32 1, i32 1}
+; CHECK: !1 = !{!"misexpect", i64 0, i64 2000, i64 1}
+; CHECK: !2 = !{!"branch_weights", i32 1, i32 2000}
+; CHECK: !3 = !{!"misexpect", i64 1, i64 2000, i64 1}
+; CHECK: !4 = !{!"branch_weights", i32 1, i32 1, i32 2000}
+; CHECK: !5 = !{!"misexpect", i64 2, i64 2000, i64 1}
+; CHECK: !6 = !{!"branch_weights", i32 2000, i32 1, i32 1}
Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-branch-correct.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-branch-correct.proftext?rev=371584&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-branch-correct.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-branch-correct.proftext Tue Sep 10 18:09:16 2019
@@ -0,0 +1,38 @@
+# IR level Instrumentation Flag
+:ir
+bar
+# Func Hash:
+29667547796
+# Num Counters:
+2
+# Counter Values:
+200000
+0
+
+baz
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+399668
+
+foo
+# Func Hash:
+29212902728
+# Num Counters:
+2
+# Counter Values:
+40803991
+1600332
+
+main
+# Func Hash:
+41605652536
+# Num Counters:
+3
+# Counter Values:
+2000000
+2000
+1
+
Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-branch.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-branch.proftext?rev=371584&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-branch.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-branch.proftext Tue Sep 10 18:09:16 2019
@@ -0,0 +1,38 @@
+# IR level Instrumentation Flag
+:ir
+bar
+# Func Hash:
+29667547796
+# Num Counters:
+2
+# Counter Values:
+399668
+1600332
+
+baz
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+399668
+
+foo
+# Func Hash:
+29212902728
+# Num Counters:
+2
+# Counter Values:
+40803991
+1600332
+
+main
+# Func Hash:
+41605652536
+# Num Counters:
+3
+# Counter Values:
+2000000
+2000
+1
+
Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-switch-correct.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-switch-correct.proftext?rev=371584&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-switch-correct.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-switch-correct.proftext Tue Sep 10 18:09:16 2019
@@ -0,0 +1,16 @@
+# IR level Instrumentation Flag
+:ir
+main
+# Func Hash:
+74054140268
+# Num Counters:
+7
+# Counter Values:
+0
+0
+20000
+0
+0
+1
+0
+
Added: llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-switch.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-switch.proftext?rev=371584&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-switch.proftext (added)
+++ llvm/trunk/test/Transforms/PGOProfile/Inputs/misexpect-switch.proftext Tue Sep 10 18:09:16 2019
@@ -0,0 +1,16 @@
+# IR level Instrumentation Flag
+:ir
+main
+# Func Hash:
+74054140268
+# Num Counters:
+7
+# Counter Values:
+3973
+3970
+0
+11889
+8111
+1
+0
+
Added: llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-correct.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-correct.ll?rev=371584&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-correct.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-correct.ll Tue Sep 10 18:09:16 2019
@@ -0,0 +1,94 @@
+; RUN: llvm-profdata merge %S/Inputs/misexpect-branch-correct.proftext -o %t.profdata
+
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pgo-warn-misexpect -pass-remarks=misexpect 2>&1 | FileCheck %s
+
+; New PM
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pgo-warn-misexpect -pass-remarks=misexpect -S 2>&1 | FileCheck %s
+
+; CHECK-NOT: warning: {{.*}}
+; CHECK-NOT: remark: {{.*}}
+; CHECK: !{!"misexpect", i64 1, i64 2000, i64 1}
+
+
+; ModuleID = 'misexpect-branch-correct.c'
+source_filename = "misexpect-branch-correct.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at inner_loop = constant i32 100, align 4
+ at outer_loop = constant i32 2000, align 4
+
+; Function Attrs: nounwind
+define i32 @bar() #0 {
+entry:
+ %rando = alloca i32, align 4
+ %x = alloca i32, align 4
+ %0 = bitcast i32* %rando to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) #4
+ %call = call i32 (...) @buzz()
+ store i32 %call, i32* %rando, align 4, !tbaa !3
+ %1 = bitcast i32* %x to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %1) #4
+ store i32 0, i32* %x, align 4, !tbaa !3
+ %2 = load i32, i32* %rando, align 4, !tbaa !3
+ %rem = srem i32 %2, 200000
+ %cmp = icmp eq i32 %rem, 0
+ %lnot = xor i1 %cmp, true
+ %lnot1 = xor i1 %lnot, true
+ %lnot.ext = zext i1 %lnot1 to i32
+ %conv = sext i32 %lnot.ext to i64
+ %expval = call i64 @llvm.expect.i64(i64 %conv, i64 0)
+ %tobool = icmp ne i64 %expval, 0
+ br i1 %tobool, label %if.then, label %if.else
+
+if.then: ; preds = %entry
+ %3 = load i32, i32* %rando, align 4, !tbaa !3
+ %call2 = call i32 @baz(i32 %3)
+ store i32 %call2, i32* %x, align 4, !tbaa !3
+ br label %if.end
+
+if.else: ; preds = %entry
+ %call3 = call i32 @foo(i32 50)
+ store i32 %call3, i32* %x, align 4, !tbaa !3
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ %4 = load i32, i32* %x, align 4, !tbaa !3
+ %5 = bitcast i32* %x to i8*
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %5) #4
+ %6 = bitcast i32* %rando to i8*
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %6) #4
+ ret i32 %4
+}
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+declare i32 @buzz(...) #2
+
+; Function Attrs: nounwind readnone willreturn
+declare i64 @llvm.expect.i64(i64, i64) #3
+
+declare i32 @baz(i32) #2
+
+declare i32 @foo(i32) #2
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind willreturn }
+attributes #2 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { nounwind readnone willreturn }
+attributes #4 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = !{i32 1, !"wchar_size", i32 4}
+!2 = !{!"clang version 10.0.0 (c20270bfffc9d6965219de339d66c61e9fe7d82d)"}
+!3 = !{!4, !4, i64 0}
+!4 = !{!"int", !5, i64 0}
+!5 = !{!"omnipotent char", !6, i64 0}
+!6 = !{!"Simple C/C++ TBAA"}
Added: llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-stripped.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-stripped.ll?rev=371584&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-stripped.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-stripped.ll Tue Sep 10 18:09:16 2019
@@ -0,0 +1,115 @@
+
+; RUN: llvm-profdata merge %S/Inputs/misexpect-branch.proftext -o %t.profdata
+
+
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pgo-warn-misexpect 2>&1 | FileCheck %s --check-prefix=WARNING
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pass-remarks=misexpect 2>&1 | FileCheck %s --check-prefix=REMARK
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pgo-warn-misexpect -pass-remarks=misexpect 2>&1 | FileCheck %s --check-prefix=BOTH
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s --check-prefix=DISABLED
+
+; New PM
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pgo-warn-misexpect -S 2>&1 | FileCheck %s --check-prefix=WARNING
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pass-remarks=misexpect -S 2>&1 | FileCheck %s --check-prefix=REMARK
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pgo-warn-misexpect -pass-remarks=misexpect -S 2>&1 | FileCheck %s --check-prefix=BOTH
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s --check-prefix=DISABLED
+
+
+
+; WARNING-DAG: warning: <unknown>:0:0: 19.98%
+; WARNING-NOT: remark: <unknown>:0:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 19.98% (399668 / 2000000) of profiled executions.
+
+; REMARK-NOT: warning: <unknown>:0:0: 19.98%
+; REMARK-DAG: remark: <unknown>:0:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 19.98% (399668 / 2000000) of profiled executions.
+
+; BOTH-DAG: warning: <unknown>:0:0: 19.98%
+; BOTH-DAG: remark: <unknown>:0:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 19.98% (399668 / 2000000) of profiled executions.
+
+; DISABLED-NOT: warning: <unknown>:0:0: 19.98%
+; DISABLED-NOT: remark: <unknown>:0:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 19.98% (399668 / 2000000) of profiled executions.
+
+; CHECK-DAG: !{!"misexpect", i64 1, i64 2000, i64 1}
+
+
+
+; ModuleID = 'misexpect-branch.c'
+source_filename = "misexpect-branch.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at inner_loop = constant i32 100, align 4
+ at outer_loop = constant i32 2000, align 4
+
+; Function Attrs: nounwind
+define i32 @bar() #0 {
+entry:
+ %rando = alloca i32, align 4
+ %x = alloca i32, align 4
+ %0 = bitcast i32* %rando to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) #4
+ %call = call i32 (...) @buzz()
+ store i32 %call, i32* %rando, align 4, !tbaa !3
+ %1 = bitcast i32* %x to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %1) #4
+ store i32 0, i32* %x, align 4, !tbaa !3
+ %2 = load i32, i32* %rando, align 4, !tbaa !3
+ %rem = srem i32 %2, 200000
+ %cmp = icmp eq i32 %rem, 0
+ %lnot = xor i1 %cmp, true
+ %lnot1 = xor i1 %lnot, true
+ %lnot.ext = zext i1 %lnot1 to i32
+ %conv = sext i32 %lnot.ext to i64
+ %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1)
+ %tobool = icmp ne i64 %expval, 0
+ br i1 %tobool, label %if.then, label %if.else
+
+if.then: ; preds = %entry
+ %3 = load i32, i32* %rando, align 4, !tbaa !3
+ %call2 = call i32 @baz(i32 %3)
+ store i32 %call2, i32* %x, align 4, !tbaa !3
+ br label %if.end
+
+if.else: ; preds = %entry
+ %call3 = call i32 @foo(i32 50)
+ store i32 %call3, i32* %x, align 4, !tbaa !3
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ %4 = load i32, i32* %x, align 4, !tbaa !3
+ %5 = bitcast i32* %x to i8*
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %5) #4
+ %6 = bitcast i32* %rando to i8*
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %6) #4
+ ret i32 %4
+}
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+declare i32 @buzz(...) #2
+
+; Function Attrs: nounwind readnone willreturn
+declare i64 @llvm.expect.i64(i64, i64) #3
+
+declare i32 @baz(i32) #2
+
+declare i32 @foo(i32) #2
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind willreturn }
+attributes #2 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { nounwind readnone willreturn }
+attributes #4 = { nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = !{i32 1, !"wchar_size", i32 4}
+!2 = !{!"clang version 10.0.0 (trunk c20270bfffc9d6965219de339d66c61e9fe7d82d)"}
+!3 = !{!4, !4, i64 0}
+!4 = !{!"int", !5, i64 0}
+!5 = !{!"omnipotent char", !6, i64 0}
+!6 = !{!"Simple C/C++ TBAA"}
Added: llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-unpredictable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-unpredictable.ll?rev=371584&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-unpredictable.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/misexpect-branch-unpredictable.ll Tue Sep 10 18:09:16 2019
@@ -0,0 +1,89 @@
+; RUN: llvm-profdata merge %S/Inputs/misexpect-branch-correct.proftext -o %t.profdata
+
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pgo-warn-misexpect -pass-remarks=misexpect 2>&1 | FileCheck %s
+
+; New PM
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pgo-warn-misexpect -pass-remarks=misexpect -S 2>&1 | FileCheck %s
+
+; CHECK-NOT: warning: {{.*}}
+; CHECK-NOT: remark: {{.*}}
+; CHECK-NOT: !"misexpect"
+
+
+; ModuleID = 'misexpect-branch-unpredictable.c'
+source_filename = "clang/test/Profile/misexpect-branch-unpredictable.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at inner_loop = constant i32 100, align 4
+ at outer_loop = constant i32 2000, align 4
+
+; Function Attrs: nounwind
+define i32 @bar() #0 {
+entry:
+ %rando = alloca i32, align 4
+ %x = alloca i32, align 4
+ %0 = bitcast i32* %rando to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) #3
+ %call = call i32 (...) @buzz()
+ store i32 %call, i32* %rando, align 4, !tbaa !2
+ %1 = bitcast i32* %x to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %1) #3
+ store i32 0, i32* %x, align 4, !tbaa !2
+ %2 = load i32, i32* %rando, align 4, !tbaa !2
+ %rem = srem i32 %2, 200000
+ %cmp = icmp eq i32 %rem, 0
+ %lnot = xor i1 %cmp, true
+ %lnot1 = xor i1 %lnot, true
+ %lnot.ext = zext i1 %lnot1 to i32
+ %conv = sext i32 %lnot.ext to i64
+ %tobool = icmp ne i64 %conv, 0
+ br i1 %tobool, label %if.then, label %if.else, !unpredictable !6
+
+if.then: ; preds = %entry
+ %3 = load i32, i32* %rando, align 4, !tbaa !2
+ %call2 = call i32 @baz(i32 %3)
+ store i32 %call2, i32* %x, align 4, !tbaa !2
+ br label %if.end
+
+if.else: ; preds = %entry
+ %call3 = call i32 @foo(i32 50)
+ store i32 %call3, i32* %x, align 4, !tbaa !2
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ %4 = load i32, i32* %x, align 4, !tbaa !2
+ %5 = bitcast i32* %x to i8*
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %5) #3
+ %6 = bitcast i32* %rando to i8*
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %6) #3
+ ret i32 %4
+}
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+declare i32 @buzz(...) #2
+
+declare i32 @baz(i32) #2
+
+declare i32 @foo(i32) #2
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind willreturn }
+attributes #2 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { nounwind }
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"Fuchsia clang version 10.0.0 (153b453014c94291c8c6cf6320b2f46df40f26f3) (based on LLVM 10.0.0svn)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C/C++ TBAA"}
+!6 = !{}
Added: llvm/trunk/test/Transforms/PGOProfile/misexpect-branch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/misexpect-branch.ll?rev=371584&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/misexpect-branch.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/misexpect-branch.ll Tue Sep 10 18:09:16 2019
@@ -0,0 +1,130 @@
+
+; RUN: llvm-profdata merge %S/Inputs/misexpect-branch.proftext -o %t.profdata
+
+
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pgo-warn-misexpect 2>&1 | FileCheck %s --check-prefix=WARNING
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pass-remarks=misexpect 2>&1 | FileCheck %s --check-prefix=REMARK
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pgo-warn-misexpect -pass-remarks=misexpect 2>&1 | FileCheck %s --check-prefix=BOTH
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s --check-prefix=DISABLED
+
+; New PM
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pgo-warn-misexpect -S 2>&1 | FileCheck %s --check-prefix=WARNING
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pass-remarks=misexpect -S 2>&1 | FileCheck %s --check-prefix=REMARK
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pgo-warn-misexpect -pass-remarks=misexpect -S 2>&1 | FileCheck %s --check-prefix=BOTH
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s --check-prefix=DISABLED
+
+
+
+; WARNING-DAG: warning: misexpect-branch.c:22:0: 19.98%
+; WARNING-NOT: remark: misexpect-branch.c:22:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 19.98% (399668 / 2000000) of profiled executions.
+
+; REMARK-NOT: warning: misexpect-branch.c:22:0: 19.98%
+; REMARK-DAG: remark: misexpect-branch.c:22:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 19.98% (399668 / 2000000) of profiled executions.
+
+; BOTH-DAG: warning: misexpect-branch.c:22:0: 19.98%
+; BOTH-DAG: remark: misexpect-branch.c:22:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 19.98% (399668 / 2000000) of profiled executions.
+
+; DISABLED-NOT: warning: misexpect-branch.c:22:0: 19.98%
+; DISABLED-NOT: remark: misexpect-branch.c:22:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 19.98% (399668 / 2000000) of profiled executions.
+
+; CHECK-DAG: !{!"misexpect", i64 1, i64 2000, i64 1}
+
+
+
+; ModuleID = 'misexpect-branch.c'
+source_filename = "misexpect-branch.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at inner_loop = constant i32 100, align 4
+ at outer_loop = constant i32 2000, align 4
+
+; Function Attrs: nounwind
+define i32 @bar() #0 !dbg !6 {
+entry:
+ %rando = alloca i32, align 4
+ %x = alloca i32, align 4
+ %0 = bitcast i32* %rando to i8*, !dbg !9
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) #4, !dbg !9
+ %call = call i32 (...) @buzz(), !dbg !9
+ store i32 %call, i32* %rando, align 4, !dbg !9, !tbaa !10
+ %1 = bitcast i32* %x to i8*, !dbg !14
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %1) #4, !dbg !14
+ store i32 0, i32* %x, align 4, !dbg !14, !tbaa !10
+ %2 = load i32, i32* %rando, align 4, !dbg !15, !tbaa !10
+ %rem = srem i32 %2, 200000, !dbg !15
+ %cmp = icmp eq i32 %rem, 0, !dbg !15
+ %lnot = xor i1 %cmp, true, !dbg !15
+ %lnot1 = xor i1 %lnot, true, !dbg !15
+ %lnot.ext = zext i1 %lnot1 to i32, !dbg !15
+ %conv = sext i32 %lnot.ext to i64, !dbg !15
+ %expval = call i64 @llvm.expect.i64(i64 %conv, i64 1), !dbg !15
+ %tobool = icmp ne i64 %expval, 0, !dbg !15
+ br i1 %tobool, label %if.then, label %if.else, !dbg !15
+
+if.then: ; preds = %entry
+ %3 = load i32, i32* %rando, align 4, !dbg !16, !tbaa !10
+ %call2 = call i32 @baz(i32 %3), !dbg !16
+ store i32 %call2, i32* %x, align 4, !dbg !16, !tbaa !10
+ br label %if.end, !dbg !17
+
+if.else: ; preds = %entry
+ %call3 = call i32 @foo(i32 50), !dbg !18
+ store i32 %call3, i32* %x, align 4, !dbg !18, !tbaa !10
+ br label %if.end
+
+if.end: ; preds = %if.else, %if.then
+ %4 = load i32, i32* %x, align 4, !dbg !19, !tbaa !10
+ %5 = bitcast i32* %x to i8*, !dbg !20
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %5) #4, !dbg !20
+ %6 = bitcast i32* %rando to i8*, !dbg !20
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %6) #4, !dbg !20
+ ret i32 %4, !dbg !19
+}
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+declare i32 @buzz(...) #2
+
+; Function Attrs: nounwind readnone willreturn
+declare i64 @llvm.expect.i64(i64, i64) #3
+
+declare i32 @baz(i32) #2
+
+declare i32 @foo(i32) #2
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind willreturn }
+attributes #2 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #3 = { nounwind readnone willreturn }
+attributes #4 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+!llvm.ident = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk c20270bfffc9d6965219de339d66c61e9fe7d82d)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "<stdin>", directory: ".")
+!2 = !{}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{!"clang version 10.0.0 (trunk c20270bfffc9d6965219de339d66c61e9fe7d82d)"}
+!6 = distinct !DISubprogram(name: "bar", scope: !7, file: !7, line: 19, type: !8, scopeLine: 19, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
+!7 = !DIFile(filename: "misexpect-branch.c", directory: ".")
+!8 = !DISubroutineType(types: !2)
+!9 = !DILocation(line: 20, scope: !6)
+!10 = !{!11, !11, i64 0}
+!11 = !{!"int", !12, i64 0}
+!12 = !{!"omnipotent char", !13, i64 0}
+!13 = !{!"Simple C/C++ TBAA"}
+!14 = !DILocation(line: 21, scope: !6)
+!15 = !DILocation(line: 22, scope: !6)
+!16 = !DILocation(line: 23, scope: !6)
+!17 = !DILocation(line: 24, scope: !6)
+!18 = !DILocation(line: 25, scope: !6)
+!19 = !DILocation(line: 27, scope: !6)
+!20 = !DILocation(line: 28, scope: !6)
Added: llvm/trunk/test/Transforms/PGOProfile/misexpect-switch-default.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/misexpect-switch-default.ll?rev=371584&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/misexpect-switch-default.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/misexpect-switch-default.ll Tue Sep 10 18:09:16 2019
@@ -0,0 +1,196 @@
+
+; RUN: llvm-profdata merge %S/Inputs/misexpect-switch.proftext -o %t.profdata
+
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pgo-warn-misexpect 2>&1 | FileCheck %s --check-prefix=WARNING
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pass-remarks=misexpect 2>&1 | FileCheck %s --check-prefix=REMARK
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pgo-warn-misexpect -pass-remarks=misexpect 2>&1 | FileCheck %s --check-prefix=BOTH
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s --check-prefix=DISABLED
+
+; New PM
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pgo-warn-misexpect -S 2>&1 | FileCheck %s --check-prefix=WARNING
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pass-remarks=misexpect -S 2>&1 | FileCheck %s --check-prefix=REMARK
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pgo-warn-misexpect -pass-remarks=misexpect -S 2>&1 | FileCheck %s --check-prefix=BOTH
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s --check-prefix=DISABLED
+
+; WARNING-DAG: warning: <unknown>:0:0: 0.00%
+; WARNING-NOT: remark: <unknown>:0:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 0.00% (0 / 27943) of profiled executions.
+
+; REMARK-NOT: warning: <unknown>:0:0: 0.00%
+; REMARK-DAG: remark: <unknown>:0:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 0.00% (0 / 27943) of profiled executions.
+
+; BOTH-DAG: warning: <unknown>:0:0: 0.00%
+; BOTH-DAG: remark: <unknown>:0:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 0.00% (0 / 27943) of profiled executions.
+
+; DISABLED-NOT: warning: <unknown>:0:0: 0.00%
+; DISABLED-NOT: remark: <unknown>:0:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 0.00% (0 / 27943) of profiled executions.
+
+; DISABLED-NOT: warning: <unknown>:0:0: 0.00%
+; DISABLED-NOT: remark: <unknown>:0:0: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 0.00% (0 / 27943) of profiled executions.
+
+; CORRECT-NOT: warning: {{.*}}
+; CORRECT-NOT: remark: {{.*}}
+; CHECK-DAG: !{!"misexpect", i64 0, i64 2000, i64 1}
+
+
+
+; ModuleID = 'misexpect-switch.c'
+source_filename = "misexpect-switch.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at inner_loop = dso_local constant i32 1000, align 4
+ at outer_loop = dso_local constant i32 20, align 4
+ at arry_size = dso_local constant i32 25, align 4
+ at arry = dso_local global [25 x i32] zeroinitializer, align 16
+
+; Function Attrs: nounwind uwtable
+define dso_local void @init_arry() #0 {
+entry:
+ %i = alloca i32, align 4
+ %0 = bitcast i32* %i to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) #6
+ store i32 0, i32* %i, align 4, !tbaa !4
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %1 = load i32, i32* %i, align 4, !tbaa !4
+ %cmp = icmp slt i32 %1, 25
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %call = call i32 @rand() #6
+ %rem = srem i32 %call, 10
+ %2 = load i32, i32* %i, align 4, !tbaa !4
+ %idxprom = sext i32 %2 to i64
+ %arrayidx = getelementptr inbounds [25 x i32], [25 x i32]* @arry, i64 0, i64 %idxprom
+ store i32 %rem, i32* %arrayidx, align 4, !tbaa !4
+ br label %for.inc
+
+for.inc: ; preds = %for.body
+ %3 = load i32, i32* %i, align 4, !tbaa !4
+ %inc = add nsw i32 %3, 1
+ store i32 %inc, i32* %i, align 4, !tbaa !4
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ %4 = bitcast i32* %i to i8*
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %4) #6
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #2
+
+; Function Attrs: nounwind
+declare dso_local i32 @rand() #3
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind uwtable
+define dso_local i32 @main() #0 {
+entry:
+ %retval = alloca i32, align 4
+ %val = alloca i32, align 4
+ %j = alloca i32, align 4
+ %condition = alloca i32, align 4
+ store i32 0, i32* %retval, align 4
+ call void @init_arry()
+ %0 = bitcast i32* %val to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) #6
+ store i32 0, i32* %val, align 4, !tbaa !4
+ %1 = bitcast i32* %j to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %1) #6
+ store i32 0, i32* %j, align 4, !tbaa !4
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %2 = load i32, i32* %j, align 4, !tbaa !4
+ %cmp = icmp slt i32 %2, 20000
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %3 = bitcast i32* %condition to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %3) #6
+ %call = call i32 @rand() #6
+ %rem = srem i32 %call, 5
+ store i32 %rem, i32* %condition, align 4, !tbaa !4
+ %4 = load i32, i32* %condition, align 4, !tbaa !4
+ %conv = zext i32 %4 to i64
+ %expval = call i64 @llvm.expect.i64(i64 %conv, i64 6)
+ switch i64 %expval, label %sw.default [
+ i64 0, label %sw.bb
+ i64 1, label %sw.bb2
+ i64 2, label %sw.bb2
+ i64 3, label %sw.bb2
+ i64 4, label %sw.bb3
+ ]
+
+sw.bb: ; preds = %for.body
+ %call1 = call i32 @sum(i32* getelementptr inbounds ([25 x i32], [25 x i32]* @arry, i64 0, i64 0), i32 25)
+ %5 = load i32, i32* %val, align 4, !tbaa !4
+ %add = add nsw i32 %5, %call1
+ store i32 %add, i32* %val, align 4, !tbaa !4
+ br label %sw.epilog
+
+sw.bb2: ; preds = %for.body, %for.body, %for.body
+ br label %sw.epilog
+
+sw.bb3: ; preds = %for.body
+ %call4 = call i32 @random_sample(i32* getelementptr inbounds ([25 x i32], [25 x i32]* @arry, i64 0, i64 0), i32 25)
+ %6 = load i32, i32* %val, align 4, !tbaa !4
+ %add5 = add nsw i32 %6, %call4
+ store i32 %add5, i32* %val, align 4, !tbaa !4
+ br label %sw.epilog
+
+sw.default: ; preds = %for.body
+ unreachable
+
+sw.epilog: ; preds = %sw.bb3, %sw.bb2, %sw.bb
+ %7 = bitcast i32* %condition to i8*
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %7) #6
+ br label %for.inc
+
+for.inc: ; preds = %sw.epilog
+ %8 = load i32, i32* %j, align 4, !tbaa !4
+ %inc = add nsw i32 %8, 1
+ store i32 %inc, i32* %j, align 4, !tbaa !4
+ br label %for.cond
+
+for.end: ; preds = %for.cond
+ %9 = bitcast i32* %j to i8*
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %9) #6
+ %10 = bitcast i32* %val to i8*
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %10) #6
+ ret i32 0
+}
+
+; Function Attrs: nounwind readnone willreturn
+declare i64 @llvm.expect.i64(i64, i64) #4
+
+declare dso_local i32 @sum(i32*, i32) #5
+
+declare dso_local i32 @random_sample(i32*, i32) #5
+
+attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind willreturn }
+attributes #2 = { nounwind readnone speculatable willreturn }
+attributes #3 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #4 = { nounwind readnone willreturn }
+attributes #5 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #6 = { nounwind }
+
+!llvm.module.flags = !{!0, !1, !2}
+!llvm.ident = !{!3}
+
+!0 = !{i32 2, !"Dwarf Version", i32 4}
+!1 = !{i32 2, !"Debug Info Version", i32 3}
+!2 = !{i32 1, !"wchar_size", i32 4}
+!3 = !{!"clang version 10.0.0 (60b79b85b1763d3d25630261e5cd1adb7f0835bc)"}
+!4 = !{!5, !5, i64 0}
+!5 = !{!"int", !6, i64 0}
+!6 = !{!"omnipotent char", !7, i64 0}
+!7 = !{!"Simple C/C++ TBAA"}
Added: llvm/trunk/test/Transforms/PGOProfile/misexpect-switch.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PGOProfile/misexpect-switch.ll?rev=371584&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/PGOProfile/misexpect-switch.ll (added)
+++ llvm/trunk/test/Transforms/PGOProfile/misexpect-switch.ll Tue Sep 10 18:09:16 2019
@@ -0,0 +1,293 @@
+
+; RUN: llvm-profdata merge %S/Inputs/misexpect-switch.proftext -o %t.profdata
+; RUN: llvm-profdata merge %S/Inputs/misexpect-switch-correct.proftext -o %t.c.profdata
+
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pgo-warn-misexpect 2>&1 | FileCheck %s --check-prefix=WARNING
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pass-remarks=misexpect 2>&1 | FileCheck %s --check-prefix=REMARK
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S -pgo-warn-misexpect -pass-remarks=misexpect 2>&1 | FileCheck %s --check-prefix=BOTH
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s --check-prefix=DISABLED
+
+; New PM
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pgo-warn-misexpect -S 2>&1 | FileCheck %s --check-prefix=WARNING
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pass-remarks=misexpect -S 2>&1 | FileCheck %s --check-prefix=REMARK
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -pgo-warn-misexpect -pass-remarks=misexpect -S 2>&1 | FileCheck %s --check-prefix=BOTH
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.profdata -S 2>&1 | FileCheck %s --check-prefix=DISABLED
+
+; RUN: opt < %s -lower-expect -pgo-instr-use -pgo-test-profile-file=%t.c.profdata -S -pgo-warn-misexpect -pass-remarks=misexpect 2>&1 | FileCheck %s --check-prefix=CORRECT
+; RUN: opt < %s -passes="function(lower-expect),pgo-instr-use" -pgo-test-profile-file=%t.c.profdata -pgo-warn-misexpect -pass-remarks=misexpect -S 2>&1 | FileCheck %s --check-prefix=CORRECT
+
+; WARNING-DAG: warning: misexpect-switch.c:26:5: 0.00%
+; WARNING-NOT: remark: misexpect-switch.c:26:5: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 0.00% (0 / 8112) of profiled executions.
+
+; REMARK-NOT: warning: misexpect-switch.c:26:5: 0.00%
+; REMARK-DAG: remark: misexpect-switch.c:26:5: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 0.00% (0 / 8112) of profiled executions.
+
+; BOTH-DAG: warning: misexpect-switch.c:26:5: 0.00%
+; BOTH-DAG: remark: misexpect-switch.c:26:5: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 0.00% (0 / 8112) of profiled executions.
+
+; DISABLED-NOT: warning: misexpect-switch.c:26:5: 0.00%
+; DISABLED-NOT: remark: misexpect-switch.c:26:5: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 0.00% (0 / 8112) of profiled executions.
+
+; DISABLED-NOT: warning: misexpect-switch.c:26:5: 0.00%
+; DISABLED-NOT: remark: misexpect-switch.c:26:5: Potential performance regression from use of the llvm.expect intrinsic: Annotation was correct on 0.00% (0 / 8112) of profiled executions.
+
+; CORRECT-NOT: warning: {{.*}}
+; CORRECT-NOT: remark: {{.*}}
+; CHECK-DAG: !{!"misexpect", i64 0, i64 2000, i64 1}
+
+
+
+; ModuleID = 'misexpect-switch.c'
+source_filename = "misexpect-switch.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at inner_loop = dso_local constant i32 1000, align 4, !dbg !0
+ at outer_loop = dso_local constant i32 20, align 4, !dbg !6
+ at arry_size = dso_local constant i32 25, align 4, !dbg !10
+ at arry = dso_local global [25 x i32] zeroinitializer, align 16, !dbg !12
+
+; Function Attrs: nounwind uwtable
+define dso_local void @init_arry() #0 !dbg !21 {
+entry:
+ %i = alloca i32, align 4
+ %0 = bitcast i32* %i to i8*, !dbg !26
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) #6, !dbg !26
+ call void @llvm.dbg.declare(metadata i32* %i, metadata !25, metadata !DIExpression()), !dbg !27
+ store i32 0, i32* %i, align 4, !dbg !28, !tbaa !30
+ br label %for.cond, !dbg !34
+
+for.cond: ; preds = %for.inc, %entry
+ %1 = load i32, i32* %i, align 4, !dbg !35, !tbaa !30
+ %cmp = icmp slt i32 %1, 25, !dbg !37
+ br i1 %cmp, label %for.body, label %for.end, !dbg !38
+
+for.body: ; preds = %for.cond
+ %call = call i32 @rand() #6, !dbg !39
+ %rem = srem i32 %call, 10, !dbg !41
+ %2 = load i32, i32* %i, align 4, !dbg !42, !tbaa !30
+ %idxprom = sext i32 %2 to i64, !dbg !43
+ %arrayidx = getelementptr inbounds [25 x i32], [25 x i32]* @arry, i64 0, i64 %idxprom, !dbg !43
+ store i32 %rem, i32* %arrayidx, align 4, !dbg !44, !tbaa !30
+ br label %for.inc, !dbg !45
+
+for.inc: ; preds = %for.body
+ %3 = load i32, i32* %i, align 4, !dbg !46, !tbaa !30
+ %inc = add nsw i32 %3, 1, !dbg !46
+ store i32 %inc, i32* %i, align 4, !dbg !46, !tbaa !30
+ br label %for.cond, !dbg !47, !llvm.loop !48
+
+for.end: ; preds = %for.cond
+ %4 = bitcast i32* %i to i8*, !dbg !50
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %4) #6, !dbg !50
+ ret void, !dbg !50
+}
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #2
+
+; Function Attrs: nounwind
+declare dso_local i32 @rand() #3
+
+; Function Attrs: argmemonly nounwind willreturn
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind uwtable
+define dso_local i32 @main() #0 !dbg !51 {
+entry:
+ %retval = alloca i32, align 4
+ %val = alloca i32, align 4
+ %j = alloca i32, align 4
+ %condition = alloca i32, align 4
+ store i32 0, i32* %retval, align 4
+ call void @init_arry(), !dbg !62
+ %0 = bitcast i32* %val to i8*, !dbg !63
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %0) #6, !dbg !63
+ call void @llvm.dbg.declare(metadata i32* %val, metadata !55, metadata !DIExpression()), !dbg !64
+ store i32 0, i32* %val, align 4, !dbg !64, !tbaa !30
+ %1 = bitcast i32* %j to i8*, !dbg !65
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %1) #6, !dbg !65
+ call void @llvm.dbg.declare(metadata i32* %j, metadata !56, metadata !DIExpression()), !dbg !66
+ store i32 0, i32* %j, align 4, !dbg !67, !tbaa !30
+ br label %for.cond, !dbg !68
+
+for.cond: ; preds = %for.inc, %entry
+ %2 = load i32, i32* %j, align 4, !dbg !69, !tbaa !30
+ %cmp = icmp slt i32 %2, 20000, !dbg !70
+ br i1 %cmp, label %for.body, label %for.end, !dbg !71
+
+for.body: ; preds = %for.cond
+ %3 = bitcast i32* %condition to i8*, !dbg !72
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* %3) #6, !dbg !72
+ call void @llvm.dbg.declare(metadata i32* %condition, metadata !57, metadata !DIExpression()), !dbg !73
+ %call = call i32 @rand() #6, !dbg !74
+ %rem = srem i32 %call, 5, !dbg !75
+ store i32 %rem, i32* %condition, align 4, !dbg !73, !tbaa !30
+ %4 = load i32, i32* %condition, align 4, !dbg !76, !tbaa !30
+ %conv = zext i32 %4 to i64, !dbg !76
+ %expval = call i64 @llvm.expect.i64(i64 %conv, i64 0), !dbg !77
+ switch i64 %expval, label %sw.default [
+ i64 0, label %sw.bb
+ i64 1, label %sw.bb2
+ i64 2, label %sw.bb2
+ i64 3, label %sw.bb2
+ i64 4, label %sw.bb3
+ ], !dbg !78
+
+sw.bb: ; preds = %for.body
+ %call1 = call i32 @sum(i32* getelementptr inbounds ([25 x i32], [25 x i32]* @arry, i64 0, i64 0), i32 25), !dbg !79
+ %5 = load i32, i32* %val, align 4, !dbg !81, !tbaa !30
+ %add = add nsw i32 %5, %call1, !dbg !81
+ store i32 %add, i32* %val, align 4, !dbg !81, !tbaa !30
+ br label %sw.epilog, !dbg !82
+
+sw.bb2: ; preds = %for.body, %for.body, %for.body
+ br label %sw.epilog, !dbg !83
+
+sw.bb3: ; preds = %for.body
+ %call4 = call i32 @random_sample(i32* getelementptr inbounds ([25 x i32], [25 x i32]* @arry, i64 0, i64 0), i32 25), !dbg !84
+ %6 = load i32, i32* %val, align 4, !dbg !85, !tbaa !30
+ %add5 = add nsw i32 %6, %call4, !dbg !85
+ store i32 %add5, i32* %val, align 4, !dbg !85, !tbaa !30
+ br label %sw.epilog, !dbg !86
+
+sw.default: ; preds = %for.body
+ unreachable, !dbg !87
+
+sw.epilog: ; preds = %sw.bb3, %sw.bb2, %sw.bb
+ %7 = bitcast i32* %condition to i8*, !dbg !88
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %7) #6, !dbg !88
+ br label %for.inc, !dbg !89
+
+for.inc: ; preds = %sw.epilog
+ %8 = load i32, i32* %j, align 4, !dbg !90, !tbaa !30
+ %inc = add nsw i32 %8, 1, !dbg !90
+ store i32 %inc, i32* %j, align 4, !dbg !90, !tbaa !30
+ br label %for.cond, !dbg !91, !llvm.loop !92
+
+for.end: ; preds = %for.cond
+ %9 = bitcast i32* %j to i8*, !dbg !94
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %9) #6, !dbg !94
+ %10 = bitcast i32* %val to i8*, !dbg !94
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* %10) #6, !dbg !94
+ ret i32 0, !dbg !95
+}
+
+; Function Attrs: nounwind readnone willreturn
+declare i64 @llvm.expect.i64(i64, i64) #4
+
+declare dso_local i32 @sum(i32*, i32) #5
+
+declare dso_local i32 @random_sample(i32*, i32) #5
+
+attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind willreturn }
+attributes #2 = { nounwind readnone speculatable willreturn }
+attributes #3 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #4 = { nounwind readnone willreturn }
+attributes #5 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #6 = { nounwind }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!17, !18, !19}
+!llvm.ident = !{!20}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "inner_loop", scope: !2, file: !3, line: 7, type: !8, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 10.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+!3 = !DIFile(filename: "misexpect-switch.c", directory: ".")
+!4 = !{}
+!5 = !{!0, !6, !10, !12}
+!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
+!7 = distinct !DIGlobalVariable(name: "outer_loop", scope: !2, file: !3, line: 8, type: !8, isLocal: false, isDefinition: true)
+!8 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !9)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
+!11 = distinct !DIGlobalVariable(name: "arry_size", scope: !2, file: !3, line: 9, type: !8, isLocal: false, isDefinition: true)
+!12 = !DIGlobalVariableExpression(var: !13, expr: !DIExpression())
+!13 = distinct !DIGlobalVariable(name: "arry", scope: !2, file: !3, line: 11, type: !14, isLocal: false, isDefinition: true)
+!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 800, elements: !15)
+!15 = !{!16}
+!16 = !DISubrange(count: 25)
+!17 = !{i32 2, !"Dwarf Version", i32 4}
+!18 = !{i32 2, !"Debug Info Version", i32 3}
+!19 = !{i32 1, !"wchar_size", i32 4}
+!20 = !{!"clang version 10.0.0"}
+!21 = distinct !DISubprogram(name: "init_arry", scope: !3, file: !3, line: 13, type: !22, scopeLine: 13, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !24)
+!22 = !DISubroutineType(types: !23)
+!23 = !{null}
+!24 = !{!25}
+!25 = !DILocalVariable(name: "i", scope: !21, file: !3, line: 14, type: !9)
+!26 = !DILocation(line: 14, column: 3, scope: !21)
+!27 = !DILocation(line: 14, column: 7, scope: !21)
+!28 = !DILocation(line: 15, column: 10, scope: !29)
+!29 = distinct !DILexicalBlock(scope: !21, file: !3, line: 15, column: 3)
+!30 = !{!31, !31, i64 0}
+!31 = !{!"int", !32, i64 0}
+!32 = !{!"omnipotent char", !33, i64 0}
+!33 = !{!"Simple C/C++ TBAA"}
+!34 = !DILocation(line: 15, column: 8, scope: !29)
+!35 = !DILocation(line: 15, column: 15, scope: !36)
+!36 = distinct !DILexicalBlock(scope: !29, file: !3, line: 15, column: 3)
+!37 = !DILocation(line: 15, column: 17, scope: !36)
+!38 = !DILocation(line: 15, column: 3, scope: !29)
+!39 = !DILocation(line: 16, column: 15, scope: !40)
+!40 = distinct !DILexicalBlock(scope: !36, file: !3, line: 15, column: 35)
+!41 = !DILocation(line: 16, column: 22, scope: !40)
+!42 = !DILocation(line: 16, column: 10, scope: !40)
+!43 = !DILocation(line: 16, column: 5, scope: !40)
+!44 = !DILocation(line: 16, column: 13, scope: !40)
+!45 = !DILocation(line: 17, column: 3, scope: !40)
+!46 = !DILocation(line: 15, column: 30, scope: !36)
+!47 = !DILocation(line: 15, column: 3, scope: !36)
+!48 = distinct !{!48, !38, !49}
+!49 = !DILocation(line: 17, column: 3, scope: !29)
+!50 = !DILocation(line: 18, column: 1, scope: !21)
+!51 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 20, type: !52, scopeLine: 20, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !54)
+!52 = !DISubroutineType(types: !53)
+!53 = !{!9}
+!54 = !{!55, !56, !57}
+!55 = !DILocalVariable(name: "val", scope: !51, file: !3, line: 22, type: !9)
+!56 = !DILocalVariable(name: "j", scope: !51, file: !3, line: 23, type: !9)
+!57 = !DILocalVariable(name: "condition", scope: !58, file: !3, line: 25, type: !61)
+!58 = distinct !DILexicalBlock(scope: !59, file: !3, line: 24, column: 49)
+!59 = distinct !DILexicalBlock(scope: !60, file: !3, line: 24, column: 3)
+!60 = distinct !DILexicalBlock(scope: !51, file: !3, line: 24, column: 3)
+!61 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!62 = !DILocation(line: 21, column: 3, scope: !51)
+!63 = !DILocation(line: 22, column: 3, scope: !51)
+!64 = !DILocation(line: 22, column: 7, scope: !51)
+!65 = !DILocation(line: 23, column: 3, scope: !51)
+!66 = !DILocation(line: 23, column: 7, scope: !51)
+!67 = !DILocation(line: 24, column: 10, scope: !60)
+!68 = !DILocation(line: 24, column: 8, scope: !60)
+!69 = !DILocation(line: 24, column: 15, scope: !59)
+!70 = !DILocation(line: 24, column: 17, scope: !59)
+!71 = !DILocation(line: 24, column: 3, scope: !60)
+!72 = !DILocation(line: 25, column: 5, scope: !58)
+!73 = !DILocation(line: 25, column: 14, scope: !58)
+!74 = !DILocation(line: 25, column: 26, scope: !58)
+!75 = !DILocation(line: 25, column: 33, scope: !58)
+!76 = !DILocation(line: 26, column: 30, scope: !58)
+!77 = !DILocation(line: 26, column: 13, scope: !58)
+!78 = !DILocation(line: 26, column: 5, scope: !58)
+!79 = !DILocation(line: 28, column: 14, scope: !80)
+!80 = distinct !DILexicalBlock(scope: !58, file: !3, line: 26, column: 45)
+!81 = !DILocation(line: 28, column: 11, scope: !80)
+!82 = !DILocation(line: 29, column: 7, scope: !80)
+!83 = !DILocation(line: 33, column: 7, scope: !80)
+!84 = !DILocation(line: 35, column: 14, scope: !80)
+!85 = !DILocation(line: 35, column: 11, scope: !80)
+!86 = !DILocation(line: 36, column: 7, scope: !80)
+!87 = !DILocation(line: 38, column: 7, scope: !80)
+!88 = !DILocation(line: 40, column: 3, scope: !59)
+!89 = !DILocation(line: 40, column: 3, scope: !58)
+!90 = !DILocation(line: 24, column: 44, scope: !59)
+!91 = !DILocation(line: 24, column: 3, scope: !59)
+!92 = distinct !{!92, !71, !93}
+!93 = !DILocation(line: 40, column: 3, scope: !60)
+!94 = !DILocation(line: 43, column: 1, scope: !51)
+!95 = !DILocation(line: 42, column: 3, scope: !51)
More information about the llvm-commits
mailing list