<commit_before>/*
    PicoGUI Client/Server Test Application
    Copyright (C) 2003 by Mat Sutcliffe <oktal@gmx.co.uk>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "csutil/ref.h"
#include "igraphic/imageio.h"
#include "ivideo/graph3d.h"
#include "ivideo/fontserv.h"
#include "iutil/event.h"
#include "iutil/evdefs.h"
#include "cstool/initapp.h"
#include "iutil/objreg.h"
#include "cssys/sysfunc.h"
//#include "ivaria/gclient.h"
#include "ivaria/gserver.h"

CS_IMPLEMENT_APPLICATION

iObjectRegistry *objreg;
csRef<iGraphics3D> G3D;

bool HandleEvent (iEvent &ev)
{
  if (ev.Type == csevBroadcast)
  {
    if (ev.Command.Code == cscmdPreProcess)
    {
      G3D->BeginDraw (CSDRAW_2DGRAPHICS);
    }
    else if (ev.Command.Code == cscmdPostProcess)
    {
      G3D->FinishDraw ();
      G3D->Print (0);
    }
    else return false;
  }
  else if (ev.Type == csevKeyDown && ev.Key.Char == 'q')
  {
    csInitializer::CloseApplication (objreg);
  }
  else return false;

  csSleep(5);

  return true;
}

int main (int argc, char *argv[])
{
  objreg = csInitializer::CreateEnvironment (argc, argv);
  if (! objreg)
  {
    fprintf (stderr, "Failed to create environment.\n");
    return 1;
  }

  bool ok = csInitializer::RequestPlugins (objreg,
    CS_REQUEST_SOFTWARE3D,
    CS_REQUEST_FONTSERVER,
    CS_REQUEST_IMAGELOADER,
//  CS_REQUEST_PLUGIN ("crystalspace.gui.pico.client", iGUIClientHelper),
    CS_REQUEST_PLUGIN ("crystalspace.gui.pico.server", iGUIServer),
    CS_REQUEST_END);
  if (! ok)
  {
    fprintf (stderr, "Failed to load plugins.\n");
    return 2;
  }

  G3D = CS_QUERY_REGISTRY (objreg, iGraphics3D);
  if (! G3D)
  {
    fprintf (stderr, "Failed to find 3d graphics driver.\n");
    return 3;
  }

  ok = G3D->Open ();
  if (! ok)
  {
    fprintf (stderr, "Failed to open 3d graphics display.\n");
    return 3;
  }

  ok = csInitializer::SetupEventHandler (objreg, HandleEvent,
    CSMASK_Nothing | CSMASK_Keyboard);
  if (! ok)
  {
    fprintf (stderr, "Failed to setup event handler.\n");
    return 5;
  }

  ok = csInitializer::OpenApplication (objreg);
  if (! ok)
  {
    fprintf (stderr, "Failed to open application.\n");
    return 6;
  }

  csDefaultRunLoop (objreg);

  // G3D->Close ();
  G3D = 0;
  csInitializer::DestroyApplication (objreg);
  return 0;
}
<commit_msg>Fixed some references that were held too long in pgtest.<commit_after>/*
    PicoGUI Client/Server Test Application
    Copyright (C) 2003 by Mat Sutcliffe <oktal@gmx.co.uk>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "csgfx/memimage.h"
#include "csutil/ref.h"
#include "igraphic/imageio.h"
#include "ivideo/graph2d.h"
#include "ivideo/graph3d.h"
#include "ivideo/fontserv.h"
#include "ivideo/txtmgr.h"
#include "iutil/event.h"
#include "iutil/evdefs.h"
#include "cstool/initapp.h"
#include "iutil/objreg.h"
#include "cssys/sysfunc.h"
//#include "ivaria/gclient.h"
#include "ivaria/gserver.h"

CS_IMPLEMENT_APPLICATION

iObjectRegistry *objreg;
csRef<iGraphics3D> G3D;

csRef<iTextureHandle> Target;

bool HandleEvent (iEvent &ev)
{
  if (ev.Type == csevBroadcast)
  {
    if (ev.Command.Code == cscmdPreProcess)
    {
      G3D->BeginDraw (CSDRAW_2DGRAPHICS);
      /*G3D->DrawPixmap (Target, 0, 0,
        256, 256,
        0, 0, 256, 256, 0);*/
    }
    else if (ev.Command.Code == cscmdPostProcess)
    {
      G3D->FinishDraw ();
      G3D->Print (0);
      csSleep (5);
    }
    else return false;
  }
  else if (ev.Type == csevKeyDown && ev.Key.Char == 'q')
  {
    csInitializer::CloseApplication (objreg);
  }
  else return false;

  csSleep(5);

  return true;
}

int main (int argc, char *argv[])
{
  objreg = csInitializer::CreateEnvironment (argc, argv);
  if (! objreg)
  {
    fprintf (stderr, "Failed to create environment.\n");
    return 1;
  }

  bool ok = csInitializer::RequestPlugins (objreg,
    CS_REQUEST_OPENGL3D,
    CS_REQUEST_IMAGELOADER,
    CS_REQUEST_PLUGIN ("crystalspace.gui.pico.server", iGUIServer),
    CS_REQUEST_FONTSERVER,
    CS_REQUEST_IMAGELOADER,
//  CS_REQUEST_PLUGIN ("crystalspace.gui.pico.client", iGUIClientHelper),
    CS_REQUEST_END);
  if (! ok)
  {
    fprintf (stderr, "Failed to load plugins.\n");
    return 2;
  }

  G3D = CS_QUERY_REGISTRY (objreg, iGraphics3D);
  if (! G3D)
  {
    fprintf (stderr, "Failed to find 3d graphics driver.\n");
    return 3;
  }

  ok = G3D->Open ();
  if (! ok)
  {
    fprintf (stderr, "Failed to open 3d graphics display.\n");
    return 3;
  }

  ok = csInitializer::SetupEventHandler (objreg, HandleEvent,
    CSMASK_Nothing | CSMASK_Keyboard);
  if (! ok)
  {
    fprintf (stderr, "Failed to setup event handler.\n");
    return 5;
  }

  csRef<iGraphics2D> G2D = csRef<iGraphics2D> (CS_QUERY_REGISTRY (objreg, iGraphics2D));
  if (! G2D)
  {
    fprintf (stderr, "Failed to find 2d graphics driver.\n");
    return 3;
  }

  csRef<iGUIServer> gui = csRef<iGUIServer> (CS_QUERY_REGISTRY (objreg, iGUIServer));
  if (! gui)
  {
    fprintf (stderr, "Failed to find GUI server.\n");
    return 3;
  }

  /*char* data = new char[256*256*4];
  csRef<iImage> tex = new csImageMemory (
    256, 256, data, false, CS_IMGFMT_TRUECOLOR | CS_IMGFMT_ALPHA, 0);

  Target = G3D->GetTextureManager ()->RegisterTexture (tex, CS_TEXTURE_3D);
  Target->Prepare ();

  gui->SetTarget (Target);*/

  G2D->SetMouseCursor (csmcNone);

  ok = csInitializer::OpenApplication (objreg);
  if (! ok)
  {
    fprintf (stderr, "Failed to open application.\n");
    return 6;
  }

  csDefaultRunLoop (objreg);

  // G3D->Close ();
  gui = 0;
  G2D = 0;
  G3D = 0;
  csInitializer::DestroyApplication (objreg);
  return 0;
}
<|endoftext|>


<commit_before>//===- Steensgaard.cpp - Context Insensitive Alias Analysis ---------------===//
//
// This pass uses the data structure graphs to implement a simple context
// insensitive alias analysis.  It does this by computing the local analysis
// graphs for all of the functions, then merging them together into a single big
// graph without cloning.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure.h"
#include "llvm/Analysis/DSGraph.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Module.h"
#include "Support/Statistic.h"

namespace {
  Statistic<> NumNoAlias  ("steens", "Number of 'no alias' replies");
  Statistic<> NumMayAlias ("steens", "Number of 'may alias' replies");
};

namespace {
  class Steens : public Pass, public AliasAnalysis {
    DSGraph *ResultGraph;
    DSGraph *GlobalsGraph;  // FIXME: Eliminate globals graph stuff from DNE
  public:
    Steens() : ResultGraph(0) {}
    ~Steens() { assert(ResultGraph == 0 && "releaseMemory not called?"); }

    //------------------------------------------------
    // Implement the Pass API
    //

    // run - Build up the result graph, representing the pointer graph for the
    // program.
    //
    bool run(Module &M);

    virtual void releaseMemory() { delete ResultGraph; ResultGraph = 0; }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();                    // Does not transform code...
      AU.addRequired<LocalDataStructures>();   // Uses local dsgraph
      AU.addRequired<AliasAnalysis>();         // Chains to another AA impl...
    }

    // print - Implement the Pass::print method...
    void print(std::ostream &O, const Module *M) const {
      assert(ResultGraph && "Result graph has not yet been computed!");
      ResultGraph->writeGraphToFile(O, "steensgaards");
    }

    //------------------------------------------------
    // Implement the AliasAnalysis API
    //

    // alias - This is the only method here that does anything interesting...
    Result alias(const Value *V1, const Value *V2);

    /// canCallModify - Not implemented yet: FIXME
    ///
    Result canCallModify(const CallInst &CI, const Value *Ptr) {
      return MayAlias;
    }

    /// canInvokeModify - Not implemented yet: FIXME
    ///
    Result canInvokeModify(const InvokeInst &I, const Value *Ptr) {
      return MayAlias;
    }

  private:
    void ResolveFunctionCall(Function *F, const DSCallSite &Call,
                             DSNodeHandle &RetVal);
  };

  // Register the pass...
  RegisterOpt<Steens> X("steens-aa",
                        "Steensgaard's FlowInsensitive/ConIns alias analysis");

  // Register as an implementation of AliasAnalysis
  RegisterAnalysisGroup<AliasAnalysis, Steens> Y;
}

/// ResolveFunctionCall - Resolve the actual arguments of a call to function F
/// with the specified call site descriptor.  This function links the arguments
/// and the return value for the call site context-insensitively.
///
void Steens::ResolveFunctionCall(Function *F, const DSCallSite &Call,
                                 DSNodeHandle &RetVal) {
  assert(ResultGraph != 0 && "Result graph not allocated!");
  hash_map<Value*, DSNodeHandle> &ValMap = ResultGraph->getScalarMap();

  // Handle the return value of the function...
  if (Call.getRetVal().getNode() && RetVal.getNode())
    RetVal.mergeWith(Call.getRetVal());

  // Loop over all pointer arguments, resolving them to their provided pointers
  unsigned PtrArgIdx = 0;
  for (Function::aiterator AI = F->abegin(), AE = F->aend(); AI != AE; ++AI) {
    hash_map<Value*, DSNodeHandle>::iterator I = ValMap.find(AI);
    if (I != ValMap.end())    // If its a pointer argument...
      I->second.mergeWith(Call.getPtrArg(PtrArgIdx++));
  }
}

/// run - Build up the result graph, representing the pointer graph for the
/// program.
///
bool Steens::run(Module &M) {
  assert(ResultGraph == 0 && "Result graph already allocated!");
  LocalDataStructures &LDS = getAnalysis<LocalDataStructures>();

  // Create a new, empty, graph...
  ResultGraph = new DSGraph();
  GlobalsGraph = new DSGraph();
  ResultGraph->setGlobalsGraph(GlobalsGraph);
  // RetValMap - Keep track of the return values for all functions that return
  // valid pointers.
  //
  hash_map<Function*, DSNodeHandle> RetValMap;

  // Loop over the rest of the module, merging graphs for non-external functions
  // into this graph.
  //
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isExternal()) {
      hash_map<Value*, DSNodeHandle> ValMap;
      {  // Scope to free NodeMap memory ASAP
        hash_map<const DSNode*, DSNodeHandle> NodeMap;
        const DSGraph &FDSG = LDS.getDSGraph(*I);
        DSNodeHandle RetNode = ResultGraph->cloneInto(FDSG, ValMap, NodeMap);

        // Keep track of the return node of the function's graph if it returns a
        // value...
        //
        if (RetNode.getNode())
          RetValMap[I] = RetNode;
      }

      // Incorporate the inlined Function's ScalarMap into the global
      // ScalarMap...
      hash_map<Value*, DSNodeHandle> &GVM = ResultGraph->getScalarMap();
      for (hash_map<Value*, DSNodeHandle>::iterator I = ValMap.begin(),
             E = ValMap.end(); I != E; ++I)
        GVM[I->first].mergeWith(I->second);
    }

  // FIXME: Must recalculate and use the Incomplete markers!!

  // Now that we have all of the graphs inlined, we can go about eliminating
  // call nodes...
  //
  std::vector<DSCallSite> &Calls =
    ResultGraph->getAuxFunctionCalls();
  assert(Calls.empty() && "Aux call list is already in use??");

  // Start with a copy of the original call sites...
  Calls = ResultGraph->getFunctionCalls();

  for (unsigned i = 0; i != Calls.size(); ) {
    DSCallSite &CurCall = Calls[i];

    // Loop over the called functions, eliminating as many as possible...
    std::vector<GlobalValue*> CallTargets;
    if (CurCall.isDirectCall())
      CallTargets.push_back(CurCall.getCalleeFunc());
    else
      CallTargets = CurCall.getCalleeNode()->getGlobals();

    for (unsigned c = 0; c != CallTargets.size(); ) {
      // If we can eliminate this function call, do so!
      bool Eliminated = false;
      if (Function *F = dyn_cast<Function>(CallTargets[c]))
        if (!F->isExternal()) {
          ResolveFunctionCall(F, CurCall, RetValMap[F]);
          Eliminated = true;
        }
      if (Eliminated)
        CallTargets.erase(CallTargets.begin()+c);
      else
        ++c;  // Cannot eliminate this call, skip over it...
    }

    if (CallTargets.empty())          // Eliminated all calls?
      Calls.erase(Calls.begin()+i);   // Remove from call list...
    else
      ++i;                            // Skip this call site...
  }

  // Update the "incomplete" markers on the nodes, ignoring unknownness due to
  // incoming arguments...
  ResultGraph->maskIncompleteMarkers();
  ResultGraph->markIncompleteNodes(DSGraph::IgnoreFormalArgs);

  // Remove any nodes that are dead after all of the merging we have done...
  // FIXME: We should be able to disable the globals graph for steens!
  ResultGraph->removeDeadNodes(DSGraph::KeepUnreachableGlobals);

  DEBUG(print(std::cerr, &M));
  return false;
}

// alias - This is the only method here that does anything interesting...
AliasAnalysis::Result Steens::alias(const Value *V1, const Value *V2) {
  assert(ResultGraph && "Result graph has not been computed yet!");

  hash_map<Value*, DSNodeHandle> &GSM = ResultGraph->getScalarMap();

  hash_map<Value*, DSNodeHandle>::iterator I = GSM.find(const_cast<Value*>(V1));
  if (I != GSM.end() && I->second.getNode()) {
    DSNodeHandle &V1H = I->second;
    hash_map<Value*, DSNodeHandle>::iterator J=GSM.find(const_cast<Value*>(V2));
    if (J != GSM.end() && J->second.getNode()) {
      DSNodeHandle &V2H = J->second;
      // If the two pointers point to different data structure graph nodes, they
      // cannot alias!
      if (V1H.getNode() != V2H.getNode()) {  // FIXME: Handle incompleteness!
        ++NumNoAlias;
        return NoAlias;
      }
      // FIXME: If the two pointers point to the same node, and the offsets are
      // different, and the LinkIndex vector doesn't alias the section, then the
      // two pointers do not alias.  We need access size information for the two
      // accesses though!
      //
    }
  }

  // Since Steensgaard cannot do any better, count it as a 'may alias'
  ++NumMayAlias;

  // If we cannot determine alias properties based on our graph, fall back on
  // some other AA implementation.
  //
  return getAnalysis<AliasAnalysis>().alias(V1, V2);
}
<commit_msg>Remove explicit result counters<commit_after>//===- Steensgaard.cpp - Context Insensitive Alias Analysis ---------------===//
//
// This pass uses the data structure graphs to implement a simple context
// insensitive alias analysis.  It does this by computing the local analysis
// graphs for all of the functions, then merging them together into a single big
// graph without cloning.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure.h"
#include "llvm/Analysis/DSGraph.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Module.h"

namespace {
  class Steens : public Pass, public AliasAnalysis {
    DSGraph *ResultGraph;
    DSGraph *GlobalsGraph;  // FIXME: Eliminate globals graph stuff from DNE
  public:
    Steens() : ResultGraph(0) {}
    ~Steens() { assert(ResultGraph == 0 && "releaseMemory not called?"); }

    //------------------------------------------------
    // Implement the Pass API
    //

    // run - Build up the result graph, representing the pointer graph for the
    // program.
    //
    bool run(Module &M);

    virtual void releaseMemory() { delete ResultGraph; ResultGraph = 0; }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesAll();                    // Does not transform code...
      AU.addRequired<LocalDataStructures>();   // Uses local dsgraph
      AU.addRequired<AliasAnalysis>();         // Chains to another AA impl...
    }

    // print - Implement the Pass::print method...
    void print(std::ostream &O, const Module *M) const {
      assert(ResultGraph && "Result graph has not yet been computed!");
      ResultGraph->writeGraphToFile(O, "steensgaards");
    }

    //------------------------------------------------
    // Implement the AliasAnalysis API
    //

    // alias - This is the only method here that does anything interesting...
    Result alias(const Value *V1, const Value *V2);

    /// canCallModify - Not implemented yet: FIXME
    ///
    Result canCallModify(const CallInst &CI, const Value *Ptr) {
      return MayAlias;
    }

    /// canInvokeModify - Not implemented yet: FIXME
    ///
    Result canInvokeModify(const InvokeInst &I, const Value *Ptr) {
      return MayAlias;
    }

  private:
    void ResolveFunctionCall(Function *F, const DSCallSite &Call,
                             DSNodeHandle &RetVal);
  };

  // Register the pass...
  RegisterOpt<Steens> X("steens-aa",
                        "Steensgaard's alias analysis (DSGraph based)");

  // Register as an implementation of AliasAnalysis
  RegisterAnalysisGroup<AliasAnalysis, Steens> Y;
}

/// ResolveFunctionCall - Resolve the actual arguments of a call to function F
/// with the specified call site descriptor.  This function links the arguments
/// and the return value for the call site context-insensitively.
///
void Steens::ResolveFunctionCall(Function *F, const DSCallSite &Call,
                                 DSNodeHandle &RetVal) {
  assert(ResultGraph != 0 && "Result graph not allocated!");
  hash_map<Value*, DSNodeHandle> &ValMap = ResultGraph->getScalarMap();

  // Handle the return value of the function...
  if (Call.getRetVal().getNode() && RetVal.getNode())
    RetVal.mergeWith(Call.getRetVal());

  // Loop over all pointer arguments, resolving them to their provided pointers
  unsigned PtrArgIdx = 0;
  for (Function::aiterator AI = F->abegin(), AE = F->aend(); AI != AE; ++AI) {
    hash_map<Value*, DSNodeHandle>::iterator I = ValMap.find(AI);
    if (I != ValMap.end())    // If its a pointer argument...
      I->second.mergeWith(Call.getPtrArg(PtrArgIdx++));
  }
}

/// run - Build up the result graph, representing the pointer graph for the
/// program.
///
bool Steens::run(Module &M) {
  assert(ResultGraph == 0 && "Result graph already allocated!");
  LocalDataStructures &LDS = getAnalysis<LocalDataStructures>();

  // Create a new, empty, graph...
  ResultGraph = new DSGraph();
  GlobalsGraph = new DSGraph();
  ResultGraph->setGlobalsGraph(GlobalsGraph);
  // RetValMap - Keep track of the return values for all functions that return
  // valid pointers.
  //
  hash_map<Function*, DSNodeHandle> RetValMap;

  // Loop over the rest of the module, merging graphs for non-external functions
  // into this graph.
  //
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isExternal()) {
      hash_map<Value*, DSNodeHandle> ValMap;
      {  // Scope to free NodeMap memory ASAP
        hash_map<const DSNode*, DSNodeHandle> NodeMap;
        const DSGraph &FDSG = LDS.getDSGraph(*I);
        DSNodeHandle RetNode = ResultGraph->cloneInto(FDSG, ValMap, NodeMap);

        // Keep track of the return node of the function's graph if it returns a
        // value...
        //
        if (RetNode.getNode())
          RetValMap[I] = RetNode;
      }

      // Incorporate the inlined Function's ScalarMap into the global
      // ScalarMap...
      hash_map<Value*, DSNodeHandle> &GVM = ResultGraph->getScalarMap();
      for (hash_map<Value*, DSNodeHandle>::iterator I = ValMap.begin(),
             E = ValMap.end(); I != E; ++I)
        GVM[I->first].mergeWith(I->second);
    }

  // FIXME: Must recalculate and use the Incomplete markers!!

  // Now that we have all of the graphs inlined, we can go about eliminating
  // call nodes...
  //
  std::vector<DSCallSite> &Calls =
    ResultGraph->getAuxFunctionCalls();
  assert(Calls.empty() && "Aux call list is already in use??");

  // Start with a copy of the original call sites...
  Calls = ResultGraph->getFunctionCalls();

  for (unsigned i = 0; i != Calls.size(); ) {
    DSCallSite &CurCall = Calls[i];

    // Loop over the called functions, eliminating as many as possible...
    std::vector<GlobalValue*> CallTargets;
    if (CurCall.isDirectCall())
      CallTargets.push_back(CurCall.getCalleeFunc());
    else
      CallTargets = CurCall.getCalleeNode()->getGlobals();

    for (unsigned c = 0; c != CallTargets.size(); ) {
      // If we can eliminate this function call, do so!
      bool Eliminated = false;
      if (Function *F = dyn_cast<Function>(CallTargets[c]))
        if (!F->isExternal()) {
          ResolveFunctionCall(F, CurCall, RetValMap[F]);
          Eliminated = true;
        }
      if (Eliminated)
        CallTargets.erase(CallTargets.begin()+c);
      else
        ++c;  // Cannot eliminate this call, skip over it...
    }

    if (CallTargets.empty())          // Eliminated all calls?
      Calls.erase(Calls.begin()+i);   // Remove from call list...
    else
      ++i;                            // Skip this call site...
  }

  // Update the "incomplete" markers on the nodes, ignoring unknownness due to
  // incoming arguments...
  ResultGraph->maskIncompleteMarkers();
  ResultGraph->markIncompleteNodes(DSGraph::IgnoreFormalArgs);

  // Remove any nodes that are dead after all of the merging we have done...
  // FIXME: We should be able to disable the globals graph for steens!
  ResultGraph->removeDeadNodes(DSGraph::KeepUnreachableGlobals);

  //print(std::cerr, &M);
  return false;
}

// alias - This is the only method here that does anything interesting...
AliasAnalysis::Result Steens::alias(const Value *V1, const Value *V2) {
  assert(ResultGraph && "Result graph has not been computed yet!");

  hash_map<Value*, DSNodeHandle> &GSM = ResultGraph->getScalarMap();

  hash_map<Value*, DSNodeHandle>::iterator I = GSM.find(const_cast<Value*>(V1));
  if (I != GSM.end() && I->second.getNode()) {
    DSNodeHandle &V1H = I->second;
    hash_map<Value*, DSNodeHandle>::iterator J=GSM.find(const_cast<Value*>(V2));
    if (J != GSM.end() && J->second.getNode()) {
      DSNodeHandle &V2H = J->second;
      // If the two pointers point to different data structure graph nodes, they
      // cannot alias!
      if (V1H.getNode() != V2H.getNode())    // FIXME: Handle incompleteness!
        return NoAlias;

      // FIXME: If the two pointers point to the same node, and the offsets are
      // different, and the LinkIndex vector doesn't alias the section, then the
      // two pointers do not alias.  We need access size information for the two
      // accesses though!
      //
    }
  }

  // If we cannot determine alias properties based on our graph, fall back on
  // some other AA implementation.
  //
  return getAnalysis<AliasAnalysis>().alias(V1, V2);
}
<|endoftext|>


<commit_before>/*
 * This file is part of Peli - universal JSON interaction library
 * Copyright (C) 2014  Alexey Chernov <4ernov@gmail.com>
 *
 * Peli is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <sstream>
#include <iostream>

#include "peli/json/value.h"

using namespace std;

using namespace peli;

namespace
{
	template<class ExceptionType> bool has_thrown_on(const string& text)
	{
		bool thrown { };

		istringstream is(text);
		json::value v;

		try
		{
			is >> v;
		}
		catch (const ExceptionType&)
		{
			thrown = true;
		}

		return thrown;
	}
}

int check()
{
	const string str1 = "   [\n\tnull   ]\r\n  ";
	const wstring str2 = L"[  \r\tnull   ]\n\t  \n  \n\r  ";

	istringstream is1(str1);
	json::value v1;
	is1 >> v1;

	wistringstream is2(str2);
	json::wvalue v2;
	is2 >> v2;

	const json::array& obj1(get<json::array>(v1));
	const json::warray& obj2(get<json::warray>(v2));
	json::array ch1 { json::value() };
	json::warray ch2 { json::wvalue() };

	if (obj1 != ch1)
		return 1;

	if (obj2 != ch2)
		return 2;

	if (!obj1[0].null())
		return 3;

	return 0;
}

int check_typos()
{
	if (!has_thrown_on<invalid_argument>("nil"))
		return 4;

	if (!has_thrown_on<invalid_argument>("nuul"))
		return 5;

	if (!has_thrown_on<invalid_argument>("nul"))
		return 6;

	return 0;
}

int main(int, char**)
{
	if (const auto r = check())
	{
		return r;
	}

	if (const auto r = check_typos())
	{
		return r;
	}

	return 0;
}
<commit_msg>Fix JSON null typo parsing test<commit_after>/*
 * This file is part of Peli - universal JSON interaction library
 * Copyright (C) 2014  Alexey Chernov <4ernov@gmail.com>
 *
 * Peli is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <sstream>
#include <iostream>

#include "peli/json/value.h"

using namespace std;

using namespace peli;

namespace
{
	template<class ExceptionType> bool has_thrown_on(const string& text)
	{
		bool thrown { };

		istringstream is(text);
		json::value v;

		try
		{
			is >> v;
		}
		catch (const ExceptionType&)
		{
			thrown = true;
		}

		return thrown;
	}
}

int check()
{
	const string str1 = "   [\n\tnull   ]\r\n  ";
	const wstring str2 = L"[  \r\tnull   ]\n\t  \n  \n\r  ";

	istringstream is1(str1);
	json::value v1;
	is1 >> v1;

	wistringstream is2(str2);
	json::wvalue v2;
	is2 >> v2;

	const json::array& obj1(get<json::array>(v1));
	const json::warray& obj2(get<json::warray>(v2));
	json::array ch1 { json::value() };
	json::warray ch2 { json::wvalue() };

	if (obj1 != ch1)
		return 1;

	if (obj2 != ch2)
		return 2;

	if (!obj1[0].null())
		return 3;

	return 0;
}

int check_typos()
{
	if (!has_thrown_on<invalid_argument>("[nil]"))
		return 4;

	if (!has_thrown_on<invalid_argument>("[nuul]"))
		return 5;

	if (!has_thrown_on<invalid_argument>("[nul]"))
		return 6;

	return 0;
}

int main(int, char**)
{
	if (const auto r = check())
	{
		return r;
	}

	if (const auto r = check_typos())
	{
		return r;
	}

	return 0;
}
<|endoftext|>


<commit_before>//===-- llvm/lib/Target/AArch64/AArch64CallLowering.cpp - Call lowering ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements the lowering of LLVM calls to machine code calls for
/// GlobalISel.
///
//===----------------------------------------------------------------------===//

#include "AArch64CallLowering.h"
#include "AArch64ISelLowering.h"

#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;

#ifndef LLVM_BUILD_GLOBAL_ISEL
#error "This shouldn't be built without GISel"
#endif

AArch64CallLowering::AArch64CallLowering(const AArch64TargetLowering &TLI)
  : CallLowering(&TLI) {
}

bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
                                      const Value *Val, unsigned VReg) const {
  MachineFunction &MF = MIRBuilder.getMF();
  const Function &F = *MF.getFunction();

  MachineInstrBuilder MIB = MIRBuilder.buildInstr(AArch64::RET_ReallyLR);
  assert(MIB.getInstr() && "Unable to build a return instruction?!");

  assert(((Val && VReg) || (!Val && !VReg)) && "Return value without a vreg");
  if (VReg) {
    MIRBuilder.setInstr(*MIB.getInstr(), /* Before */ true);
    const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
    CCAssignFn *AssignFn = TLI.CCAssignFnForReturn(F.getCallingConv());

    handleAssignments(
        MIRBuilder, AssignFn, MVT::getVT(Val->getType()), VReg,
        [&](MachineIRBuilder &MIRBuilder, unsigned ValReg, unsigned PhysReg) {
          MIRBuilder.buildCopy(PhysReg, ValReg);
          MIB.addUse(PhysReg, RegState::Implicit);
        });
  }
  return true;
}

bool AArch64CallLowering::handleAssignments(MachineIRBuilder &MIRBuilder,
                                            CCAssignFn *AssignFn,
                                            ArrayRef<MVT> ArgTypes,
                                            ArrayRef<unsigned> ArgRegs,
                                            AssignFnTy AssignValToReg) const {
  MachineFunction &MF = MIRBuilder.getMF();
  const Function &F = *MF.getFunction();

  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext());

  unsigned NumArgs = ArgTypes.size();
  auto CurVT = ArgTypes.begin();
  for (unsigned i = 0; i != NumArgs; ++i, ++CurVT) {
    bool Res = AssignFn(i, *CurVT, *CurVT, CCValAssign::Full, ISD::ArgFlagsTy(),
                        CCInfo);
    assert(!Res && "Call operand has unhandled type");
    (void)Res;
  }
  assert(ArgLocs.size() == ArgTypes.size() &&
         "We have a different number of location and args?!");
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];

    assert(VA.isRegLoc() && "Not yet implemented");

    switch (VA.getLocInfo()) {
    default:
      llvm_unreachable("Unknown loc info!");
    case CCValAssign::Full:
      break;
    case CCValAssign::BCvt:
      // We don't care about bitcast.
      break;
    case CCValAssign::AExt:
      // Existing high bits are fine for anyext (whatever they are).
      break;
    case CCValAssign::SExt:
    case CCValAssign::ZExt:
      // Zero/Sign extend the register.
      assert(0 && "Not yet implemented");
      break;
    }

    // Everything checks out, tell the caller where we've decided this
    // parameter/return value should go.
    AssignValToReg(MIRBuilder, ArgRegs[i], VA.getLocReg());
  }
  return true;
}

bool AArch64CallLowering::lowerFormalArguments(
    MachineIRBuilder &MIRBuilder, const Function::ArgumentListType &Args,
    ArrayRef<unsigned> VRegs) const {
  MachineFunction &MF = MIRBuilder.getMF();
  const Function &F = *MF.getFunction();

  SmallVector<MVT, 8> ArgTys;
  for (auto &Arg : Args)
    ArgTys.push_back(MVT::getVT(Arg.getType()));

  const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
  CCAssignFn *AssignFn =
      TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false);

  return handleAssignments(
      MIRBuilder, AssignFn, ArgTys, VRegs,
      [](MachineIRBuilder &MIRBuilder, unsigned ValReg, unsigned PhysReg) {
        MIRBuilder.getMBB().addLiveIn(PhysReg);
        MIRBuilder.buildCopy(ValReg, PhysReg);
      });
}

bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
                                    const CallInst &CI, unsigned CalleeReg,
                                    unsigned ResReg,
                                    ArrayRef<unsigned> ArgRegs) const {
  MachineFunction &MF = MIRBuilder.getMF();
  const Function &F = *MF.getFunction();

  // First step is to marshall all the function's parameters into the correct
  // physregs and memory locations. Gather the sequence of argument types that
  // we'll pass to the assigner function.
  SmallVector<MVT, 8> ArgTys;
  for (auto &Arg : CI.arg_operands())
    ArgTys.push_back(MVT::getVT(Arg->getType()));

  // Find out which ABI gets to decide where things go.
  const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
  CCAssignFn *CallAssignFn =
      TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false);

  // And finally we can do the actual assignments. For a call we need to keep
  // track of the registers used because they'll be implicit uses of the BL.
  SmallVector<unsigned, 8> PhysRegs;
  handleAssignments(
      MIRBuilder, CallAssignFn, ArgTys, ArgRegs,
      [&](MachineIRBuilder &MIRBuilder, unsigned ValReg, unsigned PhysReg) {
        MIRBuilder.buildCopy(PhysReg, ValReg);
        PhysRegs.push_back(PhysReg);
      });

  // Now we can build the actual call instruction.
  MachineInstrBuilder MIB;
  if (CalleeReg)
    MIB = MIRBuilder.buildInstr(AArch64::BLR).addUse(CalleeReg);
  else
    MIB = MIRBuilder.buildInstr(AArch64::BL)
              .addGlobalAddress(CI.getCalledFunction());

  // Tell the call which registers are clobbered.
  auto TRI = MF.getSubtarget().getRegisterInfo();
  MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv()));

  for (auto Reg : PhysRegs)
    MIB.addUse(Reg, RegState::Implicit);

  // Finally we can copy the returned value back into its virtual-register. In
  // symmetry with the arugments, the physical register must be an
  // implicit-define of the call instruction.
  CCAssignFn *RetAssignFn = TLI.CCAssignFnForReturn(F.getCallingConv());
  if (!CI.getType()->isVoidTy())
    handleAssignments(
        MIRBuilder, RetAssignFn, MVT::getVT(CI.getType()), ResReg,
        [&](MachineIRBuilder &MIRBuilder, unsigned ValReg, unsigned PhysReg) {
          MIRBuilder.buildCopy(ValReg, PhysReg);
          MIB.addDef(PhysReg, RegState::Implicit);
        });

  return true;
}
<commit_msg>[AArch64][CallLowering] Do not assert for not implemented part.<commit_after>//===-- llvm/lib/Target/AArch64/AArch64CallLowering.cpp - Call lowering ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements the lowering of LLVM calls to machine code calls for
/// GlobalISel.
///
//===----------------------------------------------------------------------===//

#include "AArch64CallLowering.h"
#include "AArch64ISelLowering.h"

#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;

#ifndef LLVM_BUILD_GLOBAL_ISEL
#error "This shouldn't be built without GISel"
#endif

AArch64CallLowering::AArch64CallLowering(const AArch64TargetLowering &TLI)
  : CallLowering(&TLI) {
}

bool AArch64CallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
                                      const Value *Val, unsigned VReg) const {
  MachineFunction &MF = MIRBuilder.getMF();
  const Function &F = *MF.getFunction();

  MachineInstrBuilder MIB = MIRBuilder.buildInstr(AArch64::RET_ReallyLR);
  assert(MIB.getInstr() && "Unable to build a return instruction?!");

  assert(((Val && VReg) || (!Val && !VReg)) && "Return value without a vreg");
  if (VReg) {
    MIRBuilder.setInstr(*MIB.getInstr(), /* Before */ true);
    const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
    CCAssignFn *AssignFn = TLI.CCAssignFnForReturn(F.getCallingConv());

    handleAssignments(
        MIRBuilder, AssignFn, MVT::getVT(Val->getType()), VReg,
        [&](MachineIRBuilder &MIRBuilder, unsigned ValReg, unsigned PhysReg) {
          MIRBuilder.buildCopy(PhysReg, ValReg);
          MIB.addUse(PhysReg, RegState::Implicit);
        });
  }
  return true;
}

bool AArch64CallLowering::handleAssignments(MachineIRBuilder &MIRBuilder,
                                            CCAssignFn *AssignFn,
                                            ArrayRef<MVT> ArgTypes,
                                            ArrayRef<unsigned> ArgRegs,
                                            AssignFnTy AssignValToReg) const {
  MachineFunction &MF = MIRBuilder.getMF();
  const Function &F = *MF.getFunction();

  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, F.getContext());

  unsigned NumArgs = ArgTypes.size();
  auto CurVT = ArgTypes.begin();
  for (unsigned i = 0; i != NumArgs; ++i, ++CurVT) {
    bool Res = AssignFn(i, *CurVT, *CurVT, CCValAssign::Full, ISD::ArgFlagsTy(),
                        CCInfo);
    if (Res)
      return false;
  }
  assert(ArgLocs.size() == ArgTypes.size() &&
         "We have a different number of location and args?!");
  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
    CCValAssign &VA = ArgLocs[i];

    // FIXME: Support non-register argument.
    if (!VA.isRegLoc())
      return false;

    switch (VA.getLocInfo()) {
    default:
      //  Unknown loc info!
      return false;
    case CCValAssign::Full:
      break;
    case CCValAssign::BCvt:
      // We don't care about bitcast.
      break;
    case CCValAssign::AExt:
      // Existing high bits are fine for anyext (whatever they are).
      break;
    case CCValAssign::SExt:
    case CCValAssign::ZExt:
      // Zero/Sign extend the register.
      // FIXME: Not yet implemented
      return false;
    }

    // Everything checks out, tell the caller where we've decided this
    // parameter/return value should go.
    AssignValToReg(MIRBuilder, ArgRegs[i], VA.getLocReg());
  }
  return true;
}

bool AArch64CallLowering::lowerFormalArguments(
    MachineIRBuilder &MIRBuilder, const Function::ArgumentListType &Args,
    ArrayRef<unsigned> VRegs) const {
  MachineFunction &MF = MIRBuilder.getMF();
  const Function &F = *MF.getFunction();

  SmallVector<MVT, 8> ArgTys;
  for (auto &Arg : Args)
    ArgTys.push_back(MVT::getVT(Arg.getType()));

  const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
  CCAssignFn *AssignFn =
      TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false);

  return handleAssignments(
      MIRBuilder, AssignFn, ArgTys, VRegs,
      [](MachineIRBuilder &MIRBuilder, unsigned ValReg, unsigned PhysReg) {
        MIRBuilder.getMBB().addLiveIn(PhysReg);
        MIRBuilder.buildCopy(ValReg, PhysReg);
      });
}

bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
                                    const CallInst &CI, unsigned CalleeReg,
                                    unsigned ResReg,
                                    ArrayRef<unsigned> ArgRegs) const {
  MachineFunction &MF = MIRBuilder.getMF();
  const Function &F = *MF.getFunction();

  // First step is to marshall all the function's parameters into the correct
  // physregs and memory locations. Gather the sequence of argument types that
  // we'll pass to the assigner function.
  SmallVector<MVT, 8> ArgTys;
  for (auto &Arg : CI.arg_operands())
    ArgTys.push_back(MVT::getVT(Arg->getType()));

  // Find out which ABI gets to decide where things go.
  const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>();
  CCAssignFn *CallAssignFn =
      TLI.CCAssignFnForCall(F.getCallingConv(), /*IsVarArg=*/false);

  // And finally we can do the actual assignments. For a call we need to keep
  // track of the registers used because they'll be implicit uses of the BL.
  SmallVector<unsigned, 8> PhysRegs;
  handleAssignments(
      MIRBuilder, CallAssignFn, ArgTys, ArgRegs,
      [&](MachineIRBuilder &MIRBuilder, unsigned ValReg, unsigned PhysReg) {
        MIRBuilder.buildCopy(PhysReg, ValReg);
        PhysRegs.push_back(PhysReg);
      });

  // Now we can build the actual call instruction.
  MachineInstrBuilder MIB;
  if (CalleeReg)
    MIB = MIRBuilder.buildInstr(AArch64::BLR).addUse(CalleeReg);
  else
    MIB = MIRBuilder.buildInstr(AArch64::BL)
              .addGlobalAddress(CI.getCalledFunction());

  // Tell the call which registers are clobbered.
  auto TRI = MF.getSubtarget().getRegisterInfo();
  MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv()));

  for (auto Reg : PhysRegs)
    MIB.addUse(Reg, RegState::Implicit);

  // Finally we can copy the returned value back into its virtual-register. In
  // symmetry with the arugments, the physical register must be an
  // implicit-define of the call instruction.
  CCAssignFn *RetAssignFn = TLI.CCAssignFnForReturn(F.getCallingConv());
  if (!CI.getType()->isVoidTy())
    handleAssignments(
        MIRBuilder, RetAssignFn, MVT::getVT(CI.getType()), ResReg,
        [&](MachineIRBuilder &MIRBuilder, unsigned ValReg, unsigned PhysReg) {
          MIRBuilder.buildCopy(ValReg, PhysReg);
          MIB.addDef(PhysReg, RegState::Implicit);
        });

  return true;
}
<|endoftext|>


<commit_before>//===- LoopInvariantCodeMotion.cpp - Code to perform loop fusion-----------===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// This file implements loop invariant code motion.
//
//===----------------------------------------------------------------------===//

#include <iomanip>
#include <sstream>

#include "mlir/AffineOps/AffineOps.h"
#include "mlir/Analysis/AffineAnalysis.h"
#include "mlir/Analysis/AffineStructures.h"
#include "mlir/Analysis/LoopAnalysis.h"
#include "mlir/Analysis/SliceAnalysis.h"
#include "mlir/Analysis/Utils.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Builders.h"
#include "mlir/Pass/Pass.h"
#include "mlir/StandardOps/Ops.h"
#include "mlir/Transforms/LoopUtils.h"
#include "mlir/Transforms/Passes.h"
#include "mlir/Transforms/Utils.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

#define DEBUG_TYPE "licm"

using llvm::SetVector;

using namespace mlir;

namespace {

/// Loop invariant code motion (LICM) pass.
/// TODO(asabne) : The pass is missing zero-trip tests.
/// TODO(asabne) : Check for the presence of side effects before hoisting.
struct LoopInvariantCodeMotion : public FunctionPass<LoopInvariantCodeMotion> {
  void runOnFunction() override;
  void runOnAffineForOp(AffineForOp forOp);
  std::vector<AffineForOp> forOps;
};
} // end anonymous namespace

FunctionPassBase *mlir::createLoopInvariantCodeMotionPass() {
  return new LoopInvariantCodeMotion();
}

void LoopInvariantCodeMotion::runOnAffineForOp(AffineForOp forOp) {
  auto *loopBody = forOp.getBody();

  // This is the place where hoisted instructions would reside.
  FuncBuilder b(forOp.getOperation());

  // This vector is used to place loop invariant operations.
  SmallVector<Operation *, 8> opsToMove;

  SetVector<Operation *> loopDefinedOps;
  // Generate forward slice which contains ops that fall under the transitive
  // definition closure following the loop induction variable.
  getForwardSlice(forOp, &loopDefinedOps);

  for (auto i : loopDefinedOps) {
    LLVM_DEBUG(i->print(llvm::dbgs() << "\nLoop-dependent op\n"));
  }

  for (auto &op : *loopBody) {
    // If the operation is loop invariant, insert it into opsToMove.
    if (!op.isa<AffineForOp>() && !op.isa<AffineTerminatorOp>() &&
        loopDefinedOps.count(&op) != 1) {
      LLVM_DEBUG(op.print(llvm::dbgs() << "\nLICM'ing op\n"));
      opsToMove.push_back(&op);
    }
  }

  // For all instructions that we found to be invariant, place them sequentially
  // right before the for loop.
  for (auto *op : opsToMove) {
    op->moveBefore(forOp);
  }

  LLVM_DEBUG(forOp.getOperation()->print(llvm::dbgs() << "\nModified loop\n"));

  // If the for loop body has a single operation (the terminator), erase it.
  if (forOp.getBody()->getOperations().size() == 1) {
    assert(forOp.getBody()->getOperations().front().isa<AffineTerminatorOp>());
    forOp.erase();
  }
}

void LoopInvariantCodeMotion::runOnFunction() {
  forOps.clear();

  // Gather all loops in a function, and order them in innermost-loop-first
  // order. This way, we first LICM from the inner loop, and place the ops in
  // the outer loop, which in turn can be further LICM'ed. This saves iterating
  // on the inner loop operations while LICMing through the outer loop.
  getFunction().walk<AffineForOp>(
      [&](AffineForOp forOp) { forOps.push_back(forOp); });
  // We gather loops first, and then go over them later because we don't want to
  // mess the iterators up.
  for (auto forOp : forOps) {
    auto *forInst = forOp.getOperation();
    LLVM_DEBUG(forInst->print(llvm::dbgs() << "\nOriginal loop\n"));
    runOnAffineForOp(forOp);
  }
}

static PassRegistration<LoopInvariantCodeMotion>
    pass("loop-invariant-code-motion",
         "Hoist loop invariant instructions outside of the loop");
<commit_msg>    Fix LLVM_DEBUG instances<commit_after>//===- LoopInvariantCodeMotion.cpp - Code to perform loop fusion-----------===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// This file implements loop invariant code motion.
//
//===----------------------------------------------------------------------===//

#include <iomanip>
#include <sstream>

#include "mlir/AffineOps/AffineOps.h"
#include "mlir/Analysis/AffineAnalysis.h"
#include "mlir/Analysis/AffineStructures.h"
#include "mlir/Analysis/LoopAnalysis.h"
#include "mlir/Analysis/SliceAnalysis.h"
#include "mlir/Analysis/Utils.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Builders.h"
#include "mlir/Pass/Pass.h"
#include "mlir/StandardOps/Ops.h"
#include "mlir/Transforms/LoopUtils.h"
#include "mlir/Transforms/Passes.h"
#include "mlir/Transforms/Utils.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

#define DEBUG_TYPE "licm"

using llvm::SetVector;

using namespace mlir;

namespace {

/// Loop invariant code motion (LICM) pass.
/// TODO(asabne) : The pass is missing zero-trip tests.
/// TODO(asabne) : Check for the presence of side effects before hoisting.
struct LoopInvariantCodeMotion : public FunctionPass<LoopInvariantCodeMotion> {
  void runOnFunction() override;
  void runOnAffineForOp(AffineForOp forOp);
  std::vector<AffineForOp> forOps;
};
} // end anonymous namespace

FunctionPassBase *mlir::createLoopInvariantCodeMotionPass() {
  return new LoopInvariantCodeMotion();
}

void LoopInvariantCodeMotion::runOnAffineForOp(AffineForOp forOp) {
  auto *loopBody = forOp.getBody();

  // This is the place where hoisted instructions would reside.
  FuncBuilder b(forOp.getOperation());

  // This vector is used to place loop invariant operations.
  SmallVector<Operation *, 8> opsToMove;

  SetVector<Operation *> loopDefinedOps;
  // Generate forward slice which contains ops that fall under the transitive
  // definition closure following the loop induction variable.
  getForwardSlice(forOp, &loopDefinedOps);

  LLVM_DEBUG(for (auto i
                  : loopDefinedOps) {
    (i->print(llvm::dbgs() << "\nLoop-dependent op\n"));
  });

  for (auto &op : *loopBody) {
    // If the operation is loop invariant, insert it into opsToMove.
    if (!op.isa<AffineForOp>() && !op.isa<AffineTerminatorOp>() &&
        loopDefinedOps.count(&op) != 1) {
      LLVM_DEBUG(op.print(llvm::dbgs() << "\nLICM'ing op\n"));
      opsToMove.push_back(&op);
    }
  }

  // For all instructions that we found to be invariant, place them sequentially
  // right before the for loop.
  for (auto *op : opsToMove) {
    op->moveBefore(forOp);
  }

  LLVM_DEBUG(forOp.getOperation()->print(llvm::dbgs() << "\nModified loop\n"));

  // If the for loop body has a single operation (the terminator), erase it.
  if (forOp.getBody()->getOperations().size() == 1) {
    assert(forOp.getBody()->getOperations().front().isa<AffineTerminatorOp>());
    forOp.erase();
  }
}

void LoopInvariantCodeMotion::runOnFunction() {
  forOps.clear();

  // Gather all loops in a function, and order them in innermost-loop-first
  // order. This way, we first LICM from the inner loop, and place the ops in
  // the outer loop, which in turn can be further LICM'ed. This saves iterating
  // on the inner loop operations while LICMing through the outer loop.
  getFunction().walk<AffineForOp>(
      [&](AffineForOp forOp) { forOps.push_back(forOp); });
  // We gather loops first, and then go over them later because we don't want to
  // mess the iterators up.
  for (auto op : forOps) {
    LLVM_DEBUG(op.getOperation()->print(llvm::dbgs() << "\nOriginal loop\n"));
    runOnAffineForOp(op);
  }
}

static PassRegistration<LoopInvariantCodeMotion>
    pass("loop-invariant-code-motion",
         "Hoist loop invariant instructions outside of the loop");
<|endoftext|>


<commit_before>//===- ValuePropagation.cpp - Propagate information derived control flow --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Value Propagation pass.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "value-propagation"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/LazyValueInfo.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;

STATISTIC(NumPhis,    "Number of phis propagated");
STATISTIC(NumSelects, "Number of selects propagated");

namespace {
  class ValuePropagation : public FunctionPass {
    LazyValueInfo *LVI;

    bool processSelect(SelectInst *SI);
    bool processPHI(PHINode *P);

  public:
    static char ID;
    ValuePropagation(): FunctionPass(ID) { }

    bool runOnFunction(Function &F);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<LazyValueInfo>();
    }
  };
}

char ValuePropagation::ID = 0;
INITIALIZE_PASS(ValuePropagation, "value-propagation",
                "Value Propagation", false, false);

// Public interface to the Value Propagation pass
Pass *llvm::createValuePropagationPass() {
  return new ValuePropagation();
}

bool ValuePropagation::processSelect(SelectInst *S) {
  Constant *C = LVI->getConstant(S->getOperand(0), S->getParent());
  if (!C) return false;

  ConstantInt *CI = dyn_cast<ConstantInt>(C);
  if (!CI) return false;

  if (CI->isZero()) {
    S->replaceAllUsesWith(S->getOperand(2));
    S->eraseFromParent();
  } else if (CI->isOne()) {
    S->replaceAllUsesWith(S->getOperand(1));
    S->eraseFromParent();
  } else {
    assert(0 && "Select on constant is neither 0 nor 1?");
  }

  ++NumSelects;

  return true;
}

bool ValuePropagation::processPHI(PHINode *P) {
  bool changed = false;

  BasicBlock *BB = P->getParent();
  for (unsigned i = 0; i < P->getNumIncomingValues(); ++i) {
    Constant *C = LVI->getConstantOnEdge(P->getIncomingValue(i),
                                         P->getIncomingBlock(i),
                                         BB);
    if (!C || C == P->getIncomingValue(i)) continue;

    P->setIncomingValue(i, C);
    changed = true;
  }

  if (Value *ConstVal = P->hasConstantValue()) {
    P->replaceAllUsesWith(ConstVal);
    P->eraseFromParent();
    changed = true;
  }

  ++NumPhis;

  return changed;
}

bool ValuePropagation::runOnFunction(Function &F) {
  LVI = &getAnalysis<LazyValueInfo>();

  bool changed = false;

  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) {
      Instruction *II = BI++;
      if (SelectInst *SI = dyn_cast<SelectInst>(II))
        changed |= processSelect(SI);
      else if (PHINode *P = dyn_cast<PHINode>(II))
        changed |= processPHI(P);
    }

  if (changed)
    for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
      SimplifyInstructionsInBlock(FI);

  return changed;
}
<commit_msg>Cleanups suggested by Chris.<commit_after>//===- ValuePropagation.cpp - Propagate information derived control flow --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Value Propagation pass.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "value-propagation"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/LazyValueInfo.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;

STATISTIC(NumPhis,    "Number of phis propagated");
STATISTIC(NumSelects, "Number of selects propagated");

namespace {
  class ValuePropagation : public FunctionPass {
    LazyValueInfo *LVI;

    bool processSelect(SelectInst *SI);
    bool processPHI(PHINode *P);

  public:
    static char ID;
    ValuePropagation(): FunctionPass(ID) { }

    bool runOnFunction(Function &F);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<LazyValueInfo>();
    }
  };
}

char ValuePropagation::ID = 0;
INITIALIZE_PASS(ValuePropagation, "value-propagation",
                "Value Propagation", false, false);

// Public interface to the Value Propagation pass
Pass *llvm::createValuePropagationPass() {
  return new ValuePropagation();
}

bool ValuePropagation::processSelect(SelectInst *S) {
  if (S->getType()->isVectorTy()) return false;

  Constant *C = LVI->getConstant(S->getOperand(0), S->getParent());
  if (!C) return false;

  ConstantInt *CI = dyn_cast<ConstantInt>(C);
  if (!CI) return false;

  S->replaceAllUsesWith(S->getOperand(CI->isOne() ? 1 : 2));
  S->eraseFromParent();

  ++NumSelects;

  return true;
}

bool ValuePropagation::processPHI(PHINode *P) {
  bool Changed = false;

  BasicBlock *BB = P->getParent();
  for (unsigned i = 0, e = P->getNumIncomingValues(); i < e; ++i) {
    Value *Incoming = P->getIncomingValue(i);
    if (isa<Constant>(Incoming)) continue;

    Constant *C = LVI->getConstantOnEdge(P->getIncomingValue(i),
                                         P->getIncomingBlock(i),
                                         BB);
    if (!C) continue;

    P->setIncomingValue(i, C);
    Changed = true;
  }

  if (Value *ConstVal = P->hasConstantValue()) {
    P->replaceAllUsesWith(ConstVal);
    P->eraseFromParent();
    Changed = true;
  }

  ++NumPhis;

  return Changed;
}

bool ValuePropagation::runOnFunction(Function &F) {
  LVI = &getAnalysis<LazyValueInfo>();

  bool Changed = false;

  for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
    for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) {
      Instruction *II = BI++;
      if (SelectInst *SI = dyn_cast<SelectInst>(II))
        Changed |= processSelect(SI);
      else if (PHINode *P = dyn_cast<PHINode>(II))
        Changed |= processPHI(P);
    }

  if (Changed)
    for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
      SimplifyInstructionsInBlock(FI);

  return changed;
}
<|endoftext|>


<commit_before>#include "core/tz.hpp"
#include "core/assert.hpp"
#include "core/report.hpp"
#include "core/peripherals/monitor.hpp"
#include "core/profiling/zone.hpp"

#if TZ_VULKAN
#include "gl/impl/backend/vk2/tz_vulkan.hpp"
#elif TZ_OGL
#include "gl/impl/backend/ogl2/tz_opengl.hpp"
#endif

#include <cstdio>

namespace tz
{
	tz::Window* wnd = nullptr;
	bool initialised = false;
	InitialiseInfo init_info = {};

	void initialise(InitialiseInfo init)
	{
		TZ_PROFZONE("Topaz Initialise", TZ_PROFCOL_BLUE);
		tz_report("%s v%u.%u.%u (%s)", init.name, init.version.major, init.version.minor, init.version.patch, tz::info().to_string().c_str());
		tz::GameInfo game_info{.name = init.name, .version = init.version, .engine = tz::info()};
		// Ensure we're not already initialised before doing anything.
		tz_assert(wnd == nullptr && !initialised, "tz::initialise(): Already initialised (wnd = %p, init = %d)", wnd, initialised);

		// Firstly, initialise GLFW.
		{
			TZ_PROFZONE("GLFW Initialise", TZ_PROFCOL_BLUE);
			[[maybe_unused]] int glfw_ret = glfwInit();
			tz_assert(glfw_ret == GLFW_TRUE, "GLFW initialisation returned without crashing, but we still failed to initialise. Most likely a platform-specific error has occurred. Does your machine support window creation?");
		}
		// Then, initialise peripherals.
		{
			tz::detail::peripherals::monitor::initialise();
		}
		// After that, create the window.
		{
			WindowHintList hints;
			if(init.flags.contains(ApplicationFlag::HiddenWindow))
			{
				hints.add(WindowHint{.hint = GLFW_VISIBLE, .value = GLFW_FALSE});
			}

			std::string window_title = init.name;
			#if TZ_DEBUG
				window_title = game_info.to_string();
			#endif // TZ_DEBUG

			WindowInitArgs wargs
			{
				.width = static_cast<int>(init.dimensions[0]),
				.height = static_cast<int>(init.dimensions[1]),
				.title = window_title.c_str(),
				.flags =
				{
					.resizeable = !init.flags.contains(ApplicationFlag::UnresizeableWindow)
				}
			};

			wnd = new tz::Window{wargs, hints};
		}
		// Finally, initialise render backends.
		{
			#if TZ_VULKAN
				tz::gl::vk2::initialise(game_info);
			#elif TZ_OGL
				tz::gl::ogl2::initialise();
			#endif
		}

		initialised = true;
		init_info = init;
	}

	void terminate()
	{
		TZ_PROFZONE("Topaz Terminate", TZ_PROFCOL_BLUE);
		tz_assert(wnd != nullptr && initialised, "tz::terminate(): Not initialised");
		#if TZ_VULKAN
			tz::gl::vk2::terminate();
		#elif TZ_OGL
			tz::gl::ogl2::terminate();
		#endif

		delete wnd;

		tz::detail::peripherals::monitor::terminate();
		{
			TZ_PROFZONE("GLFW Terminate", TZ_PROFCOL_BLUE);
			glfwTerminate();
		}
		initialised = false;
	}

	Window& window()
	{
		tz_assert(wnd != nullptr, "tz::window(): Not initialised");
		return *wnd;
	}

	bool is_initialised()
	{
		return initialised;
	}
}
<commit_msg>* Fix warning where gameinfo variable is unused for ogl release, by making it [[maybe_unused]]<commit_after>#include "core/tz.hpp"
#include "core/assert.hpp"
#include "core/report.hpp"
#include "core/peripherals/monitor.hpp"
#include "core/profiling/zone.hpp"

#if TZ_VULKAN
#include "gl/impl/backend/vk2/tz_vulkan.hpp"
#elif TZ_OGL
#include "gl/impl/backend/ogl2/tz_opengl.hpp"
#endif

#include <cstdio>

namespace tz
{
	tz::Window* wnd = nullptr;
	bool initialised = false;
	InitialiseInfo init_info = {};

	void initialise(InitialiseInfo init)
	{
		TZ_PROFZONE("Topaz Initialise", TZ_PROFCOL_BLUE);
		tz_report("%s v%u.%u.%u (%s)", init.name, init.version.major, init.version.minor, init.version.patch, tz::info().to_string().c_str());
		[[maybe_unused]] tz::GameInfo game_info{.name = init.name, .version = init.version, .engine = tz::info()};
		// Ensure we're not already initialised before doing anything.
		tz_assert(wnd == nullptr && !initialised, "tz::initialise(): Already initialised (wnd = %p, init = %d)", wnd, initialised);

		// Firstly, initialise GLFW.
		{
			TZ_PROFZONE("GLFW Initialise", TZ_PROFCOL_BLUE);
			[[maybe_unused]] int glfw_ret = glfwInit();
			tz_assert(glfw_ret == GLFW_TRUE, "GLFW initialisation returned without crashing, but we still failed to initialise. Most likely a platform-specific error has occurred. Does your machine support window creation?");
		}
		// Then, initialise peripherals.
		{
			tz::detail::peripherals::monitor::initialise();
		}
		// After that, create the window.
		{
			WindowHintList hints;
			if(init.flags.contains(ApplicationFlag::HiddenWindow))
			{
				hints.add(WindowHint{.hint = GLFW_VISIBLE, .value = GLFW_FALSE});
			}

			std::string window_title = init.name;
			#if TZ_DEBUG
				window_title = game_info.to_string();
			#endif // TZ_DEBUG

			WindowInitArgs wargs
			{
				.width = static_cast<int>(init.dimensions[0]),
				.height = static_cast<int>(init.dimensions[1]),
				.title = window_title.c_str(),
				.flags =
				{
					.resizeable = !init.flags.contains(ApplicationFlag::UnresizeableWindow)
				}
			};

			wnd = new tz::Window{wargs, hints};
		}
		// Finally, initialise render backends.
		{
			#if TZ_VULKAN
				tz::gl::vk2::initialise(game_info);
			#elif TZ_OGL
				tz::gl::ogl2::initialise();
			#endif
		}

		initialised = true;
		init_info = init;
	}

	void terminate()
	{
		TZ_PROFZONE("Topaz Terminate", TZ_PROFCOL_BLUE);
		tz_assert(wnd != nullptr && initialised, "tz::terminate(): Not initialised");
		#if TZ_VULKAN
			tz::gl::vk2::terminate();
		#elif TZ_OGL
			tz::gl::ogl2::terminate();
		#endif

		delete wnd;

		tz::detail::peripherals::monitor::terminate();
		{
			TZ_PROFZONE("GLFW Terminate", TZ_PROFCOL_BLUE);
			glfwTerminate();
		}
		initialised = false;
	}

	Window& window()
	{
		tz_assert(wnd != nullptr, "tz::window(): Not initialised");
		return *wnd;
	}

	bool is_initialised()
	{
		return initialised;
	}
}
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
#include <string.h>  // for strdup
#include <algorithm>
#include <stdexcept>
#include <string>

#include "paddle/fluid/framework/init.h"
#include "paddle/fluid/framework/operator.h"
#include "paddle/fluid/platform/device_context.h"
#include "paddle/fluid/platform/place.h"
#include "paddle/fluid/string/piece.h"

namespace paddle {
namespace framework {

std::once_flag gflags_init_flag;
std::once_flag p2p_init_flag;

void InitGflags(std::vector<std::string> argv) {
  std::call_once(gflags_init_flag, [&]() {
    argv.insert(argv.begin(), "dummy");
    int argc = argv.size();
    char **arr = new char *[argv.size()];
    std::string line;
    for (size_t i = 0; i < argv.size(); i++) {
      arr[i] = &argv[i][0];
      line += argv[i];
      line += ' ';
    }
    google::ParseCommandLineFlags(&argc, &arr, true);
    VLOG(1) << "Init commandline: " << line;
  });
}

void InitP2P(std::vector<int> devices) {
#ifdef PADDLE_WITH_CUDA
  std::call_once(p2p_init_flag, [&]() {
    int count = devices.size();
    for (int i = 0; i < count; ++i) {
      for (int j = 0; j < count; ++j) {
        if (devices[i] == devices[j]) continue;
        int can_acess = -1;
        PADDLE_ENFORCE(
            cudaDeviceCanAccessPeer(&can_acess, devices[i], devices[j]),
            "Failed to test P2P access.");
        if (can_acess != 1) {
          LOG(WARNING) << "Cannot enable P2P access from " << devices[i]
                       << " to " << devices[j];
        } else {
          cudaSetDevice(devices[i]);
          cudaDeviceEnablePeerAccess(devices[j], 0);
        }
      }
    }
  });
#endif
}

void InitDevices(bool init_p2p) {
  /*Init all available devices by default */
  std::vector<int> devices;
#ifdef PADDLE_WITH_CUDA
  try {
    int count = platform::GetCUDADeviceCount();
    for (int i = 0; i < count; ++i) {
      devices.push_back(i);
    }
  } catch (const std::exception &exp) {
    LOG(WARNING) << "Compiled with WITH_GPU, but no GPU found in runtime.";
  }
#else
  LOG(WARNING)
      << "'CUDA' is not supported, Please re-compile with WITH_GPU option";
#endif
  InitDevices(init_p2p, devices);
}

void InitDevices(bool init_p2p, const std::vector<int> devices) {
  std::vector<platform::Place> places;
  int count = 0;
#ifdef PADDLE_WITH_CUDA
  try {
    count = platform::GetCUDADeviceCount();
  } catch (const std::exception &exp) {
    LOG(WARNING) << "Compiled with WITH_GPU, but no GPU found in runtime.";
  }
#else
  LOG(WARNING)
      << "'CUDA' is not supported, Please re-compile with WITH_GPU option";
#endif

  for (size_t i = 0; i < devices.size(); ++i) {
    if (devices[i] >= count || devices[i] < 0) {
      LOG(WARNING) << "Invalid devices id.";
      continue;
    }
    places.emplace_back(platform::CUDAPlace(devices[i]));
  }
  if (init_p2p) {
    InitP2P(devices);
  }
  places.emplace_back(platform::CPUPlace());
  platform::DeviceContextPool::Init(places);
}

void InitGLOG(const std::string &prog_name) {
  // glog will not hold the ARGV[0] inside.
  // Use strdup to alloc a new string.
  google::InitGoogleLogging(strdup(prog_name.c_str()));
  google::InstallFailureSignalHandler();
}

}  // namespace framework
}  // namespace paddle
<commit_msg>initial with only 1 mkl/openblas threads for each pthreads<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
#include <string.h>  // for strdup
#include <algorithm>
#include <stdexcept>
#include <string>

#include "paddle/fluid/framework/init.h"
#include "paddle/fluid/framework/operator.h"
#include "paddle/fluid/operators/math/blas.h"
#include "paddle/fluid/platform/device_context.h"
#include "paddle/fluid/platform/place.h"
#include "paddle/fluid/string/piece.h"

namespace paddle {
namespace framework {

std::once_flag gflags_init_flag;
std::once_flag p2p_init_flag;

void InitGflags(std::vector<std::string> argv) {
  std::call_once(gflags_init_flag, [&]() {
    argv.insert(argv.begin(), "dummy");
    int argc = argv.size();
    char **arr = new char *[argv.size()];
    std::string line;
    for (size_t i = 0; i < argv.size(); i++) {
      arr[i] = &argv[i][0];
      line += argv[i];
      line += ' ';
    }
    google::ParseCommandLineFlags(&argc, &arr, true);
    VLOG(1) << "Init commandline: " << line;
  });
}

void InitP2P(std::vector<int> devices) {
#ifdef PADDLE_WITH_CUDA
  std::call_once(p2p_init_flag, [&]() {
    int count = devices.size();
    for (int i = 0; i < count; ++i) {
      for (int j = 0; j < count; ++j) {
        if (devices[i] == devices[j]) continue;
        int can_acess = -1;
        PADDLE_ENFORCE(
            cudaDeviceCanAccessPeer(&can_acess, devices[i], devices[j]),
            "Failed to test P2P access.");
        if (can_acess != 1) {
          LOG(WARNING) << "Cannot enable P2P access from " << devices[i]
                       << " to " << devices[j];
        } else {
          cudaSetDevice(devices[i]);
          cudaDeviceEnablePeerAccess(devices[j], 0);
        }
      }
    }
  });
#endif
}

void InitDevices(bool init_p2p) {
  /*Init all available devices by default */
  std::vector<int> devices;
#ifdef PADDLE_WITH_CUDA
  try {
    int count = platform::GetCUDADeviceCount();
    for (int i = 0; i < count; ++i) {
      devices.push_back(i);
    }
  } catch (const std::exception &exp) {
    LOG(WARNING) << "Compiled with WITH_GPU, but no GPU found in runtime.";
  }
#else
  LOG(WARNING)
      << "'CUDA' is not supported, Please re-compile with WITH_GPU option";
#endif
  InitDevices(init_p2p, devices);
}

void InitDevices(bool init_p2p, const std::vector<int> devices) {
  std::vector<platform::Place> places;
  int count = 0;
#ifdef PADDLE_WITH_CUDA
  try {
    count = platform::GetCUDADeviceCount();
  } catch (const std::exception &exp) {
    LOG(WARNING) << "Compiled with WITH_GPU, but no GPU found in runtime.";
  }
#else
  LOG(WARNING)
      << "'CUDA' is not supported, Please re-compile with WITH_GPU option";
#endif

  for (size_t i = 0; i < devices.size(); ++i) {
    if (devices[i] >= count || devices[i] < 0) {
      LOG(WARNING) << "Invalid devices id.";
      continue;
    }
    places.emplace_back(platform::CUDAPlace(devices[i]));
  }
  if (init_p2p) {
    InitP2P(devices);
  }
  places.emplace_back(platform::CPUPlace());
  platform::DeviceContextPool::Init(places);
#ifndef PADDLE_WITH_MKLDNN
  operators::math::SetNumThreads(1);
#endif
}

void InitGLOG(const std::string &prog_name) {
  // glog will not hold the ARGV[0] inside.
  // Use strdup to alloc a new string.
  google::InitGoogleLogging(strdup(prog_name.c_str()));
  google::InstallFailureSignalHandler();
}

}  // namespace framework
}  // namespace paddle
<|endoftext|>


<commit_before>#ifdef TUT_CPP

#include <cstddef>
#include <memory>
#include <functional>
#include <string>
#include <iostream>

#include "../hpp/tut/tut.hpp"

int main(int, char*[])
{
    /// leveraging our data abstraction
    tut::data_abstraction da(10);
    std::cout << tut::func(da);
    std::cout << tut::func_ex(da);

    /// we don't need std::bind for stand-alone functions - they're much easier to pass around than
    /// member functions.
    const auto fp(&tut::func);
    std::cout << fp(da);

    /// leveraging structural polymorphism
    std::cout << tut::pow(da);
    std::cout << tut::pow_ex(da);

    /// leveraging static polymorphism
    std::cout << tut::op(3, 5);
    std::cout << tut::op(3.0f, 5.0f);
    std::cout << tut::op('3', '5');

    /// make a widget, and cast it back and forth
    auto widget = std::make_unique<tut::widget>(12345, 101.0f, true);
    auto castable = xtd::cast_unique<xtd::castable>(std::move(widget));
    auto widget_again = xtd::cast_unique<tut::widget>(std::move(castable));

    /// check its replacability :)
    std::cout << tut::should_replace_with(*widget_again, 100.0f, 12345);
    return 0;
}

#endif
<commit_msg>Added std::endl for legibility.<commit_after>#ifdef TUT_CPP

#include <cstddef>
#include <memory>
#include <functional>
#include <string>
#include <iostream>

#include "../hpp/tut/tut.hpp"

int main(int, char*[])
{
    /// leveraging our data abstraction
    tut::data_abstraction da(10);
    std::cout << tut::func(da) << std::endl;
    std::cout << tut::func_ex(da) << std::endl;

    /// we don't need std::bind for stand-alone functions - they're much easier to pass around than
    /// member functions.
    const auto fp(&tut::func);
    std::cout << fp(da) << std::endl;

    /// leveraging structural polymorphism
    std::cout << tut::pow(da) << std::endl;
    std::cout << tut::pow_ex(da) << std::endl;

    /// leveraging static polymorphism
    std::cout << tut::op(3, 5) << std::endl;
    std::cout << tut::op(3.0f, 5.0f) << std::endl;
    std::cout << tut::op('3', '5') << std::endl;

    /// make a widget, and cast it back and forth
    auto widget = std::make_unique<tut::widget>(12345, 101.0f, true);
    auto castable = xtd::cast_unique<xtd::castable>(std::move(widget));
    auto widget_again = xtd::cast_unique<tut::widget>(std::move(castable));

    /// check its replacability :)
    std::cout << tut::should_replace_with(*widget_again, 100.0f, 12345) << std::endl;
    return 0;
}

#endif
<|endoftext|>


<commit_before>/*
 * Ubitrack - Library for Ubiquitous Tracking
 * Copyright 2006, Technische Universitaet Muenchen, and individual
 * contributors as indicated by the @authors tag. See the
 * copyright.txt in the distribution for a full listing of individual
 * contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

/**
 * @ingroup vision_components
 * @file
 * Reads stereo camera images and intrinsics to generate a depth map
 *
 * @author Philipp Mller
 * @TODO:
 *		- Get 2D Points from Ubitrack Components
 *		- Performance: Delete bad image pairs in vector m_imageList too reduce computation time
 *		- Performance: Use boost smart pointers instead of .Clone() for debug image outputs
 *		- desynch issues if you start calibration in fast succession, maybe mutex lock
 */

#include <string>
#include <list>
#include <iostream>
#include <iomanip>
#include <strstream>
#include <log4cpp/Category.hh>

#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>

#include <utDataflow/TriggerComponent.h>
#include <utDataflow/TriggerInPort.h>
#include <utDataflow/TriggerOutPort.h>
#include <utDataflow/ComponentFactory.h>
#include <utMeasurement/Measurement.h>

#include <utUtil/TracingProvider.h>
#include <opencv/cv.h>
#include <utVision/Image.h>

// OpenCV calib
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <algorithm>
#include <iterator>
#include <ctype.h>
// OpenCV calib end

// get a logger
static log4cpp::Category& logger(log4cpp::Category::getInstance("Ubitrack.Vision.StereoCameraCalibrationOpenCV"));

using namespace Ubitrack;
using namespace Ubitrack::Vision;

namespace Ubitrack { namespace Drivers {

/**
* @ingroup vision_components
*
* @par Input Ports
* None.
*
* @par Output Ports
* \c Output push port of type Ubitrack::Measurement::ImageMeasurement.
*
* @par Configuration
* The configuration tag contains a \c <dsvl_input> configuration.
* For details, see the DirectShow documentation...
*
*/
class StereoCameraCalibrationOpenCVComponent
	: public Dataflow::TriggerComponent
{
public:
	StereoCameraCalibrationOpenCVComponent(const std::string& sName, boost::shared_ptr< Graph::UTQLSubgraph >);
	~StereoCameraCalibrationOpenCVComponent();

	/** ubitrack start */
	void start();

	/** ubitrack stop */
	void stop();

	void compute(Measurement::Timestamp t);

	void stereoCalibration(Measurement::Timestamp timeStamp);

protected:
	// Input edges
	Dataflow::TriggerInPort< Measurement::PositionList > m_objectPoints;
	Dataflow::TriggerInPort< Measurement::PositionList2 > m_cornersLeft;
	Dataflow::TriggerInPort< Measurement::PositionList2 > m_cornersRight;
	// Output edges
	Dataflow::TriggerOutPort< Measurement::Pose > m_outRelativePose;
	Dataflow::PushSupplier< Measurement::CameraIntrinsics > m_outIntrinsicsLeft;
	Dataflow::PushSupplier< Measurement::CameraIntrinsics > m_outIntrinsicsRight;

private:
	//std::vector< Measurement::ImageMeasurement > m_imageList;
	std::vector<std::vector<cv::Point2f> > m_imagePoints[2];
};

StereoCameraCalibrationOpenCVComponent::StereoCameraCalibrationOpenCVComponent(const std::string& sName, boost::shared_ptr< Graph::UTQLSubgraph > subgraph)
	: Dataflow::TriggerComponent(sName, subgraph)
	, m_objectPoints("GridPoints", *this)
	, m_cornersLeft("CornersLeft", *this)
	, m_cornersRight("CornersRight", *this)
	, m_outIntrinsicsLeft("IntrisicsLeft", *this)
	, m_outIntrinsicsRight("IntrisicsRight", *this)
	, m_outRelativePose("RelativePose", *this)
{

}

StereoCameraCalibrationOpenCVComponent::~StereoCameraCalibrationOpenCVComponent()
{

}

void StereoCameraCalibrationOpenCVComponent::start()
{
	Component::start();
}

void StereoCameraCalibrationOpenCVComponent::stop()
{
	Component::stop();
}

void StereoCameraCalibrationOpenCVComponent::compute(Measurement::Timestamp t)
{
	if (m_cornersLeft.get()->size() != m_cornersRight.get()->size())
	{
		LOG4CPP_INFO(logger, "Number of found corners differs.");
		return;
	}

	// Left image corners
	m_imagePoints[0].resize(m_imagePoints[0].size() + 1);
	m_imagePoints[0][m_imagePoints[0].size() - 1].resize(m_cornersLeft.get()->size());
	for (int i = 0; i < m_cornersLeft.get()->size(); i++)
	{
		Ubitrack::Math::Vector2d& utCornerLeft = m_cornersLeft.get()->data()[i];
		m_imagePoints[0][m_imagePoints[0].size()-1][i] = cv::Point2f((float)utCornerLeft[0], (float)utCornerLeft[1]);
	}

	// Right image corners
	m_imagePoints[1].resize(m_imagePoints[1].size() + 1);
	m_imagePoints[1][m_imagePoints[1].size() - 1].resize(m_cornersRight.get()->size());
	for (int i = 0; i < m_cornersRight.get()->size(); i++)
	{
		Ubitrack::Math::Vector2d& utCornerRight = m_cornersRight.get()->data()[i];
		m_imagePoints[1][m_imagePoints[1].size() - 1][i] = cv::Point2f((float)utCornerRight[0], (float)utCornerRight[1]);
	}

	LOG4CPP_INFO(logger, "Starting stereo calibration with " << m_imagePoints[0].size() << " image pairs.");

	stereoCalibration(t);
}

void StereoCameraCalibrationOpenCVComponent::stereoCalibration(Measurement::Timestamp timeStamp)
{
	// DEBUG FOR NOW USE FIXED SIZE, LATER USE ATTRIBUTES
	const cv::Size imageSize = cv::Size(640, 480);
	int nimages = m_imagePoints[0].size();
	if (nimages < 2)
	{
		LOG4CPP_INFO(logger, "Too few pairs to run the calibration");
		return;
	}

	// Chessboard 3D points, where z is always 0
	std::vector< std::vector<cv::Point3f> > objectPoints;
	objectPoints.resize(nimages);

	const std::vector< Math::Vector<double, 3> >& points3D = *m_objectPoints.get();
	// For each image pair
	for (int i = 0; i < nimages; i++)
	{
		objectPoints[i].resize(points3D.size());
		for (int j = 0; j < points3D.size(); j++)
		{
			objectPoints[i][j] = cv::Point3f(static_cast<float>(points3D[j][0]),
				static_cast<float>(points3D[j][1]), static_cast<float>(points3D[j][2])/*0.0f*/);
		}
	}

	LOG4CPP_INFO(logger, "Running stereo calibration ...");
	// cameraMatrix: intrinsic camera data
	// distCoeffs: distortion coefficients
	cv::Mat cameraMatrix[2], distCoeffs[2];
	// Init both camera matrices based on computed image points
	cameraMatrix[0] = cv::initCameraMatrix2D(objectPoints, m_imagePoints[0], imageSize, 0);
	cameraMatrix[1] = cv::initCameraMatrix2D(objectPoints, m_imagePoints[1], imageSize, 0);
	cv::Mat R, T, E, F;

	// RMS: Root Mean Square error https://en.wikipedia.org/wiki/Root_mean_square
	double rms = cv::stereoCalibrate(objectPoints, m_imagePoints[0], m_imagePoints[1],
		cameraMatrix[0], distCoeffs[0],
		cameraMatrix[1], distCoeffs[1],
		imageSize, R, T, E, F,
		cv::CALIB_FIX_ASPECT_RATIO +
		cv::CALIB_ZERO_TANGENT_DIST +
		cv::CALIB_USE_INTRINSIC_GUESS +
		cv::CALIB_SAME_FOCAL_LENGTH +
		cv::CALIB_RATIONAL_MODEL +
		cv::CALIB_FIX_K3 + cv::CALIB_FIX_K4 + cv::CALIB_FIX_K5,		// Distortion model approximation used
		cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 100, 1e-5));
	LOG4CPP_INFO(logger, "RMS error= " << rms);

	// CALIBRATION QUALITY CHECK
	// Because the output fundamental matrix implicitly
	// includes all the output information,
	// we can check the quality of calibration using the
	// epipolar geometry constraint: m2^t*F*m1=0
	double err = 0;
	int npoints = 0;
	std::vector<cv::Vec3f> lines[2];
	for (int i = 0; i < nimages; i++)
	{
		int npt = (int)m_imagePoints[0][i].size();
		cv::Mat imgpt[2];
		for (int k = 0; k < 2; k++)
		{
			imgpt[k] = cv::Mat(m_imagePoints[k][i]);
			cv::undistortPoints(imgpt[k], imgpt[k], cameraMatrix[k], distCoeffs[k], cv::Mat(), cameraMatrix[k]);
			cv::computeCorrespondEpilines(imgpt[k], k + 1, F, lines[k]);
		}
		for (int j = 0; j < npt; j++)
		{
			double errij = fabs(m_imagePoints[0][i][j].x*lines[1][j][0] +
				m_imagePoints[0][i][j].y*lines[1][j][1] + lines[1][j][2]) +
				fabs(m_imagePoints[1][i][j].x*lines[0][j][0] +
				m_imagePoints[1][i][j].y*lines[0][j][1] + lines[0][j][2]);
			err += errij;
		}
		npoints += npt;
	}
	LOG4CPP_INFO(logger, "Average epipolar error = " << err / npoints);

	// Save intrinsic parameters
	Math::CameraIntrinsics<double> camIntrisics[2];
	for (int i = 0; i < 2; i++)
	{
		Math::Matrix<double, 3, 3> tmpIntrinsics = Math::Matrix<double, 3, 3>((double*)cameraMatrix[i].data);
		Math::Vector4d tmpDist = Math::Vector4d((double*)distCoeffs[i].data);
		camIntrisics[i] = Math::CameraIntrinsics<double>(tmpIntrinsics, tmpDist, imageSize.width, imageSize.height);
	}
	m_outIntrinsicsLeft.send(Measurement::CameraIntrinsics(timeStamp, camIntrisics[0]));
	m_outIntrinsicsRight.send(Measurement::CameraIntrinsics(timeStamp, camIntrisics[1]));

	// DEBUG START
	// Write in fixed file OpenCV style
	cv::FileStorage fs("C:\\Users\\FAR-Student\\Desktop\\Phil\\CalibDataset\\intrinsics.yml", cv::FileStorage::WRITE);
	if (fs.isOpened())
	{
		fs << "M1" << cameraMatrix[0] << "D1" << distCoeffs[0] <<
			"M2" << cameraMatrix[1] << "D2" << distCoeffs[1];
		fs.release();
	}
	else
		LOG4CPP_ERROR(logger, "Error: can not save the intrinsic parameters.");
	// DEBUG END

	cv::Mat R1, R2, P1, P2, Q;
	cv::Rect validRoi[2];

	cv::stereoRectify(cameraMatrix[0], distCoeffs[0],
		cameraMatrix[1], distCoeffs[1],
		imageSize, R, T, R1, R2, P1, P2, Q,
		cv::CALIB_ZERO_DISPARITY, 1, imageSize, &validRoi[0], &validRoi[1]);

	// Save extrinsic parameters
	Math::Pose poseCam1ToCam2 = Math::Pose(Math::Quaternion(Math::Matrix<double, 3, 3>((double*)R.data)), Math::Vector3d((double*)T.data));
	m_outRelativePose.send(Measurement::Pose(timeStamp, poseCam1ToCam2));

	// DEBUG START
	// Write in fixed file OpenCV style
	fs.open("C:\\Users\\FAR-Student\\Desktop\\Phil\\CalibDataset\\extrinsics.yml", cv::FileStorage::WRITE);
	if (fs.isOpened())
	{
		fs << "R" << R << "T" << T << "R1" << R1 << "R2" << R2 << "P1" << P1 << "P2" << P2 << "Q" << Q;
		fs.release();
	}
	else
		LOG4CPP_ERROR(logger, "Error: can not save the extrinsic parameters.");
	// DEBUG END
}

} } // namespace Ubitrack::Driver

UBITRACK_REGISTER_COMPONENT(Dataflow::ComponentFactory* const cf) {
	cf->registerComponent< Ubitrack::Drivers::StereoCameraCalibrationOpenCVComponent >("StereoCameraCalibrationOpenCVComponent");
}

<commit_msg>Safty commit before checkout of older version for comparison.<commit_after>/*
 * Ubitrack - Library for Ubiquitous Tracking
 * Copyright 2006, Technische Universitaet Muenchen, and individual
 * contributors as indicated by the @authors tag. See the
 * copyright.txt in the distribution for a full listing of individual
 * contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

/**
 * @ingroup vision_components
 * @file
 * Reads stereo camera images and intrinsics to generate a depth map
 *
 * @author Philipp Mller
 * @TODO:
 *		- Get 2D Points from Ubitrack Components
 *		- Performance: Delete bad image pairs in vector m_imageList too reduce computation time
 *		- Performance: Use boost smart pointers instead of .Clone() for debug image outputs
 *		- desynch issues if you start calibration in fast succession, maybe mutex lock
 */

#include <string>
#include <list>
#include <iostream>
#include <iomanip>
#include <strstream>
#include <log4cpp/Category.hh>

#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>

#include <utDataflow/TriggerComponent.h>
#include <utDataflow/TriggerInPort.h>
#include <utDataflow/TriggerOutPort.h>
#include <utDataflow/ComponentFactory.h>
#include <utMeasurement/Measurement.h>

#include <utUtil/TracingProvider.h>
#include <opencv/cv.h>
#include <utVision/Image.h>

// OpenCV calib
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <algorithm>
#include <iterator>
#include <ctype.h>
// OpenCV calib end

// get a logger
static log4cpp::Category& logger(log4cpp::Category::getInstance("Ubitrack.Vision.StereoCameraCalibrationOpenCV"));

using namespace Ubitrack;
using namespace Ubitrack::Vision;

namespace Ubitrack { namespace Drivers {

/**
* @ingroup vision_components
*
* @par Input Ports
* None.
*
* @par Output Ports
* \c Output push port of type Ubitrack::Measurement::ImageMeasurement.
*
* @par Configuration
* The configuration tag contains a \c <dsvl_input> configuration.
* For details, see the DirectShow documentation...
*
*/
class StereoCameraCalibrationOpenCVComponent
	: public Dataflow::TriggerComponent
{
public:
	StereoCameraCalibrationOpenCVComponent(const std::string& sName, boost::shared_ptr< Graph::UTQLSubgraph >);
	~StereoCameraCalibrationOpenCVComponent();

	/** ubitrack start */
	void start();

	/** ubitrack stop */
	void stop();

	void compute(Measurement::Timestamp t);

	void stereoCalibration(Measurement::Timestamp timeStamp);

protected:
	// Input edges
	Dataflow::TriggerInPort< Measurement::PositionList > m_objectPoints;
	Dataflow::TriggerInPort< Measurement::PositionList2 > m_cornersLeft;
	Dataflow::TriggerInPort< Measurement::PositionList2 > m_cornersRight;
	// Output edges
	Dataflow::TriggerOutPort< Measurement::Pose > m_outRelativePose;
	Dataflow::PushSupplier< Measurement::CameraIntrinsics > m_outIntrinsicsLeft;
	Dataflow::PushSupplier< Measurement::CameraIntrinsics > m_outIntrinsicsRight;

private:
	//std::vector< Measurement::ImageMeasurement > m_imageList;
	std::vector<std::vector<cv::Point2f> > m_imagePoints[2];
};

StereoCameraCalibrationOpenCVComponent::StereoCameraCalibrationOpenCVComponent(const std::string& sName, boost::shared_ptr< Graph::UTQLSubgraph > subgraph)
	: Dataflow::TriggerComponent(sName, subgraph)
	, m_objectPoints("GridPoints", *this)
	, m_cornersLeft("CornersLeft", *this)
	, m_cornersRight("CornersRight", *this)
	, m_outIntrinsicsLeft("IntrisicsLeft", *this)
	, m_outIntrinsicsRight("IntrisicsRight", *this)
	, m_outRelativePose("RelativePose", *this)
{

}

StereoCameraCalibrationOpenCVComponent::~StereoCameraCalibrationOpenCVComponent()
{

}

void StereoCameraCalibrationOpenCVComponent::start()
{
	Component::start();
}

void StereoCameraCalibrationOpenCVComponent::stop()
{
	Component::stop();
}

void StereoCameraCalibrationOpenCVComponent::compute(Measurement::Timestamp t)
{
	if (m_cornersLeft.get()->size() != m_cornersRight.get()->size())
	{
		LOG4CPP_INFO(logger, "Number of found corners differs.");
		return;
	}

	// Conversion von ubitrack coordinates to OpenCV gives even worse results
	// Conversion: x,y ==> x,-y

	// Left image corners
	m_imagePoints[0].resize(m_imagePoints[0].size() + 1);
	m_imagePoints[0][m_imagePoints[0].size() - 1].resize(m_cornersLeft.get()->size());
	for (int i = 0; i < m_cornersLeft.get()->size(); i++)
	{
		Ubitrack::Math::Vector2d& utCornerLeft = m_cornersLeft.get()->data()[i];
		m_imagePoints[0][m_imagePoints[0].size()-1][i] = cv::Point2f((float)utCornerLeft[0], (float)utCornerLeft[1]);
	}

	// Right image corners
	m_imagePoints[1].resize(m_imagePoints[1].size() + 1);
	m_imagePoints[1][m_imagePoints[1].size() - 1].resize(m_cornersRight.get()->size());
	for (int i = 0; i < m_cornersRight.get()->size(); i++)
	{
		Ubitrack::Math::Vector2d& utCornerRight = m_cornersRight.get()->data()[i];
		m_imagePoints[1][m_imagePoints[1].size() - 1][i] = cv::Point2f((float)utCornerRight[0], (float)utCornerRight[1]);
	}

	LOG4CPP_INFO(logger, "Starting stereo calibration with " << m_imagePoints[0].size() << " image pairs.");

	stereoCalibration(t);
}

void StereoCameraCalibrationOpenCVComponent::stereoCalibration(Measurement::Timestamp timeStamp)
{
	// DEBUG FOR NOW USE FIXED SIZE, LATER USE ATTRIBUTES
	const cv::Size imageSize = cv::Size(640, 480);
	int nimages = m_imagePoints[0].size();
	if (nimages < 2)
	{
		LOG4CPP_INFO(logger, "Too few pairs to run the calibration");
		return;
	}

	// Chessboard 3D points, where z is always 0
	std::vector< std::vector<cv::Point3f> > objectPoints;
	objectPoints.resize(nimages);

	const std::vector< Math::Vector<double, 3> >& points3D = *m_objectPoints.get();
	// For each image pair
	for (int i = 0; i < nimages; i++)
	{
		objectPoints[i].resize(points3D.size());
		for (int j = 0; j < points3D.size(); j++)
		{
			objectPoints[i][j] = cv::Point3f(static_cast<float>(points3D[j][0]),
				static_cast<float>(points3D[j][1]), static_cast<float>(points3D[j][2])/*0.0f*/);
		}
	}

	LOG4CPP_INFO(logger, "Running stereo calibration ...");
	// cameraMatrix: intrinsic camera data
	// distCoeffs: distortion coefficients
	cv::Mat cameraMatrix[2], distCoeffs[2];
	// Init both camera matrices based on computed image points
	cameraMatrix[0] = cv::initCameraMatrix2D(objectPoints, m_imagePoints[0], imageSize, 0);
	cameraMatrix[1] = cv::initCameraMatrix2D(objectPoints, m_imagePoints[1], imageSize, 0);
	cv::Mat R, T, E, F;

	// RMS: Root Mean Square error https://en.wikipedia.org/wiki/Root_mean_square
	double rms = cv::stereoCalibrate(objectPoints, m_imagePoints[0], m_imagePoints[1],
		cameraMatrix[0], distCoeffs[0],
		cameraMatrix[1], distCoeffs[1],
		imageSize, R, T, E, F,
		cv::CALIB_FIX_ASPECT_RATIO +
		cv::CALIB_ZERO_TANGENT_DIST +
		cv::CALIB_USE_INTRINSIC_GUESS +
		cv::CALIB_SAME_FOCAL_LENGTH +
		cv::CALIB_RATIONAL_MODEL +
		cv::CALIB_FIX_K3 + cv::CALIB_FIX_K4 + cv::CALIB_FIX_K5,		// Distortion model approximation used
		cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 100, 1e-5));
	LOG4CPP_INFO(logger, "RMS error= " << rms);

	// CALIBRATION QUALITY CHECK
	// Because the output fundamental matrix implicitly
	// includes all the output information,
	// we can check the quality of calibration using the
	// epipolar geometry constraint: m2^t*F*m1=0
	double err = 0;
	int npoints = 0;
	std::vector<cv::Vec3f> lines[2];
	for (int i = 0; i < nimages; i++)
	{
		int npt = (int)m_imagePoints[0][i].size();
		cv::Mat imgpt[2];
		for (int k = 0; k < 2; k++)
		{
			imgpt[k] = cv::Mat(m_imagePoints[k][i]);
			cv::undistortPoints(imgpt[k], imgpt[k], cameraMatrix[k], distCoeffs[k], cv::Mat(), cameraMatrix[k]);
			cv::computeCorrespondEpilines(imgpt[k], k + 1, F, lines[k]);
		}
		for (int j = 0; j < npt; j++)
		{
			double errij = fabs(m_imagePoints[0][i][j].x*lines[1][j][0] +
				m_imagePoints[0][i][j].y*lines[1][j][1] + lines[1][j][2]) +
				fabs(m_imagePoints[1][i][j].x*lines[0][j][0] +
				m_imagePoints[1][i][j].y*lines[0][j][1] + lines[0][j][2]);
			err += errij;
		}
		npoints += npt;
	}
	LOG4CPP_INFO(logger, "Average epipolar error = " << err / npoints);

	// Save intrinsic parameters
	Math::CameraIntrinsics<double> camIntrisics[2];
	for (int i = 0; i < 2; i++)
	{
		Math::Matrix<double, 3, 3> tmpIntrinsics = Math::Matrix<double, 3, 3>((double*)cameraMatrix[i].data);
		Math::Vector4d tmpDist = Math::Vector4d((double*)distCoeffs[i].data);
		camIntrisics[i] = Math::CameraIntrinsics<double>(tmpIntrinsics, tmpDist, imageSize.width, imageSize.height);
	}
	m_outIntrinsicsLeft.send(Measurement::CameraIntrinsics(timeStamp, camIntrisics[0]));
	m_outIntrinsicsRight.send(Measurement::CameraIntrinsics(timeStamp, camIntrisics[1]));

	// DEBUG START
	// Write in fixed file OpenCV style
	cv::FileStorage fs("C:\\Users\\FAR-Student\\Desktop\\Phil\\CalibDataset\\intrinsics.yml", cv::FileStorage::WRITE);
	if (fs.isOpened())
	{
		fs << "M1" << cameraMatrix[0] << "D1" << distCoeffs[0] <<
			"M2" << cameraMatrix[1] << "D2" << distCoeffs[1];
		fs.release();
	}
	else
		LOG4CPP_ERROR(logger, "Error: can not save the intrinsic parameters.");
	// DEBUG END

	cv::Mat R1, R2, P1, P2, Q;
	cv::Rect validRoi[2];

	cv::stereoRectify(cameraMatrix[0], distCoeffs[0],
		cameraMatrix[1], distCoeffs[1],
		imageSize, R, T, R1, R2, P1, P2, Q,
		cv::CALIB_ZERO_DISPARITY, 1, imageSize, &validRoi[0], &validRoi[1]);

	// Save extrinsic parameters
	Math::Pose poseCam1ToCam2 = Math::Pose(Math::Quaternion(Math::Matrix<double, 3, 3>((double*)R.data)), Math::Vector3d((double*)T.data));
	m_outRelativePose.send(Measurement::Pose(timeStamp, poseCam1ToCam2));

	// DEBUG START
	// Write in fixed file OpenCV style
	fs.open("C:\\Users\\FAR-Student\\Desktop\\Phil\\CalibDataset\\extrinsics.yml", cv::FileStorage::WRITE);
	if (fs.isOpened())
	{
		fs << "R" << R << "T" << T << "R1" << R1 << "R2" << R2 << "P1" << P1 << "P2" << P2 << "Q" << Q;
		fs.release();
	}
	else
		LOG4CPP_ERROR(logger, "Error: can not save the extrinsic parameters.");
	// DEBUG END
}

} } // namespace Ubitrack::Driver

UBITRACK_REGISTER_COMPONENT(Dataflow::ComponentFactory* const cf) {
	cf->registerComponent< Ubitrack::Drivers::StereoCameraCalibrationOpenCVComponent >("StereoCameraCalibrationOpenCVComponent");
}

<|endoftext|>