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)); } } }
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()); }
// 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; } } }
/* 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; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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") ; } }