Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 0 additions & 108 deletions src/hotspot/share/adlc/formssel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,14 +453,6 @@ Form::DataType InstructForm::is_ideal_store() const {
return _matrule->is_ideal_store();
}

// Return 'true' if this instruction matches an ideal vector node
bool InstructForm::is_vector() const {
if( _matrule == nullptr ) return false;

return _matrule->is_vector();
}


// Return the input register that must match the output register
// If this is not required, return 0
uint InstructForm::two_address(FormDict &globals) {
Expand Down Expand Up @@ -767,51 +759,6 @@ int InstructForm::memory_operand(FormDict &globals) const {
return NO_MEMORY_OPERAND;
}

// This instruction captures the machine-independent bottom_type
// Expected use is for pointer vs oop determination for LoadP
bool InstructForm::captures_bottom_type(FormDict &globals) const {
if (_matrule && _matrule->_rChild &&
(!strcmp(_matrule->_rChild->_opType,"CastPP") || // new result type
!strcmp(_matrule->_rChild->_opType,"CastDD") ||
!strcmp(_matrule->_rChild->_opType,"CastFF") ||
!strcmp(_matrule->_rChild->_opType,"CastII") ||
!strcmp(_matrule->_rChild->_opType,"CastLL") ||
!strcmp(_matrule->_rChild->_opType,"CastVV") ||
!strcmp(_matrule->_rChild->_opType,"CastX2P") || // new result type
!strcmp(_matrule->_rChild->_opType,"DecodeN") ||
!strcmp(_matrule->_rChild->_opType,"EncodeP") ||
!strcmp(_matrule->_rChild->_opType,"DecodeNKlass") ||
!strcmp(_matrule->_rChild->_opType,"EncodePKlass") ||
!strcmp(_matrule->_rChild->_opType,"LoadN") ||
!strcmp(_matrule->_rChild->_opType,"LoadNKlass") ||
!strcmp(_matrule->_rChild->_opType,"CreateEx") || // type of exception
!strcmp(_matrule->_rChild->_opType,"CheckCastPP") ||
!strcmp(_matrule->_rChild->_opType,"GetAndSetP") ||
!strcmp(_matrule->_rChild->_opType,"GetAndSetN") ||
!strcmp(_matrule->_rChild->_opType,"RotateLeft") ||
!strcmp(_matrule->_rChild->_opType,"RotateRight") ||
#if INCLUDE_SHENANDOAHGC
!strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeP") ||
!strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN") ||
#endif
!strcmp(_matrule->_rChild->_opType,"StrInflatedCopy") ||
!strcmp(_matrule->_rChild->_opType,"VectorCmpMasked")||
!strcmp(_matrule->_rChild->_opType,"VectorMaskGen")||
!strcmp(_matrule->_rChild->_opType,"VerifyVectorAlignment")||
!strcmp(_matrule->_rChild->_opType,"CompareAndExchangeP") ||
!strcmp(_matrule->_rChild->_opType,"CompareAndExchangeN"))) return true;
else if ( is_ideal_load() == Form::idealP ) return true;
else if ( is_ideal_store() != Form::none ) return true;

if (needs_base_oop_edge(globals)) return true;

if (is_vector()) return true;
if (is_mach_constant()) return true;

return false;
}


// Access instr_cost attribute or return null.
const char* InstructForm::cost() {
for (Attribute* cur = _attribs; cur != nullptr; cur = (Attribute*)cur->_next) {
Expand Down Expand Up @@ -1181,9 +1128,6 @@ const char *InstructForm::mach_base_class(FormDict &globals) const {
}
else if (is_mach_constant()) {
return "MachConstantNode";
}
else if (captures_bottom_type(globals)) {
return "MachTypeNode";
} else {
return "MachNode";
}
Expand Down Expand Up @@ -4337,58 +4281,6 @@ Form::DataType MatchRule::is_ideal_load() const {
return ideal_load;
}

bool MatchRule::is_vector() const {
static const char *vector_list[] = {
"AddVB","AddVS","AddVI","AddVL","AddVHF","AddVF","AddVD",
"SubVB","SubVS","SubVI","SubVL","SubVHF","SubVF","SubVD",
"MulVB","MulVS","MulVI","MulVL","MulVHF","MulVF","MulVD",
"DivVHF","DivVF","DivVD",
"AbsVB","AbsVS","AbsVI","AbsVL","AbsVF","AbsVD",
"NegVF","NegVD","NegVI","NegVL",
"SqrtVD","SqrtVF","SqrtVHF",
"AndV" ,"XorV" ,"OrV",
"MaxV", "MinV", "MinVHF", "MaxVHF", "UMinV", "UMaxV",
"CompressV", "ExpandV", "CompressM", "CompressBitsV", "ExpandBitsV",
"AddReductionVI", "AddReductionVL",
"AddReductionVHF", "AddReductionVF", "AddReductionVD",
"MulReductionVI", "MulReductionVL",
"MulReductionVHF", "MulReductionVF", "MulReductionVD",
"MaxReductionV", "MinReductionV",
"AndReductionV", "OrReductionV", "XorReductionV",
"MulAddVS2VI", "MacroLogicV",
"LShiftCntV","RShiftCntV",
"LShiftVB","LShiftVS","LShiftVI","LShiftVL",
"RShiftVB","RShiftVS","RShiftVI","RShiftVL",
"URShiftVB","URShiftVS","URShiftVI","URShiftVL",
"Replicate","ReverseV","ReverseBytesV",
"RoundDoubleModeV","RotateLeftV" , "RotateRightV", "LoadVector","StoreVector",
"LoadVectorGather", "StoreVectorScatter", "LoadVectorGatherMasked", "StoreVectorScatterMasked",
"SelectFromTwoVector", "VectorTest", "VectorLoadMask", "VectorStoreMask", "VectorBlend", "VectorInsert",
"VectorRearrange", "VectorLoadShuffle", "VectorLoadConst",
"VectorCastB2X", "VectorCastS2X", "VectorCastI2X",
"VectorCastL2X", "VectorCastF2X", "VectorCastD2X", "VectorCastF2HF", "VectorCastHF2F",
"VectorUCastB2X", "VectorUCastS2X", "VectorUCastI2X",
"VectorMaskWrapper","VectorMaskCmp","VectorReinterpret","LoadVectorMasked","StoreVectorMasked",
"FmaVD", "FmaVF", "FmaVHF", "PopCountVI", "PopCountVL", "PopulateIndex", "VectorLongToMask",
"CountLeadingZerosV", "CountTrailingZerosV", "SignumVF", "SignumVD", "SaturatingAddV", "SaturatingSubV",
// Next are vector mask ops.
"MaskAll", "AndVMask", "OrVMask", "XorVMask", "VectorMaskCast",
"RoundVF", "RoundVD",
// Next are not supported currently.
"PackB","PackS","PackI","PackL","PackF","PackD","Pack2L","Pack2D",
"ExtractB","ExtractUB","ExtractC","ExtractS","ExtractI","ExtractL","ExtractF","ExtractD"
};
int cnt = sizeof(vector_list)/sizeof(char*);
if (_rChild) {
const char *opType = _rChild->_opType;
for (int i=0; i<cnt; i++)
if (strcmp(opType,vector_list[i]) == 0)
return true;
}
return false;
}


bool MatchRule::skip_antidep_check() const {
// Some loads operate on what is effectively immutable memory so we
// should skip the anti dep computations. For some of these nodes
Expand Down
9 changes: 1 addition & 8 deletions src/hotspot/share/adlc/formssel.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2026, 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
Expand Down Expand Up @@ -169,7 +169,6 @@ class InstructForm : public Form {
virtual bool is_ideal_safepoint() const; // node matches 'SafePoint'
virtual bool is_ideal_nop() const; // node matches 'Nop'
virtual bool is_ideal_control() const; // control node
virtual bool is_vector() const; // vector instruction

virtual Form::CallType is_ideal_call() const; // matches ideal 'Call'
virtual Form::DataType is_ideal_load() const; // node matches ideal 'LoadXNode'
Expand Down Expand Up @@ -199,11 +198,6 @@ class InstructForm : public Form {
MANY_MEMORY_OPERANDS = 999999
};


// This instruction captures the machine-independent bottom_type
// Expected use is for pointer vs oop determination for LoadP
virtual bool captures_bottom_type(FormDict& globals) const;

virtual const char *cost(); // Access ins_cost attribute
virtual uint num_opnds(); // Count of num_opnds for MachNode class
// Counts USE_DEF opnds twice. See also num_unique_opnds().
Expand Down Expand Up @@ -1065,7 +1059,6 @@ class MatchRule : public MatchNode {
bool is_ideal_goto() const; // node matches ideal 'Goto'
bool is_ideal_loopEnd() const; // node matches ideal 'LoopEnd'
bool is_ideal_bool() const; // node matches ideal 'Bool'
bool is_vector() const; // vector instruction
Form::DataType is_ideal_load() const;// node matches ideal 'LoadXNode'
// Should antidep checks be disabled for this rule
// See definition of MatchRule::skip_antidep_check
Expand Down
41 changes: 17 additions & 24 deletions src/hotspot/share/adlc/output_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1324,11 +1324,8 @@ static void generate_peepreplace( FILE *fp, FormDict &globals, int peephole_numb
fprintf(fp, " root->add_req(inst%d->in(%d)); // unmatched ideal edge\n",
inst_num, unmatched_edge);
}
// If new instruction captures bottom type
if( root_form->captures_bottom_type(globals) ) {
// Get bottom type from instruction whose result we are replacing
fprintf(fp, " root->_bottom_type = inst%d->bottom_type();\n", inst_num);
}
// Get bottom type from instruction whose result we are replacing
fprintf(fp, " root->_bottom_type = inst%d->bottom_type();\n", inst_num);
// Define result register and result operand
fprintf(fp, " ra_->set_oop (root, ra_->is_oop(inst%d));\n", inst_num);
fprintf(fp, " ra_->set_pair(root->_idx, ra_->get_reg_second(inst%d), ra_->get_reg_first(inst%d));\n", inst_num, inst_num);
Expand Down Expand Up @@ -1587,11 +1584,8 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
fprintf(fp, " ((MachIfNode*)n%d)->_fcnt = _fcnt;\n", cnt);
}

// Fill in the bottom_type where requested
if (node->captures_bottom_type(_globalNames) &&
new_inst->captures_bottom_type(_globalNames)) {
fprintf(fp, " ((MachTypeNode*)n%d)->_bottom_type = bottom_type();\n", cnt);
}
// Fill in the bottom_type
fprintf(fp, " n%d->_bottom_type = bottom_type();\n", cnt);

const char *resultOper = new_inst->reduce_result();
fprintf(fp," n%d->set_opnd_array(0, state->MachOperGenerator(%s));\n",
Expand Down Expand Up @@ -3965,13 +3959,15 @@ void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *inden
}
}

// Fill in the bottom_type where requested
if (inst->captures_bottom_type(_globalNames)) {
if (strncmp("MachCall", inst->mach_base_class(_globalNames), strlen("MachCall")) != 0
&& strncmp("MachIf", inst->mach_base_class(_globalNames), strlen("MachIf")) != 0) {
fprintf(fp_cpp, "%s node->_bottom_type = _leaf->bottom_type();\n", indent);
}
// Fill in the bottom_type
if (inst->_matrule != nullptr && strcmp(inst->_matrule->_opType, "PrefetchAllocation") == 0) {
// Special case, with AllocatePrefetchStyle == 3, this should be Type::MEMORY, but the graph
// seems unsound, needs further investigation
Comment on lines +3964 to +3965
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "unsound" here? Can you create a follow-up to track this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, in the ideal graph, a PrefetchAllocationNode is a Type::ABIO or Type::MEMORY. As a result, they are connected to previous and subsequent abio and memory nodes, respectively. However, when lowered to MachNodes, since the rule are declared match(PrefetchAllocation mem), they become Type::BOTTOM, but their inputs and outputs are still abio or memory nodes, hence the unsoundness.

With the PR, at least when AllocatePrefetchStyle != 3, they preserve their correct type after matching. For AllocatePrefetchStyle == 3, it is more difficult, because memory nodes participate in anti-dependency computations, so we need to make further modifications to ensure that a PrefetchAllocationNode has a control input, and they act as a full store (its anti-dependencies do not need computing).

I filed JDK-8382547.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks!

fprintf(fp_cpp, "%s node->_bottom_type = Type::ABIO;\n", indent);
} else {
fprintf(fp_cpp, "%s node->_bottom_type = _leaf->bottom_type();\n", indent);
}

if( inst->is_ideal_if() ) {
fprintf(fp_cpp, "%s node->_prob = _leaf->as_If()->_prob;\n", indent);
fprintf(fp_cpp, "%s node->_fcnt = _leaf->as_If()->_fcnt;\n", indent);
Expand Down Expand Up @@ -4026,10 +4022,8 @@ void InstructForm::define_cisc_version(ArchDesc& AD, FILE* fp_cpp) {
fprintf(fp_cpp, "MachNode *%sNode::cisc_version(int offset) {\n", this->_ident);
// Create the MachNode object
fprintf(fp_cpp, " %sNode *node = new %sNode();\n", name, name);
// Fill in the bottom_type where requested
if ( this->captures_bottom_type(AD.globalNames()) ) {
fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n");
}
// Fill in the bottom_type
fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n");

uint cur_num_opnds = num_opnds();
if (cur_num_opnds > 1 && cur_num_opnds != num_unique_opnds()) {
Expand Down Expand Up @@ -4075,10 +4069,9 @@ void InstructForm::define_short_branch_methods(ArchDesc& AD, FILE* fp_cpp) {
fprintf(fp_cpp, " node->_prob = _prob;\n");
fprintf(fp_cpp, " node->_fcnt = _fcnt;\n");
}
// Fill in the bottom_type where requested
if ( this->captures_bottom_type(AD.globalNames()) ) {
fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n");
}

// Fill in the bottom_type
fprintf(fp_cpp, " node->_bottom_type = bottom_type();\n");

fprintf(fp_cpp, "\n");
// Short branch version must use same node index for access
Expand Down
108 changes: 1 addition & 107 deletions src/hotspot/share/adlc/output_h.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2026, 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
Expand Down Expand Up @@ -1841,112 +1841,6 @@ void ArchDesc::declareClasses(FILE *fp) {
fprintf(fp," virtual const Pipeline *pipeline() const;\n");
}

// Generate virtual function for MachNodeX::bottom_type when necessary
//
// Note on accuracy: Pointer-types of machine nodes need to be accurate,
// or else alias analysis on the matched graph may produce bad code.
// Moreover, the aliasing decisions made on machine-node graph must be
// no less accurate than those made on the ideal graph, or else the graph
// may fail to schedule. (Reason: Memory ops which are reordered in
// the ideal graph might look interdependent in the machine graph,
// thereby removing degrees of scheduling freedom that the optimizer
// assumed would be available.)
//
// %%% We should handle many of these cases with an explicit ADL clause:
// instruct foo() %{ ... bottom_type(TypeRawPtr::BOTTOM); ... %}
if( data_type != Form::none ) {
// A constant's bottom_type returns a Type containing its constant value

// !!!!!
// Convert all ints, floats, ... to machine-independent TypeXs
// as is done for pointers
//
// Construct appropriate constant type containing the constant value.
fprintf(fp," virtual const class Type *bottom_type() const {\n");
switch( data_type ) {
case Form::idealI:
fprintf(fp," return TypeInt::make(opnd_array(1)->constant());\n");
break;
case Form::idealP:
case Form::idealN:
case Form::idealNKlass:
fprintf(fp," return opnd_array(1)->type();\n");
break;
case Form::idealD:
fprintf(fp," return TypeD::make(opnd_array(1)->constantD());\n");
break;
case Form::idealH:
fprintf(fp," return TypeH::make(opnd_array(1)->constantH());\n");
break;
case Form::idealF:
fprintf(fp," return TypeF::make(opnd_array(1)->constantF());\n");
break;
case Form::idealL:
fprintf(fp," return TypeLong::make(opnd_array(1)->constantL());\n");
break;
default:
assert( false, "Unimplemented()" );
break;
}
fprintf(fp," };\n");
}
/* else if ( instr->_matrule && instr->_matrule->_rChild &&
( strcmp("ConvF2I",instr->_matrule->_rChild->_opType)==0
|| strcmp("ConvD2I",instr->_matrule->_rChild->_opType)==0 ) ) {
// !!!!! !!!!!
// Provide explicit bottom type for conversions to int
// On Intel the result operand is a stackSlot, untyped.
fprintf(fp," virtual const class Type *bottom_type() const {");
fprintf(fp, " return TypeInt::INT;");
fprintf(fp, " };\n");
}*/
else if( instr->is_ideal_copy() &&
!strcmp(instr->_matrule->_lChild->_opType,"stackSlotP") ) {
// !!!!!
// Special hack for ideal Copy of pointer. Bottom type is oop or not depending on input.
fprintf(fp," const Type *bottom_type() const { return in(1)->bottom_type(); } // Copy?\n");
}
else if( instr->is_ideal_loadPC() ) {
// LoadPCNode provides the return address of a call to native code.
// Define its bottom type to be TypeRawPtr::BOTTOM instead of TypePtr::BOTTOM
// since it is a pointer to an internal VM location and must have a zero offset.
// Allocation detects derived pointers, in part, by their non-zero offsets.
fprintf(fp," const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } // LoadPC?\n");
}
else if( instr->is_ideal_box() ) {
// BoxNode provides the address of a stack slot.
// Define its bottom type to be TypeRawPtr::BOTTOM instead of TypePtr::BOTTOM
// This prevents raise_above_anti_dependences from complaining. It will
// complain if it sees that the pointer base is TypePtr::BOTTOM since
// it doesn't understand what that might alias.
fprintf(fp," const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } // Box?\n");
}
else if (instr->_matrule && instr->_matrule->_rChild &&
(!strcmp(instr->_matrule->_rChild->_opType,"CMoveP") || !strcmp(instr->_matrule->_rChild->_opType,"CMoveN")) ) {
int offset = 1;
// Special special hack to see if the Cmp? has been incorporated in the conditional move
MatchNode *rl = instr->_matrule->_rChild->_lChild;
if (rl && !strcmp(rl->_opType, "Binary") && rl->_rChild && strncmp(rl->_rChild->_opType, "Cmp", 3) == 0) {
offset = 2;
fprintf(fp," const Type *bottom_type() const { if (req() == 3) return in(2)->bottom_type();\n\tconst Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // %s\n",
offset, offset+1, offset+1, instr->_matrule->_rChild->_opType);
} else {
// Special hack for ideal CMove; ideal type depends on inputs
fprintf(fp," const Type *bottom_type() const { const Type *t = in(oper_input_base()+%d)->bottom_type(); return (req() <= oper_input_base()+%d) ? t : t->meet(in(oper_input_base()+%d)->bottom_type()); } // %s\n",
offset, offset+1, offset+1, instr->_matrule->_rChild->_opType);
}
}
else if (instr->is_tls_instruction()) {
// Special hack for tlsLoadP
fprintf(fp," const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } // tlsLoadP\n");
}
else if ( instr->is_ideal_if() ) {
fprintf(fp," const Type *bottom_type() const { return TypeTuple::IFBOTH; } // matched IfNode\n");
}
else if ( instr->is_ideal_membar() ) {
fprintf(fp," const Type *bottom_type() const { return TypeTuple::MEMBAR; } // matched MemBar\n");
}

// Check where 'ideal_type' must be customized
/*
if ( instr->_matrule && instr->_matrule->_rChild &&
Expand Down
Loading