<commit_before>// Copyright 2016 Alessio Sclocco <a.sclocco@vu.nl>
//
// 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 <vector>
#include <iostream>
#include <exception>
#include <iomanip>
#include <ctime>
#include <algorithm>

#include <configuration.hpp>

#include <ArgumentList.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Correlator.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, const unsigned int outputSize, cl::Buffer * output_d, const unsigned int cellMapSize, cl::Buffer * cellMapX_d, cl::Buffer * cellMapY_d);

int main(int argc, char * argv[]) {
  bool reInit = true;
  unsigned int padding = 0;
  unsigned int nrIterations = 0;
  unsigned int clPlatformID = 0;
  unsigned int clDeviceID = 0;
  // Constraints
  unsigned int vectorSize = 0;
  unsigned int maxThreads = 0;
  unsigned int maxItems = 0;
  unsigned int maxUnroll = 0;
  // Scenario
  unsigned int nrChannels = 0;
  unsigned int nrStations = 0;
  unsigned int nrSamples = 0;
  unsigned int nrBaselines = 0;
  unsigned int nrCells = 0;
  // Configuration
  TuneBench::CorrelatorConf conf;

  try {
    isa::utils::ArgumentList args(argc, argv);

    clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
    clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
    vectorSize = args.getSwitchArgument< unsigned int >("-vector");
    maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
    maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    maxUnroll = args.getSwitchArgument< unsigned int >("-max_unroll");
    conf.setSequentialTime(args.getSwitch("-sequential_time"));
    conf.setParallelTime(args.getSwitch("-parallel_time"));
    nrChannels = args.getSwitchArgument< unsigned int >("-channels");
    nrStations = args.getSwitchArgument< unsigned int >("-stations");
    nrSamples = args.getSwitchArgument< unsigned int >("-samples");
  } catch ( isa::utils::EmptyCommandLine & err ) {
    std::cerr << argv[0] << " -opencl_platform ... -opencl_device ... -padding ... -iterations ... -vector ... -max_threads ... -max_items ... [-sequential_time | -parallel_time] -channels ... -stations ... -samples ..." << std::endl;
    return 1;
  } catch ( std::exception & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  cl::Context clContext;
  std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
  std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
  std::vector< std::vector< cl::CommandQueue > > * clQueues = 0;

  // Allocate host memory
  nrBaselines = (nrStations * (nrStations + 1)) / 2;
  std::vector< inputDataType > input(nrChannels * nrStations * isa::utils::pad(nrSamples * nrPolarizations * 2, padding));
  std::vector< outputDataType > output(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2), output_c(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2);
  std::vector< unsigned int > cellMapX;
  std::vector< unsigned int > cellMapY;
  cl::Buffer input_d, output_d, cellMapX_d, cellMapY_d;

  // Populate input
  srand(time(0));
  for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
    for ( unsigned int station = 0; station < nrStations; station++ ) {
      for ( unsigned int sample = 0; sample < nrSamples; sample++ ) {
        for ( unsigned int polarization = 0; polarization < nrPolarizations; polarization++ ) {
          // Real
          input[(channel * nrStations * isa::utils::pad(nrSamples * nrPolarizations * 2, padding)) + (station * isa::utils::pad(nrSamples * nrPolarizations * 2, padding)) + (sample * nrPolarizations * 2) + (polarization * 2)] = rand() % magicValue;
          // Imaginary
          input[(channel * nrStations * isa::utils::pad(nrSamples * nrPolarizations * 2, padding)) + (station * isa::utils::pad(nrSamples * nrPolarizations * 2, padding)) + (sample * nrPolarizations * 2) + (polarization * 2) + 1] = rand() % magicValue;
        }
      }
    }
  }
  // Compute CPU control results
  std::fill(output.begin(), output.end(), 0);
  std::fill(output_c.begin(), output_c.end(), 0);
  TuneBench::correlator(input, output_c, padding, nrChannels, nrStations, nrSamples, nrPolarizations);

  std::cout << std::fixed << std::endl;
  std::cout << "# nrChannels nrStations nrSamples nrPolarizations nrBaselines nrCells *configuration* GFLOP/s time stdDeviation COV" << std::endl << std::endl;

  for ( unsigned int threads = vectorSize; threads <= maxThreads; threads += vectorSize ) {
    conf.setNrThreadsD0(threads);
    for ( unsigned int threads = 1; (conf.getNrThreadsD0() * threads) <= maxThreads; threads++ ) {
      conf.setNrThreadsD2(threads);
      if ( nrChannels % conf.getNrThreadsD2() != 0 ) {
        continue;
      }
      for ( unsigned int width = 1; width <= maxItems; width++ ) {
        conf.setCellWidth(width);
        for ( unsigned int height = 1; height <= maxItems; height++ ) {
          conf.setCellHeight(height);
          if ( conf.getSequentialTime() && (5 + (4 * (conf.getCellWidth() + conf.getCellHeight())) + (8 * (conf.getCellWidth() * conf.getCellHeight()))) > maxItems ) {
            continue;
          } else if ( conf.getParallelTime() && (7 + (4 * (conf.getCellWidth() + conf.getCellHeight())) + (8 * (conf.getCellWidth() * conf.getCellHeight()))) > maxItems ) {
            continue;
          }
          nrCells = generateCellMap(conf, cellMapX, cellMapY, nrStations);
          for ( unsigned int items = 1; items <= maxUnroll; items++ ) {
            if ( conf.getSequentialTime() ) {
              conf.setNrItemsD1(items);
              if ( nrSamples % conf.getNrItemsD1() != 0 ) {
                continue;
              }
            } else if ( conf.getParallelTime() ) {
              conf.setNrItemsD0(items);
              if ( nrSamples % (conf.getNrThreadsD0() * conf.getNrItemsD0()) != 0 ) {
                continue;
              }
            }
            // Generate kernel
            double gflops = isa::utils::giga(static_cast< uint64_t >(nrChannels) * nrSamples * nrCells * conf.getCellWidth() * conf.getCellHeight() * 32.0);
            cl::Event clEvent;
            cl::Kernel * kernel;
            isa::utils::Timer timer;
            std::string * code = TuneBench::getCorrelatorOpenCL(conf, inputDataName, padding, nrChannels, nrStations, nrSamples, nrPolarizations, nrCells);

            if ( reInit ) {
              delete clQueues;
              clQueues = new std::vector< std::vector< cl::CommandQueue > >();
              isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
              try {
                initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), &input, &input_d, nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2, &output_d, nrCells, &cellMapX_d, &cellMapY_d);
              } catch ( cl::Error & err ) {
                return -1;
              }
              reInit = false;
            }
            try {
              kernel = isa::OpenCL::compile("correlator", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
              (clQueues->at(clDeviceID)[0]).enqueueWriteBuffer(cellMapX_d, CL_FALSE, 0, cellMapX.size() * sizeof(unsigned int), reinterpret_cast< void * >(cellMapX.data()));
              (clQueues->at(clDeviceID)[0]).enqueueWriteBuffer(cellMapY_d, CL_FALSE, 0, cellMapY.size() * sizeof(unsigned int), reinterpret_cast< void * >(cellMapY.data()));
            } catch ( isa::OpenCL::OpenCLError & err ) {
              std::cerr << err.what() << std::endl;
              delete code;
              break;
            } catch ( cl::Error & err ) {
              std::cerr << err.what() << std::endl;
              delete code;
              break;
            }
            delete code;

            cl::NDRange global, local;
            if ( conf.getSequentialTime() ) {
              global = cl::NDRange(isa::utils::pad(nrCells, conf.getNrThreadsD0()), 1, nrChannels);
              local = cl::NDRange(conf.getNrThreadsD0(), 1, conf.getNrThreadsD2());
            } else if ( conf.getParallelTime() ) {
              global = cl::NDRange(nrSamples / conf.getNrItemsD0(), nrCells, nrChannels);
              local = cl::NDRange(conf.getNrThreadsD0(), 1, conf.getNrThreadsD2());
            }

            kernel->setArg(0, input_d);
            kernel->setArg(1, output_d);
            kernel->setArg(2, cellMapX_d);
            kernel->setArg(3, cellMapY_d);

            try {
              // Warm-up run
              clQueues->at(clDeviceID)[0].finish();
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
              clEvent.wait();
              // Tuning runs
              for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
                timer.start();
                clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
                clEvent.wait();
                timer.stop();
              }
              clQueues->at(clDeviceID)[0].enqueueReadBuffer(output_d, CL_TRUE, 0, output.size() * sizeof(outputDataType), reinterpret_cast< void * >(output.data()), 0, &clEvent);
              clEvent.wait();
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL kernel execution error (";
              std::cerr << conf.print();
              std::cerr << "): ";
              std::cerr << std::to_string(err.err()) << std::endl;
              delete kernel;
              if ( err.err() == -4 || err.err() == -61 ) {
                return -1;
              }
              reInit = true;
              break;
            }
            delete kernel;

            bool error = false;
            for ( unsigned int cell = 0; cell < nrCells; cell++ ) {
              int stationX = cellMapX[cell];
              int stationY = cellMapY[cell];

              for ( unsigned int width = 0; width < conf.getCellWidth(); width++ ) {
                for ( unsigned int height = 0; height < conf.getCellHeight(); height++ ) {
                  unsigned int baseline = (((stationY + height) * ((stationY + height) + 1)) / 2) + (stationX + width);

                  for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
                    for ( unsigned int polarization0 = 0; polarization0 < nrPolarizations; polarization0++ ) {
                      for ( unsigned int polarization1 = 0; polarization1 < nrPolarizations; polarization1++ ) {
                        if ( !isa::utils::same(output[(baseline * nrChannels * nrPolarizations * nrPolarizations * 2) + (channel * nrPolarizations * nrPolarizations * 2) + (polarization0 * nrPolarizations * 2) + (polarization1 * 2)], output_c[(baseline * nrChannels * nrPolarizations * nrPolarizations * 2) + (channel * nrPolarizations * nrPolarizations * 2) + (polarization0 * nrPolarizations * 2) + (polarization1 * 2)]) ) {
                          std::cerr << "Output error (" << conf.print() << ")." << std::endl;
                          error = true;
                          break;
                        }
                        if ( !isa::utils::same(output[(baseline * nrChannels * nrPolarizations * nrPolarizations * 2) + (channel * nrPolarizations * nrPolarizations * 2) + (polarization0 * nrPolarizations * 2) + (polarization1 * 2) + 1], output_c[(baseline * nrChannels * nrPolarizations * nrPolarizations * 2) + (channel * nrPolarizations * nrPolarizations * 2) + (polarization0 * nrPolarizations * 2) + (polarization1 * 2) + 1]) ) {
                          std::cerr << "Output error (" << conf.print() << ")." << std::endl;
                          error = true;
                          break;
                        }
                      }
                      if ( error ) {
                        break;
                      }
                    }
                    if ( error ) {
                      break;
                    }
                  }
                  if ( error ) {
                    break;
                  }
                }
                if ( error ) {
                  break;
                }
              }
              if ( error ) {
                break;
              }
            }
            if ( error ) {
              continue;
            }

            std::cout << nrChannels << " " << nrStations << " " << nrSamples << " " << nrPolarizations << " " << nrBaselines << " " << nrCells << " ";
            std::cout << conf.print() << " ";
            std::cout << std::setprecision(3);
            std::cout << gflops / timer.getAverageTime() << " ";
            std::cout << std::setprecision(6);
            std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " " << timer.getCoefficientOfVariation() << std::endl;
          }
        }
      }
    }
  }
  std::cout << std::endl;

  return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, const unsigned int outputSize, cl::Buffer * output_d, const unsigned int cellMapSize, cl::Buffer * cellMapX_d, cl::Buffer * cellMapY_d) {
  try {
    *input_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, input->size() * sizeof(inputDataType), 0, 0);
    *output_d = cl::Buffer(clContext, CL_MEM_WRITE_ONLY, outputSize * sizeof(outputDataType), 0, 0);
    *cellMapX_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, cellMapSize * sizeof(unsigned int), 0, 0);
    *cellMapY_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, cellMapSize * sizeof(unsigned int), 0, 0);
    clQueue->enqueueWriteBuffer(*input_d, CL_FALSE, 0, input->size() * sizeof(inputDataType), reinterpret_cast< void * >(input->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error (memory initialization): " << std::to_string(err.err()) << "." << std::endl;
    throw;
  }
}

<commit_msg>Usage message updated.<commit_after>// Copyright 2016 Alessio Sclocco <a.sclocco@vu.nl>
//
// 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 <vector>
#include <iostream>
#include <exception>
#include <iomanip>
#include <ctime>
#include <algorithm>

#include <configuration.hpp>

#include <ArgumentList.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Correlator.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, const unsigned int outputSize, cl::Buffer * output_d, const unsigned int cellMapSize, cl::Buffer * cellMapX_d, cl::Buffer * cellMapY_d);

int main(int argc, char * argv[]) {
  bool reInit = true;
  unsigned int padding = 0;
  unsigned int nrIterations = 0;
  unsigned int clPlatformID = 0;
  unsigned int clDeviceID = 0;
  // Constraints
  unsigned int vectorSize = 0;
  unsigned int maxThreads = 0;
  unsigned int maxItems = 0;
  unsigned int maxUnroll = 0;
  // Scenario
  unsigned int nrChannels = 0;
  unsigned int nrStations = 0;
  unsigned int nrSamples = 0;
  unsigned int nrBaselines = 0;
  unsigned int nrCells = 0;
  // Configuration
  TuneBench::CorrelatorConf conf;

  try {
    isa::utils::ArgumentList args(argc, argv);

    clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
    clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    padding = args.getSwitchArgument< unsigned int >("-padding");
    nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
    vectorSize = args.getSwitchArgument< unsigned int >("-vector");
    maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
    maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    maxUnroll = args.getSwitchArgument< unsigned int >("-max_unroll");
    conf.setSequentialTime(args.getSwitch("-sequential_time"));
    conf.setParallelTime(args.getSwitch("-parallel_time"));
    nrChannels = args.getSwitchArgument< unsigned int >("-channels");
    nrStations = args.getSwitchArgument< unsigned int >("-stations");
    nrSamples = args.getSwitchArgument< unsigned int >("-samples");
  } catch ( isa::utils::EmptyCommandLine & err ) {
    std::cerr << argv[0] << " -opencl_platform ... -opencl_device ... -padding ... -iterations ... -vector ... -max_threads ... -max_items ... -max_unroll ... [-sequential_time | -parallel_time] -channels ... -stations ... -samples ..." << std::endl;
    return 1;
  } catch ( std::exception & err ) {
    std::cerr << err.what() << std::endl;
    return 1;
  }

  cl::Context clContext;
  std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
  std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
  std::vector< std::vector< cl::CommandQueue > > * clQueues = 0;

  // Allocate host memory
  nrBaselines = (nrStations * (nrStations + 1)) / 2;
  std::vector< inputDataType > input(nrChannels * nrStations * isa::utils::pad(nrSamples * nrPolarizations * 2, padding));
  std::vector< outputDataType > output(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2), output_c(nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2);
  std::vector< unsigned int > cellMapX;
  std::vector< unsigned int > cellMapY;
  cl::Buffer input_d, output_d, cellMapX_d, cellMapY_d;

  // Populate input
  srand(time(0));
  for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
    for ( unsigned int station = 0; station < nrStations; station++ ) {
      for ( unsigned int sample = 0; sample < nrSamples; sample++ ) {
        for ( unsigned int polarization = 0; polarization < nrPolarizations; polarization++ ) {
          // Real
          input[(channel * nrStations * isa::utils::pad(nrSamples * nrPolarizations * 2, padding)) + (station * isa::utils::pad(nrSamples * nrPolarizations * 2, padding)) + (sample * nrPolarizations * 2) + (polarization * 2)] = rand() % magicValue;
          // Imaginary
          input[(channel * nrStations * isa::utils::pad(nrSamples * nrPolarizations * 2, padding)) + (station * isa::utils::pad(nrSamples * nrPolarizations * 2, padding)) + (sample * nrPolarizations * 2) + (polarization * 2) + 1] = rand() % magicValue;
        }
      }
    }
  }
  // Compute CPU control results
  std::fill(output.begin(), output.end(), 0);
  std::fill(output_c.begin(), output_c.end(), 0);
  TuneBench::correlator(input, output_c, padding, nrChannels, nrStations, nrSamples, nrPolarizations);

  std::cout << std::fixed << std::endl;
  std::cout << "# nrChannels nrStations nrSamples nrPolarizations nrBaselines nrCells *configuration* GFLOP/s time stdDeviation COV" << std::endl << std::endl;

  for ( unsigned int threads = vectorSize; threads <= maxThreads; threads += vectorSize ) {
    conf.setNrThreadsD0(threads);
    for ( unsigned int threads = 1; (conf.getNrThreadsD0() * threads) <= maxThreads; threads++ ) {
      conf.setNrThreadsD2(threads);
      if ( nrChannels % conf.getNrThreadsD2() != 0 ) {
        continue;
      }
      for ( unsigned int width = 1; width <= maxItems; width++ ) {
        conf.setCellWidth(width);
        for ( unsigned int height = 1; height <= maxItems; height++ ) {
          conf.setCellHeight(height);
          if ( conf.getSequentialTime() && (5 + (4 * (conf.getCellWidth() + conf.getCellHeight())) + (8 * (conf.getCellWidth() * conf.getCellHeight()))) > maxItems ) {
            continue;
          } else if ( conf.getParallelTime() && (7 + (4 * (conf.getCellWidth() + conf.getCellHeight())) + (8 * (conf.getCellWidth() * conf.getCellHeight()))) > maxItems ) {
            continue;
          }
          nrCells = generateCellMap(conf, cellMapX, cellMapY, nrStations);
          for ( unsigned int items = 1; items <= maxUnroll; items++ ) {
            if ( conf.getSequentialTime() ) {
              conf.setNrItemsD1(items);
              if ( nrSamples % conf.getNrItemsD1() != 0 ) {
                continue;
              }
            } else if ( conf.getParallelTime() ) {
              conf.setNrItemsD0(items);
              if ( nrSamples % (conf.getNrThreadsD0() * conf.getNrItemsD0()) != 0 ) {
                continue;
              }
            }
            // Generate kernel
            double gflops = isa::utils::giga(static_cast< uint64_t >(nrChannels) * nrSamples * nrCells * conf.getCellWidth() * conf.getCellHeight() * 32.0);
            cl::Event clEvent;
            cl::Kernel * kernel;
            isa::utils::Timer timer;
            std::string * code = TuneBench::getCorrelatorOpenCL(conf, inputDataName, padding, nrChannels, nrStations, nrSamples, nrPolarizations, nrCells);

            if ( reInit ) {
              delete clQueues;
              clQueues = new std::vector< std::vector< cl::CommandQueue > >();
              isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
              try {
                initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), &input, &input_d, nrChannels * nrBaselines * nrPolarizations * nrPolarizations * 2, &output_d, nrCells, &cellMapX_d, &cellMapY_d);
              } catch ( cl::Error & err ) {
                return -1;
              }
              reInit = false;
            }
            try {
              kernel = isa::OpenCL::compile("correlator", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
              (clQueues->at(clDeviceID)[0]).enqueueWriteBuffer(cellMapX_d, CL_FALSE, 0, cellMapX.size() * sizeof(unsigned int), reinterpret_cast< void * >(cellMapX.data()));
              (clQueues->at(clDeviceID)[0]).enqueueWriteBuffer(cellMapY_d, CL_FALSE, 0, cellMapY.size() * sizeof(unsigned int), reinterpret_cast< void * >(cellMapY.data()));
            } catch ( isa::OpenCL::OpenCLError & err ) {
              std::cerr << err.what() << std::endl;
              delete code;
              break;
            } catch ( cl::Error & err ) {
              std::cerr << err.what() << std::endl;
              delete code;
              break;
            }
            delete code;

            cl::NDRange global, local;
            if ( conf.getSequentialTime() ) {
              global = cl::NDRange(isa::utils::pad(nrCells, conf.getNrThreadsD0()), 1, nrChannels);
              local = cl::NDRange(conf.getNrThreadsD0(), 1, conf.getNrThreadsD2());
            } else if ( conf.getParallelTime() ) {
              global = cl::NDRange(nrSamples / conf.getNrItemsD0(), nrCells, nrChannels);
              local = cl::NDRange(conf.getNrThreadsD0(), 1, conf.getNrThreadsD2());
            }

            kernel->setArg(0, input_d);
            kernel->setArg(1, output_d);
            kernel->setArg(2, cellMapX_d);
            kernel->setArg(3, cellMapY_d);

            try {
              // Warm-up run
              clQueues->at(clDeviceID)[0].finish();
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
              clEvent.wait();
              // Tuning runs
              for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
                timer.start();
                clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &clEvent);
                clEvent.wait();
                timer.stop();
              }
              clQueues->at(clDeviceID)[0].enqueueReadBuffer(output_d, CL_TRUE, 0, output.size() * sizeof(outputDataType), reinterpret_cast< void * >(output.data()), 0, &clEvent);
              clEvent.wait();
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL kernel execution error (";
              std::cerr << conf.print();
              std::cerr << "): ";
              std::cerr << std::to_string(err.err()) << std::endl;
              delete kernel;
              if ( err.err() == -4 || err.err() == -61 ) {
                return -1;
              }
              reInit = true;
              break;
            }
            delete kernel;

            bool error = false;
            for ( unsigned int cell = 0; cell < nrCells; cell++ ) {
              int stationX = cellMapX[cell];
              int stationY = cellMapY[cell];

              for ( unsigned int width = 0; width < conf.getCellWidth(); width++ ) {
                for ( unsigned int height = 0; height < conf.getCellHeight(); height++ ) {
                  unsigned int baseline = (((stationY + height) * ((stationY + height) + 1)) / 2) + (stationX + width);

                  for ( unsigned int channel = 0; channel < nrChannels; channel++ ) {
                    for ( unsigned int polarization0 = 0; polarization0 < nrPolarizations; polarization0++ ) {
                      for ( unsigned int polarization1 = 0; polarization1 < nrPolarizations; polarization1++ ) {
                        if ( !isa::utils::same(output[(baseline * nrChannels * nrPolarizations * nrPolarizations * 2) + (channel * nrPolarizations * nrPolarizations * 2) + (polarization0 * nrPolarizations * 2) + (polarization1 * 2)], output_c[(baseline * nrChannels * nrPolarizations * nrPolarizations * 2) + (channel * nrPolarizations * nrPolarizations * 2) + (polarization0 * nrPolarizations * 2) + (polarization1 * 2)]) ) {
                          std::cerr << "Output error (" << conf.print() << ")." << std::endl;
                          error = true;
                          break;
                        }
                        if ( !isa::utils::same(output[(baseline * nrChannels * nrPolarizations * nrPolarizations * 2) + (channel * nrPolarizations * nrPolarizations * 2) + (polarization0 * nrPolarizations * 2) + (polarization1 * 2) + 1], output_c[(baseline * nrChannels * nrPolarizations * nrPolarizations * 2) + (channel * nrPolarizations * nrPolarizations * 2) + (polarization0 * nrPolarizations * 2) + (polarization1 * 2) + 1]) ) {
                          std::cerr << "Output error (" << conf.print() << ")." << std::endl;
                          error = true;
                          break;
                        }
                      }
                      if ( error ) {
                        break;
                      }
                    }
                    if ( error ) {
                      break;
                    }
                  }
                  if ( error ) {
                    break;
                  }
                }
                if ( error ) {
                  break;
                }
              }
              if ( error ) {
                break;
              }
            }
            if ( error ) {
              continue;
            }

            std::cout << nrChannels << " " << nrStations << " " << nrSamples << " " << nrPolarizations << " " << nrBaselines << " " << nrCells << " ";
            std::cout << conf.print() << " ";
            std::cout << std::setprecision(3);
            std::cout << gflops / timer.getAverageTime() << " ";
            std::cout << std::setprecision(6);
            std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " " << timer.getCoefficientOfVariation() << std::endl;
          }
        }
      }
    }
  }
  std::cout << std::endl;

  return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< inputDataType > * input, cl::Buffer * input_d, const unsigned int outputSize, cl::Buffer * output_d, const unsigned int cellMapSize, cl::Buffer * cellMapX_d, cl::Buffer * cellMapY_d) {
  try {
    *input_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, input->size() * sizeof(inputDataType), 0, 0);
    *output_d = cl::Buffer(clContext, CL_MEM_WRITE_ONLY, outputSize * sizeof(outputDataType), 0, 0);
    *cellMapX_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, cellMapSize * sizeof(unsigned int), 0, 0);
    *cellMapY_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, cellMapSize * sizeof(unsigned int), 0, 0);
    clQueue->enqueueWriteBuffer(*input_d, CL_FALSE, 0, input->size() * sizeof(inputDataType), reinterpret_cast< void * >(input->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error (memory initialization): " << std::to_string(err.err()) << "." << std::endl;
    throw;
  }
}

<|endoftext|>


<commit_before>#include "CurlWikiGrabber.h"

//! Todo: look for better implementation
static std::string gotContent = "";
static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    gotContent.append(ptr, size * nmemb);
    return size * nmemb;
}

//! TODO: change to passing page title
std::string CurlWikiGrabber::grabUrl(std::string url)
{
    CURL *handle = curl_easy_init();

    if(NULL == handle)
    {
        throw WalkerException("error initiating curl");
    }

    curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
    curl_easy_setopt(handle, CURLOPT_USERAGENT, "WikiWalker/ test program");
    curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_callback);
    gotContent = "";
    curl_easy_perform(handle);

    curl_easy_cleanup(handle);
    handle = NULL;
    return std::string(gotContent);
}

// note to self: API
// https://en.wikipedia.org/w/api.php
// /w/api.php?action=query&format=json&prop=links&pllimit=100&titles=<title>
<commit_msg>Parse content with Json::Reader<commit_after>#include "CurlWikiGrabber.h"
#include <json/json.h>

//! Todo: look for better implementation
static std::string gotContent = "";
static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
    gotContent.append(ptr, size * nmemb);
    return size * nmemb;
}

//! TODO: change to passing page title
std::string CurlWikiGrabber::grabUrl(std::string url)
{
    CURL *handle = curl_easy_init();

    if(NULL == handle)
    {
        throw WalkerException("error initiating curl");
    }

    curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
    curl_easy_setopt(handle, CURLOPT_USERAGENT, "WikiWalker/ test program");
    curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_callback);
    gotContent = "";
    curl_easy_perform(handle);

    curl_easy_cleanup(handle);
    handle = NULL;

    Json::Reader reader;
    Json::Value document;
    bool success = reader.parse(gotContent, document, false);

    if(!success) {
        throw WalkerException("Error parsing JSON");
    }

    return std::string(gotContent);
}

// note to self: API
// https://en.wikipedia.org/w/api.php
// /w/api.php?action=query&format=json&prop=links&plnamespace=0&titles=<title>
// maybe &pllimit=100
<|endoftext|>


<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/InvocationOptions.h"
#include "cling/Interpreter/ClingOptions.h"

#include "clang/Driver/Options.h"

#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Support/raw_ostream.h"

#include <memory>

using namespace clang;
using namespace cling::driver::clingoptions;

using namespace llvm;
using namespace llvm::opt;

namespace {

#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
               HELPTEXT, METAVAR)
#include "cling/Interpreter/ClingOptions.inc"
#undef OPTION
#undef PREFIX

  static const OptTable::Info ClingInfoTable[] = {
#define PREFIX(NAME, VALUE)
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
               HELPTEXT, METAVAR)   \
  { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
    FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
#include "cling/Interpreter/ClingOptions.inc"
#undef OPTION
#undef PREFIX
  };

  class ClingOptTable : public OptTable {
  public:
    ClingOptTable()
      : OptTable(ClingInfoTable,
                 sizeof(ClingInfoTable) / sizeof(ClingInfoTable[0])) {}
  };

  static OptTable* CreateClingOptTable() {
    return new ClingOptTable();
  }

  static void ParseStartupOpts(cling::InvocationOptions& Opts,
                               InputArgList& Args /* , Diags */) {
    Opts.ErrorOut = Args.hasArg(OPT__errorout);
    Opts.NoLogo = Args.hasArg(OPT__nologo);
    Opts.ShowVersion = Args.hasArg(OPT_version);
    Opts.Verbose = Args.hasArg(OPT_v);
    Opts.Help = Args.hasArg(OPT_help);
    if (Args.hasArg(OPT__metastr, OPT__metastr_EQ)) {
      Arg* MetaStringArg = Args.getLastArg(OPT__metastr, OPT__metastr_EQ);
      Opts.MetaString = MetaStringArg->getValue();
      if (Opts.MetaString.length() == 0) {
        llvm::errs() << "ERROR: meta string must be non-empty! Defaulting to '.'.\n";
        Opts.MetaString = ".";
      }
    }
  }

  static void ParseLinkerOpts(cling::InvocationOptions& Opts,
                              InputArgList& Args /* , Diags */) {
    Opts.LibsToLoad = Args.getAllArgValues(OPT_l);
    std::vector<std::string> LibPaths = Args.getAllArgValues(OPT_L);
    for (size_t i = 0; i < LibPaths.size(); ++i)
      Opts.LibSearchPath.push_back(LibPaths[i]);
  }

  static void ParseInputs(cling::InvocationOptions& Opts,
                          int argc, const char* const argv[]) {
    if (argc <= 1) { return; }
    unsigned MissingArgIndex, MissingArgCount;
    std::unique_ptr<OptTable> OptsC1(clang::driver::createDriverOptTable());
    Opts.Inputs.clear();
    std::unique_ptr<InputArgList> Args(
        OptsC1->ParseArgs(argv+1, argv + argc, MissingArgIndex, MissingArgCount));
    for (ArgList::const_iterator it = Args->begin(),
           ie = Args->end(); it != ie; ++it) {
      if ( (*it)->getOption().getKind() == Option::InputClass ) {
          Opts.Inputs.push_back(std::string( (*it)->getValue() ) );
      }
    }
  }
}

cling::InvocationOptions
cling::InvocationOptions::CreateFromArgs(int argc, const char* const argv[],
                                         std::vector<unsigned>& leftoverArgs
                                         /* , Diagnostic &Diags */) {
  InvocationOptions ClingOpts;
  std::unique_ptr<OptTable> Opts(CreateClingOptTable());
  unsigned MissingArgIndex, MissingArgCount;
  std::unique_ptr<InputArgList> Args(
    Opts->ParseArgs(argv, argv + argc, MissingArgIndex, MissingArgCount));

  //if (MissingArgCount)
  //  Diags.Report(diag::err_drv_missing_argument)
  //    << Args->getArgString(MissingArgIndex) << MissingArgCount;

  // Forward unknown arguments.
  for (ArgList::const_iterator it = Args->begin(),
         ie = Args->end(); it != ie; ++it) {
    if ((*it)->getOption().getKind() == Option::UnknownClass
        ||(*it)->getOption().getKind() == Option::InputClass) {
      leftoverArgs.push_back((*it)->getIndex());
    }
  }
  ParseStartupOpts(ClingOpts, *Args /* , Diags */);
  ParseLinkerOpts(ClingOpts, *Args /* , Diags */);
  ParseInputs(ClingOpts, argc, argv);
  return ClingOpts;
}

void cling::InvocationOptions::PrintHelp() {
  std::unique_ptr<OptTable> Opts(CreateClingOptTable());

  Opts->PrintHelp(llvm::outs(), "cling",
                  "cling: LLVM/clang C++ Interpreter: http://cern.ch/cling");

  llvm::outs() << "\n\n";

  std::unique_ptr<OptTable> OptsC1(clang::driver::createDriverOptTable());
  OptsC1->PrintHelp(llvm::outs(), "clang -cc1",
                    "LLVM 'Clang' Compiler: http://clang.llvm.org");

}
<commit_msg>Do not interpret /Users/... as /U sers; fixes MacOS cling tests.<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/InvocationOptions.h"
#include "cling/Interpreter/ClingOptions.h"

#include "clang/Driver/Options.h"

#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Support/raw_ostream.h"

#include <memory>

using namespace clang;
using namespace cling::driver::clingoptions;

using namespace llvm;
using namespace llvm::opt;

namespace {

#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
               HELPTEXT, METAVAR)
#include "cling/Interpreter/ClingOptions.inc"
#undef OPTION
#undef PREFIX

  static const OptTable::Info ClingInfoTable[] = {
#define PREFIX(NAME, VALUE)
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
               HELPTEXT, METAVAR)   \
  { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
    FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
#include "cling/Interpreter/ClingOptions.inc"
#undef OPTION
#undef PREFIX
  };

  class ClingOptTable : public OptTable {
  public:
    ClingOptTable()
      : OptTable(ClingInfoTable,
                 sizeof(ClingInfoTable) / sizeof(ClingInfoTable[0])) {}
  };

  static OptTable* CreateClingOptTable() {
    return new ClingOptTable();
  }

  static void ParseStartupOpts(cling::InvocationOptions& Opts,
                               InputArgList& Args /* , Diags */) {
    Opts.ErrorOut = Args.hasArg(OPT__errorout);
    Opts.NoLogo = Args.hasArg(OPT__nologo);
    Opts.ShowVersion = Args.hasArg(OPT_version);
    Opts.Verbose = Args.hasArg(OPT_v);
    Opts.Help = Args.hasArg(OPT_help);
    if (Args.hasArg(OPT__metastr, OPT__metastr_EQ)) {
      Arg* MetaStringArg = Args.getLastArg(OPT__metastr, OPT__metastr_EQ);
      Opts.MetaString = MetaStringArg->getValue();
      if (Opts.MetaString.length() == 0) {
        llvm::errs() << "ERROR: meta string must be non-empty! Defaulting to '.'.\n";
        Opts.MetaString = ".";
      }
    }
  }

  static void ParseLinkerOpts(cling::InvocationOptions& Opts,
                              InputArgList& Args /* , Diags */) {
    Opts.LibsToLoad = Args.getAllArgValues(OPT_l);
    std::vector<std::string> LibPaths = Args.getAllArgValues(OPT_L);
    for (size_t i = 0; i < LibPaths.size(); ++i)
      Opts.LibSearchPath.push_back(LibPaths[i]);
  }

  static void ParseInputs(cling::InvocationOptions& Opts,
                          int argc, const char* const argv[]) {
    if (argc <= 1) { return; }
    unsigned MissingArgIndex, MissingArgCount;
    std::unique_ptr<OptTable> OptsC1(clang::driver::createDriverOptTable());
    Opts.Inputs.clear();
    // see Driver::getIncludeExcludeOptionFlagMasks()
    unsigned ExcludeOptionFlagMasks
      = clang::driver::options::NoDriverOption | clang::driver::options::CLOption;
    std::unique_ptr<InputArgList> Args(
        OptsC1->ParseArgs(argv+1, argv + argc, MissingArgIndex, MissingArgCount,
                          0, ExcludeOptionFlagMasks));
    for (ArgList::const_iterator it = Args->begin(),
           ie = Args->end(); it != ie; ++it) {
      if ( (*it)->getOption().getKind() == Option::InputClass ) {
          Opts.Inputs.push_back(std::string( (*it)->getValue() ) );
      }
    }
  }
}

cling::InvocationOptions
cling::InvocationOptions::CreateFromArgs(int argc, const char* const argv[],
                                         std::vector<unsigned>& leftoverArgs
                                         /* , Diagnostic &Diags */) {
  InvocationOptions ClingOpts;
  std::unique_ptr<OptTable> Opts(CreateClingOptTable());
  unsigned MissingArgIndex, MissingArgCount;
  // see Driver::getIncludeExcludeOptionFlagMasks()
  unsigned ExcludeOptionFlagMasks
    = clang::driver::options::NoDriverOption | clang::driver::options::CLOption;
  std::unique_ptr<InputArgList> Args(
    Opts->ParseArgs(argv, argv + argc, MissingArgIndex, MissingArgCount,
                    0, ExcludeOptionFlagMasks));

  //if (MissingArgCount)
  //  Diags.Report(diag::err_drv_missing_argument)
  //    << Args->getArgString(MissingArgIndex) << MissingArgCount;

  // Forward unknown arguments.
  for (ArgList::const_iterator it = Args->begin(),
         ie = Args->end(); it != ie; ++it) {
    if ((*it)->getOption().getKind() == Option::UnknownClass
        ||(*it)->getOption().getKind() == Option::InputClass) {
      leftoverArgs.push_back((*it)->getIndex());
    }
  }
  ParseStartupOpts(ClingOpts, *Args /* , Diags */);
  ParseLinkerOpts(ClingOpts, *Args /* , Diags */);
  ParseInputs(ClingOpts, argc, argv);
  return ClingOpts;
}

void cling::InvocationOptions::PrintHelp() {
  std::unique_ptr<OptTable> Opts(CreateClingOptTable());

  Opts->PrintHelp(llvm::outs(), "cling",
                  "cling: LLVM/clang C++ Interpreter: http://cern.ch/cling");

  llvm::outs() << "\n\n";

  std::unique_ptr<OptTable> OptsC1(clang::driver::createDriverOptTable());
  OptsC1->PrintHelp(llvm::outs(), "clang -cc1",
                    "LLVM 'Clang' Compiler: http://clang.llvm.org");

}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008, Willow Garage, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "billboard_line.h"

#include <OGRE/OgreSceneManager.h>
#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreVector3.h>
#include <OGRE/OgreQuaternion.h>
#include <OGRE/OgreBillboardChain.h>
#include <OGRE/OgreMaterialManager.h>
#include <OGRE/OgreTechnique.h>

#include <sstream>

#include <ros/assert.h>

#define MAX_ELEMENTS (65536 / 4)

namespace rviz
{
BillboardLine::BillboardLine(Ogre::SceneManager* scene_manager, Ogre::SceneNode* parent_node)
  : Object(scene_manager)
  , width_(0.1f)
  , current_line_(0)
  , total_elements_(0)
  , num_lines_(1)
  , max_points_per_line_(100)
  , lines_per_chain_(0)
  , current_chain_(0)
  , elements_in_current_chain_(0)
{
  if (!parent_node)
  {
    parent_node = scene_manager_->getRootSceneNode();
  }

  scene_node_ = parent_node->createChildSceneNode();

  static int count = 0;
  std::stringstream ss;
  ss << "BillboardLineMaterial" << count++;
  material_ = Ogre::MaterialManager::getSingleton().create(
      ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
  material_->setReceiveShadows(false);
  material_->getTechnique(0)->setLightingEnabled(false);

  setNumLines(num_lines_);
  setMaxPointsPerLine(max_points_per_line_);
}

BillboardLine::~BillboardLine()
{
  V_Chain::iterator it = chains_.begin();
  V_Chain::iterator end = chains_.end();
  for (; it != end; ++it)
  {
    scene_manager_->destroyBillboardChain(*it);
  }

  scene_manager_->destroySceneNode(scene_node_->getName());

  Ogre::MaterialManager::getSingleton().remove(material_->getName());
}

Ogre::BillboardChain* BillboardLine::createChain()
{
  std::stringstream ss;
  static int count = 0;
  ss << "BillboardLine chain" << count++;
  Ogre::BillboardChain* chain = scene_manager_->createBillboardChain(ss.str());
  chain->setMaterialName(material_->getName());
  scene_node_->attachObject(chain);

  chains_.push_back(chain);

  return chain;
}

void BillboardLine::clear()
{
  V_Chain::iterator it = chains_.begin();
  V_Chain::iterator end = chains_.end();
  for (; it != end; ++it)
  {
    (*it)->clearAllChains();
  }

  current_line_ = 0;
  total_elements_ = 0;
  current_chain_ = 0;
  elements_in_current_chain_ = 0;

  for (V_uint32::iterator it = num_elements_.begin(); it != num_elements_.end(); ++it)
  {
    *it = 0;
  }
}

void BillboardLine::setupChains()
{
  uint32_t total_points = max_points_per_line_ * num_lines_;
  uint32_t num_chains = total_points / MAX_ELEMENTS;
  if (total_points % MAX_ELEMENTS != 0)
  {
    ++num_chains;
  }

  for (uint32_t i = chains_.size(); i < num_chains; ++i)
  {
    createChain();
  }

  lines_per_chain_ = max_points_per_line_ > 0 ? MAX_ELEMENTS / max_points_per_line_ : 1;

  V_Chain::iterator it = chains_.begin();
  V_Chain::iterator end = chains_.end();
  for (; it != end; ++it)
  {
    (*it)->setMaxChainElements(max_points_per_line_);

    // shorten the number of chains in the last bbchain, to avoid memory wasteage
    if (it + 1 == end)
    {
      uint32_t lines_left = num_lines_ % lines_per_chain_;

      // Handle the case where num_lines_ is a multiple of lines_per_chain
      if (lines_left == 0)
      {
        (*it)->setNumberOfChains(lines_per_chain_);
      }
      else
      {
        (*it)->setNumberOfChains(lines_left);
      }
    }
    else
    {
      (*it)->setNumberOfChains(lines_per_chain_);
    }
  }
}

void BillboardLine::setMaxPointsPerLine(uint32_t max)
{
  max_points_per_line_ = max;

  setupChains();
}

void BillboardLine::setNumLines(uint32_t num)
{
  num_lines_ = num;

  setupChains();

  num_elements_.resize(num);

  for (V_uint32::iterator it = num_elements_.begin(); it != num_elements_.end(); ++it)
  {
    *it = 0;
  }
}

void BillboardLine::newLine()
{
  ++current_line_;

  ROS_ASSERT(current_line_ < num_lines_);
}

void BillboardLine::addPoint(const Ogre::Vector3& point)
{
  addPoint(point, color_);
}

void BillboardLine::addPoint(const Ogre::Vector3& point, const Ogre::ColourValue& color)
{
  ++num_elements_[current_line_];
  ++total_elements_;

  ROS_ASSERT(num_elements_[current_line_] <= max_points_per_line_);

  ++elements_in_current_chain_;
  if (elements_in_current_chain_ > MAX_ELEMENTS)
  {
    ++current_chain_;
    elements_in_current_chain_ = 1;
  }

  Ogre::BillboardChain::Element e;
  e.position = point;
  e.width = width_;
  e.colour = color;
  chains_[current_chain_]->addChainElement(current_line_ % lines_per_chain_, e);
}

void BillboardLine::setLineWidth(float width)
{
  width_ = width;

  for (uint32_t line = 0; line < num_lines_; ++line)
  {
    uint32_t element_count = num_elements_[line];

    for (uint32_t i = 0; i < element_count; ++i)
    {
      Ogre::BillboardChain* c = chains_[line / lines_per_chain_];
      Ogre::BillboardChain::Element e = c->getChainElement(line % lines_per_chain_, i);

      e.width = width_;
      c->updateChainElement(line % lines_per_chain_, i, e);
    }
  }
}

void BillboardLine::setPosition(const Ogre::Vector3& position)
{
  scene_node_->setPosition(position);
}

void BillboardLine::setOrientation(const Ogre::Quaternion& orientation)
{
  scene_node_->setOrientation(orientation);
}

void BillboardLine::setScale(const Ogre::Vector3& /*scale*/)
{
  // Setting scale doesn't really make sense here
}

void BillboardLine::setColor(float r, float g, float b, float a)
{
  if (a < 0.9998)
  {
    material_->getTechnique(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
    material_->getTechnique(0)->setDepthWriteEnabled(false);
  }
  else
  {
    material_->getTechnique(0)->setSceneBlending(Ogre::SBT_REPLACE);
    material_->getTechnique(0)->setDepthWriteEnabled(true);
  }

  color_ = Ogre::ColourValue(r, g, b, a);

  for (uint32_t line = 0; line < num_lines_; ++line)
  {
    uint32_t element_count = num_elements_[line];

    for (uint32_t i = 0; i < element_count; ++i)
    {
      Ogre::BillboardChain* c = chains_[line / lines_per_chain_];
      Ogre::BillboardChain::Element e = c->getChainElement(line % lines_per_chain_, i);

      e.colour = color_;
      c->updateChainElement(line % lines_per_chain_, i, e);
    }
  }
}

const Ogre::Vector3& BillboardLine::getPosition()
{
  return scene_node_->getPosition();
}

const Ogre::Quaternion& BillboardLine::getOrientation()
{
  return scene_node_->getOrientation();
}

} // namespace rviz
<commit_msg>BillboardLine: Fix handling of many points (> 16384) (#1662)<commit_after>/*
 * Copyright (c) 2008, Willow Garage, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "billboard_line.h"

#include <OGRE/OgreSceneManager.h>
#include <OGRE/OgreSceneNode.h>
#include <OGRE/OgreVector3.h>
#include <OGRE/OgreQuaternion.h>
#include <OGRE/OgreBillboardChain.h>
#include <OGRE/OgreMaterialManager.h>
#include <OGRE/OgreTechnique.h>

#include <sstream>

#include <ros/assert.h>

#define MAX_ELEMENTS (65536 / 4)

namespace rviz
{
BillboardLine::BillboardLine(Ogre::SceneManager* scene_manager, Ogre::SceneNode* parent_node)
  : Object(scene_manager)
  , width_(0.1f)
  , current_line_(0)
  , total_elements_(0)
  , num_lines_(1)
  , max_points_per_line_(100)
  , lines_per_chain_(0)
  , current_chain_(0)
  , elements_in_current_chain_(0)
{
  if (!parent_node)
  {
    parent_node = scene_manager_->getRootSceneNode();
  }

  scene_node_ = parent_node->createChildSceneNode();

  static int count = 0;
  std::stringstream ss;
  ss << "BillboardLineMaterial" << count++;
  material_ = Ogre::MaterialManager::getSingleton().create(
      ss.str(), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
  material_->setReceiveShadows(false);
  material_->getTechnique(0)->setLightingEnabled(false);

  setNumLines(num_lines_);
}

BillboardLine::~BillboardLine()
{
  V_Chain::iterator it = chains_.begin();
  V_Chain::iterator end = chains_.end();
  for (; it != end; ++it)
  {
    scene_manager_->destroyBillboardChain(*it);
  }

  scene_manager_->destroySceneNode(scene_node_->getName());

  Ogre::MaterialManager::getSingleton().remove(material_->getName());
}

Ogre::BillboardChain* BillboardLine::createChain()
{
  std::stringstream ss;
  static int count = 0;
  ss << "BillboardLine chain" << count++;
  Ogre::BillboardChain* chain = scene_manager_->createBillboardChain(ss.str());
  chain->setMaterialName(material_->getName());
  scene_node_->attachObject(chain);

  chains_.push_back(chain);

  return chain;
}

void BillboardLine::clear()
{
  V_Chain::iterator it = chains_.begin();
  V_Chain::iterator end = chains_.end();
  for (; it != end; ++it)
  {
    (*it)->clearAllChains();
  }

  current_line_ = 0;
  total_elements_ = 0;
  current_chain_ = 0;
  elements_in_current_chain_ = 0;

  for (V_uint32::iterator it = num_elements_.begin(); it != num_elements_.end(); ++it)
  {
    *it = 0;
  }
}

void BillboardLine::setupChains()
{
  uint32_t total_points = max_points_per_line_ * num_lines_;
  uint32_t num_chains = total_points / MAX_ELEMENTS;
  if (total_points % MAX_ELEMENTS != 0)
  {
    ++num_chains;
  }

  for (uint32_t i = chains_.size(); i < num_chains; ++i)
  {
    createChain();
  }

  lines_per_chain_ = max_points_per_line_ > 0 ? MAX_ELEMENTS / max_points_per_line_ : 1;

  V_Chain::iterator it = chains_.begin();
  V_Chain::iterator end = chains_.end();
  for (; it != end; ++it)
  {
    (*it)->setMaxChainElements(max_points_per_line_);

    // shorten the number of chains in the last bbchain, to avoid memory wasteage
    if (it + 1 == end)
    {
      uint32_t lines_left = num_lines_ % lines_per_chain_;

      // Handle the case where num_lines_ is a multiple of lines_per_chain
      if (lines_left == 0)
      {
        (*it)->setNumberOfChains(lines_per_chain_);
      }
      else
      {
        (*it)->setNumberOfChains(lines_left);
      }
    }
    else
    {
      (*it)->setNumberOfChains(lines_per_chain_);
    }
  }
}

void BillboardLine::setMaxPointsPerLine(uint32_t max)
{
  if (max <= MAX_ELEMENTS)
  {
    max_points_per_line_ = max;
    setupChains();
  }
  else // need to split points across several lines
  {
    ROS_ASSERT(num_lines_ == 1);
    max_points_per_line_ = MAX_ELEMENTS;
    num_lines_ = max / MAX_ELEMENTS;
    if (max % MAX_ELEMENTS != 0)
      ++num_lines_;
    setNumLines(num_lines_);
  }
}

void BillboardLine::setNumLines(uint32_t num)
{
  num_lines_ = num;

  setupChains();

  num_elements_.resize(num);

  for (V_uint32::iterator it = num_elements_.begin(); it != num_elements_.end(); ++it)
  {
    *it = 0;
  }
}

void BillboardLine::newLine()
{
  ++current_line_;

  ROS_ASSERT(current_line_ < num_lines_);
}

void BillboardLine::addPoint(const Ogre::Vector3& point)
{
  addPoint(point, color_);
}

void BillboardLine::addPoint(const Ogre::Vector3& point, const Ogre::ColourValue& color)
{
  ++elements_in_current_chain_;
  if (elements_in_current_chain_ > MAX_ELEMENTS)
  {
    ++current_chain_;
    elements_in_current_chain_ = 1;

    if (max_points_per_line_ == MAX_ELEMENTS)
      newLine();
  }

  ++num_elements_[current_line_];
  ++total_elements_;

  ROS_ASSERT(num_elements_[current_line_] < max_points_per_line_);

  Ogre::BillboardChain::Element e;
  e.position = point;
  e.width = width_;
  e.colour = color;
  chains_[current_chain_]->addChainElement(current_line_ % lines_per_chain_, e);
}

void BillboardLine::setLineWidth(float width)
{
  width_ = width;

  for (uint32_t line = 0; line < num_lines_; ++line)
  {
    uint32_t element_count = num_elements_[line];

    for (uint32_t i = 0; i < element_count; ++i)
    {
      Ogre::BillboardChain* c = chains_[line / lines_per_chain_];
      Ogre::BillboardChain::Element e = c->getChainElement(line % lines_per_chain_, i);

      e.width = width_;
      c->updateChainElement(line % lines_per_chain_, i, e);
    }
  }
}

void BillboardLine::setPosition(const Ogre::Vector3& position)
{
  scene_node_->setPosition(position);
}

void BillboardLine::setOrientation(const Ogre::Quaternion& orientation)
{
  scene_node_->setOrientation(orientation);
}

void BillboardLine::setScale(const Ogre::Vector3& /*scale*/)
{
  // Setting scale doesn't really make sense here
}

void BillboardLine::setColor(float r, float g, float b, float a)
{
  if (a < 0.9998)
  {
    material_->getTechnique(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
    material_->getTechnique(0)->setDepthWriteEnabled(false);
  }
  else
  {
    material_->getTechnique(0)->setSceneBlending(Ogre::SBT_REPLACE);
    material_->getTechnique(0)->setDepthWriteEnabled(true);
  }

  color_ = Ogre::ColourValue(r, g, b, a);

  for (uint32_t line = 0; line < num_lines_; ++line)
  {
    uint32_t element_count = num_elements_[line];

    for (uint32_t i = 0; i < element_count; ++i)
    {
      Ogre::BillboardChain* c = chains_[line / lines_per_chain_];
      Ogre::BillboardChain::Element e = c->getChainElement(line % lines_per_chain_, i);

      e.colour = color_;
      c->updateChainElement(line % lines_per_chain_, i, e);
    }
  }
}

const Ogre::Vector3& BillboardLine::getPosition()
{
  return scene_node_->getPosition();
}

const Ogre::Quaternion& BillboardLine::getOrientation()
{
  return scene_node_->getOrientation();
}

} // namespace rviz
<|endoftext|>


<commit_before>// Check that we can get the first function argument logged
// using a custom logging function.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=arg1-logger-" %run %t 2>&1 | FileCheck %s
//
// After all that, clean up the XRay log file.
//
// RUN: rm arg1-logger-*
//
// At the time of writing, the ARM trampolines weren't written yet.
// XFAIL: arm || aarch64

#include "xray/xray_interface.h"

#include <cinttypes>
#include <cstdio>

void arg1logger(int32_t fn, XRayEntryType t, uint64_t a1) {
  printf("Arg1: %" PRIx64 ", XRayEntryType %u\n", a1, t);
}

[[clang::xray_always_instrument, clang::xray_log_args(1)]] void foo(void *) {}

int main() {
  // CHECK: XRay: Log file in 'arg1-logger-{{.*}}'

  __xray_set_handler_arg1(arg1logger);
  foo(nullptr);
  // CHECK: Arg1: 0, XRayEntryType 0

  __xray_remove_handler_arg1();
  foo((void *) 0xBADC0DE);
  // nothing expected to see here

  __xray_set_handler_arg1(arg1logger);
  foo((void *) 0xDEADBEEFCAFE);
  // CHECK-NEXT: Arg1: deadbeefcafe, XRayEntryType 0
  foo((void *) -1);
  // CHECK-NEXT: Arg1: ffffffffffffffff, XRayEntryType 0
}
<commit_msg>[PowerPC] mark xray test as unsupported on powerpcle in testsuite<commit_after>// Check that we can get the first function argument logged
// using a custom logging function.
//
// RUN: %clangxx_xray -std=c++11 %s -o %t
// RUN: XRAY_OPTIONS="patch_premain=true verbosity=1 xray_logfile_base=arg1-logger-" %run %t 2>&1 | FileCheck %s
//
// After all that, clean up the XRay log file.
//
// RUN: rm arg1-logger-*
//
// At the time of writing, the ARM trampolines weren't written yet.
// XFAIL: arm || aarch64
// See the mailing list discussion of r296998.
// UNSUPPORTED: powerpc64le

#include "xray/xray_interface.h"

#include <cinttypes>
#include <cstdio>

void arg1logger(int32_t fn, XRayEntryType t, uint64_t a1) {
  printf("Arg1: %" PRIx64 ", XRayEntryType %u\n", a1, t);
}

[[clang::xray_always_instrument, clang::xray_log_args(1)]] void foo(void *) {}

int main() {
  // CHECK: XRay: Log file in 'arg1-logger-{{.*}}'

  __xray_set_handler_arg1(arg1logger);
  foo(nullptr);
  // CHECK: Arg1: 0, XRayEntryType 0

  __xray_remove_handler_arg1();
  foo((void *) 0xBADC0DE);
  // nothing expected to see here

  __xray_set_handler_arg1(arg1logger);
  foo((void *) 0xDEADBEEFCAFE);
  // CHECK-NEXT: Arg1: deadbeefcafe, XRayEntryType 0
  foo((void *) -1);
  // CHECK-NEXT: Arg1: ffffffffffffffff, XRayEntryType 0
}
<|endoftext|>


<commit_before>//===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implements the info about Mips target spec.
//
//===----------------------------------------------------------------------===//

#include "Mips.h"
#include "MipsTargetMachine.h"
#include "llvm/PassManager.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;

extern "C" void LLVMInitializeMipsTarget() {
  // Register the target.
  RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget);
  RegisterTargetMachine<MipselTargetMachine> Y(TheMipselTarget);
  RegisterTargetMachine<Mips64ebTargetMachine> A(TheMips64Target);
  RegisterTargetMachine<Mips64elTargetMachine> B(TheMips64elTarget);
}

// DataLayout --> Big-endian, 32-bit pointer/ABI/alignment
// The stack is always 8 byte aligned
// On function prologue, the stack is created by decrementing
// its pointer. Once decremented, all references are done with positive
// offset from the stack/frame pointer, using StackGrowsUp enables
// an easier handling.
// Using CodeModel::Large enables different CALL behavior.
MipsTargetMachine::
MipsTargetMachine(const Target &T, StringRef TT,
                  StringRef CPU, StringRef FS,
                  Reloc::Model RM, CodeModel::Model CM,
                  bool isLittle):
  LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
  Subtarget(TT, CPU, FS, isLittle),
  DataLayout(isLittle ?
             (Subtarget.isABI_N64() ?
              "e-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-n32" :
              "e-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32") :
             (Subtarget.isABI_N64() ?
              "E-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-n32" :
              "E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32")),
  InstrInfo(*this),
  FrameLowering(Subtarget),
  TLInfo(*this), TSInfo(*this), JITInfo() {
}

MipsebTargetMachine::
MipsebTargetMachine(const Target &T, StringRef TT,
                    StringRef CPU, StringRef FS,
                    Reloc::Model RM, CodeModel::Model CM) :
  MipsTargetMachine(T, TT, CPU, FS, RM, CM, false) {}

MipselTargetMachine::
MipselTargetMachine(const Target &T, StringRef TT,
                    StringRef CPU, StringRef FS,
                    Reloc::Model RM, CodeModel::Model CM) :
  MipsTargetMachine(T, TT, CPU, FS, RM, CM, true) {}

Mips64ebTargetMachine::
Mips64ebTargetMachine(const Target &T, StringRef TT,
                      StringRef CPU, StringRef FS,
                      Reloc::Model RM, CodeModel::Model CM) :
  MipsTargetMachine(T, TT, CPU, FS, RM, CM, false) {}

Mips64elTargetMachine::
Mips64elTargetMachine(const Target &T, StringRef TT,
                      StringRef CPU, StringRef FS,
                      Reloc::Model RM, CodeModel::Model CM) :
  MipsTargetMachine(T, TT, CPU, FS, RM, CM, true) {}

// Install an instruction selector pass using
// the ISelDag to gen Mips code.
bool MipsTargetMachine::
addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
{
  PM.add(createMipsISelDag(*this));
  return false;
}

// Implemented by targets that want to run passes immediately before
// machine code is emitted. return true if -print-machineinstrs should
// print out the code after the passes.
bool MipsTargetMachine::
addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
{
  PM.add(createMipsDelaySlotFillerPass(*this));
  return true;
}

bool MipsTargetMachine::
addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) {
  // Do not restore $gp if target is Mips64.
  // In N32/64, $gp is a callee-saved register.
  if (!Subtarget.hasMips64())
    PM.add(createMipsEmitGPRestorePass(*this));
  return true;
}

bool MipsTargetMachine::
addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) {
  PM.add(createMipsExpandPseudoPass(*this));
  return true;
}

bool MipsTargetMachine::addCodeEmitter(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel,
                                          JITCodeEmitter &JCE) {
  // Machine code emitter pass for Mips.
  PM.add(createMipsJITCodeEmitterPass(*this, JCE));
  return false;
}

<commit_msg>Add f128 to datalayout string.<commit_after>//===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implements the info about Mips target spec.
//
//===----------------------------------------------------------------------===//

#include "Mips.h"
#include "MipsTargetMachine.h"
#include "llvm/PassManager.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;

extern "C" void LLVMInitializeMipsTarget() {
  // Register the target.
  RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget);
  RegisterTargetMachine<MipselTargetMachine> Y(TheMipselTarget);
  RegisterTargetMachine<Mips64ebTargetMachine> A(TheMips64Target);
  RegisterTargetMachine<Mips64elTargetMachine> B(TheMips64elTarget);
}

// DataLayout --> Big-endian, 32-bit pointer/ABI/alignment
// The stack is always 8 byte aligned
// On function prologue, the stack is created by decrementing
// its pointer. Once decremented, all references are done with positive
// offset from the stack/frame pointer, using StackGrowsUp enables
// an easier handling.
// Using CodeModel::Large enables different CALL behavior.
MipsTargetMachine::
MipsTargetMachine(const Target &T, StringRef TT,
                  StringRef CPU, StringRef FS,
                  Reloc::Model RM, CodeModel::Model CM,
                  bool isLittle):
  LLVMTargetMachine(T, TT, CPU, FS, RM, CM),
  Subtarget(TT, CPU, FS, isLittle),
  DataLayout(isLittle ?
             (Subtarget.isABI_N64() ?
              "e-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-n32" :
              "e-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32") :
             (Subtarget.isABI_N64() ?
              "E-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-n32" :
              "E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32")),
  InstrInfo(*this),
  FrameLowering(Subtarget),
  TLInfo(*this), TSInfo(*this), JITInfo() {
}

MipsebTargetMachine::
MipsebTargetMachine(const Target &T, StringRef TT,
                    StringRef CPU, StringRef FS,
                    Reloc::Model RM, CodeModel::Model CM) :
  MipsTargetMachine(T, TT, CPU, FS, RM, CM, false) {}

MipselTargetMachine::
MipselTargetMachine(const Target &T, StringRef TT,
                    StringRef CPU, StringRef FS,
                    Reloc::Model RM, CodeModel::Model CM) :
  MipsTargetMachine(T, TT, CPU, FS, RM, CM, true) {}

Mips64ebTargetMachine::
Mips64ebTargetMachine(const Target &T, StringRef TT,
                      StringRef CPU, StringRef FS,
                      Reloc::Model RM, CodeModel::Model CM) :
  MipsTargetMachine(T, TT, CPU, FS, RM, CM, false) {}

Mips64elTargetMachine::
Mips64elTargetMachine(const Target &T, StringRef TT,
                      StringRef CPU, StringRef FS,
                      Reloc::Model RM, CodeModel::Model CM) :
  MipsTargetMachine(T, TT, CPU, FS, RM, CM, true) {}

// Install an instruction selector pass using
// the ISelDag to gen Mips code.
bool MipsTargetMachine::
addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
{
  PM.add(createMipsISelDag(*this));
  return false;
}

// Implemented by targets that want to run passes immediately before
// machine code is emitted. return true if -print-machineinstrs should
// print out the code after the passes.
bool MipsTargetMachine::
addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
{
  PM.add(createMipsDelaySlotFillerPass(*this));
  return true;
}

bool MipsTargetMachine::
addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) {
  // Do not restore $gp if target is Mips64.
  // In N32/64, $gp is a callee-saved register.
  if (!Subtarget.hasMips64())
    PM.add(createMipsEmitGPRestorePass(*this));
  return true;
}

bool MipsTargetMachine::
addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel) {
  PM.add(createMipsExpandPseudoPass(*this));
  return true;
}

bool MipsTargetMachine::addCodeEmitter(PassManagerBase &PM,
                                          CodeGenOpt::Level OptLevel,
                                          JITCodeEmitter &JCE) {
  // Machine code emitter pass for Mips.
  PM.add(createMipsJITCodeEmitterPass(*this, JCE));
  return false;
}

<|endoftext|>


<commit_before>//===- Reassociate.cpp - Reassociate binary expressions -------------------===//
//
// This pass reassociates commutative expressions in an order that is designed
// to promote better constant propagation, GCSE, LICM, PRE...
//
// For example: 4 + (x + 5) -> x + (4 + 5)
//
// Note that this pass works best if left shifts have been promoted to explicit
// multiplies before this pass executes.
//
// In the implementation of this algorithm, constants are assigned rank = 0,
// function arguments are rank = 1, and other values are assigned ranks
// corresponding to the reverse post order traversal of current function
// (starting at 2), which effectively gives values in deep loops higher rank
// than values not in loops.
//
// This code was originally written by Chris Lattner, and was then cleaned up
// and perfected by Casey Carter.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Function.h"
#include "llvm/iOperators.h"
#include "llvm/Type.h"
#include "llvm/Pass.h"
#include "llvm/Constant.h"
#include "llvm/Support/CFG.h"
#include "Support/Debug.h"
#include "Support/PostOrderIterator.h"
#include "Support/Statistic.h"

namespace {
  Statistic<> NumLinear ("reassociate","Number of insts linearized");
  Statistic<> NumChanged("reassociate","Number of insts reassociated");
  Statistic<> NumSwapped("reassociate","Number of insts with operands swapped");

  class Reassociate : public FunctionPass {
    std::map<BasicBlock*, unsigned> RankMap;
    std::map<Instruction*, unsigned> InstRankMap;
  public:
    bool runOnFunction(Function &F);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
    }
  private:
    void BuildRankMap(Function &F);
    unsigned getRank(Value *V);
    bool ReassociateExpr(BinaryOperator *I);
    bool ReassociateBB(BasicBlock *BB);
  };

  RegisterOpt<Reassociate> X("reassociate", "Reassociate expressions");
}

Pass *createReassociatePass() { return new Reassociate(); }

void Reassociate::BuildRankMap(Function &F) {
  unsigned i = 2;
  ReversePostOrderTraversal<Function*> RPOT(&F);
  for (ReversePostOrderTraversal<Function*>::rpo_iterator I = RPOT.begin(),
         E = RPOT.end(); I != E; ++I)
    RankMap[*I] = ++i << 16;
}

unsigned Reassociate::getRank(Value *V) {
  if (isa<Argument>(V)) return 1;   // Function argument...
  if (Instruction *I = dyn_cast<Instruction>(V)) {
    // If this is an expression, return the 1+MAX(rank(LHS), rank(RHS)) so that
    // we can reassociate expressions for code motion!  Since we do not recurse
    // for PHI nodes, we cannot have infinite recursion here, because there
    // cannot be loops in the value graph that do not go through PHI nodes.
    //
    if (I->getOpcode() == Instruction::PHINode ||
        I->getOpcode() == Instruction::Alloca ||
        I->getOpcode() == Instruction::Malloc || isa<TerminatorInst>(I) ||
        I->mayWriteToMemory())  // Cannot move inst if it writes to memory!
      return RankMap[I->getParent()];

    unsigned &CachedRank = InstRankMap[I];
    if (CachedRank) return CachedRank;    // Rank already known?

    // If not, compute it!
    unsigned Rank = 0, MaxRank = RankMap[I->getParent()];
    for (unsigned i = 0, e = I->getNumOperands();
         i != e && Rank != MaxRank; ++i)
      Rank = std::max(Rank, getRank(I->getOperand(i)));

    DEBUG(std::cerr << "Calculated Rank[" << V->getName() << "] = "
                    << Rank+1 << "\n");

    return CachedRank = Rank+1;
  }

  // Otherwise it's a global or constant, rank 0.
  return 0;
}

bool Reassociate::ReassociateExpr(BinaryOperator *I) {
  Value *LHS = I->getOperand(0);
  Value *RHS = I->getOperand(1);
  unsigned LHSRank = getRank(LHS);
  unsigned RHSRank = getRank(RHS);

  bool Changed = false;

  // Make sure the LHS of the operand always has the greater rank...
  if (LHSRank < RHSRank) {
    bool Success = !I->swapOperands();
    assert(Success && "swapOperands failed");

    std::swap(LHS, RHS);
    std::swap(LHSRank, RHSRank);
    Changed = true;
    ++NumSwapped;
    DEBUG(std::cerr << "Transposed: " << I
          /* << " Result BB: " << I->getParent()*/);
  }

  // If the LHS is the same operator as the current one is, and if we are the
  // only expression using it...
  //
  if (BinaryOperator *LHSI = dyn_cast<BinaryOperator>(LHS))
    if (LHSI->getOpcode() == I->getOpcode() && LHSI->use_size() == 1) {
      // If the rank of our current RHS is less than the rank of the LHS's LHS,
      // then we reassociate the two instructions...
      if (RHSRank < getRank(LHSI->getOperand(0))) {
        unsigned TakeOp = 0;
        if (BinaryOperator *IOp = dyn_cast<BinaryOperator>(LHSI->getOperand(0)))
          if (IOp->getOpcode() == LHSI->getOpcode())
            TakeOp = 1;   // Hoist out non-tree portion

        // Convert ((a + 12) + 10) into (a + (12 + 10))
        I->setOperand(0, LHSI->getOperand(TakeOp));
        LHSI->setOperand(TakeOp, RHS);
        I->setOperand(1, LHSI);

        // Move the LHS expression forward, to ensure that it is dominated by
        // its operands.
        LHSI->getParent()->getInstList().remove(LHSI);
        I->getParent()->getInstList().insert(I, LHSI);

        ++NumChanged;
        DEBUG(std::cerr << "Reassociated: " << I/* << " Result BB: "
                                                   << I->getParent()*/);

        // Since we modified the RHS instruction, make sure that we recheck it.
        ReassociateExpr(LHSI);
        ReassociateExpr(I);
        return true;
      }
    }

  return Changed;
}

// NegateValue - Insert instructions before the instruction pointed to by BI,
// that computes the negative version of the value specified.  The negative
// version of the value is returned, and BI is left pointing at the instruction
// that should be processed next by the reassociation pass.
//
static Value *NegateValue(Value *V, BasicBlock::iterator &BI) {
  // We are trying to expose opportunity for reassociation.  One of the things
  // that we want to do to achieve this is to push a negation as deep into an
  // expression chain as possible, to expose the add instructions.  In practice,
  // this means that we turn this:
  //   X = -(A+12+C+D)   into    X = -A + -12 + -C + -D = -12 + -A + -C + -D
  // so that later, a: Y = 12+X could get reassociated with the -12 to eliminate
  // the constants.  We assume that instcombine will clean up the mess later if
  // we introduce tons of unneccesary negation instructions...
  //
  if (Instruction *I = dyn_cast<Instruction>(V))
    if (I->getOpcode() == Instruction::Add && I->use_size() == 1) {
      Value *RHS = NegateValue(I->getOperand(1), BI);
      Value *LHS = NegateValue(I->getOperand(0), BI);

      // We must actually insert a new add instruction here, because the neg
      // instructions do not dominate the old add instruction in general.  By
      // adding it now, we are assured that the neg instructions we just
      // inserted dominate the instruction we are about to insert after them.
      //
      return BinaryOperator::create(Instruction::Add, LHS, RHS,
                                    I->getName()+".neg",
                                    cast<Instruction>(RHS)->getNext());
    }

  // Insert a 'neg' instruction that subtracts the value from zero to get the
  // negation.
  //
  return BI = BinaryOperator::createNeg(V, V->getName() + ".neg", BI);
}

bool Reassociate::ReassociateBB(BasicBlock *BB) {
  bool Changed = false;
  for (BasicBlock::iterator BI = BB->begin(); BI != BB->end(); ++BI) {

    DEBUG(std::cerr << "Processing: " << *BI);
    if (BI->getOpcode() == Instruction::Sub && !BinaryOperator::isNeg(BI)) {
      // Convert a subtract into an add and a neg instruction... so that sub
      // instructions can be commuted with other add instructions...
      //
      // Calculate the negative value of Operand 1 of the sub instruction...
      // and set it as the RHS of the add instruction we just made...
      //
      std::string Name = BI->getName();
      BI->setName("");
      Instruction *New =
        BinaryOperator::create(Instruction::Add, BI->getOperand(0),
                               BI->getOperand(1), Name, BI);

      // Everyone now refers to the add instruction...
      BI->replaceAllUsesWith(New);

      // Put the new add in the place of the subtract... deleting the subtract
      BB->getInstList().erase(BI);

      BI = New;
      New->setOperand(1, NegateValue(New->getOperand(1), BI));

      Changed = true;
      DEBUG(std::cerr << "Negated: " << New /*<< " Result BB: " << BB*/);
    }

    // If this instruction is a commutative binary operator, and the ranks of
    // the two operands are sorted incorrectly, fix it now.
    //
    if (BI->isAssociative()) {
      BinaryOperator *I = cast<BinaryOperator>(BI);
      if (!I->use_empty()) {
        // Make sure that we don't have a tree-shaped computation.  If we do,
        // linearize it.  Convert (A+B)+(C+D) into ((A+B)+C)+D
        //
        Instruction *LHSI = dyn_cast<Instruction>(I->getOperand(0));
        Instruction *RHSI = dyn_cast<Instruction>(I->getOperand(1));
        if (LHSI && (int)LHSI->getOpcode() == I->getOpcode() &&
            RHSI && (int)RHSI->getOpcode() == I->getOpcode() &&
            RHSI->use_size() == 1) {
          // Insert a new temporary instruction... (A+B)+C
          BinaryOperator *Tmp = BinaryOperator::create(I->getOpcode(), LHSI,
                                                       RHSI->getOperand(0),
                                                       RHSI->getName()+".ra",
                                                       BI);
          BI = Tmp;
          I->setOperand(0, Tmp);
          I->setOperand(1, RHSI->getOperand(1));

          // Process the temporary instruction for reassociation now.
          I = Tmp;
          ++NumLinear;
          Changed = true;
          DEBUG(std::cerr << "Linearized: " << I/* << " Result BB: " << BB*/);
        }

        // Make sure that this expression is correctly reassociated with respect
        // to it's used values...
        //
        Changed |= ReassociateExpr(I);
      }
    }
  }

  return Changed;
}

bool Reassociate::runOnFunction(Function &F) {
  // Recalculate the rank map for F
  BuildRankMap(F);

  bool Changed = false;
  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
    Changed |= ReassociateBB(FI);

  // We are done with the rank map...
  RankMap.clear();
  InstRankMap.clear();
  return Changed;
}
<commit_msg>Fix bug: Reassociate/2003-08-12-InfiniteLoop.ll<commit_after>//===- Reassociate.cpp - Reassociate binary expressions -------------------===//
//
// This pass reassociates commutative expressions in an order that is designed
// to promote better constant propagation, GCSE, LICM, PRE...
//
// For example: 4 + (x + 5) -> x + (4 + 5)
//
// Note that this pass works best if left shifts have been promoted to explicit
// multiplies before this pass executes.
//
// In the implementation of this algorithm, constants are assigned rank = 0,
// function arguments are rank = 1, and other values are assigned ranks
// corresponding to the reverse post order traversal of current function
// (starting at 2), which effectively gives values in deep loops higher rank
// than values not in loops.
//
// This code was originally written by Chris Lattner, and was then cleaned up
// and perfected by Casey Carter.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Function.h"
#include "llvm/iOperators.h"
#include "llvm/Type.h"
#include "llvm/Pass.h"
#include "llvm/Constant.h"
#include "llvm/Support/CFG.h"
#include "Support/Debug.h"
#include "Support/PostOrderIterator.h"
#include "Support/Statistic.h"

namespace {
  Statistic<> NumLinear ("reassociate","Number of insts linearized");
  Statistic<> NumChanged("reassociate","Number of insts reassociated");
  Statistic<> NumSwapped("reassociate","Number of insts with operands swapped");

  class Reassociate : public FunctionPass {
    std::map<BasicBlock*, unsigned> RankMap;
    std::map<Instruction*, unsigned> InstRankMap;
  public:
    bool runOnFunction(Function &F);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
    }
  private:
    void BuildRankMap(Function &F);
    unsigned getRank(Value *V);
    bool ReassociateExpr(BinaryOperator *I);
    bool ReassociateBB(BasicBlock *BB);
  };

  RegisterOpt<Reassociate> X("reassociate", "Reassociate expressions");
}

Pass *createReassociatePass() { return new Reassociate(); }

void Reassociate::BuildRankMap(Function &F) {
  unsigned i = 2;
  ReversePostOrderTraversal<Function*> RPOT(&F);
  for (ReversePostOrderTraversal<Function*>::rpo_iterator I = RPOT.begin(),
         E = RPOT.end(); I != E; ++I)
    RankMap[*I] = ++i << 16;
}

unsigned Reassociate::getRank(Value *V) {
  if (isa<Argument>(V)) return 1;   // Function argument...
  if (Instruction *I = dyn_cast<Instruction>(V)) {
    // If this is an expression, return the 1+MAX(rank(LHS), rank(RHS)) so that
    // we can reassociate expressions for code motion!  Since we do not recurse
    // for PHI nodes, we cannot have infinite recursion here, because there
    // cannot be loops in the value graph that do not go through PHI nodes.
    //
    if (I->getOpcode() == Instruction::PHINode ||
        I->getOpcode() == Instruction::Alloca ||
        I->getOpcode() == Instruction::Malloc || isa<TerminatorInst>(I) ||
        I->mayWriteToMemory())  // Cannot move inst if it writes to memory!
      return RankMap[I->getParent()];

    unsigned &CachedRank = InstRankMap[I];
    if (CachedRank) return CachedRank;    // Rank already known?

    // If not, compute it!
    unsigned Rank = 0, MaxRank = RankMap[I->getParent()];
    for (unsigned i = 0, e = I->getNumOperands();
         i != e && Rank != MaxRank; ++i)
      Rank = std::max(Rank, getRank(I->getOperand(i)));

    DEBUG(std::cerr << "Calculated Rank[" << V->getName() << "] = "
                    << Rank+1 << "\n");

    return CachedRank = Rank+1;
  }

  // Otherwise it's a global or constant, rank 0.
  return 0;
}

bool Reassociate::ReassociateExpr(BinaryOperator *I) {
  Value *LHS = I->getOperand(0);
  Value *RHS = I->getOperand(1);
  unsigned LHSRank = getRank(LHS);
  unsigned RHSRank = getRank(RHS);

  bool Changed = false;

  // Make sure the LHS of the operand always has the greater rank...
  if (LHSRank < RHSRank) {
    bool Success = !I->swapOperands();
    assert(Success && "swapOperands failed");

    std::swap(LHS, RHS);
    std::swap(LHSRank, RHSRank);
    Changed = true;
    ++NumSwapped;
    DEBUG(std::cerr << "Transposed: " << I
          /* << " Result BB: " << I->getParent()*/);
  }

  // If the LHS is the same operator as the current one is, and if we are the
  // only expression using it...
  //
  if (BinaryOperator *LHSI = dyn_cast<BinaryOperator>(LHS))
    if (LHSI->getOpcode() == I->getOpcode() && LHSI->use_size() == 1) {
      // If the rank of our current RHS is less than the rank of the LHS's LHS,
      // then we reassociate the two instructions...

      unsigned TakeOp = 0;
      if (BinaryOperator *IOp = dyn_cast<BinaryOperator>(LHSI->getOperand(0)))
        if (IOp->getOpcode() == LHSI->getOpcode())
          TakeOp = 1;   // Hoist out non-tree portion

      if (RHSRank < getRank(LHSI->getOperand(TakeOp))) {
        // Convert ((a + 12) + 10) into (a + (12 + 10))
        I->setOperand(0, LHSI->getOperand(TakeOp));
        LHSI->setOperand(TakeOp, RHS);
        I->setOperand(1, LHSI);

        // Move the LHS expression forward, to ensure that it is dominated by
        // its operands.
        LHSI->getParent()->getInstList().remove(LHSI);
        I->getParent()->getInstList().insert(I, LHSI);

        ++NumChanged;
        DEBUG(std::cerr << "Reassociated: " << I/* << " Result BB: "
                                                   << I->getParent()*/);

        // Since we modified the RHS instruction, make sure that we recheck it.
        ReassociateExpr(LHSI);
        ReassociateExpr(I);
        return true;
      }
    }

  return Changed;
}

// NegateValue - Insert instructions before the instruction pointed to by BI,
// that computes the negative version of the value specified.  The negative
// version of the value is returned, and BI is left pointing at the instruction
// that should be processed next by the reassociation pass.
//
static Value *NegateValue(Value *V, BasicBlock::iterator &BI) {
  // We are trying to expose opportunity for reassociation.  One of the things
  // that we want to do to achieve this is to push a negation as deep into an
  // expression chain as possible, to expose the add instructions.  In practice,
  // this means that we turn this:
  //   X = -(A+12+C+D)   into    X = -A + -12 + -C + -D = -12 + -A + -C + -D
  // so that later, a: Y = 12+X could get reassociated with the -12 to eliminate
  // the constants.  We assume that instcombine will clean up the mess later if
  // we introduce tons of unneccesary negation instructions...
  //
  if (Instruction *I = dyn_cast<Instruction>(V))
    if (I->getOpcode() == Instruction::Add && I->use_size() == 1) {
      Value *RHS = NegateValue(I->getOperand(1), BI);
      Value *LHS = NegateValue(I->getOperand(0), BI);

      // We must actually insert a new add instruction here, because the neg
      // instructions do not dominate the old add instruction in general.  By
      // adding it now, we are assured that the neg instructions we just
      // inserted dominate the instruction we are about to insert after them.
      //
      return BinaryOperator::create(Instruction::Add, LHS, RHS,
                                    I->getName()+".neg",
                                    cast<Instruction>(RHS)->getNext());
    }

  // Insert a 'neg' instruction that subtracts the value from zero to get the
  // negation.
  //
  return BI = BinaryOperator::createNeg(V, V->getName() + ".neg", BI);
}

bool Reassociate::ReassociateBB(BasicBlock *BB) {
  bool Changed = false;
  for (BasicBlock::iterator BI = BB->begin(); BI != BB->end(); ++BI) {

    DEBUG(std::cerr << "Processing: " << *BI);
    if (BI->getOpcode() == Instruction::Sub && !BinaryOperator::isNeg(BI)) {
      // Convert a subtract into an add and a neg instruction... so that sub
      // instructions can be commuted with other add instructions...
      //
      // Calculate the negative value of Operand 1 of the sub instruction...
      // and set it as the RHS of the add instruction we just made...
      //
      std::string Name = BI->getName();
      BI->setName("");
      Instruction *New =
        BinaryOperator::create(Instruction::Add, BI->getOperand(0),
                               BI->getOperand(1), Name, BI);

      // Everyone now refers to the add instruction...
      BI->replaceAllUsesWith(New);

      // Put the new add in the place of the subtract... deleting the subtract
      BB->getInstList().erase(BI);

      BI = New;
      New->setOperand(1, NegateValue(New->getOperand(1), BI));

      Changed = true;
      DEBUG(std::cerr << "Negated: " << New /*<< " Result BB: " << BB*/);
    }

    // If this instruction is a commutative binary operator, and the ranks of
    // the two operands are sorted incorrectly, fix it now.
    //
    if (BI->isAssociative()) {
      BinaryOperator *I = cast<BinaryOperator>(BI);
      if (!I->use_empty()) {
        // Make sure that we don't have a tree-shaped computation.  If we do,
        // linearize it.  Convert (A+B)+(C+D) into ((A+B)+C)+D
        //
        Instruction *LHSI = dyn_cast<Instruction>(I->getOperand(0));
        Instruction *RHSI = dyn_cast<Instruction>(I->getOperand(1));
        if (LHSI && (int)LHSI->getOpcode() == I->getOpcode() &&
            RHSI && (int)RHSI->getOpcode() == I->getOpcode() &&
            RHSI->use_size() == 1) {
          // Insert a new temporary instruction... (A+B)+C
          BinaryOperator *Tmp = BinaryOperator::create(I->getOpcode(), LHSI,
                                                       RHSI->getOperand(0),
                                                       RHSI->getName()+".ra",
                                                       BI);
          BI = Tmp;
          I->setOperand(0, Tmp);
          I->setOperand(1, RHSI->getOperand(1));

          // Process the temporary instruction for reassociation now.
          I = Tmp;
          ++NumLinear;
          Changed = true;
          DEBUG(std::cerr << "Linearized: " << I/* << " Result BB: " << BB*/);
        }

        // Make sure that this expression is correctly reassociated with respect
        // to it's used values...
        //
        Changed |= ReassociateExpr(I);
      }
    }
  }

  return Changed;
}

bool Reassociate::runOnFunction(Function &F) {
  // Recalculate the rank map for F
  BuildRankMap(F);

  bool Changed = false;
  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
    Changed |= ReassociateBB(FI);

  // We are done with the rank map...
  RankMap.clear();
  InstRankMap.clear();
  return Changed;
}
<|endoftext|>