Commit 042e4752 authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Work on updating the QASM3 MLIR



Convert generic If statement generator to using SCF::If

It is semantically very close to what we need: conditioned on an i1 Value thus simplifying the code.

Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 1551bfee
Loading
Loading
Loading
Loading
+21 −63
Original line number Diff line number Diff line

#include "expression_handler.hpp"
#include "qasm3_visitor.hpp"

#include "mlir/Dialect/SCF/SCF.h"
namespace {
// ATM, we don't try to convert everything to the
// special Quantum If-Then-Else Op.
@@ -201,82 +201,40 @@ antlrcpp::Any qasm3_visitor::visitBranchingStatement(
    }
  }

  // TODO: The below code could be rewritten to an AffineIfOp/SCF::IfOp:
  // Map it to a Value
  qasm3_expression_generator exp_generator(builder, symbol_table, file_name);
  exp_generator.visit(conditional_expr);
  // Boolean check value:
  auto expr_value = exp_generator.current_value;

  // build up the program block
  auto currRegion = builder.getBlock()->getParent();
  auto savept = builder.saveInsertionPoint();
  auto thenBlock = builder.createBlock(currRegion, currRegion->end());
  auto elseBlock = builder.createBlock(currRegion, currRegion->end());
  mlir::Block* exitBlock = nullptr;
  // If we have an else block from programBlock,
  // then create a stand alone exit block that both
  // then and else can fall to
  if (context->programBlock().size() == 2) {
    exitBlock = builder.createBlock(currRegion, currRegion->end());
  } else {
    exitBlock = elseBlock;
  }

  // Build up the THEN Block
  builder.setInsertionPointToStart(thenBlock);
  // Create SCF If Op:
  // SCF IfOp (switching on a boolean value) matches what we need here,
  // an AffineIfOp requires an integer set and will be lowered to SCF's IfOp later,
  // hence is not a good solution.
  const bool hasElseBlock = context->programBlock().size() == 2;
  auto scfIfOp = builder.create<mlir::scf::IfOp>(location, mlir::TypeRange(),
                                           expr_value, hasElseBlock);

  // Build up the 'then' region:
  auto thenBodyBuilder = scfIfOp.getThenBodyBuilder();
  auto cached_builder = builder;
  builder = thenBodyBuilder;
  symbol_table.enter_new_scope();
  // Get the conditional code and visit the nodes
  auto conditional_code = context->programBlock(0);
  visitChildren(conditional_code);    

  // Need to check if we have a branch out of
  // this thenBlock, if so do not add a branch
  // to the exitblock
  mlir::Operation& last_op = thenBlock->back();
  auto branchOps = thenBlock->getOps<mlir::BranchOp>();
  auto branch_to_exit = true;
  for (auto b : branchOps) {
    if (b.dest() == current_loop_exit_block ||
        b.dest() == current_loop_header_block ||
        b.dest() == current_loop_incrementor_block) {
      branch_to_exit = false;
      break;
    }
  }
  if (branch_to_exit) {
    builder.create<mlir::BranchOp>(location, exitBlock);
  }
  symbol_table.exit_scope();

  // If we have a second program block then we have an else stmt
  builder.setInsertionPointToStart(elseBlock);
  if (context->programBlock().size() == 2) {
  if (hasElseBlock) {
    auto elseBodyBuilder = scfIfOp.getElseBodyBuilder();
    builder = elseBodyBuilder;
    symbol_table.enter_new_scope();
    // Visit the second programBlock
    visitChildren(context->programBlock(1));
    branch_to_exit = true;
    for (auto b : branchOps) {
      if (b.dest() == current_loop_exit_block ||
          b.dest() == current_loop_header_block ||
          b.dest() == current_loop_incrementor_block) {
        branch_to_exit = false;
        break;
      }
    }
    if (branch_to_exit) {
      builder.create<mlir::BranchOp>(location, exitBlock);
    }

    symbol_table.exit_scope();
  }

  // Restore the insertion point and create the conditional statement
  builder.restoreInsertionPoint(savept);
  builder.create<mlir::CondBranchOp>(location, expr_value, thenBlock,
                                     elseBlock);
  builder.setInsertionPointToStart(exitBlock);

  symbol_table.set_last_created_block(exitBlock);

  // Restore builder
  builder = cached_builder;
  return 0;
}
}  // namespace qcor
 No newline at end of file