/*
 * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#include "opto/addnode.hpp"
#include "opto/callnode.hpp"
#include "opto/cfgnode.hpp"
#include "opto/idealKit.hpp"
#include "opto/runtime.hpp"

// Static initialization

// This declares the position where vars are kept in the cvstate
// For some degree of consistency we use the TypeFunc enum to
// soak up spots in the inputs even though we only use early Control
// and Memory slots. (So far.)
const uint IdealKit::first_var = TypeFunc::Parms + 1;

//----------------------------IdealKit-----------------------------------------
IdealKit::IdealKit(GraphKit* gkit, bool delay_all_transforms, bool has_declarations) :
  C(gkit->C), _gvn(gkit->gvn()) {
  _initial_ctrl = gkit->control();
  _initial_memory = gkit->merged_memory();
  _initial_i_o = gkit->i_o();
  _delay_all_transforms = delay_all_transforms;
  _var_ct = 0;
  _cvstate = nullptr;
  // We can go memory state free or else we need the entire memory state
  assert(_initial_memory == nullptr || _initial_memory->Opcode() == Op_MergeMem, "memory must be pre-split");
  assert(!_gvn.is_IterGVN(), "IdealKit can't be used during Optimize phase");
  int init_size = 5;
  _pending_cvstates = new (C->node_arena()) GrowableArray<Node*>(C->node_arena(), init_size, 0, nullptr);
  DEBUG_ONLY(_state = new (C->node_arena()) GrowableArray<int>(C->node_arena(), init_size, 0, 0));
  if (!has_declarations) {
     declarations_done();
  }
}

//----------------------------sync_kit-----------------------------------------
void IdealKit::sync_kit(GraphKit* gkit) {
  set_all_memory(gkit->merged_memory());
  set_i_o(gkit->i_o());
  set_ctrl(gkit->control());
}

//-------------------------------if_then-------------------------------------
// Create:  if(left relop right)
//          /  \
//   iffalse    iftrue
// Push the iffalse cvstate onto the stack. The iftrue becomes the current cvstate.
void IdealKit::if_then(Node* left, BoolTest::mask relop,
                       Node* right, float prob, float cnt, bool push_new_state) {
  assert((state() & (BlockS|LoopS|IfThenS|ElseS)), "bad state for new If");
  Node* bol;
  if (left->bottom_type()->isa_ptr() == nullptr) {
    if (left->bottom_type()->isa_int() != nullptr) {
      bol = Bool(CmpI(left, right), relop);
    } else {
      assert(left->bottom_type()->isa_long() != nullptr, "what else?");
      bol = Bool(CmpL(left, right), relop);
    }

  } else {
    bol = Bool(CmpP(left, right), relop);
  }
  // Delay gvn.transform on if-nodes until construction is finished
  // to prevent a constant bool input from discarding a control output.
  IfNode* iff = delay_transform(new IfNode(ctrl(), bol, prob, cnt))->as_If();
  Node* then  = IfTrue(iff);
  Node* elsen = IfFalse(iff);
  Node* else_cvstate = copy_cvstate();
  else_cvstate->set_req(TypeFunc::Control, elsen);
  _pending_cvstates->push(else_cvstate);
  DEBUG_ONLY(if (push_new_state) _state->push(IfThenS));
  set_ctrl(then);
}

//-------------------------------else_-------------------------------------
// Pop the else cvstate off the stack, and push the (current) then cvstate.
// The else cvstate becomes the current cvstate.
void IdealKit::else_() {
  assert(state() == IfThenS, "bad state for new Else");
  Node* else_cvstate = _pending_cvstates->pop();
  DEBUG_ONLY(_state->pop());
  // save current (then) cvstate for later use at endif
  _pending_cvstates->push(_cvstate);
  DEBUG_ONLY(_state->push(ElseS));
  _cvstate = else_cvstate;
}

//-------------------------------end_if-------------------------------------
// Merge the "then" and "else" cvstates.
//
// The if_then() pushed a copy of the current state for later use
// as the initial state for a future "else" clause.  The
// current state then became the initial state for the
// then clause.  If an "else" clause was encountered, it will
// pop the top state and use it for it's initial state.
// It will also push the current state (the state at the end of
// the "then" clause) for latter use at the end_if.
//
// At the endif, the states are:
// 1) else exists a) current state is end of "else" clause
//                b) top stack state is end of "then" clause
//
// 2) no else:    a) current state is end of "then" clause
//                b) top stack state is from the "if_then" which
//                   would have been the initial state of the else.
//
// Merging the states is accomplished by:
//   1) make a label for the merge
//   2) terminate the current state with a goto to the label
//   3) pop the top state from the stack and make it the
//        current state
//   4) bind the label at the current state.  Binding a label
//        terminates the current state with a goto to the
//        label and makes the label's state the current state.
//
void IdealKit::end_if() {
  assert(state() & (IfThenS|ElseS), "bad state for new Endif");
  Node* lab = make_label(1);

  // Node* join_state = _pending_cvstates->pop();
                  /* merging, join */
  goto_(lab);
  _cvstate = _pending_cvstates->pop();

  bind(lab);
  DEBUG_ONLY(_state->pop());
}

//-------------------------------loop-------------------------------------
// Create the loop head portion (*) of:
//  *     iv = init
//  *  top: (region node)
//  *     if (iv relop limit) {
//           loop body
//           i = i + 1
//           goto top
//  *     } else // exits loop
//
// Pushes the loop top cvstate first, then the else (loop exit) cvstate
// onto the stack.
void IdealKit::loop(GraphKit* gkit, int nargs, IdealVariable& iv, Node* init, BoolTest::mask relop, Node* limit, float prob, float cnt) {
  assert((state() & (BlockS|LoopS|IfThenS|ElseS)), "bad state for new loop");
  // Sync IdealKit and graphKit.
  gkit->sync_kit(*this);
  // Add Parse Predicates.
  gkit->add_parse_predicates(nargs);
  // Update IdealKit memory.
  sync_kit(gkit);
  set(iv, init);
  Node* head = make_label(1);
  bind(head);
  _pending_cvstates->push(head); // push for use at end_loop
  _cvstate = copy_cvstate();
  if_then(value(iv), relop, limit, prob, cnt, false /* no new state */);
  DEBUG_ONLY(_state->push(LoopS));
  assert(ctrl()->is_IfTrue(), "true branch stays in loop");
  assert(_pending_cvstates->top()->in(TypeFunc::Control)->is_IfFalse(), "false branch exits loop");
}

//-------------------------------end_loop-------------------------------------
// Creates the goto top label.
// Expects the else (loop exit) cvstate to be on top of the
// stack, and the loop top cvstate to be 2nd.
void IdealKit::end_loop() {
  assert((state() == LoopS), "bad state for new end_loop");
  Node* exit = _pending_cvstates->pop();
  Node* head = _pending_cvstates->pop();
  goto_(head);
  clear(head);
  DEBUG_ONLY(_state->pop());
  _cvstate = exit;
}

//-------------------------------make_label-------------------------------------
// Creates a label.  The number of goto's
// must be specified (which should be 1 less than
// the number of precedessors.)
Node* IdealKit::make_label(int goto_ct) {
  assert(_cvstate != nullptr, "must declare variables before labels");
  Node* lab = new_cvstate();
  int sz = 1 + goto_ct + 1 /* fall thru */;
  Node* reg = delay_transform(new RegionNode(sz));
  lab->init_req(TypeFunc::Control, reg);
  return lab;
}

//-------------------------------bind-------------------------------------
// Bind a label at the current cvstate by simulating
// a goto to the label.
void IdealKit::bind(Node* lab) {
  goto_(lab, true /* bind */);
  _cvstate = lab;
}

//-------------------------------goto_-------------------------------------
// Make the current cvstate a predecessor of the label,
// creating phi's to merge values.  If bind is true and
// this is not the last control edge, then ensure that
// all live values have phis created. Used to create phis
// at loop-top regions.
void IdealKit::goto_(Node* lab, bool bind) {
  Node* reg = lab->in(TypeFunc::Control);
  // find next empty slot in region
  uint slot = 1;
  while (slot < reg->req() && reg->in(slot) != nullptr) slot++;
  assert(slot < reg->req(), "too many gotos");
  // If this is last predecessor, then don't force phi creation
  if (slot == reg->req() - 1) bind = false;
  reg->init_req(slot, ctrl());
  assert(first_var + _var_ct == _cvstate->req(), "bad _cvstate size");
  for (uint i = first_var; i < _cvstate->req(); i++) {

    // l is the value of var reaching the label. Could be a single value
    // reaching the label, or a phi that merges multiples values reaching
    // the label.  The latter is true if the label's input: in(..) is
    // a phi whose control input is the region node for the label.

    Node* l = lab->in(i);
    // Get the current value of the var
    Node* m = _cvstate->in(i);
    // If the var went unused no need for a phi
    if (m == nullptr) {
      continue;
    } else if (l == nullptr || m == l) {
      // Only one unique value "m" is known to reach this label so a phi
      // is not yet necessary unless:
      //    the label is being bound and all predecessors have not been seen,
      //    in which case "bind" will be true.
      if (bind) {
        m = promote_to_phi(m, reg);
      }
      // Record the phi/value used for this var in the label's cvstate
      lab->set_req(i, m);
    } else {
      // More than one value for the variable reaches this label so
      // a create a phi if one does not already exist.
      if (!was_promoted_to_phi(l, reg)) {
        l = promote_to_phi(l, reg);
        lab->set_req(i, l);
      }
      // Record in the phi, the var's value from the current state
      l->set_req(slot, m);
    }
  }
  do_memory_merge(_cvstate, lab);
  stop();
}

//-----------------------------promote_to_phi-----------------------------------
Node* IdealKit::promote_to_phi(Node* n, Node* reg) {
  assert(!was_promoted_to_phi(n, reg), "n already promoted to phi on this region");
  // Get a conservative type for the phi
  const BasicType bt = n->bottom_type()->basic_type();
  const Type* ct = Type::get_const_basic_type(bt);
  return delay_transform(PhiNode::make(reg, n, ct));
}

//-----------------------------declarations_done-------------------------------
void IdealKit::declarations_done() {
  _cvstate = new_cvstate();   // initialize current cvstate
  set_ctrl(_initial_ctrl);    // initialize control in current cvstate
  set_all_memory(_initial_memory);// initialize memory in current cvstate
  set_i_o(_initial_i_o);      // initialize i_o in current cvstate
  DEBUG_ONLY(_state->push(BlockS));
}

//-----------------------------transform-----------------------------------
Node* IdealKit::transform(Node* n) {
  if (_delay_all_transforms) {
    return delay_transform(n);
  } else {
    n = gvn().transform(n);
    C->record_for_igvn(n);
    return n;
  }
}

//-----------------------------delay_transform-----------------------------------
Node* IdealKit::delay_transform(Node* n) {
  // Delay transform until IterativeGVN
  gvn().set_type(n, n->bottom_type());
  C->record_for_igvn(n);
  return n;
}

//-----------------------------new_cvstate-----------------------------------
Node* IdealKit::new_cvstate() {
  uint sz = _var_ct + first_var;
  return new Node(sz);
}

//-----------------------------copy_cvstate-----------------------------------
Node* IdealKit::copy_cvstate() {
  Node* ns = new_cvstate();
  for (uint i = 0; i < ns->req(); i++) ns->init_req(i, _cvstate->in(i));
  // We must clone memory since it will be updated as we do stores.
  ns->set_req(TypeFunc::Memory, MergeMemNode::make(ns->in(TypeFunc::Memory)));
  return ns;
}

//-----------------------------clear-----------------------------------
void IdealKit::clear(Node* m) {
  for (uint i = 0; i < m->req(); i++) m->set_req(i, nullptr);
}

//-----------------------------IdealVariable----------------------------
IdealVariable::IdealVariable(IdealKit &k) {
  k.declare(this);
}

Node* IdealKit::memory(uint alias_idx) {
  MergeMemNode* mem = merged_memory();
  Node* p = mem->memory_at(alias_idx);
  _gvn.set_type(p, Type::MEMORY);  // must be mapped
  return p;
}

void IdealKit::set_memory(Node* mem, uint alias_idx) {
  merged_memory()->set_memory_at(alias_idx, mem);
}

//----------------------------- make_load ----------------------------
Node* IdealKit::load(Node* ctl,
                     Node* adr,
                     const Type* t,
                     BasicType bt,
                     int adr_idx,
                     bool require_atomic_access,
                     MemNode::MemOrd mo,
                     LoadNode::ControlDependency control_dependency) {

  assert(adr_idx != Compile::AliasIdxTop, "use other make_load factory" );
  const TypePtr* adr_type = nullptr; // debug-mode-only argument
  DEBUG_ONLY(adr_type = C->get_adr_type(adr_idx));
  Node* mem = memory(adr_idx);
  Node* ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency, require_atomic_access);
  return transform(ld);
}

Node* IdealKit::store(Node* ctl, Node* adr, Node *val, BasicType bt,
                      int adr_idx,
                      MemNode::MemOrd mo, bool require_atomic_access,
                      bool mismatched) {
  assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory");
  const TypePtr* adr_type = nullptr;
  DEBUG_ONLY(adr_type = C->get_adr_type(adr_idx));
  Node *mem = memory(adr_idx);
  Node* st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo, require_atomic_access);
  if (mismatched) {
    st->as_Store()->set_mismatched_access();
  }
  st = transform(st);
  set_memory(st, adr_idx);

  return st;
}

//---------------------------- do_memory_merge --------------------------------
// The memory from one merging cvstate needs to be merged with the memory for another
// join cvstate. If the join cvstate doesn't have a merged memory yet then we
// can just copy the state from the merging cvstate

// Merge one slow path into the rest of memory.
void IdealKit::do_memory_merge(Node* merging, Node* join) {

  // Get the region for the join state
  Node* join_region = join->in(TypeFunc::Control);
  assert(join_region != nullptr, "join region must exist");
  if (join->in(TypeFunc::I_O) == nullptr ) {
    join->set_req(TypeFunc::I_O,  merging->in(TypeFunc::I_O));
  }
  if (join->in(TypeFunc::Memory) == nullptr ) {
    join->set_req(TypeFunc::Memory,  merging->in(TypeFunc::Memory));
    return;
  }

  // The control flow for merging must have already been attached to the join region
  // we need its index for the phis.
  uint slot;
  for (slot = 1; slot < join_region->req() ; slot ++ ) {
    if (join_region->in(slot) == merging->in(TypeFunc::Control)) break;
  }
  assert(slot !=  join_region->req(), "edge must already exist");

  MergeMemNode* join_m    = join->in(TypeFunc::Memory)->as_MergeMem();
  MergeMemNode* merging_m = merging->in(TypeFunc::Memory)->as_MergeMem();

  // join_m should be an ancestor mergemem of merging
  // Slow path memory comes from the current map (which is from a slow call)
  // Fast path/null path memory comes from the call's input

  // Merge the other fast-memory inputs with the new slow-default memory.
  // for (MergeMemStream mms(merged_memory(), fast_mem->as_MergeMem()); mms.next_non_empty2(); ) {
  for (MergeMemStream mms(join_m, merging_m); mms.next_non_empty2(); ) {
    Node* join_slice = mms.force_memory();
    Node* merging_slice = mms.memory2();
    if (join_slice != merging_slice) {
      PhiNode* phi;
      // bool new_phi = false;
      // Is the phi for this slice one that we created for this join region or simply
      // one we copied? If it is ours then add
      if (join_slice->is_Phi() && join_slice->as_Phi()->region() == join_region) {
        phi = join_slice->as_Phi();
      } else {
        // create the phi with join_slice filling supplying memory for all of the
        // control edges to the join region
        phi = PhiNode::make(join_region, join_slice, Type::MEMORY, mms.adr_type(C));
        phi = (PhiNode*) delay_transform(phi);
        // gvn().set_type(phi, Type::MEMORY);
        // new_phi = true;
      }
      // Now update the phi with the slice for the merging slice
      phi->set_req(slot, merging_slice/* slow_path, slow_slice */);
      // this updates join_m with the phi
      mms.set_memory(phi);
    }
  }

  Node* join_io    = join->in(TypeFunc::I_O);
  Node* merging_io = merging->in(TypeFunc::I_O);
  if (join_io != merging_io) {
    PhiNode* phi;
    if (join_io->is_Phi() && join_io->as_Phi()->region() == join_region) {
      phi = join_io->as_Phi();
    } else {
      phi = PhiNode::make(join_region, join_io, Type::ABIO);
      phi = (PhiNode*) delay_transform(phi);
      join->set_req(TypeFunc::I_O, phi);
    }
    phi->set_req(slot, merging_io);
  }
}


//----------------------------- make_call  ----------------------------
// Trivial runtime call
Node* IdealKit::make_leaf_call(const TypeFunc *slow_call_type,
                               address slow_call,
                               const char *leaf_name,
                               Node* parm0,
                               Node* parm1,
                               Node* parm2,
                               Node* parm3) {

  // We only handle taking in RawMem and modifying RawMem
  const TypePtr* adr_type = TypeRawPtr::BOTTOM;
  uint adr_idx = C->get_alias_index(adr_type);

  // Slow-path leaf call
  CallNode *call =  (CallNode*)new CallLeafNode( slow_call_type, slow_call, leaf_name, adr_type);

  // Set fixed predefined input arguments
  call->init_req( TypeFunc::Control, ctrl() );
  call->init_req( TypeFunc::I_O    , top() )     ;   // does no i/o
  // Narrow memory as only memory input
  call->init_req( TypeFunc::Memory , memory(adr_idx));
  call->init_req( TypeFunc::FramePtr, top() /* frameptr() */ );
  call->init_req( TypeFunc::ReturnAdr, top() );

  if (parm0 != nullptr)  call->init_req(TypeFunc::Parms+0, parm0);
  if (parm1 != nullptr)  call->init_req(TypeFunc::Parms+1, parm1);
  if (parm2 != nullptr)  call->init_req(TypeFunc::Parms+2, parm2);
  if (parm3 != nullptr)  call->init_req(TypeFunc::Parms+3, parm3);

  // Node *c = _gvn.transform(call);
  call = (CallNode *) _gvn.transform(call);
  Node *c = call; // dbx gets confused with call call->dump()

  // Slow leaf call has no side-effects, sets few values

  set_ctrl(transform( new ProjNode(call,TypeFunc::Control) ));

  // Make memory for the call
  Node* mem = _gvn.transform( new ProjNode(call, TypeFunc::Memory) );

  // Set the RawPtr memory state only.
  set_memory(mem, adr_idx);

  assert(C->alias_type(call->adr_type()) == C->alias_type(adr_type),
         "call node must be constructed correctly");
  Node* res = nullptr;
  if (slow_call_type->range()->cnt() > TypeFunc::Parms) {
    assert(slow_call_type->range()->cnt() == TypeFunc::Parms+1, "only one return value");
    res = transform(new ProjNode(call, TypeFunc::Parms));
  }
  return res;
}

void IdealKit::make_leaf_call_no_fp(const TypeFunc *slow_call_type,
                              address slow_call,
                              const char *leaf_name,
                              const TypePtr* adr_type,
                              Node* parm0,
                              Node* parm1,
                              Node* parm2,
                              Node* parm3) {

  // We only handle taking in RawMem and modifying RawMem
  uint adr_idx = C->get_alias_index(adr_type);

  // Slow-path leaf call
  CallNode *call =  (CallNode*)new CallLeafNoFPNode( slow_call_type, slow_call, leaf_name, adr_type);

  // Set fixed predefined input arguments
  call->init_req( TypeFunc::Control, ctrl() );
  call->init_req( TypeFunc::I_O    , top() )     ;   // does no i/o
  // Narrow memory as only memory input
  call->init_req( TypeFunc::Memory , memory(adr_idx));
  call->init_req( TypeFunc::FramePtr, top() /* frameptr() */ );
  call->init_req( TypeFunc::ReturnAdr, top() );

  if (parm0 != nullptr)  call->init_req(TypeFunc::Parms+0, parm0);
  if (parm1 != nullptr)  call->init_req(TypeFunc::Parms+1, parm1);
  if (parm2 != nullptr)  call->init_req(TypeFunc::Parms+2, parm2);
  if (parm3 != nullptr)  call->init_req(TypeFunc::Parms+3, parm3);

  // Node *c = _gvn.transform(call);
  call = (CallNode *) _gvn.transform(call);
  Node *c = call; // dbx gets confused with call call->dump()

  // Slow leaf call has no side-effects, sets few values

  set_ctrl(transform( new ProjNode(call,TypeFunc::Control) ));

  // Make memory for the call
  Node* mem = _gvn.transform( new ProjNode(call, TypeFunc::Memory) );

  // Set the RawPtr memory state only.
  set_memory(mem, adr_idx);

  assert(C->alias_type(call->adr_type()) == C->alias_type(adr_type),
         "call node must be constructed correctly");
}
