2017-04-03 22:55:37 +08:00
|
|
|
//===------ PerfMonitor.cpp - Generate a run-time performance monitor. -======//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2017-04-03 22:55:37 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "polly/CodeGen/PerfMonitor.h"
|
|
|
|
#include "polly/CodeGen/RuntimeDebugBuilder.h"
|
2017-06-02 16:01:22 +08:00
|
|
|
#include "polly/ScopInfo.h"
|
2017-04-03 22:55:37 +08:00
|
|
|
#include "llvm/ADT/Triple.h"
|
2020-03-10 00:15:14 +08:00
|
|
|
#include "llvm/ADT/Twine.h"
|
2019-12-13 06:47:46 +08:00
|
|
|
#include "llvm/IR/IntrinsicsX86.h"
|
2017-04-03 22:55:37 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace polly;
|
|
|
|
|
|
|
|
Function *PerfMonitor::getAtExit() {
|
|
|
|
const char *Name = "atexit";
|
|
|
|
Function *F = M->getFunction(Name);
|
|
|
|
|
|
|
|
if (!F) {
|
|
|
|
GlobalValue::LinkageTypes Linkage = Function::ExternalLinkage;
|
|
|
|
FunctionType *Ty = FunctionType::get(Builder.getInt32Ty(),
|
|
|
|
{Builder.getInt8PtrTy()}, false);
|
|
|
|
F = Function::Create(Ty, Linkage, Name, M);
|
|
|
|
}
|
|
|
|
|
|
|
|
return F;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PerfMonitor::addToGlobalConstructors(Function *Fn) {
|
|
|
|
const char *Name = "llvm.global_ctors";
|
|
|
|
GlobalVariable *GV = M->getGlobalVariable(Name);
|
|
|
|
std::vector<Constant *> V;
|
|
|
|
|
|
|
|
if (GV) {
|
|
|
|
Constant *Array = GV->getInitializer();
|
|
|
|
for (Value *X : Array->operand_values())
|
|
|
|
V.push_back(cast<Constant>(X));
|
|
|
|
GV->eraseFromParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
StructType *ST = StructType::get(Builder.getInt32Ty(), Fn->getType(),
|
2017-05-10 10:39:35 +08:00
|
|
|
Builder.getInt8PtrTy());
|
2017-04-03 22:55:37 +08:00
|
|
|
|
2017-05-10 12:53:59 +08:00
|
|
|
V.push_back(
|
|
|
|
ConstantStruct::get(ST, Builder.getInt32(10), Fn,
|
|
|
|
ConstantPointerNull::get(Builder.getInt8PtrTy())));
|
2017-04-03 22:55:37 +08:00
|
|
|
ArrayType *Ty = ArrayType::get(ST, V.size());
|
|
|
|
|
|
|
|
GV = new GlobalVariable(*M, Ty, true, GlobalValue::AppendingLinkage,
|
|
|
|
ConstantArray::get(Ty, V), Name, nullptr,
|
|
|
|
GlobalVariable::NotThreadLocal);
|
|
|
|
}
|
|
|
|
|
|
|
|
Function *PerfMonitor::getRDTSCP() {
|
2017-04-03 23:23:08 +08:00
|
|
|
return Intrinsic::getDeclaration(M, Intrinsic::x86_rdtscp);
|
2017-04-03 22:55:37 +08:00
|
|
|
}
|
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
PerfMonitor::PerfMonitor(const Scop &S, Module *M)
|
|
|
|
: M(M), Builder(M->getContext()), S(S) {
|
2017-04-03 22:55:37 +08:00
|
|
|
if (Triple(M->getTargetTriple()).getArch() == llvm::Triple::x86_64)
|
|
|
|
Supported = true;
|
|
|
|
else
|
|
|
|
Supported = false;
|
|
|
|
}
|
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
static void TryRegisterGlobal(Module *M, const char *Name,
|
|
|
|
Constant *InitialValue, Value **Location) {
|
|
|
|
*Location = M->getGlobalVariable(Name);
|
|
|
|
|
|
|
|
if (!*Location)
|
|
|
|
*Location = new GlobalVariable(
|
|
|
|
*M, InitialValue->getType(), true, GlobalValue::WeakAnyLinkage,
|
|
|
|
InitialValue, Name, nullptr, GlobalVariable::InitialExecTLSModel);
|
2017-06-06 23:56:50 +08:00
|
|
|
}
|
2017-06-02 16:01:22 +08:00
|
|
|
|
|
|
|
// Generate a unique name that is usable as a LLVM name for a scop to name its
|
|
|
|
// performance counter.
|
|
|
|
static std::string GetScopUniqueVarname(const Scop &S) {
|
|
|
|
std::string EntryString, ExitString;
|
|
|
|
std::tie(EntryString, ExitString) = S.getEntryExitStr();
|
|
|
|
|
2020-03-10 00:15:14 +08:00
|
|
|
return (Twine("__polly_perf_in_") + S.getFunction().getName() + "_from__" +
|
|
|
|
EntryString + "__to__" + ExitString)
|
|
|
|
.str();
|
2017-06-02 16:01:22 +08:00
|
|
|
}
|
2017-04-03 22:55:37 +08:00
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
void PerfMonitor::addScopCounter() {
|
|
|
|
const std::string varname = GetScopUniqueVarname(S);
|
[CodeGen] Track trip counts per-scop for performance measurement.
- Add a counter that is incremented once on exit from a scop.
- Test cases got split into two: one to test the cycles, and another one
to test trip counts.
- Sample output:
```name=sample-output.txt
scop function, entry block name, exit block name, total time, trip count
warmup, %entry.split, %polly.merge_new_and_old, 5180, 1
f, %entry.split, %polly.merge_new_and_old, 409944, 500
g, %entry.split, %polly.merge_new_and_old, 1226, 1
```
Differential Revision: https://reviews.llvm.org/D33822
llvm-svn: 304543
2017-06-02 19:36:52 +08:00
|
|
|
TryRegisterGlobal(M, (varname + "_cycles").c_str(), Builder.getInt64(0),
|
2017-06-02 16:01:22 +08:00
|
|
|
&CyclesInCurrentScopPtr);
|
[CodeGen] Track trip counts per-scop for performance measurement.
- Add a counter that is incremented once on exit from a scop.
- Test cases got split into two: one to test the cycles, and another one
to test trip counts.
- Sample output:
```name=sample-output.txt
scop function, entry block name, exit block name, total time, trip count
warmup, %entry.split, %polly.merge_new_and_old, 5180, 1
f, %entry.split, %polly.merge_new_and_old, 409944, 500
g, %entry.split, %polly.merge_new_and_old, 1226, 1
```
Differential Revision: https://reviews.llvm.org/D33822
llvm-svn: 304543
2017-06-02 19:36:52 +08:00
|
|
|
|
|
|
|
TryRegisterGlobal(M, (varname + "_trip_count").c_str(), Builder.getInt64(0),
|
|
|
|
&TripCountForCurrentScopPtr);
|
2017-06-02 16:01:22 +08:00
|
|
|
}
|
2017-04-03 22:55:37 +08:00
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
void PerfMonitor::addGlobalVariables() {
|
|
|
|
TryRegisterGlobal(M, "__polly_perf_cycles_total_start", Builder.getInt64(0),
|
2017-04-03 22:55:37 +08:00
|
|
|
&CyclesTotalStartPtr);
|
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
TryRegisterGlobal(M, "__polly_perf_initialized", Builder.getInt1(0),
|
2017-04-03 22:55:37 +08:00
|
|
|
&AlreadyInitializedPtr);
|
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
TryRegisterGlobal(M, "__polly_perf_cycles_in_scops", Builder.getInt64(0),
|
2017-04-03 22:55:37 +08:00
|
|
|
&CyclesInScopsPtr);
|
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
TryRegisterGlobal(M, "__polly_perf_cycles_in_scop_start", Builder.getInt64(0),
|
2017-04-03 22:55:37 +08:00
|
|
|
&CyclesInScopStartPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *InitFunctionName = "__polly_perf_init";
|
|
|
|
static const char *FinalReportingFunctionName = "__polly_perf_final";
|
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
static BasicBlock *FinalStartBB = nullptr;
|
|
|
|
static ReturnInst *ReturnFromFinal = nullptr;
|
|
|
|
|
2017-04-03 22:55:37 +08:00
|
|
|
Function *PerfMonitor::insertFinalReporting() {
|
|
|
|
// Create new function.
|
|
|
|
GlobalValue::LinkageTypes Linkage = Function::WeakODRLinkage;
|
|
|
|
FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), {}, false);
|
|
|
|
Function *ExitFn =
|
|
|
|
Function::Create(Ty, Linkage, FinalReportingFunctionName, M);
|
2017-06-02 16:01:22 +08:00
|
|
|
FinalStartBB = BasicBlock::Create(M->getContext(), "start", ExitFn);
|
|
|
|
Builder.SetInsertPoint(FinalStartBB);
|
2017-04-03 22:55:37 +08:00
|
|
|
|
|
|
|
if (!Supported) {
|
|
|
|
RuntimeDebugBuilder::createCPUPrinter(
|
|
|
|
Builder, "Polly runtime information generation not supported\n");
|
|
|
|
Builder.CreateRetVoid();
|
|
|
|
return ExitFn;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Measure current cycles and compute final timings.
|
|
|
|
Function *RDTSCPFn = getRDTSCP();
|
2018-09-11 22:17:44 +08:00
|
|
|
|
|
|
|
Value *CurrentCycles =
|
|
|
|
Builder.CreateExtractValue(Builder.CreateCall(RDTSCPFn), {0});
|
2017-04-03 22:55:37 +08:00
|
|
|
Value *CyclesStart = Builder.CreateLoad(CyclesTotalStartPtr, true);
|
|
|
|
Value *CyclesTotal = Builder.CreateSub(CurrentCycles, CyclesStart);
|
|
|
|
Value *CyclesInScops = Builder.CreateLoad(CyclesInScopsPtr, true);
|
|
|
|
|
|
|
|
// Print the runtime information.
|
|
|
|
RuntimeDebugBuilder::createCPUPrinter(Builder, "Polly runtime information\n");
|
|
|
|
RuntimeDebugBuilder::createCPUPrinter(Builder, "-------------------------\n");
|
|
|
|
RuntimeDebugBuilder::createCPUPrinter(Builder, "Total: ", CyclesTotal, "\n");
|
|
|
|
RuntimeDebugBuilder::createCPUPrinter(Builder, "Scops: ", CyclesInScops,
|
|
|
|
"\n");
|
[CodeGen] Print performance counter information in CSV.
This ensures that tools can parse performance information which Polly
generates easily.
- Sample output:
```name=out.csv
scop function, entry block name, exit block name, total time
warmup, %entry.split, %polly.merge_new_and_old, 1960
f, %entry.split, %polly.merge_new_and_old, 1238
g, %entry.split, %polly.merge_new_and_old, 1218
```
- Example code to parse output:
```lang=python, name=example-parse.py
import asciitable
import sys
table = asciitable.read('out.csv', delimiter=',')
asciitable.write(table, sys.stdout, delimiter=',')
```
llvm-svn: 304533
2017-06-02 17:20:02 +08:00
|
|
|
|
|
|
|
// Print the preamble for per-scop information.
|
|
|
|
RuntimeDebugBuilder::createCPUPrinter(Builder, "\n");
|
|
|
|
RuntimeDebugBuilder::createCPUPrinter(Builder, "Per SCoP information\n");
|
|
|
|
RuntimeDebugBuilder::createCPUPrinter(Builder, "--------------------\n");
|
|
|
|
|
|
|
|
RuntimeDebugBuilder::createCPUPrinter(
|
|
|
|
Builder, "scop function, "
|
[CodeGen] Track trip counts per-scop for performance measurement.
- Add a counter that is incremented once on exit from a scop.
- Test cases got split into two: one to test the cycles, and another one
to test trip counts.
- Sample output:
```name=sample-output.txt
scop function, entry block name, exit block name, total time, trip count
warmup, %entry.split, %polly.merge_new_and_old, 5180, 1
f, %entry.split, %polly.merge_new_and_old, 409944, 500
g, %entry.split, %polly.merge_new_and_old, 1226, 1
```
Differential Revision: https://reviews.llvm.org/D33822
llvm-svn: 304543
2017-06-02 19:36:52 +08:00
|
|
|
"entry block name, exit block name, total time, trip count\n");
|
2017-06-02 16:01:22 +08:00
|
|
|
ReturnFromFinal = Builder.CreateRetVoid();
|
2017-04-03 22:55:37 +08:00
|
|
|
return ExitFn;
|
|
|
|
}
|
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
void PerfMonitor::AppendScopReporting() {
|
2017-06-02 16:44:19 +08:00
|
|
|
if (!Supported)
|
|
|
|
return;
|
|
|
|
|
|
|
|
assert(FinalStartBB && "Expected FinalStartBB to be initialized by "
|
|
|
|
"PerfMonitor::insertFinalReporting.");
|
|
|
|
assert(ReturnFromFinal && "Expected ReturnFromFinal to be initialized by "
|
|
|
|
"PerfMonitor::insertFinalReporting.");
|
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
Builder.SetInsertPoint(FinalStartBB);
|
|
|
|
ReturnFromFinal->eraseFromParent();
|
|
|
|
|
|
|
|
Value *CyclesInCurrentScop =
|
|
|
|
Builder.CreateLoad(this->CyclesInCurrentScopPtr, true);
|
[CodeGen] Track trip counts per-scop for performance measurement.
- Add a counter that is incremented once on exit from a scop.
- Test cases got split into two: one to test the cycles, and another one
to test trip counts.
- Sample output:
```name=sample-output.txt
scop function, entry block name, exit block name, total time, trip count
warmup, %entry.split, %polly.merge_new_and_old, 5180, 1
f, %entry.split, %polly.merge_new_and_old, 409944, 500
g, %entry.split, %polly.merge_new_and_old, 1226, 1
```
Differential Revision: https://reviews.llvm.org/D33822
llvm-svn: 304543
2017-06-02 19:36:52 +08:00
|
|
|
|
|
|
|
Value *TripCountForCurrentScop =
|
|
|
|
Builder.CreateLoad(this->TripCountForCurrentScopPtr, true);
|
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
std::string EntryName, ExitName;
|
|
|
|
std::tie(EntryName, ExitName) = S.getEntryExitStr();
|
|
|
|
|
[CodeGen] Print performance counter information in CSV.
This ensures that tools can parse performance information which Polly
generates easily.
- Sample output:
```name=out.csv
scop function, entry block name, exit block name, total time
warmup, %entry.split, %polly.merge_new_and_old, 1960
f, %entry.split, %polly.merge_new_and_old, 1238
g, %entry.split, %polly.merge_new_and_old, 1218
```
- Example code to parse output:
```lang=python, name=example-parse.py
import asciitable
import sys
table = asciitable.read('out.csv', delimiter=',')
asciitable.write(table, sys.stdout, delimiter=',')
```
llvm-svn: 304533
2017-06-02 17:20:02 +08:00
|
|
|
// print in CSV for easy parsing with other tools.
|
[CodeGen] Track trip counts per-scop for performance measurement.
- Add a counter that is incremented once on exit from a scop.
- Test cases got split into two: one to test the cycles, and another one
to test trip counts.
- Sample output:
```name=sample-output.txt
scop function, entry block name, exit block name, total time, trip count
warmup, %entry.split, %polly.merge_new_and_old, 5180, 1
f, %entry.split, %polly.merge_new_and_old, 409944, 500
g, %entry.split, %polly.merge_new_and_old, 1226, 1
```
Differential Revision: https://reviews.llvm.org/D33822
llvm-svn: 304543
2017-06-02 19:36:52 +08:00
|
|
|
RuntimeDebugBuilder::createCPUPrinter(
|
|
|
|
Builder, S.getFunction().getName(), ", ", EntryName, ", ", ExitName, ", ",
|
|
|
|
CyclesInCurrentScop, ", ", TripCountForCurrentScop, "\n");
|
2017-06-02 16:01:22 +08:00
|
|
|
|
|
|
|
ReturnFromFinal = Builder.CreateRetVoid();
|
|
|
|
}
|
|
|
|
|
|
|
|
static Function *FinalReporting = nullptr;
|
|
|
|
|
2017-04-03 22:55:37 +08:00
|
|
|
void PerfMonitor::initialize() {
|
|
|
|
addGlobalVariables();
|
2017-06-02 16:01:22 +08:00
|
|
|
addScopCounter();
|
2017-04-03 22:55:37 +08:00
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
// Ensure that we only add the final reporting function once.
|
|
|
|
// On later invocations, append to the reporting function.
|
|
|
|
if (!FinalReporting) {
|
|
|
|
FinalReporting = insertFinalReporting();
|
|
|
|
|
|
|
|
Function *InitFn = insertInitFunction(FinalReporting);
|
|
|
|
addToGlobalConstructors(InitFn);
|
|
|
|
}
|
2017-04-03 22:55:37 +08:00
|
|
|
|
2017-06-02 16:01:22 +08:00
|
|
|
AppendScopReporting();
|
2017-04-03 22:55:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Function *PerfMonitor::insertInitFunction(Function *FinalReporting) {
|
|
|
|
// Insert function definition and BBs.
|
|
|
|
GlobalValue::LinkageTypes Linkage = Function::WeakODRLinkage;
|
|
|
|
FunctionType *Ty = FunctionType::get(Builder.getVoidTy(), {}, false);
|
|
|
|
Function *InitFn = Function::Create(Ty, Linkage, InitFunctionName, M);
|
|
|
|
BasicBlock *Start = BasicBlock::Create(M->getContext(), "start", InitFn);
|
|
|
|
BasicBlock *EarlyReturn =
|
|
|
|
BasicBlock::Create(M->getContext(), "earlyreturn", InitFn);
|
|
|
|
BasicBlock *InitBB = BasicBlock::Create(M->getContext(), "initbb", InitFn);
|
|
|
|
|
|
|
|
Builder.SetInsertPoint(Start);
|
|
|
|
|
|
|
|
// Check if this function was already run. If yes, return.
|
|
|
|
//
|
|
|
|
// In case profiling has been enabled in multiple translation units, the
|
|
|
|
// initializer function will be added to the global constructors list of
|
|
|
|
// each translation unit. When merging translation units, the global
|
|
|
|
// constructor lists are just appended, such that the initializer will appear
|
|
|
|
// multiple times. To avoid initializations being run multiple times (and
|
|
|
|
// especially to avoid that atExitFn is called more than once), we bail
|
2017-06-08 20:06:15 +08:00
|
|
|
// out if the initializer is run more than once.
|
2017-04-03 22:55:37 +08:00
|
|
|
Value *HasRunBefore = Builder.CreateLoad(AlreadyInitializedPtr);
|
|
|
|
Builder.CreateCondBr(HasRunBefore, EarlyReturn, InitBB);
|
|
|
|
Builder.SetInsertPoint(EarlyReturn);
|
|
|
|
Builder.CreateRetVoid();
|
|
|
|
|
|
|
|
// Keep track that this function has been run once.
|
|
|
|
Builder.SetInsertPoint(InitBB);
|
|
|
|
Value *True = Builder.getInt1(true);
|
|
|
|
Builder.CreateStore(True, AlreadyInitializedPtr);
|
|
|
|
|
|
|
|
// Register the final reporting function with atexit().
|
|
|
|
Value *FinalReportingPtr =
|
|
|
|
Builder.CreatePointerCast(FinalReporting, Builder.getInt8PtrTy());
|
|
|
|
Function *AtExitFn = getAtExit();
|
|
|
|
Builder.CreateCall(AtExitFn, {FinalReportingPtr});
|
|
|
|
|
|
|
|
if (Supported) {
|
|
|
|
// Read the currently cycle counter and store the result for later.
|
|
|
|
Function *RDTSCPFn = getRDTSCP();
|
2018-09-11 22:17:44 +08:00
|
|
|
Value *CurrentCycles =
|
|
|
|
Builder.CreateExtractValue(Builder.CreateCall(RDTSCPFn), {0});
|
2017-04-03 22:55:37 +08:00
|
|
|
Builder.CreateStore(CurrentCycles, CyclesTotalStartPtr, true);
|
|
|
|
}
|
|
|
|
Builder.CreateRetVoid();
|
|
|
|
|
|
|
|
return InitFn;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PerfMonitor::insertRegionStart(Instruction *InsertBefore) {
|
|
|
|
if (!Supported)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Builder.SetInsertPoint(InsertBefore);
|
|
|
|
Function *RDTSCPFn = getRDTSCP();
|
2018-09-11 22:17:44 +08:00
|
|
|
Value *CurrentCycles =
|
|
|
|
Builder.CreateExtractValue(Builder.CreateCall(RDTSCPFn), {0});
|
2017-04-03 22:55:37 +08:00
|
|
|
Builder.CreateStore(CurrentCycles, CyclesInScopStartPtr, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PerfMonitor::insertRegionEnd(Instruction *InsertBefore) {
|
|
|
|
if (!Supported)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Builder.SetInsertPoint(InsertBefore);
|
|
|
|
Function *RDTSCPFn = getRDTSCP();
|
|
|
|
LoadInst *CyclesStart = Builder.CreateLoad(CyclesInScopStartPtr, true);
|
2018-09-11 22:17:44 +08:00
|
|
|
Value *CurrentCycles =
|
|
|
|
Builder.CreateExtractValue(Builder.CreateCall(RDTSCPFn), {0});
|
2017-04-03 22:55:37 +08:00
|
|
|
Value *CyclesInScop = Builder.CreateSub(CurrentCycles, CyclesStart);
|
|
|
|
Value *CyclesInScops = Builder.CreateLoad(CyclesInScopsPtr, true);
|
|
|
|
CyclesInScops = Builder.CreateAdd(CyclesInScops, CyclesInScop);
|
|
|
|
Builder.CreateStore(CyclesInScops, CyclesInScopsPtr, true);
|
2017-06-02 16:01:22 +08:00
|
|
|
|
|
|
|
Value *CyclesInCurrentScop = Builder.CreateLoad(CyclesInCurrentScopPtr, true);
|
|
|
|
CyclesInCurrentScop = Builder.CreateAdd(CyclesInCurrentScop, CyclesInScop);
|
|
|
|
Builder.CreateStore(CyclesInCurrentScop, CyclesInCurrentScopPtr, true);
|
[CodeGen] Track trip counts per-scop for performance measurement.
- Add a counter that is incremented once on exit from a scop.
- Test cases got split into two: one to test the cycles, and another one
to test trip counts.
- Sample output:
```name=sample-output.txt
scop function, entry block name, exit block name, total time, trip count
warmup, %entry.split, %polly.merge_new_and_old, 5180, 1
f, %entry.split, %polly.merge_new_and_old, 409944, 500
g, %entry.split, %polly.merge_new_and_old, 1226, 1
```
Differential Revision: https://reviews.llvm.org/D33822
llvm-svn: 304543
2017-06-02 19:36:52 +08:00
|
|
|
|
|
|
|
Value *TripCountForCurrentScop =
|
|
|
|
Builder.CreateLoad(TripCountForCurrentScopPtr, true);
|
|
|
|
TripCountForCurrentScop =
|
|
|
|
Builder.CreateAdd(TripCountForCurrentScop, Builder.getInt64(1));
|
|
|
|
Builder.CreateStore(TripCountForCurrentScop, TripCountForCurrentScopPtr,
|
|
|
|
true);
|
2017-04-03 22:55:37 +08:00
|
|
|
}
|