Robot::mCompositeBlock Robot::createBlockOfOperations(uint32_t& fromActivityId, uint32_t& fromPointId, const ActivityType& t1, const ActivityType& t2,
		const Interval<uint32_t>& numSeq, const Interval<uint32_t>& seqLength) const	{

	uniform_int_distribution<uint32_t> sl(seqLength.from(), seqLength.to());
	uniform_int_distribution<uint32_t> ns(numSeq.from(), numSeq.to());

	mCompositeBlock blockActivities;
	uint32_t numberOfSequences = ns(generator);

	function<void(StaticActivity*)> storeActivity = [&blockActivities](StaticActivity *a) {
		switch (a->type())	{
			case IN:
				blockActivities.in.push_back(a);
				break;
			case INNER:
				blockActivities.w.push_back(a);
				break;
			default:
				blockActivities.out.push_back(a);
		}
	};


	for (uint32_t i = 0; i < numberOfSequences; ++i)	{

		uint32_t sequenceLength = sl(generator);

		StaticActivity *op1 = new StaticActivity(fromActivityId++, fromPointId, t1, mRobotModes, mParameters);
		blockActivities.con1.push_back(op1);
		storeActivity(op1);

		StaticActivity *op2 = nullptr;
		for (uint32_t l = 0; l+2 < sequenceLength; ++l)	{
			op2 = new StaticActivity(fromActivityId++, fromPointId, INNER, mRobotModes, mParameters);
			DynamicActivity *op2op = new DynamicActivity(fromActivityId++, op1, op2, mParameters);
			blockActivities.w.push_back(op2);
			blockActivities.mv.push_back(op2op);
			op1 = op2;
		}

		if (sequenceLength == 1)	{
			if (t1 == t2)	{
				op2 = op1;
			} else {
				throw runtime_error("Robot::mCompositeBlock Robot::createBlockOfOperations(...): "
						"Sequence of unit length must have the same types of the first and last activity");
			}
		} else {
			op2 = new StaticActivity(fromActivityId++, fromPointId, t2, mRobotModes, mParameters);
			DynamicActivity *op2op = new DynamicActivity(fromActivityId++, op1, op2, mParameters);
			blockActivities.mv.push_back(op2op);
			storeActivity(op2);
		}

		blockActivities.con2.push_back(op2);
	}

	connect(fromActivityId, blockActivities, blockActivities.con2, blockActivities.con1, false);

	return blockActivities;
}
Пример #2
0
void LinearScan::allocate_fpu_stack() {
  // First compute which FPU registers are live at the start of each basic block
  // (To minimize the amount of work we have to do if we have to merge FPU stacks)
  if (ComputeExactFPURegisterUsage) {
    Interval* intervals_in_register, *intervals_in_memory;
    create_unhandled_lists(&intervals_in_register, &intervals_in_memory, is_in_fpu_register, NULL);

    // ignore memory intervals by overwriting intervals_in_memory
    // the dummy interval is needed to enforce the walker to walk until the given id:
    // without it, the walker stops when the unhandled-list is empty -> live information
    // beyond this point would be incorrect.
    Interval* dummy_interval = new Interval(any_reg);
    dummy_interval->add_range(max_jint - 2, max_jint - 1);
    dummy_interval->set_next(Interval::end());
    intervals_in_memory = dummy_interval;

    IntervalWalker iw(this, intervals_in_register, intervals_in_memory);

    const int num_blocks = block_count();
    for (int i = 0; i < num_blocks; i++) {
      BlockBegin* b = block_at(i);

      // register usage is only needed for merging stacks -> compute only
      // when more than one predecessor.
      // the block must not have any spill moves at the beginning (checked by assertions)
      // spill moves would use intervals that are marked as handled and so the usage bit
      // would been set incorrectly

      // NOTE: the check for number_of_preds > 1 is necessary. A block with only one
      //       predecessor may have spill moves at the begin of the block.
      //       If an interval ends at the current instruction id, it is not possible
      //       to decide if the register is live or not at the block begin -> the
      //       register information would be incorrect.
      if (b->number_of_preds() > 1) {
        int id = b->first_lir_instruction_id();
        ResourceBitMap regs(FrameMap::nof_fpu_regs);

        iw.walk_to(id);   // walk after the first instruction (always a label) of the block
        assert(iw.current_position() == id, "did not walk completely to id");

        // Only consider FPU values in registers
        Interval* interval = iw.active_first(fixedKind);
        while (interval != Interval::end()) {
          int reg = interval->assigned_reg();
          assert(reg >= pd_first_fpu_reg && reg <= pd_last_fpu_reg, "no fpu register");
          assert(interval->assigned_regHi() == -1, "must not have hi register (doubles stored in one register)");
          assert(interval->from() <= id && id < interval->to(), "interval out of range");

#ifndef PRODUCT
          if (TraceFPURegisterUsage) {
            tty->print("fpu reg %d is live because of ", reg - pd_first_fpu_reg); interval->print();
          }
#endif

          regs.set_bit(reg - pd_first_fpu_reg);
          interval = interval->next();
        }

        b->set_fpu_register_usage(regs);

#ifndef PRODUCT
        if (TraceFPURegisterUsage) {
          tty->print("FPU regs for block %d, LIR instr %d): ", b->block_id(), id); regs.print_on(tty); tty->cr();
        }
#endif
      }
    }
  }

  FpuStackAllocator alloc(ir()->compilation(), this);
  _fpu_stack_allocator = &alloc;
  alloc.allocate();
  _fpu_stack_allocator = NULL;
}