Commit 0705f025 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

early prototyping for LLVM IR integration. added new quantum runtime qrt...


early prototyping for LLVM IR integration. added new quantum runtime qrt library, new syntax handler subroutine to generate qrt calls. added llvm pass to demonstrate printing ir

Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 10282c12
Loading
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -30,5 +30,6 @@ configure_file(${CMAKE_SOURCE_DIR}/scripts/qcor.in

add_subdirectory(handlers)
add_subdirectory(runtime)
add_subdirectory(passes)

install(PROGRAMS ${CMAKE_BINARY_DIR}/qcor DESTINATION bin)
+65 −44
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ using namespace clang;

namespace {

bool qrt = false;
std::string qpu_name = "tnqvm";
int shots = 0;

@@ -52,14 +53,17 @@ public:
      diagnostics.Report(D.getBeginLoc(), invalid_no_args);
    }

    function_prototype = "(";
    // Loop over the function arguments and get the
    // buffer name and any program parameter doubles.
    std::vector<std::string> program_parameters, program_arg_types;
    std::vector<std::string> bufferNames;
    for (unsigned int ii = 0; ii < FTI.NumParams; ii++) {
      auto &paramInfo = FTI.Params[ii];

      auto ident = paramInfo.Ident;
      auto &decl = FTI.Params[ii].Param;
      auto &decl = paramInfo.Param;

      auto parm_var_decl = cast<ParmVarDecl>(decl);
      if (parm_var_decl) {
        auto type = parm_var_decl->getType().getCanonicalType().getAsString();
@@ -67,15 +71,17 @@ public:
        program_parameters.push_back(ident->getName().str());
        if (type == "class xacc::internal_compiler::qreg") {
          bufferNames.push_back(ident->getName().str());
          function_prototype += "qreg " + ident->getName().str() + ", ";
        } else {
          function_prototype += type + " " + ident->getName().str() + ", ";
        }
        // else if (type == "double") {
        //   program_parameters.push_back(ident->getName().str());
        // } else {
        //   diagnostics.Report(paramInfo.IdentLoc, invalid_arg_type);
        // }
      }
    }
    function_prototype =
        "void " + kernel_name +
        function_prototype.substr(0, function_prototype.length() - 2) + ")";

    // std::cout << "FPROTO: " << function_prototype << "\n";
    // If we failed to get the name, then we fail
    if (bufferNames.empty()) {
      diagnostics.Report(D.getBeginLoc(), invalid_qreg_name);
@@ -89,6 +95,15 @@ public:
    auto kernel_src = kernel_src_and_compiler.first;
    auto compiler_name = kernel_src_and_compiler.second;

    if (qrt) {

      // call to the util function to use xacc to
      // generate new code to the OS
      qcor::map_xacc_kernel_to_qrt_calls(kernel_src, qpu_name, compiler_name,
                                         kernel_name, bufferNames, OS,
                                         (shots > 0 ? shots : 0));

    } else {
      // std::cout << "HELLO:\n" << kernel_src << "\n";
      // Write new source code in place of the
      // provided quantum code tokens
@@ -104,7 +119,8 @@ public:
      OS << "auto program = getCompiled(\"" << kernel_name << "\");\n";
      OS << "if (!program) {\n";
      OS << "std::string kernel_src = R\"##(" + kernel_src + ")##\";\n";
    OS << "program = compile(\"" + compiler_name + "\", kernel_src.c_str());\n";
      OS << "program = compile(\"" + compiler_name +
                "\", kernel_src.c_str());\n";
      OS << "}\n";
      // OS << "optimize(program);\n";

@@ -128,14 +144,18 @@ public:
        OS << "execute(" << bufferNames[0] << ".results(), program";
      }
      OS << ");\n";

      OS << "}\n";
    }

    auto s = OS.str();
    qcor::info("[qcor syntax-handler] Rewriting " + kernel_name + " to\n\n" +
               function_prototype + "{\n" + s.substr(2, s.length()) + "\n}");
  }

  void AddToPredefines(llvm::raw_string_ostream &OS) override {
    if (qrt) {
      OS << "#include \"qrt.hpp\"\n";
    }
    OS << "#include \"xacc_internal_compiler.hpp\"\nusing namespace "
          "xacc::internal_compiler;\n";
  }
@@ -176,6 +196,8 @@ public:
        shots = std::stoi(args[i]);
      } else if (args[i] == "-qcor-verbose") {
        qcor::set_verbose(true);
      } else if (args[i] == "-qrt") {
        qrt = true;
      }
    }
    return true;
@@ -187,7 +209,6 @@ public:
};

} // namespace
// static FrontendPluginRegistry::Add<QCORTEST> XXX("qcor-test", "");

static SyntaxHandlerRegistry::Add<QCORSyntaxHandler>
    X("qcor", "qcor quantum kernel syntax handler");
+1 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ target_include_directories(${LIBRARY_NAME}
                                  ${LLVM_INCLUDE_DIRS})

target_link_libraries(${LIBRARY_NAME}
                      PRIVATE ${CLANG_LIBS} ${LLVM_LIBS} xacc::xacc)
                      PRIVATE ${CLANG_LIBS} ${LLVM_LIBS} xacc::xacc xacc::quantum_gate)

if(APPLE)
  set_target_properties(${LIBRARY_NAME}
+86 −5
Original line number Diff line number Diff line
@@ -3,6 +3,8 @@
#include "xacc.hpp"
#include "xacc_service.hpp"

#include "AllGateVisitor.hpp"

namespace qcor {

void set_verbose(bool verbose) { xacc::set_verbose(verbose); }
@@ -31,7 +33,8 @@ run_token_collector(clang::Preprocessor &PP, clang::CachedTokens &Toks,
      kernel_src =
          "__qpu__ " + function_prototype + " {\n" + tmp_ss.str() + " }";
      if (compiler->canParse(kernel_src)) {
        xacc::info(compiler->name() + " could parse tokens generated by " + tc->name());
        xacc::info(compiler->name() + " could parse tokens generated by " +
                   tc->name());
        compiler_name = compiler->name();
        return std::make_pair(kernel_src, compiler_name);
      } else {
@@ -41,8 +44,86 @@ run_token_collector(clang::Preprocessor &PP, clang::CachedTokens &Toks,
  }

  // if we make it here, its not good
  xacc::error("[qcor] Invalid QCOR kernel expression, could not parse with available SyntaxHandlers / XACC Compilers.");
  xacc::error("[qcor] Invalid QCOR kernel expression, could not parse with "
              "available SyntaxHandlers / XACC Compilers.");
  return std::make_pair(kernel_src, compiler_name);
}

using namespace xacc::quantum;

class qrt_mapper : public AllGateVisitor {
protected:
  std::stringstream ss;

public:
  auto get_new_src() { return ss.str(); }

  void visit(Hadamard &h) override {
    ss << "quantum::h(" << h.getBufferNames()[0] << "[" << h.bits()[0]
       << "]);\n";
  }
  void visit(CNOT &cnot) override {
    ss << "quantum::cnot(" << cnot.getBufferNames()[0] << "[" << cnot.bits()[0]
       << "], " << cnot.getBufferNames()[1] << "[" << cnot.bits()[1] << "]);\n";
  }

  void visit(Rz &rz) override {}
  void visit(Ry &ry) override {}
  void visit(Rx &rx) override {}
  void visit(X &x) override {}
  void visit(Y &y) override {}
  void visit(Z &z) override {}
  void visit(CY &cy) override {}
  void visit(CZ &cz) override {}
  void visit(Swap &s) override {}
  void visit(CRZ &crz) override {}
  void visit(CH &ch) override {}
  void visit(S &s) override {}
  void visit(Sdg &sdg) override {}
  void visit(T &t) override {}
  void visit(Tdg &tdg) override {}
  void visit(CPhase &cphase) override {}
  void visit(Measure &measure) override {
    ss << "quantum::mz(" << measure.getBufferNames()[0] << "[" << measure.bits()[0]
       << "]);\n";
  }
  void visit(Identity &i) override {}
  void visit(U &u) override {}
  void visit(IfStmt &ifStmt) override {}
};

void map_xacc_kernel_to_qrt_calls(const std::string &kernel_str, const std::string& qpu_name,
                                  const std::string &compiler_name,
                                  const std::string &kernel_name,
                                  std::vector<std::string> bufferNames,
                                  llvm::raw_string_ostream &OS, int shots) {
  auto compiler = xacc::getCompiler(compiler_name);
  auto kernel = compiler->compile(kernel_str)->getComposites()[0];

  auto visitor = std::make_shared<qrt_mapper>();

  xacc::InstructionIterator iter(kernel);
  while (iter.hasNext()) {
    auto next = iter.next();
    if (!next->isComposite()) {
      next->accept(visitor);
    }
  }

  auto code = visitor->get_new_src();

  std::cout << "HELLO: " << code << "\n";

  OS << "quantum::initialize(\""<< qpu_name << "\", \"" << kernel_name << "\");\n";
  if (shots > 0) {
      OS << "quantum::set_shots(" << shots << ");\n";
  }
  OS << code;
  OS << "quantum::submit(" << bufferNames[0] << ".results()";
  for (unsigned int k = 1; k < bufferNames.size(); k++) {
    OS << ", " << bufferNames[k] << ".results()";
  }
  OS << ");\n";
}

} // namespace qcor
 No newline at end of file
+7 −1
Original line number Diff line number Diff line
@@ -13,6 +13,12 @@ std::pair<std::string, std::string>
run_token_collector(clang::Preprocessor &PP, clang::CachedTokens &Toks,
                    const std::string &function_prototype);

void map_xacc_kernel_to_qrt_calls(const std::string &kernel_str, const std::string& qpu_name,
                                  const std::string &compiler_name,
                                  const std::string &kernel_name,
                                  std::vector<std::string> bufferNames,
                                  llvm::raw_string_ostream &OS, int shots = 0);

void set_verbose(bool verbose);
void info(const std::string &s);

Loading