| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 
 | //===----------------------- LSUnit.cpp --------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// A Load-Store Unit for the llvm-mca tool.
///
//===----------------------------------------------------------------------===//
#include "LSUnit.h"
#include "Instruction.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
#define DEBUG_TYPE "llvm-mca"
namespace mca {
#ifndef NDEBUG
void LSUnit::dump() const {
  dbgs() << "[LSUnit] LQ_Size = " << LQ_Size << '\n';
  dbgs() << "[LSUnit] SQ_Size = " << SQ_Size << '\n';
  dbgs() << "[LSUnit] NextLQSlotIdx = " << LoadQueue.size() << '\n';
  dbgs() << "[LSUnit] NextSQSlotIdx = " << StoreQueue.size() << '\n';
}
#endif
void LSUnit::assignLQSlot(unsigned Index) {
  assert(!isLQFull());
  assert(LoadQueue.count(Index) == 0);
  LLVM_DEBUG(dbgs() << "[LSUnit] - AssignLQSlot <Idx=" << Index
                    << ",slot=" << LoadQueue.size() << ">\n");
  LoadQueue.insert(Index);
}
void LSUnit::assignSQSlot(unsigned Index) {
  assert(!isSQFull());
  assert(StoreQueue.count(Index) == 0);
  LLVM_DEBUG(dbgs() << "[LSUnit] - AssignSQSlot <Idx=" << Index
                    << ",slot=" << StoreQueue.size() << ">\n");
  StoreQueue.insert(Index);
}
bool LSUnit::reserve(const InstRef &IR) {
  const InstrDesc &Desc = IR.getInstruction()->getDesc();
  unsigned MayLoad = Desc.MayLoad;
  unsigned MayStore = Desc.MayStore;
  unsigned IsMemBarrier = Desc.HasSideEffects;
  if (!MayLoad && !MayStore)
    return false;
  const unsigned Index = IR.getSourceIndex();
  if (MayLoad) {
    if (IsMemBarrier)
      LoadBarriers.insert(Index);
    assignLQSlot(Index);
  }
  if (MayStore) {
    if (IsMemBarrier)
      StoreBarriers.insert(Index);
    assignSQSlot(Index);
  }
  return true;
}
bool LSUnit::isReady(const InstRef &IR) const {
  const unsigned Index = IR.getSourceIndex();
  bool IsALoad = LoadQueue.count(Index) != 0;
  bool IsAStore = StoreQueue.count(Index) != 0;
  assert((IsALoad || IsAStore) && "Instruction is not in queue!");
  if (IsALoad && !LoadBarriers.empty()) {
    unsigned LoadBarrierIndex = *LoadBarriers.begin();
    if (Index > LoadBarrierIndex)
      return false;
    if (Index == LoadBarrierIndex && Index != *LoadQueue.begin())
      return false;
  }
  if (IsAStore && !StoreBarriers.empty()) {
    unsigned StoreBarrierIndex = *StoreBarriers.begin();
    if (Index > StoreBarrierIndex)
      return false;
    if (Index == StoreBarrierIndex && Index != *StoreQueue.begin())
      return false;
  }
  if (NoAlias && IsALoad)
    return true;
  if (StoreQueue.size()) {
    // Check if this memory operation is younger than the older store.
    if (Index > *StoreQueue.begin())
      return false;
  }
  // Okay, we are older than the oldest store in the queue.
  // If there are no pending loads, then we can say for sure that this
  // instruction is ready.
  if (isLQEmpty())
    return true;
  // Check if there are no older loads.
  if (Index <= *LoadQueue.begin())
    return true;
  // There is at least one younger load.
  return !IsAStore;
}
void LSUnit::onInstructionExecuted(const InstRef &IR) {
  const unsigned Index = IR.getSourceIndex();
  std::set<unsigned>::iterator it = LoadQueue.find(Index);
  if (it != LoadQueue.end()) {
    LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
                      << " has been removed from the load queue.\n");
    LoadQueue.erase(it);
  }
  it = StoreQueue.find(Index);
  if (it != StoreQueue.end()) {
    LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
                      << " has been removed from the store queue.\n");
    StoreQueue.erase(it);
  }
  if (!StoreBarriers.empty() && Index == *StoreBarriers.begin()) {
    LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
                      << " has been removed from the set of store barriers.\n");
    StoreBarriers.erase(StoreBarriers.begin());
  }
  if (!LoadBarriers.empty() && Index == *LoadBarriers.begin()) {
    LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index
                      << " has been removed from the set of load barriers.\n");
    LoadBarriers.erase(LoadBarriers.begin());
  }
}
} // namespace mca
 |