blob: aefe5efd358e7110010682b94887761f64e1cf64 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "codegen/instruction-counter.h"
#include "common/logging.h"
#include "common/names.h"
using namespace impala;
using std::make_pair;
using std::max;
const char* InstructionCounter::TOTAL_INSTS = "Total Instructions";
const char* InstructionCounter::TOTAL_BLOCKS = "Total Blocks";
const char* InstructionCounter::TOTAL_FUNCTIONS = "Total Functions";
const char* InstructionCounter::TERMINATOR_INSTS = "Terminator Instructions ";
const char* InstructionCounter::BINARY_INSTS = "Binary Instructions ";
const char* InstructionCounter::MEMORY_INSTS = "Memory Instructions ";
const char* InstructionCounter::CAST_INSTS = "Cast Instructions ";
const char* InstructionCounter::OTHER_INSTS = "Other Instructions ";
InstructionCounter::InstructionCounter() {
// Create top level counters and put them into counters_
counters_.insert(make_pair(TOTAL_INSTS, 0));
counters_.insert(make_pair(TOTAL_BLOCKS, 0));
counters_.insert(make_pair(TOTAL_FUNCTIONS, 0));
// Create all instruction counter and put them into counters_. Any InstructionCount
// that has instructions delegated to it in InstructionCounter::visit(const
// Instruction &I) must be created and inserted into counters_ here.
counters_.insert(make_pair(TERMINATOR_INSTS, 0));
counters_.insert(make_pair(BINARY_INSTS, 0));
counters_.insert(make_pair(MEMORY_INSTS, 0));
counters_.insert(make_pair(CAST_INSTS, 0));
counters_.insert(make_pair(OTHER_INSTS, 0));
}
void InstructionCounter::visit(const llvm::Module& M) {
visit(M.begin(), M.end());
}
void InstructionCounter::visit(const llvm::Function& F) {
IncrementCount(TOTAL_FUNCTIONS);
visit(F.begin(), F.end());
}
void InstructionCounter::visit(const llvm::BasicBlock& BB) {
IncrementCount(TOTAL_BLOCKS);
visit(BB.begin(), BB.end());
}
int InstructionCounter::GetCount(const char* name) {
CounterMap::const_iterator counter = counters_.find(name);
DCHECK(counter != counters_.end());
return counter->second;
}
void InstructionCounter::visit(const llvm::Instruction& I) {
IncrementCount(TOTAL_INSTS);
switch (I.getOpcode()) {
case llvm::Instruction::Ret:
case llvm::Instruction::Br:
case llvm::Instruction::Switch:
case llvm::Instruction::IndirectBr:
case llvm::Instruction::Invoke:
case llvm::Instruction::Resume:
case llvm::Instruction::Unreachable:
IncrementCount(TERMINATOR_INSTS);
break;
case llvm::Instruction::Add:
case llvm::Instruction::FAdd:
case llvm::Instruction::Sub:
case llvm::Instruction::FSub:
case llvm::Instruction::Mul:
case llvm::Instruction::FMul:
case llvm::Instruction::UDiv:
case llvm::Instruction::SDiv:
case llvm::Instruction::FDiv:
case llvm::Instruction::URem:
case llvm::Instruction::SRem:
case llvm::Instruction::FRem:
case llvm::Instruction::Shl:
case llvm::Instruction::LShr:
case llvm::Instruction::AShr:
case llvm::Instruction::And:
case llvm::Instruction::Or:
case llvm::Instruction::Xor:
IncrementCount(BINARY_INSTS);
break;
case llvm::Instruction::Alloca:
case llvm::Instruction::Load:
case llvm::Instruction::Store:
case llvm::Instruction::Fence:
case llvm::Instruction::AtomicCmpXchg:
case llvm::Instruction::AtomicRMW:
IncrementCount(MEMORY_INSTS);
break;
case llvm::Instruction::Trunc:
case llvm::Instruction::ZExt:
case llvm::Instruction::SExt:
case llvm::Instruction::FPToUI:
case llvm::Instruction::FPToSI:
case llvm::Instruction::UIToFP:
case llvm::Instruction::SIToFP:
case llvm::Instruction::FPTrunc:
case llvm::Instruction::FPExt:
case llvm::Instruction::PtrToInt:
case llvm::Instruction::IntToPtr:
case llvm::Instruction::BitCast:
IncrementCount(CAST_INSTS);
break;
case llvm::Instruction::ICmp:
case llvm::Instruction::FCmp:
case llvm::Instruction::PHI:
case llvm::Instruction::Call:
case llvm::Instruction::Select:
case llvm::Instruction::UserOp1:
case llvm::Instruction::UserOp2:
case llvm::Instruction::VAArg:
case llvm::Instruction::ExtractElement:
case llvm::Instruction::InsertElement:
case llvm::Instruction::ShuffleVector:
case llvm::Instruction::ExtractValue:
case llvm::Instruction::InsertValue:
case llvm::Instruction::LandingPad:
case llvm::Instruction::GetElementPtr:
IncrementCount(OTHER_INSTS);
break;
default:
DCHECK(false);
}
}
void InstructionCounter::ResetCount() {
for (CounterMap::value_type& counter: counters_) counter.second = 0;
}
void InstructionCounter::PrintCounter(const char* name, int count, int max_count_len,
stringstream* stream) const {
if (count > 0) {
*stream << left << setw(max_count_len + 1) << setfill(' ') << count << setw(35)
<< setfill(' ') << name << left << setw(10 - max_count_len) << setfill(' ')
<< "Number of " << name << endl;
}
}
string InstructionCounter::PrintCounters() const {
// Find the longest length of all the InstructionCount count_ strings.
int max_count_len = 0;
stringstream count_stream;
for (const CounterMap::value_type& counter: counters_) {
count_stream << counter.second;
max_count_len =
max(max_count_len, static_cast<int>(strlen(count_stream.str().c_str())));
count_stream.str("");
}
stringstream stream;
// Print header
stream << "\n===" << string(73, '-') << "===\n\n"
<< " ... Instruction Counts ...\n\n"
<< "===" << string(73, '-') << "===\n\n";
for (const CounterMap::value_type& counter: counters_) {
// Conditional is only used in order to print the top level counters
// separate from the other counters.
if (strcmp(counter.first.c_str(), TOTAL_BLOCKS) == 0) {
stream << "\n===" << string(73, '-') << "===\n"
<< " ... Totals ...\n"
<< "===" << string(73, '-') << "===\n\n";
}
PrintCounter(counter.first.c_str(), counter.second, max_count_len, &stream);
}
stream << '\n';
return stream.str();
}
void InstructionCounter::IncrementCount(const char* name) {
CounterMap::iterator iter = counters_.find(name);
DCHECK(iter != counters_.end());
iter->second++;
}