示例#1
0
void Canonicalizer::do_LoadIndexed    (LoadIndexed*     x) {
  StableArrayConstant* array = x->array()->type()->as_StableArrayConstant();
  IntConstant* index = x->index()->type()->as_IntConstant();

  assert(array == NULL || FoldStableValues, "not enabled");

  // Constant fold loads from stable arrays.
  if (!x->mismatched() && array != NULL && index != NULL) {
    jint idx = index->value();
    if (idx < 0 || idx >= array->value()->length()) {
      // Leave the load as is. The range check will handle it.
      return;
    }

    ciConstant field_val = array->value()->element_value(idx);
    if (!field_val.is_null_or_zero()) {
      jint dimension = array->dimension();
      assert(dimension <= array->value()->array_type()->dimension(), "inconsistent info");
      ValueType* value = NULL;
      if (dimension > 1) {
        // Preserve information about the dimension for the element.
        assert(field_val.as_object()->is_array(), "not an array");
        value = new StableArrayConstant(field_val.as_object()->as_array(), dimension - 1);
      } else {
        assert(dimension == 1, "sanity");
        value = as_ValueType(field_val);
      }
      set_canonical(new Constant(value));
    }
  }
}
示例#2
0
static
String handle_static_int_constant(CPrintStyleModule *state,
				  const SuifObject *obj)
{
  IntConstant *expr =
    to<IntConstant>(obj);
  IInteger v = expr->get_value();
  return(v.to_String());
}
示例#3
0
// perform constant and interval tests on index value
bool AccessIndexed::compute_needs_range_check() {
  Constant* clength = length()->as_Constant();
  Constant* cindex = index()->as_Constant();
  if (clength && cindex) {
    IntConstant* l = clength->type()->as_IntConstant();
    IntConstant* i = cindex->type()->as_IntConstant();
    if (l && i && i->value() < l->value() && i->value() >= 0) {
      return false;
    }
  }
  return true;
}
void Canonicalizer::do_Intrinsic      (Intrinsic*       x) {
  switch (x->id()) {
  case ciMethod::_floatToRawIntBits   : {
    FloatConstant* c = x->argument_at(0)->type()->as_FloatConstant();
    if (c != NULL) {
      JavaValue v;
      v.set_jfloat(c->value());
      set_constant(v.get_jint());
    }
    break;
  }
  case ciMethod::_intBitsToFloat      : {
    IntConstant* c = x->argument_at(0)->type()->as_IntConstant();
    if (c != NULL) {
      JavaValue v;
      v.set_jint(c->value());
      set_constant(v.get_jfloat());
    }
    break;
  }
  case ciMethod::_doubleToRawLongBits : {
    DoubleConstant* c = x->argument_at(0)->type()->as_DoubleConstant();
    if (c != NULL) {
      JavaValue v;
      v.set_jdouble(c->value());
      set_constant(v.get_jlong());
    }
    break;
  }
  case ciMethod::_longBitsToDouble    : {
    LongConstant* c = x->argument_at(0)->type()->as_LongConstant();
    if (c != NULL) {
      JavaValue v;
      v.set_jlong(c->value());
      set_constant(v.get_jdouble());
    }
    break;
  }
  }
}
示例#5
0
/* Another helper function for print_var_def().   This function
 * expects that it will need to add a return before printing
 * anything, and it expects that you will add a return after
 * it is done.
 * It returns the number of bits of initialization data that it
 * generates.
 */
int
PrinterX86::process_value_block(ValueBlock *vblk)
{
    int bits_filled = 0;

    if (is_a<ExpressionValueBlock>(vblk)) {
	// An ExpressionValueBlock either holds a constant value or a
	// simple expression representing either an address relative to
	// a symbol or a pointer generated by conversion from an integer
	// constant (presumably zero).

	ExpressionValueBlock *evb = (ExpressionValueBlock*)vblk;
	Expression *exp = evb->get_expression();

	if (is_a<IntConstant>(exp)) {
	    IntConstant *ic = (IntConstant*)exp;
	    bits_filled = print_size_directive(ic->get_result_type());
	    fprint(out, ic->get_value());
	    cur_opnd_cnt++;
	}
	else if (is_a<FloatConstant>(exp)) {
	    FloatConstant *fc = (FloatConstant*)exp;
	    bits_filled = print_size_directive(fc->get_result_type());
	    fputs(fc->get_value().c_str(), out);
	    cur_opnd_cnt++;
	}
	else {
	    // We use non-constant ExpressionValueBlocks to hold a symbolic
	    // address, optionally with an offset, or a pointer initializer
	    // consisting of a `convert' expression.
	    // A SymbolAddressExpression represents a plain symbolic
	    // address.
	    // An address obtained by conversion from another type is a
	    // unary expression with opcode "convert".
	    // A symbol+delta is represented by an add whose first operand
	    // is the load-address and whose second is an IntConstant
	    // expression.
	    // No other kind of "expression" is recognized.

	    if (is_a<UnaryExpression>(exp)) {
		UnaryExpression *ux = (UnaryExpression*)exp;
		claim(ux->get_opcode() == k_convert,
		      "unexpected unary expression in expression block");
		DataType *tt = ux->get_result_type();	// target type
		claim(is_kind_of<PointerType>(tt),
		      "unexpected target type when converting initializer");
		exp = ux->get_source();
		if (is_a<IntConstant>(exp)) {
		    IntConstant *ic = (IntConstant*)exp;
		    bits_filled = print_size_directive(tt);
		    fprint(out, ic->get_value());
		    cur_opnd_cnt++;
		    return bits_filled;
		}
		// Fall through to handle symbol-relative address, on the
		// assumption that the front end validated the conversion.
	    }
	    SymbolAddressExpression *sax;
	    long delta;
	    if (is_a<BinaryExpression>(exp)) {
		BinaryExpression *bx = (BinaryExpression*)exp;
		claim(bx->get_opcode() == k_add,
		      "unexpected binary expression in expression block");
		Expression *s1 = bx->get_source1();
		Expression *s2 = bx->get_source2();
		sax = to<SymbolAddressExpression>(s1);
		delta = to<IntConstant>(s2)->get_value().c_long();
	    } else if (is_a<SymbolAddressExpression>(exp)) {
		sax = (SymbolAddressExpression*)exp;
		delta = 0;
	    } else {
		claim(false, "unexpected kind of expression block");
	    }
	    Sym *sym = sax->get_addressed_symbol();

	    // symbol initialization
	    bits_filled = print_size_directive(type_ptr);
	    print_sym(sym);
	    if (delta != 0) {
		fprintf(out, "%+ld", delta);
	    }
	    // always force the start of a new data directive
	    cur_opcode = opcode_null;
	    cur_opnd_cnt = 0;
	}
    }

    else if (is_a<MultiValueBlock>(vblk)) {
	MultiValueBlock *mvb = (MultiValueBlock*)vblk;
	for (int i = 0; i < mvb->get_sub_block_count(); i++ ) {
	    int offset = mvb->get_sub_block(i).first.c_int();
	    claim(offset >= bits_filled);

	    if (bits_filled < offset)		// pad to offset
		bits_filled += print_bit_filler(offset - bits_filled);
	    bits_filled += process_value_block(mvb->get_sub_block(i).second);
	}
	int all_bits = get_bit_size(mvb->get_type());
	if (all_bits > bits_filled)
	    bits_filled += print_bit_filler(all_bits - bits_filled);

    } else if (is_a<RepeatValueBlock>(vblk)) {
	// Simplifying assumption: We now expect the front-end
	// to remove initialization code of large arrays of zeros.
	RepeatValueBlock *rvb = (RepeatValueBlock*)vblk;
	int repeat_cnt = rvb->get_num_repetitions();

	if (repeat_cnt > 1) {		// insert .repeat pseudo-op
	    fprintf(out, "\n\t%s\t%d", x86_opcode_names[REPEAT], repeat_cnt);
	    cur_opcode = opcode_null;	// force new data directive
	}
	// actual data directive
	bits_filled = repeat_cnt * process_value_block(rvb->get_sub_block());

	if (repeat_cnt > 1) {		// insert .endr pseudo-op
	    fprintf(out, "\n\t%s", x86_opcode_names[ENDR]);
	    cur_opcode = opcode_null;	// force new data directive
	}

    } else if (is_a<UndefinedValueBlock>(vblk)) {
	bits_filled += print_bit_filler(get_bit_size(vblk->get_type()));

    } else {
	claim(false, "unexpected kind of ValueBlock");
    }
    return bits_filled;
}
// All of the array references expressions in the passed in the struct are
//  equivalent, so we can determine types of the original and use that
//  to create a new expression with which to replace everything.
bool TransformUnrolledArraysPass::ReplaceNDReference(EquivalentReferences* a)
{
  assert(a != NULL) ;
  assert(a->original != NULL) ;

  // Check to see if the reference at this stage is a constant or not
  IntConstant* constantIndex = 
    dynamic_cast<IntConstant*>(a->original->get_index()) ;
  
  if (constantIndex == NULL)
  {
    // There was no replacement made
    return false ;
  }

  Expression* baseAddress = a->original->get_base_array_address() ;
  assert(baseAddress != NULL) ;
  assert(constantIndex != NULL) ;

  // Create a replacement expression for this value.  This will either
  //  be another array reference expression or a single variable.
  Expression* replacementExp = NULL ;
  //  QualifiedType* elementType = GetQualifiedTypeOfElement(a->original) ;
  VariableSymbol* originalSymbol = GetArrayVariable(a->original) ;
  assert(originalSymbol != NULL) ;
  LString replacementName = 
    GetReplacementName(originalSymbol->get_name(), 
		       constantIndex->get_value().c_int()) ;
  int dimensionality = GetDimensionality(a->original) ;
  
  QualifiedType* elementType = originalSymbol->get_type() ;
  while (dynamic_cast<ArrayType*>(elementType->get_base_type()) != NULL)
  {
    elementType = dynamic_cast<ArrayType*>(elementType->get_base_type())->get_element_type() ;
  }
  
  // There is a special case for one dimensional arrays as opposed to all
  //  other dimensional arrays.  It only should happen if we are truly
  //  replacing an array with a one dimensional array.
  if (dimensionality == 1 && 
      dynamic_cast<ArrayReferenceExpression*>(a->original->get_parent())==NULL)
  {

    VariableSymbol* replacementVar = 
      create_variable_symbol(theEnv,
			     GetQualifiedTypeOfElement(a->original),
			     TempName(replacementName)) ;
    procDef->get_symbol_table()->append_symbol_table_object(replacementVar) ;
    
    replacementExp = 
      create_load_variable_expression(theEnv,
				      elementType->get_base_type(),
				      replacementVar) ;
  }
  else
  {
    // Create a new array with one less dimension.  This requires a new
    //  array type.
    ArrayType* varType = 
      dynamic_cast<ArrayType*>(originalSymbol->get_type()->get_base_type()) ;
    assert(varType != NULL) ;
   
    ArrayType* replacementArrayType =
      create_array_type(theEnv,
	varType->get_element_type()->get_base_type()->get_bit_size(),
	0, // bit alignment
	OneLessDimension(originalSymbol->get_type(), dimensionality),
	dynamic_cast<Expression*>(varType->get_lower_bound()->deep_clone()),
	dynamic_cast<Expression*>(varType->get_upper_bound()->deep_clone()),
	TempName(varType->get_name())) ;

    procDef->get_symbol_table()->append_symbol_table_object(replacementArrayType) ;

    VariableSymbol* replacementArraySymbol = 
      create_variable_symbol(theEnv,
			     create_qualified_type(theEnv,
						   replacementArrayType,
						   TempName(LString("qualType"))),
			     TempName(replacementName)) ;

    procDef->get_symbol_table()->append_symbol_table_object(replacementArraySymbol) ;

    // Create a new symbol address expression for this variable symbol
    SymbolAddressExpression* replacementAddrExp =
      create_symbol_address_expression(theEnv,
				       replacementArrayType,
				       replacementArraySymbol) ;

    // Now, replace the symbol address expression in the base
    //  array address with this symbol.
    ReplaceSymbol(a->original, replacementAddrExp) ;
    
    // And replace this reference with the base array address.
    replacementExp = a->original->get_base_array_address() ;
    a->original->set_base_array_address(NULL) ;
    replacementExp->set_parent(NULL) ;
  }

  // Replace all of the equivalent expressions with the newly generated
  //  replacement expression.
  assert(replacementExp != NULL) ;
  a->original->get_parent()->replace(a->original, replacementExp) ;
   
  //  ReplaceChildExpression(a->original->get_parent(),
  //			 a->original,
  //			 replacementExp) ;

  list<ArrayReferenceExpression*>::iterator equivIter = 
    a->allEquivalent.begin() ;
  while (equivIter != a->allEquivalent.end()) 
  {
    (*equivIter)->get_parent()->replace((*equivIter),
					dynamic_cast<Expression*>(replacementExp->deep_clone())) ;
    //    ReplaceChildExpression((*equivIter)->get_parent(),
    //			   (*equivIter),
    //			   dynamic_cast<Expression*>(replacementExp->deep_clone())) ;
    ++equivIter ;
  }

  return true ;
}
static bool match_index_and_scale(Instruction*  instr,
                                  Instruction** index,
                                  int*          log2_scale,
                                  Instruction** instr_to_unpin) {
  *instr_to_unpin = NULL;

  // Skip conversion ops
  Convert* convert = instr->as_Convert();
  if (convert != NULL) {
    instr = convert->value();
  }

  ShiftOp* shift = instr->as_ShiftOp();
  if (shift != NULL) {
    if (shift->is_pinned()) {
      *instr_to_unpin = shift;
    }
    // Constant shift value?
    Constant* con = shift->y()->as_Constant();
    if (con == NULL) return false;
    // Well-known type and value?
    IntConstant* val = con->type()->as_IntConstant();
    if (val == NULL) return false;
    if (shift->x()->type() != intType) return false;
    *index = shift->x();
    int tmp_scale = val->value();
    if (tmp_scale >= 0 && tmp_scale < 4) {
      *log2_scale = tmp_scale;
      return true;
    } else {
      return false;
    }
  }

  ArithmeticOp* arith = instr->as_ArithmeticOp();
  if (arith != NULL) {
    if (arith->is_pinned()) {
      *instr_to_unpin = arith;
    }
    // Check for integer multiply
    if (arith->op() == Bytecodes::_imul) {
      // See if either arg is a known constant
      Constant* con = arith->x()->as_Constant();
      if (con != NULL) {
        *index = arith->y();
      } else {
        con = arith->y()->as_Constant();
        if (con == NULL) return false;
        *index = arith->x();
      }
      if ((*index)->type() != intType) return false;
      // Well-known type and value?
      IntConstant* val = con->type()->as_IntConstant();
      if (val == NULL) return false;
      switch (val->value()) {
      case 1: *log2_scale = 0; return true;
      case 2: *log2_scale = 1; return true;
      case 4: *log2_scale = 2; return true;
      case 8: *log2_scale = 3; return true;
      default:            return false;
      }
    }
  }

  // Unknown instruction sequence; don't touch it
  return false;
}
示例#8
0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int InlineHeuristic::EstimateInstructionWeight(Instruction* instr) {
    DebugValidator::IsNotNull(instr);

    // We estimate the size of the code based on the type
    // of the instructions. We also take into consideration constant
    // operands, because these instructions can usually be lowered
    // to fewer target instructions.
    if(instr->IsArithmetic()) {
        // It's highly probable that an instruction that already
        // has a constant operand will be folded away after inlining.
        if(instr->GetSourceOp(0)->IsConstant() ||
           instr->GetSourceOp(1)->IsConstant()) {
            return ARITHMETIC_WEIGHT;
        }
        else return ARITHMETIC_WEIGHT_CONST;
    }
    else if(instr->IsLogical()) {
        if(instr->GetSourceOp(0)->IsConstant() ||
           instr->GetSourceOp(1)->IsConstant()) {
            return LOGICAL_WEIGHT;
        }
        else return LOGICAL_WEIGHT_CONST;
    }
    else if(instr->IsConversion()) {
        // Integer extensions usually don't need any instructions.
        if(instr->IsZext() || instr->IsSext() || instr->IsTrunc()) {
            return CONVERSION_WEIGHT_EXT_TRUNC;
        }
        else if(instr->IsPtoi() || instr->IsItop() || instr->IsPtop()) {
            return CONVERSION_WEIGHT_POINTER;
        }
        else return CONVERSION_WEIGHT;
    }
    else if(instr->IsComparison()) {
        IntConstant* intConst = instr->GetSourceOp(0)->As<IntConstant>();
        if(intConst == nullptr) intConst = instr->GetSourceOp(1)->As<IntConstant>();

        if(intConst) {
            // Comparisons with zero usually don't need any
            // instructions on most targets.
            if(intConst->IsZero()) {
                return COMPARE_WEIGHT_ZERO;
            }
            else COMPARE_WEIGHT_CONST;
        }
        else if(instr->GetSourceOp(0)->IsNullConstant() ||
                instr->GetSourceOp(1)->IsIntConstant()) {
            return COMPARE_WEIGHT_ZERO;
        }
        else COMPARE_WEIGHT;
    }
    else if(instr->IsAddress() || instr->IsIndex()) {
        // If we know the index we get rid of a multiplication.
        if(instr->GetSourceOp(1)->IsIntConstant()) {
            return ADDRESS_INDEX_WEIGHT_CONST;
        }
        else return ADDRESS_INDEX_WEIGHT;
    }
    else if(instr->IsElement()) {
        return ELEMENT_WEIGHT;
    }
    else if(auto questInstr = instr->As<QuestionInstr>()) {
        // 'quest' with 0/1 as both operands can usually
        // be converted to an integer extension.
        if((questInstr->TrueOp()->IsZeroInt() ||
            questInstr->TrueOp()->IsOneInt()  ||
            questInstr->TrueOp()->IsMinusOneInt()) &&
           (questInstr->FalseOp()->IsZeroInt() ||
            questInstr->FalseOp()->IsOneInt()  ||
            questInstr->FalseOp()->IsMinusOneInt())) {
            return QUESTION_WEIGHT_ZERO_ONE;
        }
        else if(questInstr->TrueOp()->IsConstant() &&
                questInstr->FalseOp()->IsConstant()) {
            return QUESTION_WEIGHT_CONST;
        }
        else return QUESTION_WEIGHT;
    }
    else if(auto phiInstr = instr->As<PhiInstr>()) {
        return phiInstr->OperandCount() * PHI_INCOMING_WEIGHT;
    }
    else if(auto callInstr = instr->As<CallInstr>()) {
        return EstimateCallWeight(callInstr);
    }
    else if(instr->IsGoto()) {
        return GOTO_WEIGHT;
    }
    else if(instr->IsIf()) {
        return IF_WEIGHT;
    }
    else if(auto switchInstr = instr->As<SwitchInstr>()) {
        return SWITCH_WEIGHT + (switchInstr->CaseCount() * SWITCH_CASE_WEIGHT);
    }

    return AVERAGE_WEIGHT;
}
Constant* MiniConstantPropagationPass::Merge(Constant* x, Constant* y,
        LString opcode)
{
    assert(theEnv != NULL) ;

    if (x == NULL || y == NULL)
    {
        return NULL ;
    }

    IntConstant* xInt = dynamic_cast<IntConstant*>(x) ;
    IntConstant* yInt = dynamic_cast<IntConstant*>(y) ;
    FloatConstant* xFloat = dynamic_cast<FloatConstant*>(x) ;
    FloatConstant* yFloat = dynamic_cast<FloatConstant*>(y) ;

    // This mini propagation only cares for addition and subtraction.  Other
    //  propagations will be handled in a later pass.

    if (opcode == LString("add"))
    {
        if (xInt != NULL && yInt != NULL)
        {
            int mergedValue = xInt->get_value().c_int() + yInt->get_value().c_int() ;
            return create_int_constant(theEnv, xInt->get_result_type(),
                                       IInteger(mergedValue)) ;
        }
        if (xFloat != NULL && yFloat != NULL)
        {
            float mergedValue = StringToFloat(xFloat->get_value()) +
                                StringToFloat(yFloat->get_value()) ;
            return create_float_constant(theEnv, xFloat->get_result_type(),
                                         FloatToString(mergedValue)) ;
        }
        if (xInt != NULL && yFloat != NULL)
        {
            float mergedValue = xInt->get_value().c_int() +
                                StringToFloat(yFloat->get_value()) ;
            return create_float_constant(theEnv, yFloat->get_result_type(),
                                         FloatToString(mergedValue)) ;
        }
        if (xFloat != NULL && yInt != NULL)
        {
            float mergedValue = StringToFloat(xFloat->get_value()) +
                                yInt->get_value().c_int() ;
            return create_float_constant(theEnv, xFloat->get_result_type(),
                                         FloatToString(mergedValue)) ;
        }
    }

    if (opcode == LString("subtract"))
    {
        if (xInt != NULL && yInt != NULL)
        {
            int mergedValue = xInt->get_value().c_int() - yInt->get_value().c_int() ;
            return create_int_constant(theEnv, xInt->get_result_type(),
                                       IInteger(mergedValue)) ;
        }
        if (xFloat != NULL && yFloat != NULL)
        {
            float mergedValue = StringToFloat(xFloat->get_value()) -
                                StringToFloat(yFloat->get_value()) ;
            return create_float_constant(theEnv, xFloat->get_result_type(),
                                         FloatToString(mergedValue)) ;
        }
        if (xInt != NULL && yFloat != NULL)
        {
            float mergedValue = xInt->get_value().c_int() -
                                StringToFloat(yFloat->get_value()) ;
            return create_float_constant(theEnv, yFloat->get_result_type(),
                                         FloatToString(mergedValue)) ;
        }
        if (xFloat != NULL && yInt != NULL)
        {
            float mergedValue = StringToFloat(xFloat->get_value()) -
                                yInt->get_value().c_int() ;
            return create_float_constant(theEnv, xFloat->get_result_type(),
                                         FloatToString(mergedValue)) ;
        }
    }

    return NULL ;

}
void ConstantArrayPropagationPass::ReplaceLoad(LoadExpression* load,
					       ArrayReferenceExpression* ref,
					       VariableSymbol* var,
					       ValueBlock* topBlock) 
{
  list<IntConstant*> allDimensions ;
  
  IntConstant* nextIndex = dynamic_cast<IntConstant*>(ref->get_index()) ;
  if (nextIndex == NULL)
  {   
    OutputWarning("Trying to access a constant array with a nonconstant index!") ;
    delete var->remove_annote_by_name("ConstPropArray") ;
    //    assert(0) ;
    return ;
  }
  allDimensions.push_front(nextIndex) ;
  
  ArrayReferenceExpression* nextDimension = 
    dynamic_cast<ArrayReferenceExpression*>(ref->get_base_array_address()) ;
  while (nextDimension != NULL)
  {
    nextIndex = dynamic_cast<IntConstant*>(nextDimension->get_index()) ;
    assert(nextIndex != NULL) ;
    allDimensions.push_front(nextIndex) ;
    nextDimension = dynamic_cast<ArrayReferenceExpression*>(nextDimension->get_base_array_address()) ;
  }

  ValueBlock* currentBlock = topBlock ;
  
  list<IntConstant*>::iterator dimIter = allDimensions.begin() ;

  for (int i = 0 ; i < allDimensions.size() ; ++i)
  {
    MultiValueBlock* multiBlock = dynamic_cast<MultiValueBlock*>(currentBlock);
    assert(multiBlock != NULL) ;
    currentBlock = multiBlock->lookup_sub_block((*dimIter)->get_value()) ;
    ++dimIter ;
  }
  
  ExpressionValueBlock* finalBlock = 
    dynamic_cast<ExpressionValueBlock*>(currentBlock) ;
  assert(finalBlock != NULL && 
	 "Attempted to use an uninitialized constant value!") ;
  Expression* replacementValue = finalBlock->get_expression() ;
  if (dynamic_cast<IntConstant*>(replacementValue) != NULL)
  {
    IntConstant* constInt = 
      dynamic_cast<IntConstant*>(replacementValue) ;
    IntConstant* replacement =
      create_int_constant(theEnv, 
			  constInt->get_result_type(),
			  constInt->get_value()) ;
    load->get_parent()->replace(load, replacement) ;
    delete load ;
  }
  else if (dynamic_cast<FloatConstant*>(replacementValue) != NULL)
  {
    FloatConstant* constFloat = 
      dynamic_cast<FloatConstant*>(replacementValue) ;
    FloatConstant* replacement = 
      create_float_constant(theEnv,
			    constFloat->get_result_type(),
			    constFloat->get_value()) ;
    load->get_parent()->replace(load, replacement) ;
    delete load ;
  }
  else
  {
    assert(0 && "Unknown constant") ;
  }

}