<commit_before>/*
 * Copyright 2004-2014 Cray Inc.
 * Other additional copyright holders may be indicated within.
 * 
 * The entirety of this work is licensed 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 "bb.h"

#include "astutil.h"
#include "bitVec.h"
#include "expr.h"
#include "stlUtil.h"
#include "stmt.h"
#include "view.h"

#include <cstdlib>

BasicBlock::BasicBlock()
  : id(nextid++) {}

#define BB_START()                              \
  basicBlock = new BasicBlock()

// The assert tests that the expression we are adding to this basic block
// has not already been deleted.
#define BB_ADD(expr)                            \
  do {                                          \
    INT_ASSERT(expr);                           \
    basicBlock->exprs.push_back(expr);          \
  } while (0)

#define BB_STOP()                               \
  fn->basicBlocks->push_back(Steal())

#define BB_RESTART()                            \
  do {                                          \
    BB_STOP();                                  \
    BB_START();                                 \
  } while (0)

#define BBB(stmt)                               \
    buildBasicBlocks(fn, stmt)

#define BB_THREAD(src, dst)                     \
  do {                                          \
    (dst)->ins.push_back(src);                  \
    (src)->outs.push_back(dst);                 \
  } while (0)


//# Statics
BasicBlock* BasicBlock::basicBlock;
Map<LabelSymbol*,std::vector<BasicBlock*>*> BasicBlock::gotoMaps;
Map<LabelSymbol*,BasicBlock*> BasicBlock::labelMaps;
int BasicBlock::nextid;


// Returns true if the class invariants have been preserved.
bool BasicBlock::isOK()
{
  // Expressions must be live (non-NULL);
  for_vector(Expr, expr, exprs)
    if (expr == 0) return false;

  // Every in edge must have a corresponding out edge in the source block.
  for_vector(BasicBlock, source, ins) {
    bool found = false;
    for_vector(BasicBlock, bb, source->outs)
      if (bb == this) { found = true; break; }
    if (!found) return false;
  }

  // Every out edge must have a corresponding in edge in the target block.
  for_vector(BasicBlock, target, outs) {
    bool found = false;
    for_vector(BasicBlock, bb, target->ins)
      if (bb == this) { found = true; break; }
    if (!found) return false;
  }

  return true;
}

void BasicBlock::clear(FnSymbol* fn)
{
  if (!fn->basicBlocks)
    return;

  for_vector(BasicBlock, bb, *fn->basicBlocks)
    delete bb, bb = 0;
  delete fn->basicBlocks; fn->basicBlocks = 0;
}

// Reset the shared statics.
void BasicBlock::reset(FnSymbol* fn)
{
  clear(fn);
  gotoMaps.clear();
  labelMaps.clear();
  fn->basicBlocks = new std::vector<BasicBlock*>();
  nextid = 0;
}

BasicBlock* BasicBlock::Steal()
{
  BasicBlock* temp = basicBlock;
  basicBlock = 0;
  return temp;
}

// This is the top-level (public) builder function.
void buildBasicBlocks(FnSymbol* fn)
{
  BasicBlock::reset(fn);
  BasicBlock::basicBlock = new BasicBlock();    // BB_START();
  BasicBlock::buildBasicBlocks(fn, fn->body);   // BBB(fn->body);
  fn->basicBlocks->push_back(BasicBlock::Steal());    // BB_STOP();

  INT_ASSERT(verifyBasicBlocks(fn));
}

void BasicBlock::buildBasicBlocks(FnSymbol* fn, Expr* stmt)
{
  if (!stmt) return;

  if (BlockStmt* s = toBlockStmt(stmt))
  {
    CallExpr* loop = toCallExpr(s->blockInfoGet());
    if (loop)
    {
      bool cForLoop = loop->isPrimitive(PRIM_BLOCK_C_FOR_LOOP);
      // for c for loops, add the init expr before the loop body
      if (cForLoop) {
        for_alist(stmt, toBlockStmt(loop->get(1))->body) { BBB(stmt); }
      }

      // mark the top of the loop
      BasicBlock* top = basicBlock;
      BB_RESTART();

      // for c for loops, add the test expr at the loop top
      if (cForLoop) {
        for_alist(stmt, toBlockStmt(loop->get(2))->body) { BBB(stmt); }
      }

      // add the CallExpr that is the loop itself and then add the loops body
      BB_ADD(loop);
      BasicBlock* loopTop = basicBlock;
      for_alist(stmt, s->body) {
        BBB(stmt);
      }

      // for c for loops, add the incr expr after the loop body
      if (cForLoop) {
        for_alist(stmt, toBlockStmt(loop->get(3))->body) { BBB(stmt); }
      }

      BasicBlock* loopBottom = basicBlock;
      BB_RESTART();
      BasicBlock* bottom = basicBlock;

      // thread the basic blocks of the pre-loop, loop, and post-loop together
      BB_THREAD(top, loopTop);
      BB_THREAD(loopBottom, bottom);
      BB_THREAD(loopBottom, loopTop);
      BB_THREAD(top, bottom);
    }
    else
    {
      for_alist(stmt, s->body)
        BBB(stmt);
    }
  }
  else if (CondStmt* s = toCondStmt(stmt))
  {
    INT_ASSERT(s->condExpr);<commit_msg>When building basic blocks for loop, only put the test expression at the top of the loop body; not the entire blockInfo callExpr for C-For loops<commit_after>/*
 * Copyright 2004-2014 Cray Inc.
 * Other additional copyright holders may be indicated within.
 * 
 * The entirety of this work is licensed 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 "bb.h"

#include "astutil.h"
#include "bitVec.h"
#include "expr.h"
#include "stlUtil.h"
#include "stmt.h"
#include "view.h"

#include <cstdlib>

BasicBlock::BasicBlock()
  : id(nextid++) {}

#define BB_START()                              \
  basicBlock = new BasicBlock()

// The assert tests that the expression we are adding to this basic block
// has not already been deleted.
#define BB_ADD(expr)                            \
  do {                                          \
    INT_ASSERT(expr);                           \
    basicBlock->exprs.push_back(expr);          \
  } while (0)

#define BB_STOP()                               \
  fn->basicBlocks->push_back(Steal())

#define BB_RESTART()                            \
  do {                                          \
    BB_STOP();                                  \
    BB_START();                                 \
  } while (0)

#define BBB(stmt)                               \
    buildBasicBlocks(fn, stmt)

#define BB_THREAD(src, dst)                     \
  do {                                          \
    (dst)->ins.push_back(src);                  \
    (src)->outs.push_back(dst);                 \
  } while (0)


//# Statics
BasicBlock* BasicBlock::basicBlock;
Map<LabelSymbol*,std::vector<BasicBlock*>*> BasicBlock::gotoMaps;
Map<LabelSymbol*,BasicBlock*> BasicBlock::labelMaps;
int BasicBlock::nextid;


// Returns true if the class invariants have been preserved.
bool BasicBlock::isOK()
{
  // Expressions must be live (non-NULL);
  for_vector(Expr, expr, exprs)
    if (expr == 0) return false;

  // Every in edge must have a corresponding out edge in the source block.
  for_vector(BasicBlock, source, ins) {
    bool found = false;
    for_vector(BasicBlock, bb, source->outs)
      if (bb == this) { found = true; break; }
    if (!found) return false;
  }

  // Every out edge must have a corresponding in edge in the target block.
  for_vector(BasicBlock, target, outs) {
    bool found = false;
    for_vector(BasicBlock, bb, target->ins)
      if (bb == this) { found = true; break; }
    if (!found) return false;
  }

  return true;
}

void BasicBlock::clear(FnSymbol* fn)
{
  if (!fn->basicBlocks)
    return;

  for_vector(BasicBlock, bb, *fn->basicBlocks)
    delete bb, bb = 0;
  delete fn->basicBlocks; fn->basicBlocks = 0;
}

// Reset the shared statics.
void BasicBlock::reset(FnSymbol* fn)
{
  clear(fn);
  gotoMaps.clear();
  labelMaps.clear();
  fn->basicBlocks = new std::vector<BasicBlock*>();
  nextid = 0;
}

BasicBlock* BasicBlock::Steal()
{
  BasicBlock* temp = basicBlock;
  basicBlock = 0;
  return temp;
}

// This is the top-level (public) builder function.
void buildBasicBlocks(FnSymbol* fn)
{
  BasicBlock::reset(fn);
  BasicBlock::basicBlock = new BasicBlock();    // BB_START();
  BasicBlock::buildBasicBlocks(fn, fn->body);   // BBB(fn->body);
  fn->basicBlocks->push_back(BasicBlock::Steal());    // BB_STOP();

  INT_ASSERT(verifyBasicBlocks(fn));
}

void BasicBlock::buildBasicBlocks(FnSymbol* fn, Expr* stmt)
{
  if (stmt == 0)
  {

  }

  else if (BlockStmt* s = toBlockStmt(stmt))
  {
    CallExpr* loop = toCallExpr(s->blockInfoGet());

    if (loop)
    {
      bool cForLoop = loop->isPrimitive(PRIM_BLOCK_C_FOR_LOOP);

      // for c for loops, add the init expr before the loop body
      if (cForLoop) {
        for_alist(stmt, toBlockStmt(loop->get(1))->body) { BBB(stmt); }
      }

      // mark the top of the loop
      BasicBlock* top = basicBlock;

      BB_RESTART();

      // add the test expr at the loop top
      if (cForLoop) {
        for_alist(stmt, toBlockStmt(loop->get(2))->body) { BBB(stmt); }
      } else {
        BB_ADD(loop);

      }

      BasicBlock* loopTop = basicBlock;

      for_alist(stmt, s->body) {
        BBB(stmt);
      }

      // for c for loops, add the incr expr after the loop body
      if (cForLoop) {
        for_alist(stmt, toBlockStmt(loop->get(3))->body) { BBB(stmt); }
      }

      BasicBlock* loopBottom = basicBlock;

      BB_RESTART();

      BasicBlock* bottom = basicBlock;

      // thread the basic blocks of the pre-loop, loop, and post-loop together
      BB_THREAD(top,        loopTop);
      BB_THREAD(loopBottom, bottom);
      BB_THREAD(loopBottom, loopTop);
      BB_THREAD(top,        bottom);
    }
    else
    {
      for_alist(stmt, s->body)
        BBB(stmt);
    }
  }
  else if (CondStmt* s = toCondStmt(stmt))
  {
    INT_ASSERT(s->condExpr);
{'fraction_non_alphanumeric': 0.11979560938682816, 'fraction_numerical': 0.004447388342165026, 'mean_word_length': 2.3100532414657065, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2533902', 'n_tokens_mistral': 3320, 'n_tokens_neox': 3228, 'n_words': 940}