Commit 670d735e authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

added compute marker ops to mark where compiler should not add control...


added compute marker ops to mark where compiler should not add control operations. fixed a few bugs. Also set up all ctrl @ x ops to immediately map to cnot

Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 0508946b
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ gate test22 q, r, s, v {
        h r;
        h s;
        h v;
        cnot q, r;
        ctrl @ x q, r; // compiler translates to cnot
        cnot r, s;
        cnot s, v;
    } action {
@@ -64,7 +64,7 @@ ctrl @ test22 ww, qq, rr, ss, vv;
  auto llvm = qcor::mlir_compile(src, "test", qcor::OutputType::LLVMIR, true);
  std::cout << "LLVM:\n" << llvm << "\n";
  // 2 rxs, 6 hs, 6 cnots, 1 rz + decls == 19
  //   EXPECT_EQ(countSubstring(llvm, "__quantum__qis"), 19);
  EXPECT_EQ(countSubstring(llvm, "__quantum__qis"), 19);
}

int main(int argc, char **argv) {
+70 −7
Original line number Diff line number Diff line
@@ -57,8 +57,8 @@ void qasm3_visitor::createInstOps_HandleBroadcast(
      for (int i = 0; i < n; i++) {
        auto qubit_type = get_custom_opaque_type("Qubit", builder.getContext());

        auto extract_value = get_or_extract_qubit(
            qreg_names[0], i, location, symbol_table, builder);
        auto extract_value = get_or_extract_qubit(qreg_names[0], i, location,
                                                  symbol_table, builder);

        std::vector<mlir::Type> ret_types;
        for (auto q : qbit_values) {
@@ -443,6 +443,69 @@ antlrcpp::Any qasm3_visitor::visitQuantumGateCall(
    } else if (top.first == EndAction::EndAdjU) {
      builder.create<mlir::quantum::EndAdjointURegion>(location);
    } else if (top.first == EndAction::EndCtrlU) {
      auto& ops_up_to_now = builder.getBlock()->getOperations();

      // From here to line 505, we attempt to replace trivial 
      // ctrl segments with known intrinsic quantum instructions, i.e.
      // q.ctrl_region {
      // %2 = qvs.x(%1)
      // } (ctrl_bit = %0) // END CTRL
      // with 
      // %3:2 = qvs.cnot(%0, %1)
      // in order to simplify downstream optimizations
      //
      // First reverse iterate from latest op added to the first StartCtrlURegionOp
      // Keep track of all ops that are touched
      mlir::Operation* start_ctrl;
      std::vector<mlir::Operation*> ops_to_control;
      for (auto iter = ops_up_to_now.rbegin(); iter != ops_up_to_now.rend();
           ++iter) {
        auto& op = *iter;
        if (mlir::dyn_cast_or_null<mlir::quantum::StartCtrlURegion>(&op)) {
          start_ctrl = &op;
          break;
        }
        ops_to_control.push_back(&op);
      }

      // If there is one op only in that region, we can optimize it away easily
      if (ops_to_control.size() == 1) {
        // Trivial ctrl block, replace with ctrl instruction
        if (auto inst_op =
                mlir::dyn_cast_or_null<mlir::quantum::ValueSemanticsInstOp>(
                    ops_to_control[0])) {
          // For now, only handle ctrl-x, will add more later
          if (inst_op.name().str() == "x") {
            auto operands = inst_op.qubits();
            std::vector<mlir::Value> new_qbits{ctrl_bit, operands[0]};

            auto params = inst_op.params();
            auto name = inst_op.name();

            ops_to_control[0]->dropAllReferences();
            ops_to_control[0]->dropAllUses();
            ops_up_to_now.remove(*start_ctrl);
            ops_up_to_now.remove(*ops_to_control[0]);

            auto new_inst = builder.create<mlir::quantum::ValueSemanticsInstOp>(
                location,
                llvm::makeArrayRef(
                    std::vector<mlir::Type>{qubit_type, qubit_type}),
                builder.getStringAttr("cnot"), llvm::makeArrayRef(new_qbits),
                params);

            auto return_vals = new_inst.result();
            int i = 0;
            for (auto result : return_vals) {
              symbol_table.replace_symbol(qbit_values[i], result);
              i++;
            }
            action_and_extrainfo.pop();
            continue;
          }
        }
      }

      builder.create<mlir::quantum::EndCtrlURegion>(location, ctrl_bit);
    }
    action_and_extrainfo.pop();
@@ -673,16 +736,16 @@ antlrcpp::Any qasm3_visitor::visitSubroutineCall(
              context, {variable_value});
        }

        auto shape = variable_value.getType()
                             .cast<mlir::MemRefType>().getShape();
        auto shape =
            variable_value.getType().cast<mlir::MemRefType>().getShape();
        if (!shape.empty() && shape[0] == 1) {

          variable_value = builder.create<mlir::LoadOp>(
              location, variable_value,
              get_or_create_constant_index_value(0, location, 64, symbol_table,
                                                 builder));
        } else if (shape.empty()) {
          variable_value = builder.create<mlir::LoadOp>(location, variable_value);
          variable_value =
              builder.create<mlir::LoadOp>(location, variable_value);
        }
      }

+1 −1
Original line number Diff line number Diff line
@@ -169,7 +169,7 @@ antlrcpp::Any qasm3_visitor::visitQuantumGateDefinition(

      // set the new last user as the correct 
      // return value of the user
      last_user = (*users.begin())->getResult(idx);
      last_user = only_user->getResult(idx);
      users = last_user.getUsers();
    }
    result_qubit_vals.push_back(last_user);
+3 −0
Original line number Diff line number Diff line
@@ -84,6 +84,9 @@ void __quantum__rt__set_config_parameter(int8_t *key, int8_t *value) {
    mode = casted_value == "nisq" ? QRT_MODE::NISQ : QRT_MODE::FTQC;
  } else if (casted_key == "shots") {
    shots = std::stoi(casted_value);
  } else if (casted_key == "print_final_submission") {
    std::cout << "ADDING PRINT FINAL SUBMISSION\n";
    ::__print_final_submission = true;
  }

}
+7 −0
Original line number Diff line number Diff line
@@ -50,6 +50,9 @@ cl::opt<std::string> mlir_specified_func_name(
static cl::opt<bool> verbose_error(
    "verbose-error", cl::desc("Printout the full MLIR Module on error."));

static cl::opt<bool> print_final_submission(
    "print-final-submission", cl::desc("Print the XACC IR representation for submitted quantum code."));

static cl::opt<bool> OptLevelO0(
    "O0", cl::desc("Optimization level 0. Similar to clang -O0. "));

@@ -111,6 +114,10 @@ int main(int argc, char **argv) {
    extra_args.insert({"verbose_error", ""});
  }

  if (print_final_submission) {
    extra_args.insert({"print_final_submission", ""});
  }

  auto mlir_gen_result = qcor::util::mlir_gen(inputFilename, !noEntryPoint,
                                              input_func_name, extra_args);
  mlir::OwningModuleRef &module = *(mlir_gen_result.module_ref);