<commit_before>//// License: Apache 2.0. See LICENSE file in root directory.
//// Copyright(c) 2015 Intel Corporation. All Rights Reserved.

#include "ds5-private.h"

using namespace std;

#define intrinsics_string(res) #res << "\t" << array2str((float_4&)table->rect_params[res]) << endl

namespace librealsense
{
    namespace ds
    {
        ds5_rect_resolutions width_height_to_ds5_rect_resolutions(uint32_t width, uint32_t height)
        {
            for (auto& elem : resolutions_list)
            {
                if (elem.second.x == width && elem.second.y == height)
                    return elem.first;
            }
            throw invalid_value_exception("resolution not found.");
        }

        rs2_intrinsics get_intrinsic_by_resolution_coefficients_table(const std::vector<uint8_t> & raw_data, uint32_t width, uint32_t height, uint32_t fps)
        {
            auto table = check_calib<ds::coefficients_table>(raw_data);

            LOG_DEBUG(endl
                << "baseline = " << table->baseline << " mm" << endl
                << "Rect params:  \t fX\t\t fY\t\t ppX\t\t ppY \n"
                << intrinsics_string(res_1920_1080)
                << intrinsics_string(res_1280_720)
                << intrinsics_string(res_640_480)
                << intrinsics_string(res_848_480)
                << intrinsics_string(res_424_240)
                << intrinsics_string(res_640_360)
                << intrinsics_string(res_320_240)
                << intrinsics_string(res_480_270)
                << intrinsics_string(res_1280_800)
                << intrinsics_string(res_960_540));

            auto resolution = width_height_to_ds5_rect_resolutions(width, width == 848 && height == 100 ? 480 : height);
            rs2_intrinsics intrinsics;
            intrinsics.width = resolutions_list[resolution].x;
            intrinsics.height = resolutions_list[resolution].y;

            try
            {
                auto resolution = width_height_to_ds5_rect_resolutions(width, width == 848 && height == 100 ? 480 : height);
                rs2_intrinsics intrinsics;
                intrinsics.width = resolutions_list[resolution].x;
                intrinsics.height = resolutions_list[resolution].y;

                auto rect_params = static_cast<const float4>(table->rect_params[resolution]);
                // DS5U - assume ideal intrinsic params
                if ((rect_params.x == rect_params.y) && (rect_params.z == rect_params.w))
                {
                    rect_params.x = rect_params.y = intrinsics.width * 1.5f;
                    rect_params.z = intrinsics.width * 0.5f;
                    rect_params.w = intrinsics.height * 0.5f;
                }
                intrinsics.fx = rect_params[0];
                intrinsics.fy = rect_params[1];
                intrinsics.ppx = rect_params[2];
                intrinsics.ppy = rect_params[3];
                intrinsics.model = RS2_DISTORTION_BROWN_CONRADY;
                +memset(intrinsics.coeffs, 0, sizeof(intrinsics.coeffs));  // All coefficients are zeroed since rectified depth is defined as CS origin

                if (width == 848 && height == 100)
                {
                    intrinsics.height = 100;
                    if (fps <= 90)
                        intrinsics.ppy -= 190;
                }

                return intrinsics;
            }
            catch (...)
            {
                ds5_rect_resolutions resolution = res_1920_1080;
                rs2_intrinsics intrinsics;
                intrinsics.width = width;
                intrinsics.height = height;

                auto rect_params = static_cast<const float4>(table->rect_params[resolution]);
                // DS5U - assume ideal intrinsic params
                if ((rect_params.x == rect_params.y) && (rect_params.z == rect_params.w))
                {
                    rect_params.x = rect_params.y = intrinsics.width * 1.5f;
                    rect_params.z = intrinsics.width * 0.5f;
                    rect_params.w = intrinsics.height * 0.5f;
                }

                intrinsics.fx = rect_params[0] * width / resolutions_list[resolution].x;
                intrinsics.fy = rect_params[1] * height / resolutions_list[resolution].y;
                intrinsics.ppx = rect_params[2] * width / resolutions_list[resolution].x;
                intrinsics.ppy = rect_params[3] * height / resolutions_list[resolution].y;
                intrinsics.model = RS2_DISTORTION_BROWN_CONRADY;
                memset(intrinsics.coeffs, 0, sizeof(intrinsics.coeffs));  // All coefficients are zeroed since rectified depth is defined as CS origin

                return intrinsics;
            }
        }

        rs2_intrinsics get_intrinsic_fisheye_table(const std::vector<uint8_t>& raw_data, uint32_t width, uint32_t height)
        {
             auto table = check_calib<ds::fisheye_calibration_table>(raw_data);

             rs2_intrinsics intrinsics;
             auto intrin = table->intrinsic;
             intrinsics.fx = intrin(0,0);
             intrinsics.fy = intrin(1,1);
             intrinsics.ppx = intrin(2,0);
             intrinsics.ppy = intrin(2,1);
             intrinsics.model = RS2_DISTORTION_FTHETA;

             intrinsics.height = height;
             intrinsics.width = width;

             librealsense::copy(intrinsics.coeffs, table->distortion, sizeof(table->distortion));

             LOG_DEBUG(endl<< array2str((float_4&)(intrinsics.fx, intrinsics.fy, intrinsics.ppx, intrinsics.ppy)) << endl);

             return intrinsics;
        }

        rs2_intrinsics get_color_stream_intrinsic(const std::vector<uint8_t>& raw_data, uint32_t width, uint32_t height)
        {
             auto table = check_calib<ds::rgb_calibration_table>(raw_data);

             // Compensate for aspect ratio as the normalized intrinsic is calculated with 16/9 factor
             float3x3 intrin = table->intrinsic;
             static const float base_aspect_ratio_factor = 16.f / 9.f;

             // Compensate for aspect ratio
             intrin(0, 0) *= base_aspect_ratio_factor * (height / (float)width);
             intrin(2, 0) *= base_aspect_ratio_factor * (height / (float)width);

            // Calculate specific intrinsic parameters based on the normalized intrinsic and the sensor's resolution
            rs2_intrinsics calc_intrinsic{
                static_cast<int>(width),
                static_cast<int>(height),
                ((1 + intrin(2, 0))*width) / 2.f,
                ((1 + intrin(2, 1))*height) / 2.f,
                intrin(0, 0) * width / 2.f,
                intrin(1, 1) * height / 2.f,
                RS2_DISTORTION_BROWN_CONRADY
            };
            librealsense::copy(calc_intrinsic.coeffs, table->distortion, sizeof(table->distortion));
            LOG_DEBUG(endl << array2str((float_4&)(calc_intrinsic.fx, calc_intrinsic.fy, calc_intrinsic.ppx, calc_intrinsic.ppy)) << endl);

            return calc_intrinsic;
        }

        rs2_intrinsics get_intrinsic_by_resolution(const vector<uint8_t> & raw_data, calibration_table_id table_id, uint32_t width, uint32_t height, uint32_t fps)
        {
            switch (table_id)
            {
            case coefficients_table_id:
            {
                return get_intrinsic_by_resolution_coefficients_table(raw_data, width, height, fps);
            }
            case fisheye_calibration_id:
            {
                return get_intrinsic_fisheye_table(raw_data, width, height);
            }
            case rgb_calibration_id:
            {
                return get_color_stream_intrinsic(raw_data, width, height);
            }
            default:
                throw invalid_value_exception(to_string() << "Parsing Calibration table type " << table_id << " is not supported");
            }
        }

        pose get_fisheye_extrinsics_data(const vector<uint8_t> & raw_data)
        {
            auto table = check_calib<fisheye_extrinsics_table>(raw_data);

            auto rot = table->rotation;
            auto trans = table->translation;

            pose ex = {{rot(0,0), rot(1,0),rot(2,0),rot(1,0), rot(1,1),rot(2,1),rot(0,2), rot(1,2),rot(2,2)},
                       {trans[0], trans[1], trans[2]}};
            return ex;
        }

        pose get_color_stream_extrinsic(const std::vector<uint8_t>& raw_data)
        {
            auto table = check_calib<rgb_calibration_table>(raw_data);
            float3 trans_vector = table->translation_rect;
            float3x3 rect_rot_mat = table->rotation_matrix_rect;
            float trans_scale = 0.001f; // Convert units from mm to meter
            if (table->translation.x > 0.f) // Extrinsic of color is referenced to the Depth Sensor CS
            {
                trans_scale *= -1;
            }
            trans_vector.x *= trans_scale;
            trans_vector.y *= trans_scale;
            trans_vector.z *= trans_scale;

            return{ rect_rot_mat,trans_vector };
        }

        bool try_fetch_usb_device(std::vector<platform::usb_device_info>& devices,
                                         const platform::uvc_device_info& info, platform::usb_device_info& result)
        {
            for (auto it = devices.begin(); it != devices.end(); ++it)
            {
                if (it->unique_id == info.unique_id)
                {
                    bool found = false;
                    result = *it;
                    switch (info.pid)
                    {
                    case RS_USB2_PID:
                    case RS400_PID:
                    case RS405_PID:
                    case RS410_PID:
                    case RS460_PID:
                    case RS430_PID:
                    case RS420_PID:
                    case RS400_IMU_PID:
                        found = (result.mi == 3);
                        break;
                    case RS430_MM_PID:
                    case RS420_MM_PID:
                    case RS435I_PID:
                        found = (result.mi == 6);
                        break;
                    case RS415_PID:
                    case RS435_RGB_PID:
                        found = (result.mi == 5);
                        break;
                    default:
                        throw not_implemented_exception(to_string() << "USB device "
                            << std::hex << info.pid << ":" << info.vid << std::dec << " is not supported.");
                        break;
                    }

                    if (found)
                    {
                        devices.erase(it);
                        return true;
                    }
                }
            }
            return false;
        }

        std::vector<platform::uvc_device_info> filter_device_by_capability(const std::vector<platform::uvc_device_info>& devices,
            d400_caps caps)
        {
            std::vector<platform::uvc_device_info> results;

            switch (caps)
            {
                case d400_caps::CAP_FISHEYE_SENSOR:
                    std::copy_if(devices.begin(),devices.end(),std::back_inserter(results),
                        [](const platform::uvc_device_info& info)
                        { return fisheye_pid.find(info.pid) != fisheye_pid.end();});
                    break;
                default:
                    throw invalid_value_exception(to_string()
                    << "Capability filters are not implemented for val "
                    << std::hex << caps << std::dec);
            }
            return results;
        }

    } // librealsense::ds
} // namespace librealsense
<commit_msg>Code update based on recommendations.<commit_after>//// License: Apache 2.0. See LICENSE file in root directory.
//// Copyright(c) 2015 Intel Corporation. All Rights Reserved.

#include "ds5-private.h"

using namespace std;

#define intrinsics_string(res) #res << "\t" << array2str((float_4&)table->rect_params[res]) << endl

namespace librealsense
{
    namespace ds
    {
        ds5_rect_resolutions width_height_to_ds5_rect_resolutions(uint32_t width, uint32_t height)
        {
            for (auto& elem : resolutions_list)
            {
                if (elem.second.x == width && elem.second.y == height)
                    return elem.first;
            }
            return max_ds5_rect_resolutions;
        }

        rs2_intrinsics get_intrinsic_by_resolution_coefficients_table(const std::vector<uint8_t> & raw_data, uint32_t width, uint32_t height, uint32_t fps)
        {
            auto table = check_calib<ds::coefficients_table>(raw_data);

            LOG_DEBUG(endl
                << "baseline = " << table->baseline << " mm" << endl
                << "Rect params:  \t fX\t\t fY\t\t ppX\t\t ppY \n"
                << intrinsics_string(res_1920_1080)
                << intrinsics_string(res_1280_720)
                << intrinsics_string(res_640_480)
                << intrinsics_string(res_848_480)
                << intrinsics_string(res_424_240)
                << intrinsics_string(res_640_360)
                << intrinsics_string(res_320_240)
                << intrinsics_string(res_480_270)
                << intrinsics_string(res_1280_800)
                << intrinsics_string(res_960_540));

            auto resolution = width_height_to_ds5_rect_resolutions(width, width == 848 && height == 100 ? 480 : height);
            if (resolution < max_ds5_rect_resolutions)
            {
                rs2_intrinsics intrinsics;
                intrinsics.width = resolutions_list[resolution].x;
                intrinsics.height = resolutions_list[resolution].y;

                auto rect_params = static_cast<const float4>(table->rect_params[resolution]);
                // DS5U - assume ideal intrinsic params
                if ((rect_params.x == rect_params.y) && (rect_params.z == rect_params.w))
                {
                    rect_params.x = rect_params.y = intrinsics.width * 1.5f;
                    rect_params.z = intrinsics.width * 0.5f;
                    rect_params.w = intrinsics.height * 0.5f;
                }
                intrinsics.fx = rect_params[0];
                intrinsics.fy = rect_params[1];
                intrinsics.ppx = rect_params[2];
                intrinsics.ppy = rect_params[3];
                intrinsics.model = RS2_DISTORTION_BROWN_CONRADY;
                +memset(intrinsics.coeffs, 0, sizeof(intrinsics.coeffs));  // All coefficients are zeroed since rectified depth is defined as CS origin

                if (width == 848 && height == 100)
                {
                    intrinsics.height = 100;
                    if (fps <= 90)
                        intrinsics.ppy -= 190;
                }

                return intrinsics;
            }
            else
            {
                ds5_rect_resolutions resolution = res_1920_1080;
                rs2_intrinsics intrinsics;
                intrinsics.width = width;
                intrinsics.height = height;

                auto rect_params = static_cast<const float4>(table->rect_params[resolution]);
                // DS5U - assume ideal intrinsic params
                if ((rect_params.x == rect_params.y) && (rect_params.z == rect_params.w))
                {
                    rect_params.x = rect_params.y = intrinsics.width * 1.5f;
                    rect_params.z = intrinsics.width * 0.5f;
                    rect_params.w = intrinsics.height * 0.5f;
                }

                intrinsics.fx = rect_params[0] * width / resolutions_list[resolution].x;
                intrinsics.fy = rect_params[1] * height / resolutions_list[resolution].y;
                intrinsics.ppx = rect_params[2] * width / resolutions_list[resolution].x;
                intrinsics.ppy = rect_params[3] * height / resolutions_list[resolution].y;
                intrinsics.model = RS2_DISTORTION_BROWN_CONRADY;
                memset(intrinsics.coeffs, 0, sizeof(intrinsics.coeffs));  // All coefficients are zeroed since rectified depth is defined as CS origin

                return intrinsics;
            }
        }

        rs2_intrinsics get_intrinsic_fisheye_table(const std::vector<uint8_t>& raw_data, uint32_t width, uint32_t height)
        {
             auto table = check_calib<ds::fisheye_calibration_table>(raw_data);

             rs2_intrinsics intrinsics;
             auto intrin = table->intrinsic;
             intrinsics.fx = intrin(0,0);
             intrinsics.fy = intrin(1,1);
             intrinsics.ppx = intrin(2,0);
             intrinsics.ppy = intrin(2,1);
             intrinsics.model = RS2_DISTORTION_FTHETA;

             intrinsics.height = height;
             intrinsics.width = width;

             librealsense::copy(intrinsics.coeffs, table->distortion, sizeof(table->distortion));

             LOG_DEBUG(endl<< array2str((float_4&)(intrinsics.fx, intrinsics.fy, intrinsics.ppx, intrinsics.ppy)) << endl);

             return intrinsics;
        }

        rs2_intrinsics get_color_stream_intrinsic(const std::vector<uint8_t>& raw_data, uint32_t width, uint32_t height)
        {
             auto table = check_calib<ds::rgb_calibration_table>(raw_data);

             // Compensate for aspect ratio as the normalized intrinsic is calculated with 16/9 factor
             float3x3 intrin = table->intrinsic;
             static const float base_aspect_ratio_factor = 16.f / 9.f;

             // Compensate for aspect ratio
             intrin(0, 0) *= base_aspect_ratio_factor * (height / (float)width);
             intrin(2, 0) *= base_aspect_ratio_factor * (height / (float)width);

            // Calculate specific intrinsic parameters based on the normalized intrinsic and the sensor's resolution
            rs2_intrinsics calc_intrinsic{
                static_cast<int>(width),
                static_cast<int>(height),
                ((1 + intrin(2, 0))*width) / 2.f,
                ((1 + intrin(2, 1))*height) / 2.f,
                intrin(0, 0) * width / 2.f,
                intrin(1, 1) * height / 2.f,
                RS2_DISTORTION_BROWN_CONRADY
            };
            librealsense::copy(calc_intrinsic.coeffs, table->distortion, sizeof(table->distortion));
            LOG_DEBUG(endl << array2str((float_4&)(calc_intrinsic.fx, calc_intrinsic.fy, calc_intrinsic.ppx, calc_intrinsic.ppy)) << endl);

            return calc_intrinsic;
        }

        rs2_intrinsics get_intrinsic_by_resolution(const vector<uint8_t> & raw_data, calibration_table_id table_id, uint32_t width, uint32_t height, uint32_t fps)
        {
            switch (table_id)
            {
            case coefficients_table_id:
            {
                return get_intrinsic_by_resolution_coefficients_table(raw_data, width, height, fps);
            }
            case fisheye_calibration_id:
            {
                return get_intrinsic_fisheye_table(raw_data, width, height);
            }
            case rgb_calibration_id:
            {
                return get_color_stream_intrinsic(raw_data, width, height);
            }
            default:
                throw invalid_value_exception(to_string() << "Parsing Calibration table type " << table_id << " is not supported");
            }
        }

        pose get_fisheye_extrinsics_data(const vector<uint8_t> & raw_data)
        {
            auto table = check_calib<fisheye_extrinsics_table>(raw_data);

            auto rot = table->rotation;
            auto trans = table->translation;

            pose ex = {{rot(0,0), rot(1,0),rot(2,0),rot(1,0), rot(1,1),rot(2,1),rot(0,2), rot(1,2),rot(2,2)},
                       {trans[0], trans[1], trans[2]}};
            return ex;
        }

        pose get_color_stream_extrinsic(const std::vector<uint8_t>& raw_data)
        {
            auto table = check_calib<rgb_calibration_table>(raw_data);
            float3 trans_vector = table->translation_rect;
            float3x3 rect_rot_mat = table->rotation_matrix_rect;
            float trans_scale = 0.001f; // Convert units from mm to meter
            if (table->translation.x > 0.f) // Extrinsic of color is referenced to the Depth Sensor CS
            {
                trans_scale *= -1;
            }
            trans_vector.x *= trans_scale;
            trans_vector.y *= trans_scale;
            trans_vector.z *= trans_scale;

            return{ rect_rot_mat,trans_vector };
        }

        bool try_fetch_usb_device(std::vector<platform::usb_device_info>& devices,
                                         const platform::uvc_device_info& info, platform::usb_device_info& result)
        {
            for (auto it = devices.begin(); it != devices.end(); ++it)
            {
                if (it->unique_id == info.unique_id)
                {
                    bool found = false;
                    result = *it;
                    switch (info.pid)
                    {
                    case RS_USB2_PID:
                    case RS400_PID:
                    case RS405_PID:
                    case RS410_PID:
                    case RS460_PID:
                    case RS430_PID:
                    case RS420_PID:
                    case RS400_IMU_PID:
                        found = (result.mi == 3);
                        break;
                    case RS430_MM_PID:
                    case RS420_MM_PID:
                    case RS435I_PID:
                        found = (result.mi == 6);
                        break;
                    case RS415_PID:
                    case RS435_RGB_PID:
                        found = (result.mi == 5);
                        break;
                    default:
                        throw not_implemented_exception(to_string() << "USB device "
                            << std::hex << info.pid << ":" << info.vid << std::dec << " is not supported.");
                        break;
                    }

                    if (found)
                    {
                        devices.erase(it);
                        return true;
                    }
                }
            }
            return false;
        }

        std::vector<platform::uvc_device_info> filter_device_by_capability(const std::vector<platform::uvc_device_info>& devices,
            d400_caps caps)
        {
            std::vector<platform::uvc_device_info> results;

            switch (caps)
            {
                case d400_caps::CAP_FISHEYE_SENSOR:
                    std::copy_if(devices.begin(),devices.end(),std::back_inserter(results),
                        [](const platform::uvc_device_info& info)
                        { return fisheye_pid.find(info.pid) != fisheye_pid.end();});
                    break;
                default:
                    throw invalid_value_exception(to_string()
                    << "Capability filters are not implemented for val "
                    << std::hex << caps << std::dec);
            }
            return results;
        }

    } // librealsense::ds
} // namespace librealsense
<|endoftext|>


<commit_before>//===- ADCE.cpp - Code to perform aggressive dead code elimination --------===//
//
// This file implements "aggressive" dead code elimination.  ADCE is DCe where
// values are assumed to be dead until proven otherwise.  This is similar to
// SCCP, except applied to the liveness of values.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Type.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/Writer.h"
#include "llvm/iTerminators.h"
#include "llvm/iPHINode.h"
#include "llvm/Support/CFG.h"
#include "Support/STLExtras.h"
#include "Support/DepthFirstIterator.h"
#include <algorithm>
#include <iostream>
using std::cerr;

#define DEBUG_ADCE 1

namespace {

//===----------------------------------------------------------------------===//
// ADCE Class
//
// This class does all of the work of Aggressive Dead Code Elimination.
// It's public interface consists of a constructor and a doADCE() method.
//
class ADCE : public FunctionPass {
  Function *Func;                       // The function that we are working on
  std::vector<Instruction*> WorkList;   // Instructions that just became live
  std::set<Instruction*>    LiveSet;    // The set of live instructions
  bool MadeChanges;

  //===--------------------------------------------------------------------===//
  // The public interface for this class
  //
public:
  const char *getPassName() const { return "Aggressive Dead Code Elimination"; }

  // doADCE - Execute the Aggressive Dead Code Elimination Algorithm
  //
  virtual bool runOnFunction(Function *F) {
    Func = F; MadeChanges = false;
    doADCE(getAnalysis<DominanceFrontier>(DominanceFrontier::PostDomID));
    assert(WorkList.empty());
    LiveSet.clear();
    return MadeChanges;
  }
  // getAnalysisUsage - We require post dominance frontiers (aka Control
  // Dependence Graph)
  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(DominanceFrontier::PostDomID);
  }

  //===--------------------------------------------------------------------===//
  // The implementation of this class
  //
private:
  // doADCE() - Run the Aggressive Dead Code Elimination algorithm, returning
  // true if the function was modified.
  //
  void doADCE(DominanceFrontier &CDG);

  inline void markInstructionLive(Instruction *I) {
    if (LiveSet.count(I)) return;
#ifdef DEBUG_ADCE
    cerr << "Insn Live: " << I;
#endif
    LiveSet.insert(I);
    WorkList.push_back(I);
  }

  inline void markTerminatorLive(const BasicBlock *BB) {
#ifdef DEBUG_ADCE
    cerr << "Terminat Live: " << BB->getTerminator();
#endif
    markInstructionLive((Instruction*)BB->getTerminator());
  }

  // fixupCFG - Walk the CFG in depth first order, eliminating references to
  // dead blocks.
  //
  BasicBlock *fixupCFG(BasicBlock *Head, std::set<BasicBlock*> &VisitedBlocks,
		       const std::set<BasicBlock*> &AliveBlocks);
};

} // End of anonymous namespace

Pass *createAggressiveDCEPass() {
  return new ADCE();
}

// doADCE() - Run the Aggressive Dead Code Elimination algorithm, returning
// true if the function was modified.
//
void ADCE::doADCE(DominanceFrontier &CDG) {
#ifdef DEBUG_ADCE
  cerr << "Function: " << Func;
#endif

  // Iterate over all of the instructions in the function, eliminating trivially
  // dead instructions, and marking instructions live that are known to be
  // needed.  Perform the walk in depth first order so that we avoid marking any
  // instructions live in basic blocks that are unreachable.  These blocks will
  // be eliminated later, along with the instructions inside.
  //
  for (df_iterator<Function*> BBI = df_begin(Func), BBE = df_end(Func);
       BBI != BBE; ++BBI) {
    BasicBlock *BB = *BBI;
    for (BasicBlock::iterator II = BB->begin(), EI = BB->end(); II != EI; ) {
      Instruction *I = *II;

      if (I->hasSideEffects() || I->getOpcode() == Instruction::Ret) {
	markInstructionLive(I);
        ++II;  // Increment the inst iterator if the inst wasn't deleted
      } else if (isInstructionTriviallyDead(I)) {
        // Remove the instruction from it's basic block...
        delete BB->getInstList().remove(II);
        MadeChanges = true;
      } else {
        ++II;  // Increment the inst iterator if the inst wasn't deleted
      }
    }
  }

#ifdef DEBUG_ADCE
  cerr << "Processing work list\n";
#endif

  // AliveBlocks - Set of basic blocks that we know have instructions that are
  // alive in them...
  //
  std::set<BasicBlock*> AliveBlocks;

  // Process the work list of instructions that just became live... if they
  // became live, then that means that all of their operands are neccesary as
  // well... make them live as well.
  //
  while (!WorkList.empty()) {
    Instruction *I = WorkList.back(); // Get an instruction that became live...
    WorkList.pop_back();

    BasicBlock *BB = I->getParent();
    if (AliveBlocks.count(BB) == 0) {   // Basic block not alive yet...
      // Mark the basic block as being newly ALIVE... and mark all branches that
      // this block is control dependant on as being alive also...
      //
      AliveBlocks.insert(BB);   // Block is now ALIVE!
      DominanceFrontier::const_iterator It = CDG.find(BB);
      if (It != CDG.end()) {
	// Get the blocks that this node is control dependant on...
	const DominanceFrontier::DomSetType &CDB = It->second;
	for_each(CDB.begin(), CDB.end(),   // Mark all their terminators as live
		 bind_obj(this, &ADCE::markTerminatorLive));
      }

      // If this basic block is live, then the terminator must be as well!
      markTerminatorLive(BB);
    }

    // Loop over all of the operands of the live instruction, making sure that
    // they are known to be alive as well...
    //
    for (unsigned op = 0, End = I->getNumOperands(); op != End; ++op)
      if (Instruction *Operand = dyn_cast<Instruction>(I->getOperand(op)))
	markInstructionLive(Operand);
  }

#ifdef DEBUG_ADCE
  cerr << "Current Function: X = Live\n";
  for (Function::iterator I = Func->begin(), E = Func->end(); I != E; ++I)
    for (BasicBlock::iterator BI = (*I)->begin(), BE = (*I)->end();
         BI != BE; ++BI) {
      if (LiveSet.count(*BI)) cerr << "X ";
      cerr << *BI;
    }
#endif

  // After the worklist is processed, recursively walk the CFG in depth first
  // order, patching up references to dead blocks...
  //
  std::set<BasicBlock*> VisitedBlocks;
  BasicBlock *EntryBlock = fixupCFG(Func->front(), VisitedBlocks, AliveBlocks);
  if (EntryBlock && EntryBlock != Func->front()) {
    // We need to move the new entry block to be the first bb of the function
    Function::iterator EBI = find(Func->begin(), Func->end(), EntryBlock);
    std::swap(*EBI, *Func->begin()); // Exchange old location with start of fn

    while (PHINode *PN = dyn_cast<PHINode>(EntryBlock->front())) {
      assert(PN->getNumIncomingValues() == 1 &&
             "Can only have a single incoming value at this point...");
      // The incoming value must be outside of the scope of the function, a
      // global variable, constant or parameter maybe...
      //
      PN->replaceAllUsesWith(PN->getIncomingValue(0));

      // Nuke the phi node...
      delete EntryBlock->getInstList().remove(EntryBlock->begin());
    }
  }

  // Now go through and tell dead blocks to drop all of their references so they
  // can be safely deleted.
  //
  for (Function::iterator BI = Func->begin(), BE = Func->end(); BI != BE; ++BI){
    BasicBlock *BB = *BI;
    if (!AliveBlocks.count(BB)) {
      BB->dropAllReferences();
    }
  }

  // Now loop through all of the blocks and delete them.  We can safely do this
  // now because we know that there are no references to dead blocks (because
  // they have dropped all of their references...
  //
  for (Function::iterator BI = Func->begin(); BI != Func->end();) {
    if (!AliveBlocks.count(*BI)) {
      delete Func->getBasicBlocks().remove(BI);
      MadeChanges = true;
      continue;                                     // Don't increment iterator
    }
    ++BI;                                           // Increment iterator...
  }
}

// fixupCFG - Walk the CFG in depth first order, eliminating references to
// dead blocks:
//  If the BB is alive (in AliveBlocks):
//   1. Eliminate all dead instructions in the BB
//   2. Recursively traverse all of the successors of the BB:
//      - If the returned successor is non-null, update our terminator to
//         reference the returned BB
//   3. Return 0 (no update needed)
//
//  If the BB is dead (not in AliveBlocks):
//   1. Add the BB to the dead set
//   2. Recursively traverse all of the successors of the block:
//      - Only one shall return a nonnull value (or else this block should have
//        been in the alive set).
//   3. Return the nonnull child, or 0 if no non-null children.
//
BasicBlock *ADCE::fixupCFG(BasicBlock *BB, std::set<BasicBlock*> &VisitedBlocks,
			   const std::set<BasicBlock*> &AliveBlocks) {
  if (VisitedBlocks.count(BB)) return 0;   // Revisiting a node? No update.
  VisitedBlocks.insert(BB);                // We have now visited this node!

#ifdef DEBUG_ADCE
  cerr << "Fixing up BB: " << BB;
#endif

  if (AliveBlocks.count(BB)) {             // Is the block alive?
    // Yes it's alive: loop through and eliminate all dead instructions in block
    for (BasicBlock::iterator II = BB->begin(); II != BB->end()-1; )
      if (!LiveSet.count(*II)) {             // Is this instruction alive?
	// Nope... remove the instruction from it's basic block...
	delete BB->getInstList().remove(II);
	MadeChanges = true;
      } else {
        ++II;
      }

    // Recursively traverse successors of this basic block.
    for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) {
      BasicBlock *Succ = *SI;
      BasicBlock *Repl = fixupCFG(Succ, VisitedBlocks, AliveBlocks);
      if (Repl && Repl != Succ) {          // We have to replace the successor
	Succ->replaceAllUsesWith(Repl);
	MadeChanges = true;
      }
    }
    return BB;
  } else {                                 // Otherwise the block is dead...
    BasicBlock *ReturnBB = 0;              // Default to nothing live down here

    // Recursively traverse successors of this basic block.
    for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) {
      BasicBlock *RetBB = fixupCFG(*SI, VisitedBlocks, AliveBlocks);
      if (RetBB) {
	assert(ReturnBB == 0 && "One one live child allowed!");
	ReturnBB = RetBB;
      }
    }
    return ReturnBB;                       // Return the result of traversal
  }
}

<commit_msg>Fix some bugs, straighten stuff out, more work needs to be done.<commit_after>//===- ADCE.cpp - Code to perform aggressive dead code elimination --------===//
//
// This file implements "aggressive" dead code elimination.  ADCE is DCe where
// values are assumed to be dead until proven otherwise.  This is similar to
// SCCP, except applied to the liveness of values.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Type.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/Writer.h"
#include "llvm/iTerminators.h"
#include "llvm/iPHINode.h"
#include "llvm/Support/CFG.h"
#include "Support/STLExtras.h"
#include "Support/DepthFirstIterator.h"
#include <algorithm>
#include <iostream>
using std::cerr;

#define DEBUG_ADCE 1

namespace {

//===----------------------------------------------------------------------===//
// ADCE Class
//
// This class does all of the work of Aggressive Dead Code Elimination.
// It's public interface consists of a constructor and a doADCE() method.
//
class ADCE : public FunctionPass {
  Function *Func;                       // The function that we are working on
  std::vector<Instruction*> WorkList;   // Instructions that just became live
  std::set<Instruction*>    LiveSet;    // The set of live instructions
  bool MadeChanges;

  //===--------------------------------------------------------------------===//
  // The public interface for this class
  //
public:
  const char *getPassName() const { return "Aggressive Dead Code Elimination"; }

  // doADCE - Execute the Aggressive Dead Code Elimination Algorithm
  //
  virtual bool runOnFunction(Function *F) {
    Func = F; MadeChanges = false;
    doADCE(getAnalysis<DominanceFrontier>(DominanceFrontier::PostDomID));
    assert(WorkList.empty());
    LiveSet.clear();
    return MadeChanges;
  }
  // getAnalysisUsage - We require post dominance frontiers (aka Control
  // Dependence Graph)
  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
    AU.addRequired(DominanceFrontier::PostDomID);
  }

  //===--------------------------------------------------------------------===//
  // The implementation of this class
  //
private:
  // doADCE() - Run the Aggressive Dead Code Elimination algorithm, returning
  // true if the function was modified.
  //
  void doADCE(DominanceFrontier &CDG);

  inline void markInstructionLive(Instruction *I) {
    if (LiveSet.count(I)) return;
#ifdef DEBUG_ADCE
    cerr << "Insn Live: " << I;
#endif
    LiveSet.insert(I);
    WorkList.push_back(I);
  }

  inline void markTerminatorLive(const BasicBlock *BB) {
#ifdef DEBUG_ADCE
    cerr << "Terminat Live: " << BB->getTerminator();
#endif
    markInstructionLive((Instruction*)BB->getTerminator());
  }

  // fixupCFG - Walk the CFG in depth first order, eliminating references to
  // dead blocks.
  //
  BasicBlock *fixupCFG(BasicBlock *Head, std::set<BasicBlock*> &VisitedBlocks,
		       const std::set<BasicBlock*> &AliveBlocks);
};

} // End of anonymous namespace

Pass *createAggressiveDCEPass() {
  return new ADCE();
}

// doADCE() - Run the Aggressive Dead Code Elimination algorithm, returning
// true if the function was modified.
//
void ADCE::doADCE(DominanceFrontier &CDG) {
#ifdef DEBUG_ADCE
  cerr << "Function: " << Func;
#endif

  // Iterate over all of the instructions in the function, eliminating trivially
  // dead instructions, and marking instructions live that are known to be
  // needed.  Perform the walk in depth first order so that we avoid marking any
  // instructions live in basic blocks that are unreachable.  These blocks will
  // be eliminated later, along with the instructions inside.
  //
  for (df_iterator<Function*> BBI = df_begin(Func), BBE = df_end(Func);
       BBI != BBE; ++BBI) {
    BasicBlock *BB = *BBI;
    for (BasicBlock::iterator II = BB->begin(), EI = BB->end(); II != EI; ) {
      Instruction *I = *II;

      if (I->hasSideEffects() || I->getOpcode() == Instruction::Ret) {
	markInstructionLive(I);
        ++II;  // Increment the inst iterator if the inst wasn't deleted
      } else if (isInstructionTriviallyDead(I)) {
        // Remove the instruction from it's basic block...
        delete BB->getInstList().remove(II);
        MadeChanges = true;
      } else {
        ++II;  // Increment the inst iterator if the inst wasn't deleted
      }
    }
  }

#ifdef DEBUG_ADCE
  cerr << "Processing work list\n";
#endif

  // AliveBlocks - Set of basic blocks that we know have instructions that are
  // alive in them...
  //
  std::set<BasicBlock*> AliveBlocks;

  // Process the work list of instructions that just became live... if they
  // became live, then that means that all of their operands are neccesary as
  // well... make them live as well.
  //
  while (!WorkList.empty()) {
    Instruction *I = WorkList.back(); // Get an instruction that became live...
    WorkList.pop_back();

    BasicBlock *BB = I->getParent();
    if (AliveBlocks.count(BB) == 0) {   // Basic block not alive yet...
      // Mark the basic block as being newly ALIVE... and mark all branches that
      // this block is control dependant on as being alive also...
      //
      AliveBlocks.insert(BB);   // Block is now ALIVE!
      DominanceFrontier::const_iterator It = CDG.find(BB);
      if (It != CDG.end()) {
	// Get the blocks that this node is control dependant on...
	const DominanceFrontier::DomSetType &CDB = It->second;
	for_each(CDB.begin(), CDB.end(),   // Mark all their terminators as live
		 bind_obj(this, &ADCE::markTerminatorLive));
      }

      // If this basic block is live, then the terminator must be as well!
      markTerminatorLive(BB);
    }

    // Loop over all of the operands of the live instruction, making sure that
    // they are known to be alive as well...
    //
    for (unsigned op = 0, End = I->getNumOperands(); op != End; ++op)
      if (Instruction *Operand = dyn_cast<Instruction>(I->getOperand(op)))
	markInstructionLive(Operand);
  }

#ifdef DEBUG_ADCE
  cerr << "Current Function: X = Live\n";
  for (Function::iterator I = Func->begin(), E = Func->end(); I != E; ++I)
    for (BasicBlock::iterator BI = (*I)->begin(), BE = (*I)->end();
         BI != BE; ++BI) {
      if (LiveSet.count(*BI)) cerr << "X ";
      cerr << *BI;
    }
#endif

  // After the worklist is processed, recursively walk the CFG in depth first
  // order, patching up references to dead blocks...
  //
  std::set<BasicBlock*> VisitedBlocks;
  BasicBlock *EntryBlock = fixupCFG(Func->front(), VisitedBlocks, AliveBlocks);

  // Now go through and tell dead blocks to drop all of their references so they
  // can be safely deleted.  Also, as we are doing so, if the block has
  // successors that are still live (and that have PHI nodes in them), remove
  // the entry for this block from the phi nodes.
  //
  for (Function::iterator BI = Func->begin(), BE = Func->end(); BI != BE; ++BI){
    BasicBlock *BB = *BI;
    if (!AliveBlocks.count(BB)) {
      // Remove entries from successors PHI nodes if they are still alive...
      for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
        if (AliveBlocks.count(*SI)) {  // Only if the successor is alive...
          BasicBlock *Succ = *SI;
          for (BasicBlock::iterator I = Succ->begin();// Loop over all PHI nodes
               PHINode *PN = dyn_cast<PHINode>(*I); ++I)
            PN->removeIncomingValue(BB);         // Remove value for this block
        }

      BB->dropAllReferences();
    }
  }

  cerr << "Before Deleting Blocks: " << Func;

  // Now loop through all of the blocks and delete them.  We can safely do this
  // now because we know that there are no references to dead blocks (because
  // they have dropped all of their references...
  //
  for (Function::iterator BI = Func->begin(); BI != Func->end();) {
    if (!AliveBlocks.count(*BI)) {
      delete Func->getBasicBlocks().remove(BI);
      MadeChanges = true;
      continue;                                     // Don't increment iterator
    }
    ++BI;                                           // Increment iterator...
  }

  if (EntryBlock && EntryBlock != Func->front()) {
    // We need to move the new entry block to be the first bb of the function
    Function::iterator EBI = find(Func->begin(), Func->end(), EntryBlock);
    std::swap(*EBI, *Func->begin()); // Exchange old location with start of fn
  }

  while (PHINode *PN = dyn_cast<PHINode>(EntryBlock->front())) {
    assert(PN->getNumIncomingValues() == 1 &&
           "Can only have a single incoming value at this point...");
    // The incoming value must be outside of the scope of the function, a
    // global variable, constant or parameter maybe...
    //
    PN->replaceAllUsesWith(PN->getIncomingValue(0));

    // Nuke the phi node...
    delete EntryBlock->getInstList().remove(EntryBlock->begin());
  }
}

// fixupCFG - Walk the CFG in depth first order, eliminating references to
// dead blocks:
//  If the BB is alive (in AliveBlocks):
//   1. Eliminate all dead instructions in the BB
//   2. Recursively traverse all of the successors of the BB:
//      - If the returned successor is non-null, update our terminator to
//         reference the returned BB
//   3. Return 0 (no update needed)
//
//  If the BB is dead (not in AliveBlocks):
//   1. Add the BB to the dead set
//   2. Recursively traverse all of the successors of the block:
//      - Only one shall return a nonnull value (or else this block should have
//        been in the alive set).
//   3. Return the nonnull child, or 0 if no non-null children.
//
BasicBlock *ADCE::fixupCFG(BasicBlock *BB, std::set<BasicBlock*> &VisitedBlocks,
			   const std::set<BasicBlock*> &AliveBlocks) {
  if (VisitedBlocks.count(BB)) return 0;   // Revisiting a node? No update.
  VisitedBlocks.insert(BB);                // We have now visited this node!

#ifdef DEBUG_ADCE
  cerr << "Fixing up BB: " << BB;
#endif

  if (AliveBlocks.count(BB)) {             // Is the block alive?
    // Yes it's alive: loop through and eliminate all dead instructions in block
    for (BasicBlock::iterator II = BB->begin(); II != BB->end()-1; )
      if (!LiveSet.count(*II)) {             // Is this instruction alive?
	// Nope... remove the instruction from it's basic block...
	delete BB->getInstList().remove(II);
	MadeChanges = true;
      } else {
        ++II;
      }

    // Recursively traverse successors of this basic block.
    for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) {
      BasicBlock *Succ = *SI;
      BasicBlock *Repl = fixupCFG(Succ, VisitedBlocks, AliveBlocks);
      if (Repl && Repl != Succ) {          // We have to replace the successor
	Succ->replaceAllUsesWith(Repl);
	MadeChanges = true;
      }
    }
    return BB;
  } else {                                 // Otherwise the block is dead...
    BasicBlock *ReturnBB = 0;              // Default to nothing live down here

    // Recursively traverse successors of this basic block.
    for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) {
      BasicBlock *RetBB = fixupCFG(*SI, VisitedBlocks, AliveBlocks);
      if (RetBB) {
	assert(ReturnBB == 0 && "At most one live child allowed!");
	ReturnBB = RetBB;
      }
    }
    return ReturnBB;                       // Return the result of traversal
  }
}

<|endoftext|>


<commit_before>/*
 * ####                                                ####
 * ####                                                ####
 * ####                                                ####      ##
 * ####                                                ####    ####
 * ####  ############  ############  ####  ##########  ####  ####
 * ####  ####    ####  ####    ####  ####  ####        ########
 * ####  ####    ####  ####    ####  ####  ####        ########
 * ####  ####    ####  ####    ####  ####  ####        ####  ####
 * ####  ####    ####  ####    ####  ####  ####        ####    ####
 * ####  ############  ############  ####  ##########  ####      ####
 *                             ####                                ####
 * ################################                                  ####
 *            __      __              __              __      __       ####
 *   |  |    |  |    [__)    |_/     (__     |__|    |  |    [__)        ####
 *   |/\|    |__|    |  \    |  \    .__)    |  |    |__|    |             ##
 *
 *
 * DU-INO Arduino Library - Function Module
 * Aaron Mavrinac <aaron@logick.ca>
 */

#include "du-ino_mcp4922.h"
#include "du-ino_widgets.h"
#include "du-ino_function.h"

#if __has_include("du-ino_calibration.h")
#include "du-ino_calibration.h"
#define USE_CALIBRATION
#endif

#define TRIG_MS           5   // ms
#define DIGITAL_THRESH    3.0 // V
#define CV_IN_OFFSET      0.1 // V

DUINO_Function::DUINO_Function(uint8_t sc)
  : top_level_widget_(NULL)
  , saved_(false)
{
  set_switch_config(sc);

  // configure analog pins
  analogReference(EXTERNAL);
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);

  // configure DACs
  for (uint8_t i = 0; i < 2; ++i)
  {
    dac_[i] = new DUINO_MCP4922(7 - i, 8);
  }
}

void DUINO_Function::begin()
{
  static bool initialized = false;

  if (!initialized)
  {
    // initialize DACs
    dac_[0]->begin();
    dac_[1]->begin();

    // initialize outputs
    gt_out_multi(0xFF, false);

    // initialize display
    Display.begin();
    Display.clear_display();
    Display.display();

    // initialize encoder
    Encoder.begin();

    function_setup();
    initialized = true;
  }
}

void DUINO_Function::widget_setup(DUINO_Widget * top)
{
  if (!top)
  {
    return;
  }

  top_level_widget_ = top;
  top_level_widget_->invert(false);
}

void DUINO_Function::widget_loop()
{
  if (!top_level_widget_)
  {
    return;
  }

  // handle encoder button press
  DUINO_Encoder::Button b = Encoder.get_button();
  if(b == DUINO_Encoder::Clicked)
  {
    top_level_widget_->on_click();
  }
  else if(b == DUINO_Encoder::DoubleClicked)
  {
    top_level_widget_->on_double_click();
  }

  int16_t v = Encoder.get_value();
  if(v)
  {
    top_level_widget_->on_scroll(v);
  }
}

bool DUINO_Function::gt_read(DUINO_Function::Jack jack)
{
  switch (jack)
  {
    case GT1:
    case GT2:
    case GT3:
    case GT4:
      if (switch_config_ & (1 << jack))
      {
        return digitalRead(jack) == LOW ? true : false;
      }
      break;
    case CI1:
    case CI2:
    case CI3:
    case CI4:
      return cv_read(jack) > DIGITAL_THRESH;
  }

  return false;
}

bool DUINO_Function::gt_read_debounce(DUINO_Function::Jack jack)
{
  if (switch_config_ & (1 << jack))
  {
    uint16_t buffer = 0x5555;
    while (buffer && buffer != 0xFFFF)
    {
      buffer = (buffer << 1) | digitalRead(jack);
    }
    return buffer ? false : true;
  }
  else
  {
    return false;
  }
}

void DUINO_Function::gt_out(DUINO_Function::Jack jack, bool on, bool trig)
{
  switch (jack)
  {
    case GT1:
    case GT2:
    case GT3:
    case GT4:
      if ((~switch_config_) & (1 << jack))
      {
        digitalWrite(jack, on ? HIGH : LOW);
        if (trig)
        {
          delay(TRIG_MS);
          digitalWrite(jack, on ? LOW : HIGH);
        }
      }
      break;
    case CO1:
    case CO2:
    case CO3:
    case CO4:
      dac_[(jack - 4) >> 1]->output((DUINO_MCP4922::Channel)((jack - 4) & 1), on ? 0xBFF : 0x800);
      if (trig)
      {
        delay(TRIG_MS);
        dac_[(jack - 4) >> 1]->output((DUINO_MCP4922::Channel)((jack - 4) & 1), on ? 0x800 : 0xBFF);
      }
      break;
  }
}

void DUINO_Function::gt_out_multi(uint8_t jacks, bool on, bool trig)
{
  for (uint8_t i = 0; i < 4; ++i)
  {
    if (jacks & (~switch_config_) & (1 << i))
    {
      digitalWrite(i, on ? HIGH : LOW);
    }
  }
  for (uint8_t i = 4; i < 8; ++i)
  {
    if (jacks & (1 << i))
    {
      dac_[(i - 4) >> 1]->output((DUINO_MCP4922::Channel)((i - 4) & 1), on ? 0xBFF : 0x800);
    }
  }

  if (trig)
  {
    delay(TRIG_MS);
    for (uint8_t i = 0; i < 4; ++i)
    {
      if (jacks & (~switch_config_) & (1 << i))
      {
        digitalWrite(i, on ? LOW : HIGH);
      }
    }
    for (uint8_t i = 4; i < 8; ++i)
    {
      if (jacks & (1 << i))
      {
        dac_[(i - 4) >> 1]->output((DUINO_MCP4922::Channel)((i - 4) & 1), on ? 0x800 : 0xBFF);
      }
    }
  }
}

float DUINO_Function::cv_read(DUINO_Function::Jack jack)
{
  switch (jack)
  {
#ifdef USE_CALIBRATION
    case CI1:
      return cv_analog_read(A0) * CI1_PRESCALE + CI1_OFFSET;
    case CI2:
      return cv_analog_read(A1) * CI2_PRESCALE + CI2_OFFSET;
    case CI3:
      return cv_analog_read(A2) * CI3_PRESCALE + CI3_OFFSET;
    case CI4:
      return cv_analog_read(A3) * CI4_PRESCALE + CI4_OFFSET;
#else
    case CI1:
      return cv_analog_read(A0);
    case CI2:
      return cv_analog_read(A1);
    case CI3:
      return cv_analog_read(A2);
    case CI4:
      return cv_analog_read(A3);
#endif
    default:
      return 0.0;
  }
}

void DUINO_Function::cv_out(DUINO_Function::Jack jack, float value)
{
  if (jack == CO1 || jack == CO2 || jack == CO3 || jack == CO4)
  {
    // (value + 10) * ((2^12 - 1) / 20)
#ifdef USE_CALIBRATION
    float calibrated_value;
    switch (jack)
    {
      case CO1:
        calibrated_value = value * CO1_PRESCALE + CO1_OFFSET;
      case CO2:
        calibrated_value = value * CO2_PRESCALE + CO2_OFFSET;
      case CO3:
        calibrated_value = value * CO3_PRESCALE + CO3_OFFSET;
      case CO4:
        calibrated_value = value * CO4_PRESCALE + CO4_OFFSET;
    }
#else
    const float calibrated_value = value;
#endif
    uint16_t data = uint16_t((calibrated_value + 10.0) * 204.75);

    // DAC output
    dac_[(jack - 4) >> 1]->output((DUINO_MCP4922::Channel)((jack - 4) & 1), data);
  }
}

void DUINO_Function::cv_hold(bool state)
{
  // both DACs share the LDAC pin, so holding either will hold all four channels
  dac_[0]->hold(state);
}

void DUINO_Function::gt_attach_interrupt(DUINO_Function::Jack jack, void (*isr)(void), int mode)
{
  if (jack == GT3 || jack == GT4)
  {
    attachInterrupt(digitalPinToInterrupt(jack), isr, mode);
  }
}

void DUINO_Function::gt_detach_interrupt(DUINO_Function::Jack jack)
{
  if (jack == GT3 || jack == GT4)
  {
    detachInterrupt(digitalPinToInterrupt(jack));
  }
}

void DUINO_Function::set_switch_config(uint8_t sc)
{
  switch_config_ = sc;

  // configure digital pins
  for (uint8_t i = 0; i < 4; ++i)
  {
    pinMode(i, sc & (1 << i) ? INPUT : OUTPUT);
  }
}

float DUINO_Function::cv_analog_read(uint8_t pin)
{
  // value * (20 / (2^10 - 1)) - 10
  return float(analogRead(pin)) * 0.019550342130987292 - 10.0 + CV_IN_OFFSET;
}
<commit_msg>Add startup delay for fussy OLED display and power supply combinations.<commit_after>/*
 * ####                                                ####
 * ####                                                ####
 * ####                                                ####      ##
 * ####                                                ####    ####
 * ####  ############  ############  ####  ##########  ####  ####
 * ####  ####    ####  ####    ####  ####  ####        ########
 * ####  ####    ####  ####    ####  ####  ####        ########
 * ####  ####    ####  ####    ####  ####  ####        ####  ####
 * ####  ####    ####  ####    ####  ####  ####        ####    ####
 * ####  ############  ############  ####  ##########  ####      ####
 *                             ####                                ####
 * ################################                                  ####
 *            __      __              __              __      __       ####
 *   |  |    |  |    [__)    |_/     (__     |__|    |  |    [__)        ####
 *   |/\|    |__|    |  \    |  \    .__)    |  |    |__|    |             ##
 *
 *
 * DU-INO Arduino Library - Function Module
 * Aaron Mavrinac <aaron@logick.ca>
 */

#include "du-ino_mcp4922.h"
#include "du-ino_widgets.h"
#include "du-ino_function.h"

#if __has_include("du-ino_calibration.h")
#include "du-ino_calibration.h"
#define USE_CALIBRATION
#endif

#define STARTUP_DELAY     100 // ms
#define TRIG_MS           5   // ms
#define DIGITAL_THRESH    3.0 // V
#define CV_IN_OFFSET      0.1 // V

DUINO_Function::DUINO_Function(uint8_t sc)
  : top_level_widget_(NULL)
  , saved_(false)
{
  set_switch_config(sc);

  // configure analog pins
  analogReference(EXTERNAL);
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);

  // configure DACs
  for (uint8_t i = 0; i < 2; ++i)
  {
    dac_[i] = new DUINO_MCP4922(7 - i, 8);
  }
}

void DUINO_Function::begin()
{
  static bool initialized = false;

  if (!initialized)
  {
    // startup delay, to allow fussy OLED displays to work with fussy power supplies
    delay(STARTUP_DELAY);

    // initialize DACs
    dac_[0]->begin();
    dac_[1]->begin();

    // initialize outputs
    gt_out_multi(0xFF, false);

    // initialize display
    Display.begin();
    Display.clear_display();
    Display.display();

    // initialize encoder
    Encoder.begin();

    function_setup();
    initialized = true;
  }
}

void DUINO_Function::widget_setup(DUINO_Widget * top)
{
  if (!top)
  {
    return;
  }

  top_level_widget_ = top;
  top_level_widget_->invert(false);
}

void DUINO_Function::widget_loop()
{
  if (!top_level_widget_)
  {
    return;
  }

  // handle encoder button press
  DUINO_Encoder::Button b = Encoder.get_button();
  if(b == DUINO_Encoder::Clicked)
  {
    top_level_widget_->on_click();
  }
  else if(b == DUINO_Encoder::DoubleClicked)
  {
    top_level_widget_->on_double_click();
  }

  int16_t v = Encoder.get_value();
  if(v)
  {
    top_level_widget_->on_scroll(v);
  }
}

bool DUINO_Function::gt_read(DUINO_Function::Jack jack)
{
  switch (jack)
  {
    case GT1:
    case GT2:
    case GT3:
    case GT4:
      if (switch_config_ & (1 << jack))
      {
        return digitalRead(jack) == LOW ? true : false;
      }
      break;
    case CI1:
    case CI2:
    case CI3:
    case CI4:
      return cv_read(jack) > DIGITAL_THRESH;
  }

  return false;
}

bool DUINO_Function::gt_read_debounce(DUINO_Function::Jack jack)
{
  if (switch_config_ & (1 << jack))
  {
    uint16_t buffer = 0x5555;
    while (buffer && buffer != 0xFFFF)
    {
      buffer = (buffer << 1) | digitalRead(jack);
    }
    return buffer ? false : true;
  }
  else
  {
    return false;
  }
}

void DUINO_Function::gt_out(DUINO_Function::Jack jack, bool on, bool trig)
{
  switch (jack)
  {
    case GT1:
    case GT2:
    case GT3:
    case GT4:
      if ((~switch_config_) & (1 << jack))
      {
        digitalWrite(jack, on ? HIGH : LOW);
        if (trig)
        {
          delay(TRIG_MS);
          digitalWrite(jack, on ? LOW : HIGH);
        }
      }
      break;
    case CO1:
    case CO2:
    case CO3:
    case CO4:
      dac_[(jack - 4) >> 1]->output((DUINO_MCP4922::Channel)((jack - 4) & 1), on ? 0xBFF : 0x800);
      if (trig)
      {
        delay(TRIG_MS);
        dac_[(jack - 4) >> 1]->output((DUINO_MCP4922::Channel)((jack - 4) & 1), on ? 0x800 : 0xBFF);
      }
      break;
  }
}

void DUINO_Function::gt_out_multi(uint8_t jacks, bool on, bool trig)
{
  for (uint8_t i = 0; i < 4; ++i)
  {
    if (jacks & (~switch_config_) & (1 << i))
    {
      digitalWrite(i, on ? HIGH : LOW);
    }
  }
  for (uint8_t i = 4; i < 8; ++i)
  {
    if (jacks & (1 << i))
    {
      dac_[(i - 4) >> 1]->output((DUINO_MCP4922::Channel)((i - 4) & 1), on ? 0xBFF : 0x800);
    }
  }

  if (trig)
  {
    delay(TRIG_MS);
    for (uint8_t i = 0; i < 4; ++i)
    {
      if (jacks & (~switch_config_) & (1 << i))
      {
        digitalWrite(i, on ? LOW : HIGH);
      }
    }
    for (uint8_t i = 4; i < 8; ++i)
    {
      if (jacks & (1 << i))
      {
        dac_[(i - 4) >> 1]->output((DUINO_MCP4922::Channel)((i - 4) & 1), on ? 0x800 : 0xBFF);
      }
    }
  }
}

float DUINO_Function::cv_read(DUINO_Function::Jack jack)
{
  switch (jack)
  {
#ifdef USE_CALIBRATION
    case CI1:
      return cv_analog_read(A0) * CI1_PRESCALE + CI1_OFFSET;
    case CI2:
      return cv_analog_read(A1) * CI2_PRESCALE + CI2_OFFSET;
    case CI3:
      return cv_analog_read(A2) * CI3_PRESCALE + CI3_OFFSET;
    case CI4:
      return cv_analog_read(A3) * CI4_PRESCALE + CI4_OFFSET;
#else
    case CI1:
      return cv_analog_read(A0);
    case CI2:
      return cv_analog_read(A1);
    case CI3:
      return cv_analog_read(A2);
    case CI4:
      return cv_analog_read(A3);
#endif
    default:
      return 0.0;
  }
}

void DUINO_Function::cv_out(DUINO_Function::Jack jack, float value)
{
  if (jack == CO1 || jack == CO2 || jack == CO3 || jack == CO4)
  {
    // (value + 10) * ((2^12 - 1) / 20)
#ifdef USE_CALIBRATION
    float calibrated_value;
    switch (jack)
    {
      case CO1:
        calibrated_value = value * CO1_PRESCALE + CO1_OFFSET;
      case CO2:
        calibrated_value = value * CO2_PRESCALE + CO2_OFFSET;
      case CO3:
        calibrated_value = value * CO3_PRESCALE + CO3_OFFSET;
      case CO4:
        calibrated_value = value * CO4_PRESCALE + CO4_OFFSET;
    }
#else
    const float calibrated_value = value;
#endif
    uint16_t data = uint16_t((calibrated_value + 10.0) * 204.75);

    // DAC output
    dac_[(jack - 4) >> 1]->output((DUINO_MCP4922::Channel)((jack - 4) & 1), data);
  }
}

void DUINO_Function::cv_hold(bool state)
{
  // both DACs share the LDAC pin, so holding either will hold all four channels
  dac_[0]->hold(state);
}

void DUINO_Function::gt_attach_interrupt(DUINO_Function::Jack jack, void (*isr)(void), int mode)
{
  if (jack == GT3 || jack == GT4)
  {
    attachInterrupt(digitalPinToInterrupt(jack), isr, mode);
  }
}

void DUINO_Function::gt_detach_interrupt(DUINO_Function::Jack jack)
{
  if (jack == GT3 || jack == GT4)
  {
    detachInterrupt(digitalPinToInterrupt(jack));
  }
}

void DUINO_Function::set_switch_config(uint8_t sc)
{
  switch_config_ = sc;

  // configure digital pins
  for (uint8_t i = 0; i < 4; ++i)
  {
    pinMode(i, sc & (1 << i) ? INPUT : OUTPUT);
  }
}

float DUINO_Function::cv_analog_read(uint8_t pin)
{
  // value * (20 / (2^10 - 1)) - 10
  return float(analogRead(pin)) * 0.019550342130987292 - 10.0 + CV_IN_OFFSET;
}
<|endoftext|>


<commit_before>//===-- GCSE.cpp - SSA based Global Common Subexpr Elimination ------------===//
//
// This pass is designed to be a very quick global transformation that
// eliminates global common subexpressions from a function.  It does this by
// examining the SSA value graph of the function, instead of doing slow, dense,
// bit-vector computations.
//
// This pass works best if it is proceeded with a simple constant propogation
// pass and an instruction combination pass because this pass does not do any
// value numbering (in order to be speedy).
//
// This pass does not attempt to CSE load instructions, because it does not use
// pointer analysis to determine when it is safe.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/GCSE.h"
#include "llvm/Pass.h"
#include "llvm/InstrTypes.h"
#include "llvm/iMemory.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/InstIterator.h"
#include <set>
#include <algorithm>

namespace {
  class GCSE : public FunctionPass, public InstVisitor<GCSE, bool> {
    set<Instruction*> WorkList;
    DominatorSet        *DomSetInfo;
    ImmediateDominators *ImmDominator;
  public:
    const char *getPassName() const {
      return "Global Common Subexpression Elimination";
    }

    virtual bool runOnFunction(Function *F);

    // Visitation methods, these are invoked depending on the type of
    // instruction being checked.  They should return true if a common
    // subexpression was folded.
    //
    bool visitUnaryOperator(Instruction *I);
    bool visitBinaryOperator(Instruction *I);
    bool visitGetElementPtrInst(GetElementPtrInst *I);
    bool visitCastInst(CastInst *I){return visitUnaryOperator((Instruction*)I);}
    bool visitShiftInst(ShiftInst *I) {
      return visitBinaryOperator((Instruction*)I);
    }
    bool visitInstruction(Instruction *) { return false; }

  private:
    void ReplaceInstWithInst(Instruction *First, BasicBlock::iterator SI);
    void CommonSubExpressionFound(Instruction *I, Instruction *Other);

    // This transformation requires dominator and immediate dominator info
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.preservesCFG();
      AU.addRequired(DominatorSet::ID);
      AU.addRequired(ImmediateDominators::ID);
    }
  };
}

// createGCSEPass - The public interface to this file...
Pass *createGCSEPass() { return new GCSE(); }

// GCSE::runOnFunction - This is the main transformation entry point for a
// function.
//
bool GCSE::runOnFunction(Function *F) {
  bool Changed = false;

  DomSetInfo = &getAnalysis<DominatorSet>();
  ImmDominator = &getAnalysis<ImmediateDominators>();

  // Step #1: Add all instructions in the function to the worklist for
  // processing.  All of the instructions are considered to be our
  // subexpressions to eliminate if possible.
  //
  WorkList.insert(inst_begin(F), inst_end(F));

  // Step #2: WorkList processing.  Iterate through all of the instructions,
  // checking to see if there are any additionally defined subexpressions in the
  // program.  If so, eliminate them!
  //
  while (!WorkList.empty()) {
    Instruction *I = *WorkList.begin();  // Get an instruction from the worklist
    WorkList.erase(WorkList.begin());

    // Visit the instruction, dispatching to the correct visit function based on
    // the instruction type.  This does the checking.
    //
    Changed |= visit(I);
  }

  // When the worklist is empty, return whether or not we changed anything...
  return Changed;
}

// ReplaceInstWithInst - Destroy the instruction pointed to by SI, making all
// uses of the instruction use First now instead.
//
void GCSE::ReplaceInstWithInst(Instruction *First, BasicBlock::iterator SI) {
  Instruction *Second = *SI;

  // Add the first instruction back to the worklist
  WorkList.insert(First);

  // Add all uses of the second instruction to the worklist
  for (Value::use_iterator UI = Second->use_begin(), UE = Second->use_end();
       UI != UE; ++UI)
    WorkList.insert(cast<Instruction>(*UI));

  // Make all users of 'Second' now use 'First'
  Second->replaceAllUsesWith(First);

  // Erase the second instruction from the program
  delete Second->getParent()->getInstList().remove(SI);
}

// CommonSubExpressionFound - The two instruction I & Other have been found to
// be common subexpressions.  This function is responsible for eliminating one
// of them, and for fixing the worklist to be correct.
//
void GCSE::CommonSubExpressionFound(Instruction *I, Instruction *Other) {
  // I has already been removed from the worklist, Other needs to be.
  assert(WorkList.count(I) == 0 && WorkList.count(Other) &&
         "I in worklist or Other not!");
  WorkList.erase(Other);

  // Handle the easy case, where both instructions are in the same basic block
  BasicBlock *BB1 = I->getParent(), *BB2 = Other->getParent();
  if (BB1 == BB2) {
    // Eliminate the second occuring instruction.  Add all uses of the second
    // instruction to the worklist.
    //
    // Scan the basic block looking for the "first" instruction
    BasicBlock::iterator BI = BB1->begin();
    while (*BI != I && *BI != Other) {
      ++BI;
      assert(BI != BB1->end() && "Instructions not found in parent BB!");
    }

    // Keep track of which instructions occurred first & second
    Instruction *First = *BI;
    Instruction *Second = I != First ? I : Other; // Get iterator to second inst
    BI = find(BI, BB1->end(), Second);
    assert(BI != BB1->end() && "Second instruction not found in parent block!");

    // Destroy Second, using First instead.
    ReplaceInstWithInst(First, BI);

    // Otherwise, the two instructions are in different basic blocks.  If one
    // dominates the other instruction, we can simply use it
    //
  } else if (DomSetInfo->dominates(BB1, BB2)) {    // I dom Other?
    BasicBlock::iterator BI = find(BB2->begin(), BB2->end(), Other);
    assert(BI != BB2->end() && "Other not in parent basic block!");
    ReplaceInstWithInst(I, BI);
  } else if (DomSetInfo->dominates(BB2, BB1)) {    // Other dom I?
    BasicBlock::iterator BI = find(BB1->begin(), BB1->end(), I);
    assert(BI != BB1->end() && "I not in parent basic block!");
    ReplaceInstWithInst(Other, BI);
  } else {
    // Handle the most general case now.  In this case, neither I dom Other nor
    // Other dom I.  Because we are in SSA form, we are guaranteed that the
    // operands of the two instructions both dominate the uses, so we _know_
    // that there must exist a block that dominates both instructions (if the
    // operands of the instructions are globals or constants, worst case we
    // would get the entry node of the function).  Search for this block now.
    //

    // Search up the immediate dominator chain of BB1 for the shared dominator
    BasicBlock *SharedDom = (*ImmDominator)[BB1];
    while (!DomSetInfo->dominates(SharedDom, BB2))
      SharedDom = (*ImmDominator)[SharedDom];

    // At this point, shared dom must dominate BOTH BB1 and BB2...
    assert(SharedDom && DomSetInfo->dominates(SharedDom, BB1) &&
           DomSetInfo->dominates(SharedDom, BB2) && "Dominators broken!");

    // Rip 'I' out of BB1, and move it to the end of SharedDom.
    BB1->getInstList().remove(I);
    SharedDom->getInstList().insert(SharedDom->end()-1, I);

    // Eliminate 'Other' now.
    BasicBlock::iterator BI = find(BB2->begin(), BB2->end(), Other);
    assert(BI != BB2->end() && "I not in parent basic block!");
    ReplaceInstWithInst(I, BI);
  }
}

//===----------------------------------------------------------------------===//
//
// Visitation methods, these are invoked depending on the type of instruction
// being checked.  They should return true if a common subexpression was folded.
//
//===----------------------------------------------------------------------===//

bool GCSE::visitUnaryOperator(Instruction *I) {
  Value *Op = I->getOperand(0);
  Function *F = I->getParent()->getParent();

  for (Value::use_iterator UI = Op->use_begin(), UE = Op->use_end();
       UI != UE; ++UI)
    if (Instruction *Other = dyn_cast<Instruction>(*UI))
      // Check to see if this new binary operator is not I, but same operand...
      if (Other != I && Other->getOpcode() == I->getOpcode() &&
          Other->getOperand(0) == Op &&     // Is the operand the same?
          // Is it embeded in the same function?  (This could be false if LHS
          // is a constant or global!)
          Other->getParent()->getParent() == F &&

          // Check that the types are the same, since this code handles casts...
          Other->getType() == I->getType()) {

        // These instructions are identical.  Handle the situation.
        CommonSubExpressionFound(I, Other);
        return true;   // One instruction eliminated!
      }

  return false;
}

bool GCSE::visitBinaryOperator(Instruction *I) {
  Value *LHS = I->getOperand(0), *RHS = I->getOperand(1);
  Function *F = I->getParent()->getParent();

  for (Value::use_iterator UI = LHS->use_begin(), UE = LHS->use_end();
       UI != UE; ++UI)
    if (Instruction *Other = dyn_cast<Instruction>(*UI))
      // Check to see if this new binary operator is not I, but same operand...
      if (Other != I && Other->getOpcode() == I->getOpcode() &&
          // Are the LHS and RHS the same?
          Other->getOperand(0) == LHS && Other->getOperand(1) == RHS &&
          // Is it embeded in the same function?  (This could be false if LHS
          // is a constant or global!)
          Other->getParent()->getParent() == F) {

        // These instructions are identical.  Handle the situation.
        CommonSubExpressionFound(I, Other);
        return true;   // One instruction eliminated!
      }

  return false;
}

bool GCSE::visitGetElementPtrInst(GetElementPtrInst *I) {
  Value *Op = I->getOperand(0);
  Function *F = I->getParent()->getParent();

  for (Value::use_iterator UI = Op->use_begin(), UE = Op->use_end();
       UI != UE; ++UI)
    if (GetElementPtrInst *Other = dyn_cast<GetElementPtrInst>(*UI))
      // Check to see if this new binary operator is not I, but same operand...
      if (Other != I && Other->getParent()->getParent() == F &&
          Other->getType() == I->getType()) {

        // Check to see that all operators past the 0th are the same...
        unsigned i = 1, e = I->getNumOperands();
        for (; i != e; ++i)
          if (I->getOperand(i) != Other->getOperand(i)) break;

        if (i == e) {
          // These instructions are identical.  Handle the situation.
          CommonSubExpressionFound(I, Other);
          return true;   // One instruction eliminated!
        }
      }

  return false;
}
<commit_msg>Remove broken assertion.<commit_after>//===-- GCSE.cpp - SSA based Global Common Subexpr Elimination ------------===//
//
// This pass is designed to be a very quick global transformation that
// eliminates global common subexpressions from a function.  It does this by
// examining the SSA value graph of the function, instead of doing slow, dense,
// bit-vector computations.
//
// This pass works best if it is proceeded with a simple constant propogation
// pass and an instruction combination pass because this pass does not do any
// value numbering (in order to be speedy).
//
// This pass does not attempt to CSE load instructions, because it does not use
// pointer analysis to determine when it is safe.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar/GCSE.h"
#include "llvm/Pass.h"
#include "llvm/InstrTypes.h"
#include "llvm/iMemory.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/InstIterator.h"
#include <set>
#include <algorithm>

namespace {
  class GCSE : public FunctionPass, public InstVisitor<GCSE, bool> {
    set<Instruction*> WorkList;
    DominatorSet        *DomSetInfo;
    ImmediateDominators *ImmDominator;
  public:
    const char *getPassName() const {
      return "Global Common Subexpression Elimination";
    }

    virtual bool runOnFunction(Function *F);

    // Visitation methods, these are invoked depending on the type of
    // instruction being checked.  They should return true if a common
    // subexpression was folded.
    //
    bool visitUnaryOperator(Instruction *I);
    bool visitBinaryOperator(Instruction *I);
    bool visitGetElementPtrInst(GetElementPtrInst *I);
    bool visitCastInst(CastInst *I){return visitUnaryOperator((Instruction*)I);}
    bool visitShiftInst(ShiftInst *I) {
      return visitBinaryOperator((Instruction*)I);
    }
    bool visitInstruction(Instruction *) { return false; }

  private:
    void ReplaceInstWithInst(Instruction *First, BasicBlock::iterator SI);
    void CommonSubExpressionFound(Instruction *I, Instruction *Other);

    // This transformation requires dominator and immediate dominator info
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.preservesCFG();
      AU.addRequired(DominatorSet::ID);
      AU.addRequired(ImmediateDominators::ID);
    }
  };
}

// createGCSEPass - The public interface to this file...
Pass *createGCSEPass() { return new GCSE(); }

// GCSE::runOnFunction - This is the main transformation entry point for a
// function.
//
bool GCSE::runOnFunction(Function *F) {
  bool Changed = false;

  DomSetInfo = &getAnalysis<DominatorSet>();
  ImmDominator = &getAnalysis<ImmediateDominators>();

  // Step #1: Add all instructions in the function to the worklist for
  // processing.  All of the instructions are considered to be our
  // subexpressions to eliminate if possible.
  //
  WorkList.insert(inst_begin(F), inst_end(F));

  // Step #2: WorkList processing.  Iterate through all of the instructions,
  // checking to see if there are any additionally defined subexpressions in the
  // program.  If so, eliminate them!
  //
  while (!WorkList.empty()) {
    Instruction *I = *WorkList.begin();  // Get an instruction from the worklist
    WorkList.erase(WorkList.begin());

    // Visit the instruction, dispatching to the correct visit function based on
    // the instruction type.  This does the checking.
    //
    Changed |= visit(I);
  }

  // When the worklist is empty, return whether or not we changed anything...
  return Changed;
}

// ReplaceInstWithInst - Destroy the instruction pointed to by SI, making all
// uses of the instruction use First now instead.
//
void GCSE::ReplaceInstWithInst(Instruction *First, BasicBlock::iterator SI) {
  Instruction *Second = *SI;

  //cerr << "DEL " << (void*)Second << Second;

  // Add the first instruction back to the worklist
  WorkList.insert(First);

  // Add all uses of the second instruction to the worklist
  for (Value::use_iterator UI = Second->use_begin(), UE = Second->use_end();
       UI != UE; ++UI)
    WorkList.insert(cast<Instruction>(*UI));

  // Make all users of 'Second' now use 'First'
  Second->replaceAllUsesWith(First);

  // Erase the second instruction from the program
  delete Second->getParent()->getInstList().remove(SI);
}

// CommonSubExpressionFound - The two instruction I & Other have been found to
// be common subexpressions.  This function is responsible for eliminating one
// of them, and for fixing the worklist to be correct.
//
void GCSE::CommonSubExpressionFound(Instruction *I, Instruction *Other) {
  // I has already been removed from the worklist, Other needs to be.
  assert(I != Other && WorkList.count(I) == 0 && "I shouldn't be on worklist!");

  WorkList.erase(Other); // Other may not actually be on the worklist anymore...

  // Handle the easy case, where both instructions are in the same basic block
  BasicBlock *BB1 = I->getParent(), *BB2 = Other->getParent();
  if (BB1 == BB2) {
    // Eliminate the second occuring instruction.  Add all uses of the second
    // instruction to the worklist.
    //
    // Scan the basic block looking for the "first" instruction
    BasicBlock::iterator BI = BB1->begin();
    while (*BI != I && *BI != Other) {
      ++BI;
      assert(BI != BB1->end() && "Instructions not found in parent BB!");
    }

    // Keep track of which instructions occurred first & second
    Instruction *First = *BI;
    Instruction *Second = I != First ? I : Other; // Get iterator to second inst
    BI = find(BI, BB1->end(), Second);
    assert(BI != BB1->end() && "Second instruction not found in parent block!");

    // Destroy Second, using First instead.
    ReplaceInstWithInst(First, BI);

    // Otherwise, the two instructions are in different basic blocks.  If one
    // dominates the other instruction, we can simply use it
    //
  } else if (DomSetInfo->dominates(BB1, BB2)) {    // I dom Other?
    BasicBlock::iterator BI = find(BB2->begin(), BB2->end(), Other);
    assert(BI != BB2->end() && "Other not in parent basic block!");
    ReplaceInstWithInst(I, BI);
  } else if (DomSetInfo->dominates(BB2, BB1)) {    // Other dom I?
    BasicBlock::iterator BI = find(BB1->begin(), BB1->end(), I);
    assert(BI != BB1->end() && "I not in parent basic block!");
    ReplaceInstWithInst(Other, BI);
  } else {
    // Handle the most general case now.  In this case, neither I dom Other nor
    // Other dom I.  Because we are in SSA form, we are guaranteed that the
    // operands of the two instructions both dominate the uses, so we _know_
    // that there must exist a block that dominates both instructions (if the
    // operands of the instructions are globals or constants, worst case we
    // would get the entry node of the function).  Search for this block now.
    //

    // Search up the immediate dominator chain of BB1 for the shared dominator
    BasicBlock *SharedDom = (*ImmDominator)[BB1];
    while (!DomSetInfo->dominates(SharedDom, BB2))
      SharedDom = (*ImmDominator)[SharedDom];

    // At this point, shared dom must dominate BOTH BB1 and BB2...
    assert(SharedDom && DomSetInfo->dominates(SharedDom, BB1) &&
           DomSetInfo->dominates(SharedDom, BB2) && "Dominators broken!");

    // Rip 'I' out of BB1, and move it to the end of SharedDom.
    BB1->getInstList().remove(I);
    SharedDom->getInstList().insert(SharedDom->end()-1, I);

    // Eliminate 'Other' now.
    BasicBlock::iterator BI = find(BB2->begin(), BB2->end(), Other);
    assert(BI != BB2->end() && "I not in parent basic block!");
    ReplaceInstWithInst(I, BI);
  }
}

//===----------------------------------------------------------------------===//
//
// Visitation methods, these are invoked depending on the type of instruction
// being checked.  They should return true if a common subexpression was folded.
//
//===----------------------------------------------------------------------===//

bool GCSE::visitUnaryOperator(Instruction *I) {
  Value *Op = I->getOperand(0);
  Function *F = I->getParent()->getParent();

  for (Value::use_iterator UI = Op->use_begin(), UE = Op->use_end();
       UI != UE; ++UI)
    if (Instruction *Other = dyn_cast<Instruction>(*UI))
      // Check to see if this new binary operator is not I, but same operand...
      if (Other != I && Other->getOpcode() == I->getOpcode() &&
          Other->getOperand(0) == Op &&     // Is the operand the same?
          // Is it embeded in the same function?  (This could be false if LHS
          // is a constant or global!)
          Other->getParent()->getParent() == F &&

          // Check that the types are the same, since this code handles casts...
          Other->getType() == I->getType()) {

        // These instructions are identical.  Handle the situation.
        CommonSubExpressionFound(I, Other);
        return true;   // One instruction eliminated!
      }

  return false;
}

bool GCSE::visitBinaryOperator(Instruction *I) {
  Value *LHS = I->getOperand(0), *RHS = I->getOperand(1);
  Function *F = I->getParent()->getParent();

  for (Value::use_iterator UI = LHS->use_begin(), UE = LHS->use_end();
       UI != UE; ++UI)
    if (Instruction *Other = dyn_cast<Instruction>(*UI))
      // Check to see if this new binary operator is not I, but same operand...
      if (Other != I && Other->getOpcode() == I->getOpcode() &&
          // Are the LHS and RHS the same?
          Other->getOperand(0) == LHS && Other->getOperand(1) == RHS &&
          // Is it embeded in the same function?  (This could be false if LHS
          // is a constant or global!)
          Other->getParent()->getParent() == F) {

        // These instructions are identical.  Handle the situation.
        CommonSubExpressionFound(I, Other);
        return true;   // One instruction eliminated!
      }

  return false;
}

bool GCSE::visitGetElementPtrInst(GetElementPtrInst *I) {
  Value *Op = I->getOperand(0);
  Function *F = I->getParent()->getParent();

  for (Value::use_iterator UI = Op->use_begin(), UE = Op->use_end();
       UI != UE; ++UI)
    if (GetElementPtrInst *Other = dyn_cast<GetElementPtrInst>(*UI))
      // Check to see if this new binary operator is not I, but same operand...
      if (Other != I && Other->getParent()->getParent() == F &&
          Other->getType() == I->getType()) {

        // Check to see that all operators past the 0th are the same...
        unsigned i = 1, e = I->getNumOperands();
        for (; i != e; ++i)
          if (I->getOperand(i) != Other->getOperand(i)) break;

        if (i == e) {
          // These instructions are identical.  Handle the situation.
          CommonSubExpressionFound(I, Other);
          return true;   // One instruction eliminated!
        }
      }

  return false;
}
<|endoftext|>


<commit_before>#include "model_initializer.h"
#include "backend.h"
#include "biology_module_util.h"
#include "cell.h"
#include "gtest/gtest.h"
#include "resource_manager.h"
#include "test_util.h"
#include "variadic_template_parameter_util.h"

namespace bdm {
namespace model_initializer_test_internal {

TEST(ModelInitializerTest, Grid3D) {
  auto rm = ResourceManager<>::Get();

  ModelInitializer::Grid3D(2, 12, [](const std::array<double, 3>& pos) {
    Cell cell(pos);
    return cell;
  });

  auto cells = rm->Get<Cell>();
  EXPECT_EQ(8u, cells->size());
  EXPECT_ARR_EQ({0, 0, 0}, (*cells)[0].GetPosition());
  EXPECT_ARR_EQ({0, 0, 12}, (*cells)[1].GetPosition());
  EXPECT_ARR_EQ({0, 12, 0}, (*cells)[2].GetPosition());
  EXPECT_ARR_EQ({0, 12, 12}, (*cells)[3].GetPosition());
  EXPECT_ARR_EQ({12, 0, 0}, (*cells)[4].GetPosition());
  EXPECT_ARR_EQ({12, 0, 12}, (*cells)[5].GetPosition());
  EXPECT_ARR_EQ({12, 12, 0}, (*cells)[6].GetPosition());
  EXPECT_ARR_EQ({12, 12, 12}, (*cells)[7].GetPosition());
}

}  // namespace model_initializer_test_internal
}  // namespace bdm
<commit_msg>Fix failing ModelInitializer test<commit_after>#include "model_initializer.h"
#include "backend.h"
#include "biology_module_util.h"
#include "cell.h"
#include "gtest/gtest.h"
#include "resource_manager.h"
#include "test_util.h"
#include "variadic_template_parameter_util.h"

namespace bdm {
namespace model_initializer_test_internal {

TEST(ModelInitializerTest, Grid3D) {
  auto rm = ResourceManager<>::Get();
  rm->Clear();

  ModelInitializer::Grid3D(2, 12, [](const std::array<double, 3>& pos) {
    Cell cell(pos);
    return cell;
  });

  auto cells = rm->Get<Cell>();
  EXPECT_EQ(8u, cells->size());
  EXPECT_ARR_EQ({0, 0, 0}, (*cells)[0].GetPosition());
  EXPECT_ARR_EQ({0, 0, 12}, (*cells)[1].GetPosition());
  EXPECT_ARR_EQ({0, 12, 0}, (*cells)[2].GetPosition());
  EXPECT_ARR_EQ({0, 12, 12}, (*cells)[3].GetPosition());
  EXPECT_ARR_EQ({12, 0, 0}, (*cells)[4].GetPosition());
  EXPECT_ARR_EQ({12, 0, 12}, (*cells)[5].GetPosition());
  EXPECT_ARR_EQ({12, 12, 0}, (*cells)[6].GetPosition());
  EXPECT_ARR_EQ({12, 12, 12}, (*cells)[7].GetPosition());
}

}  // namespace model_initializer_test_internal
}  // namespace bdm
<|endoftext|>


<commit_before>#include <elf/oid.h>
#include <elf/memory.h>
#include <elf/time.h>
#include <elf/matchmaking.h>

namespace elf {

    enum MatchRank {
        ROOKIE_RANK = 800,
        MASTER_RANK = 2500,
        RANK_OFFSET = 100,
    };

    int get_rank_level(int rank) {
        if (rank <= ROOKIE_RANK) {
            return ROOKIE_RANK;
        } else if (rank > MASTER_RANK) {
            return MASTER_RANK;
        }
        return rank - rank % RANK_OFFSET;
    }

    struct MatchEntity {
        oid_t id;
        int elo;
        int status;
        int size;
        oid_t team_id;
        time_t time;

        std::list<MatchEntity*> children;

        int get_size() {
            if (children.empty()) {
                return size;
            }
            int total = 0;
            std::list<MatchEntity*>::iterator itr;
            for (itr = children.begin(); itr != children.end(); ++itr) {
                total += (*itr)->get_size();
            }
            return total;
        }
    };

    struct MatchRes {
        int type;
        std::vector<TeamSet> teams;
    };

    typedef std::map<int, TeamSet> rank_map_t;
    struct MatchQueue {
        int size_type;
        std::queue<MatchEntity*> candidates;
        rank_map_t ranks;
    };

    std::map<int, MatchPool*> MatchPool::s_pools;

    MatchPool::MatchPool()
        : _type(0)
        , _team_size(0)
        , _camp_size(0) {
    }

    MatchPool::MatchPool(int type, int team_size, int camp_size)
        : _type(type)
        , _team_size(team_size)
        , _camp_size(camp_size) {
    }

    MatchPool::~MatchPool() {
        for (std::map<oid_t, MatchEntity*>::iterator itr = _entities.begin();
                itr != _entities.end();
                ++itr) {
            E_DELETE itr->second;
        }
        _entities.clear();

        for (std::map<int, MatchQueue*>::iterator itr = _queues.begin();
                itr != _queues.end();
                ++ itr) {
            E_DELETE itr->second;
        }

        _queues.clear();
    }

    oid_t MatchPool::Push(int elo, int size, oid_t teamId) {
        MatchEntity *ent = E_NEW MatchEntity;
        ent->id = oid_gen();
        ent->elo = elo;
        ent->time = time_s();
        ent->status = MATCH_PENDING;
        ent->team_id = teamId;
        ent->size = size;

        push(ent);
        return ent->id;
    }

    void  MatchPool::push(MatchEntity *ent) {
        _entities[ent->id] = ent;

        std::map<int, MatchQueue*>::iterator itr = _queues.find(ent->size);
        MatchQueue *que;
        if (itr == _queues.end()) {
            que = E_NEW MatchQueue;
            que->size_type = ent->size;
            _queues[ent->size] = que;
        } else {
            que = itr->second;
        }
        que->candidates.push(ent);

        int lvl = get_rank_level(ent->elo);
        rank_map_t::iterator itr_rank = que->ranks.find(lvl);
        if (itr_rank == que->ranks.end()) {
            que->ranks.insert(std::make_pair(lvl, TeamSet()));
        }
        que->ranks[lvl].insert(ent->id);
    }

    MatchEntity *MatchPool::top(int size_type) {
        std::map<int, MatchQueue*>::iterator itr = _queues.find(size_type);
        if (itr == _queues.end()) {
            return NULL;
        }
        MatchQueue *que = itr->second;
        if (que->candidates.empty()) {
            return NULL;
        }
        MatchEntity *ent = que->candidates.front();
        que->candidates.pop();
        return ent;
    }

    /// find skill proper opponent
    MatchEntity *MatchPool::get_opponent(MatchEntity *ent) {
        int lvl = get_rank_level(ent->elo);
        std::map<int, MatchQueue*>::iterator itr = _queues.find(ent->get_size());
        if (itr == _queues.end()) {
            return NULL;
        }
        MatchQueue *que = itr->second;

        rank_map_t::iterator itr_rank = que->ranks.find(lvl);
        if (itr_rank == que->ranks.end()) {
            return NULL;
        }
        TeamSet::iterator itr_t = itr_rank->second.begin();
        for (;itr_t != itr_rank->second.end(); ++itr_t) {
            if (*itr_t != ent->id) {
                return _entities[*itr_t];
            }
        }
        return NULL;
    }

    bool MatchPool::pop(int size_type) {
        std::vector<std::vector<MatchEntity*> > camps(_camp_size);

        MatchEntity *ent = top(size_type);
        if (ent == NULL) {
            return false;
        }
        camps[0].push_back(ent);

        for (int i = 1;i < _camp_size; i++) {
            MatchEntity *opp = get_opponent(ent);
            if (opp == NULL) {
                return false;
            }
            camps[i].push_back(opp);
        }

        int size = ent->get_size();
        while (size < _camp_size) {
            MatchEntity *buddy = NULL; //get_buddy(_camp_size - size);
            if (buddy == NULL) {
                return false;
            }
            camps[0].push_back(buddy);
            for (int i = 1;i < _camp_size; i++) {
                MatchEntity *opp_buddy = get_opponent(buddy);
                if (opp_buddy == NULL) {
                    return false;
                }
                camps[i].push_back(opp_buddy);
            }
            size += buddy->get_size();
            return true;
        }
        return false;
    }

    /// pop matched team(s)
    bool MatchPool::pop(MatchRes &res) {
        std::vector<std::vector<MatchEntity*> > camps(_camp_size);

        for (int i = _team_size;i >= 1; i--) {
            pop(i);
        }

        /*
        MatchEntity *ent = top();
        if (ent == NULL) {
            return false;
        }

        camps[0].push_back(ent);

        MatchEntity *opt = get_opponent(ent);
        if (opt == NULL) {
            return false;
        }
        */

        return false;
    }

    void MatchPool::Del(const oid_t &id) {
        std::map<oid_t, MatchEntity*>::iterator itr = _entities.find(id);
        if (itr != _entities.end()) {
            MatchEntity *ent = itr->second;
            ent->status = MatchPool::MATCH_DELETED;
        }
    }

    MatchPool *MatchPool::Create(int type, int team_size, int camp_size) {
        MatchPool *pool = Get(type);
        if (pool != NULL) {
            return pool;
        }
        pool = E_NEW MatchPool(type, team_size, camp_size);
        s_pools[type] = pool;
        return pool;
    }

    MatchPool *MatchPool::Get(int type) {
        std::map<int, MatchPool*>::iterator itr = s_pools.find(type);
        MatchPool *pool = NULL;
        if (itr != s_pools.end()) {
            pool = itr->second;
        }
        return pool;
    }

    void MatchPool::Proc(std::list<MatchRes> &resList) {
        std::map<int, MatchPool*>::iterator itr;
        for (itr = s_pools.begin(); itr != s_pools.end(); ++itr) {
            MatchRes res;
            if (itr->second->pop(res)) {
                resList.push_back(res);
            }
        }
    }

    void MatchPool::Release() {
        std::map<int, MatchPool*>::iterator itr;
        for (itr = s_pools.begin(); itr != s_pools.end(); ++itr) {
            E_DELETE itr->second;
        }
        s_pools.clear();
    }

} // namespace MatchMaking
<commit_msg>[MOD] matchmaking<commit_after>#include <elf/oid.h>
#include <elf/memory.h>
#include <elf/time.h>
#include <elf/matchmaking.h>

namespace elf {

    enum MatchRank {
        ROOKIE_RANK = 800,
        MASTER_RANK = 2500,
        RANK_OFFSET = 100,
    };

    int get_rank_level(int rank) {
        if (rank <= ROOKIE_RANK) {
            return ROOKIE_RANK;
        } else if (rank > MASTER_RANK) {
            return MASTER_RANK;
        }
        return rank - rank % RANK_OFFSET;
    }

    struct MatchEntity {
        oid_t id;
        int elo;
        int status;
        int size;
        oid_t team_id;
        time_t time;

        std::list<MatchEntity*> children;

        int get_size() {
            if (children.empty()) {
                return size;
            }
            int total = 0;
            std::list<MatchEntity*>::iterator itr;
            for (itr = children.begin(); itr != children.end(); ++itr) {
                total += (*itr)->get_size();
            }
            return total;
        }
    };

    struct MatchRes {
        int type;
        std::vector<TeamSet> teams;
    };

    typedef std::map<int, TeamSet> rank_map_t;
    struct MatchQueue {
        int size_type;
        std::queue<MatchEntity*> candidates;
        rank_map_t ranks;
    };

    std::map<int, MatchPool*> MatchPool::s_pools;

    MatchPool::MatchPool()
        : _type(0)
        , _team_size(0)
        , _camp_size(0) {
    }

    MatchPool::MatchPool(int type, int team_size, int camp_size)
        : _type(type)
        , _team_size(team_size)
        , _camp_size(camp_size) {
    }

    MatchPool::~MatchPool() {
        for (std::map<oid_t, MatchEntity*>::iterator itr = _entities.begin();
                itr != _entities.end();
                ++itr) {
            E_DELETE itr->second;
        }
        _entities.clear();

        for (std::map<int, MatchQueue*>::iterator itr = _queues.begin();
                itr != _queues.end();
                ++ itr) {
            E_DELETE itr->second;
        }

        _queues.clear();
    }

    oid_t MatchPool::Push(int elo, int size, oid_t teamId) {
        MatchEntity *ent = E_NEW MatchEntity;
        ent->id = oid_gen();
        ent->elo = elo;
        ent->time = time_s();
        ent->status = MATCH_PENDING;
        ent->team_id = teamId;
        ent->size = size;

        push(ent);
        return ent->id;
    }

    void  MatchPool::push(MatchEntity *ent) {
        _entities[ent->id] = ent;

        std::map<int, MatchQueue*>::iterator itr = _queues.find(ent->size);
        MatchQueue *que;
        if (itr == _queues.end()) {
            que = E_NEW MatchQueue;
            que->size_type = ent->size;
            _queues[ent->size] = que;
        } else {
            que = itr->second;
        }
        que->candidates.push(ent);

        int lvl = get_rank_level(ent->elo);
        rank_map_t::iterator itr_rank = que->ranks.find(lvl);
        if (itr_rank == que->ranks.end()) {
            que->ranks.insert(std::make_pair(lvl, TeamSet()));
        }
        que->ranks[lvl].insert(ent->id);
    }

    MatchEntity *MatchPool::top(int size_type) {
        std::map<int, MatchQueue*>::iterator itr = _queues.find(size_type);
        if (itr == _queues.end()) {
            return NULL;
        }
        MatchQueue *que = itr->second;
        if (que->candidates.empty()) {
            return NULL;
        }
        MatchEntity *ent = que->candidates.front();
        que->candidates.pop();
        return ent;
    }

    /// find skill proper opponent
    MatchEntity *MatchPool::get_opponent(MatchEntity *ent) {
        int lvl = get_rank_level(ent->elo);
        std::map<int, MatchQueue*>::iterator itr = _queues.find(ent->get_size());
        if (itr == _queues.end()) {
            return NULL;
        }
        MatchQueue *que = itr->second;

        rank_map_t::iterator itr_rank = que->ranks.find(lvl);
        if (itr_rank == que->ranks.end()) {
            return NULL;
        }
        TeamSet::iterator itr_t = itr_rank->second.begin();
        for (;itr_t != itr_rank->second.end(); ++itr_t) {
            if (*itr_t != ent->id) {
                return _entities[*itr_t];
            }
        }
        return NULL;
    }

    bool MatchPool::pop(int size_type) {
        std::vector<std::vector<MatchEntity*> > camps(_camp_size);

        MatchEntity *ent = top(size_type);
        if (ent == NULL) {
            return false;
        }
        camps[0].push_back(ent);

        for (int i = 1;i < _camp_size; i++) {
            MatchEntity *opp = get_opponent(ent);
            if (opp == NULL) {
                return false;
            }
            camps[i].push_back(opp);
        }

        int size = ent->get_size();
        while (size < _camp_size) {
            MatchEntity *buddy = NULL; //get_buddy(_camp_size - size);
            if (buddy == NULL) {
                return false;
            }
            camps[0].push_back(buddy);
            for (int i = 1;i < _camp_size; i++) {
                MatchEntity *opp_buddy = get_opponent(buddy);
                if (opp_buddy == NULL) {
                    return false;
                }
                camps[i].push_back(opp_buddy);
            }
            size += buddy->get_size();
            return true;
        }
        return false;
    }

    /// pop matched team(s)
    bool MatchPool::pop(MatchRes &res) {
        std::vector<std::vector<MatchEntity*> > camps(_camp_size);

        for (int i = _team_size;i >= 1; i--) {
            pop(i);
        }

        /*
        MatchEntity *ent = top();
        if (ent == NULL) {
            return false;
        }

        camps[0].push_back(ent);

        MatchEntity *opt = get_opponent(ent);
        if (opt == NULL) {
            return false;
        }
        */

        return false;
    }

    void MatchPool::Del(const oid_t &id) {
        std::map<oid_t, MatchEntity*>::iterator itr = _entities.find(id);
        if (itr != _entities.end()) {
            MatchEntity *ent = itr->second;
            ent->status = MatchPool::MATCH_DELETED;
        }
    }

    MatchPool *MatchPool::Create(int type, int team_size, int camp_size) {
        MatchPool *pool = Get(type);
        if (pool != NULL) {
            return pool;
        }
        pool = E_NEW MatchPool(type, team_size, camp_size);
        s_pools[type] = pool;
        return pool;
    }

    MatchPool *MatchPool::Get(int type) {
        std::map<int, MatchPool*>::iterator itr = s_pools.find(type);
        MatchPool *pool = NULL;
        if (itr != s_pools.end()) {
            pool = itr->second;
        }
        return pool;
    }

    void MatchPool::Proc(std::list<MatchRes> &resList) {
        std::map<int, MatchPool*>::iterator itr;
        for (itr = s_pools.begin(); itr != s_pools.end(); ++itr) {
            MatchRes res;
            if (itr->second->pop(res)) {
                resList.push_back(res);
            }
        }

        // adjust ranklevel for entities.
    }

    void MatchPool::Release() {
        std::map<int, MatchPool*>::iterator itr;
        for (itr = s_pools.begin(); itr != s_pools.end(); ++itr) {
            E_DELETE itr->second;
        }
        s_pools.clear();
    }

} // namespace MatchMaking
<|endoftext|>