Skip to content

Commit f7f3447

Browse files
committedNov 18, 2020
8256453: C2: Reduce State footprint
Reviewed-by: neliasso, kvn
1 parent d2ddf07 commit f7f3447

File tree

3 files changed

+74
-93
lines changed

3 files changed

+74
-93
lines changed
 

‎src/hotspot/share/adlc/dfa.cpp

+11-27
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,6 @@
2929
static bool debug_output = false;
3030
static bool debug_output1 = false; // top level chain rules
3131

32-
//---------------------------Access to internals of class State----------------
33-
static const char *sLeft = "_kids[0]";
34-
static const char *sRight = "_kids[1]";
35-
36-
//---------------------------DFA productions-----------------------------------
37-
static const char *dfa_production = "DFA_PRODUCTION";
38-
static const char *dfa_production_set_valid = "DFA_PRODUCTION__SET_VALID";
39-
4032
//---------------------------Production State----------------------------------
4133
static const char *knownInvalid = "knownInvalid"; // The result does NOT have a rule defined
4234
static const char *knownValid = "knownValid"; // The result must be produced by a rule
@@ -111,7 +103,7 @@ class ProductionState {
111103
//---------------------------Helper Functions----------------------------------
112104
// cost_check template:
113105
// 1) if (STATE__NOT_YET_VALID(EBXREGI) || _cost[EBXREGI] > c) {
114-
// 2) DFA_PRODUCTION__SET_VALID(EBXREGI, cmovI_memu_rule, c)
106+
// 2) DFA_PRODUCTION(EBXREGI, cmovI_memu_rule, c)
115107
// 3) }
116108
//
117109
static void cost_check(FILE *fp, const char *spaces,
@@ -162,13 +154,13 @@ static void cost_check(FILE *fp, const char *spaces,
162154
}
163155

164156
// line 2)
165-
// no need to set State vector if our state is knownValid
166-
const char *production = (validity_check == knownValid) ? dfa_production : dfa_production_set_valid;
167-
fprintf(fp, "%s %s(%s, %s_rule, %s)", spaces, production, arrayIdx, rule, cost->as_string() );
168-
if( validity_check == knownValid ) {
169-
if( cost_is_below_lower_bound ) { fprintf(fp, "\t // overwrites higher cost rule"); }
170-
}
171-
fprintf(fp, "\n");
157+
fprintf(fp, "%s DFA_PRODUCTION(%s, %s_rule, %s)", spaces, arrayIdx, rule, cost->as_string() );
158+
if (validity_check == knownValid) {
159+
if (cost_is_below_lower_bound) {
160+
fprintf(fp, "\t // overwrites higher cost rule");
161+
}
162+
}
163+
fprintf(fp, "\n");
172164

173165
// line 3)
174166
if( cost_check || state_check ) {
@@ -276,7 +268,7 @@ void ArchDesc::gen_match(FILE *fp, MatchList &mList, ProductionState &status, Di
276268

277269
// Check if this rule should be used to generate the chains as well.
278270
const char *rule = /* set rule to "Invalid" for internal operands */
279-
strcmp(mList._opcode,mList._resultStr) ? mList._opcode : "Invalid";
271+
strcmp(mList._opcode, mList._resultStr) ? mList._opcode : "Invalid";
280272

281273
// If this rule produces an operand which has associated chain rules,
282274
// update the operands with the chain rule + this rule cost & this rule.
@@ -396,16 +388,8 @@ void ArchDesc::buildDFA(FILE* fp) {
396388
_attributes.output(fp);
397389
fprintf(fp, "\n");
398390
fprintf(fp, "//------------------------- Macros -----------------------------------------\n");
399-
// #define DFA_PRODUCTION(result, rule, cost)\
400-
// _cost[ (result) ] = cost; _rule[ (result) ] = rule;
401-
fprintf(fp, "#define %s(result, rule, cost)\\\n", dfa_production);
402-
fprintf(fp, " _cost[ (result) ] = cost; _rule[ (result) ] = rule;\n");
403-
fprintf(fp, "\n");
404-
405-
// #define DFA_PRODUCTION__SET_VALID(result, rule, cost)\
406-
// DFA_PRODUCTION( (result), (rule), (cost) ); STATE__SET_VALID( (result) );
407-
fprintf(fp, "#define %s(result, rule, cost)\\\n", dfa_production_set_valid);
408-
fprintf(fp, " %s( (result), (rule), (cost) ); STATE__SET_VALID( (result) );\n", dfa_production);
391+
fprintf(fp, "#define DFA_PRODUCTION(result, rule, cost)\\\n");
392+
fprintf(fp, " assert(rule < (1 << 15), \"too many rules\"); _cost[ (result) ] = cost; _rule[ (result) ] = (rule << 1) | 0x1;\n");
409393
fprintf(fp, "\n");
410394

411395
fprintf(fp, "//------------------------- DFA --------------------------------------------\n");

‎src/hotspot/share/adlc/output_h.cpp

+17-24
Original file line numberDiff line numberDiff line change
@@ -2012,26 +2012,17 @@ void ArchDesc::declareClasses(FILE *fp) {
20122012
}
20132013

20142014
void ArchDesc::defineStateClass(FILE *fp) {
2015-
static const char *state__valid = "_valid[((uint)index) >> 5] & (0x1 << (((uint)index) & 0x0001F))";
2016-
static const char *state__set_valid= "_valid[((uint)index) >> 5] |= (0x1 << (((uint)index) & 0x0001F))";
2015+
static const char *state__valid = "_rule[index] & 0x1";
20172016

20182017
fprintf(fp,"\n");
20192018
fprintf(fp,"// MACROS to inline and constant fold State::valid(index)...\n");
20202019
fprintf(fp,"// when given a constant 'index' in dfa_<arch>.cpp\n");
2021-
fprintf(fp,"// uint word = index >> 5; // Shift out bit position\n");
2022-
fprintf(fp,"// uint bitpos = index & 0x0001F; // Mask off word bits\n");
2023-
fprintf(fp,"#define STATE__VALID(index) ");
2024-
fprintf(fp," (%s)\n", state__valid);
2025-
fprintf(fp,"\n");
20262020
fprintf(fp,"#define STATE__NOT_YET_VALID(index) ");
20272021
fprintf(fp," ( (%s) == 0 )\n", state__valid);
20282022
fprintf(fp,"\n");
20292023
fprintf(fp,"#define STATE__VALID_CHILD(state,index) ");
20302024
fprintf(fp," ( state && (state->%s) )\n", state__valid);
20312025
fprintf(fp,"\n");
2032-
fprintf(fp,"#define STATE__SET_VALID(index) ");
2033-
fprintf(fp," (%s)\n", state__set_valid);
2034-
fprintf(fp,"\n");
20352026
fprintf(fp,
20362027
"//---------------------------State-------------------------------------------\n");
20372028
fprintf(fp,"// State contains an integral cost vector, indexed by machine operand opcodes,\n");
@@ -2040,16 +2031,18 @@ void ArchDesc::defineStateClass(FILE *fp) {
20402031
fprintf(fp,"// tree generated by the Label routines in ideal nodes (currently limited to\n");
20412032
fprintf(fp,"// two for convenience, but this could change).\n");
20422033
fprintf(fp,"class State : public ResourceObj {\n");
2034+
fprintf(fp,"private:\n");
2035+
fprintf(fp," unsigned int _cost[_LAST_MACH_OPER]; // Costs, indexed by operand opcodes\n");
2036+
fprintf(fp," uint16_t _rule[_LAST_MACH_OPER]; // Rule and validity, indexed by operand opcodes\n");
2037+
fprintf(fp," // Lowest bit encodes validity\n");
2038+
20432039
fprintf(fp,"public:\n");
2044-
fprintf(fp," int _id; // State identifier\n");
2045-
fprintf(fp," Node *_leaf; // Ideal (non-machine-node) leaf of match tree\n");
2046-
fprintf(fp," State *_kids[2]; // Children of state node in label tree\n");
2047-
fprintf(fp," unsigned int _cost[_LAST_MACH_OPER]; // Cost vector, indexed by operand opcodes\n");
2048-
fprintf(fp," unsigned int _rule[_LAST_MACH_OPER]; // Rule vector, indexed by operand opcodes\n");
2049-
fprintf(fp," unsigned int _valid[(_LAST_MACH_OPER/32)+1]; // Bit Map of valid Cost/Rule entries\n");
2040+
fprintf(fp," int _id; // State identifier\n");
2041+
fprintf(fp," Node *_leaf; // Ideal (non-machine-node) leaf of match tree\n");
2042+
fprintf(fp," State *_kids[2]; // Children of state node in label tree\n");
20502043
fprintf(fp,"\n");
2051-
fprintf(fp," State(void); // Constructor\n");
2052-
fprintf(fp," DEBUG_ONLY( ~State(void); ) // Destructor\n");
2044+
fprintf(fp," State(void);\n");
2045+
fprintf(fp," DEBUG_ONLY( ~State(void); )\n");
20532046
fprintf(fp,"\n");
20542047
fprintf(fp," // Methods created by ADLC and invoked by Reduce\n");
20552048
fprintf(fp," MachOper *MachOperGenerator(int opcode);\n");
@@ -2058,14 +2051,14 @@ void ArchDesc::defineStateClass(FILE *fp) {
20582051
fprintf(fp," // Assign a state to a node, definition of method produced by ADLC\n");
20592052
fprintf(fp," bool DFA( int opcode, const Node *ideal );\n");
20602053
fprintf(fp,"\n");
2061-
fprintf(fp," // Access function for _valid bit vector\n");
20622054
fprintf(fp," bool valid(uint index) {\n");
2063-
fprintf(fp," return( STATE__VALID(index) != 0 );\n");
2055+
fprintf(fp," return %s;\n", state__valid);
20642056
fprintf(fp," }\n");
2065-
fprintf(fp,"\n");
2066-
fprintf(fp," // Set function for _valid bit vector\n");
2067-
fprintf(fp," void set_valid(uint index) {\n");
2068-
fprintf(fp," STATE__SET_VALID(index);\n");
2057+
fprintf(fp," unsigned int rule(uint index) {\n");
2058+
fprintf(fp," return _rule[index] >> 1;\n");
2059+
fprintf(fp," }\n");
2060+
fprintf(fp," unsigned int cost(uint index) {\n");
2061+
fprintf(fp," return _cost[index];\n");
20692062
fprintf(fp," }\n");
20702063
fprintf(fp,"\n");
20712064
fprintf(fp,"#ifndef PRODUCT\n");

‎src/hotspot/share/opto/matcher.cpp

+46-42
Original file line numberDiff line numberDiff line change
@@ -1453,11 +1453,13 @@ MachNode *Matcher::match_tree( const Node *n ) {
14531453
uint mincost = max_juint;
14541454
uint cost = max_juint;
14551455
uint i;
1456-
for( i = 0; i < NUM_OPERANDS; i++ ) {
1457-
if( s->valid(i) && // valid entry and
1458-
s->_cost[i] < cost && // low cost and
1459-
s->_rule[i] >= NUM_OPERANDS ) // not an operand
1460-
cost = s->_cost[mincost=i];
1456+
for (i = 0; i < NUM_OPERANDS; i++) {
1457+
if (s->valid(i) && // valid entry and
1458+
s->cost(i) < cost && // low cost and
1459+
s->rule(i) >= NUM_OPERANDS) {// not an operand
1460+
mincost = i;
1461+
cost = s->cost(i);
1462+
}
14611463
}
14621464
if (mincost == max_juint) {
14631465
#ifndef PRODUCT
@@ -1468,7 +1470,7 @@ MachNode *Matcher::match_tree( const Node *n ) {
14681470
return NULL;
14691471
}
14701472
// Reduce input tree based upon the state labels to machine Nodes
1471-
MachNode *m = ReduceInst( s, s->_rule[mincost], mem );
1473+
MachNode *m = ReduceInst(s, s->rule(mincost), mem);
14721474
#ifdef ASSERT
14731475
_old2new_map.map(n->_idx, m);
14741476
_new2old_map.map(m->_idx, (Node*)n);
@@ -1836,29 +1838,28 @@ void Matcher::handle_precedence_edges(Node* n, MachNode *mach) {
18361838
}
18371839
}
18381840

1839-
void Matcher::ReduceInst_Chain_Rule( State *s, int rule, Node *&mem, MachNode *mach ) {
1841+
void Matcher::ReduceInst_Chain_Rule(State* s, int rule, Node* &mem, MachNode* mach) {
18401842
// 'op' is what I am expecting to receive
18411843
int op = _leftOp[rule];
18421844
// Operand type to catch childs result
18431845
// This is what my child will give me.
1844-
int opnd_class_instance = s->_rule[op];
1846+
unsigned int opnd_class_instance = s->rule(op);
18451847
// Choose between operand class or not.
18461848
// This is what I will receive.
18471849
int catch_op = (FIRST_OPERAND_CLASS <= op && op < NUM_OPERANDS) ? opnd_class_instance : op;
18481850
// New rule for child. Chase operand classes to get the actual rule.
1849-
int newrule = s->_rule[catch_op];
1851+
unsigned int newrule = s->rule(catch_op);
18501852

1851-
if( newrule < NUM_OPERANDS ) {
1853+
if (newrule < NUM_OPERANDS) {
18521854
// Chain from operand or operand class, may be output of shared node
1853-
assert( 0 <= opnd_class_instance && opnd_class_instance < NUM_OPERANDS,
1854-
"Bad AD file: Instruction chain rule must chain from operand");
1855+
assert(opnd_class_instance < NUM_OPERANDS, "Bad AD file: Instruction chain rule must chain from operand");
18551856
// Insert operand into array of operands for this instruction
18561857
mach->_opnds[1] = s->MachOperGenerator(opnd_class_instance);
18571858

1858-
ReduceOper( s, newrule, mem, mach );
1859+
ReduceOper(s, newrule, mem, mach);
18591860
} else {
18601861
// Chain from the result of an instruction
1861-
assert( newrule >= _LAST_MACH_OPER, "Do NOT chain from internal operand");
1862+
assert(newrule >= _LAST_MACH_OPER, "Do NOT chain from internal operand");
18621863
mach->_opnds[1] = s->MachOperGenerator(_reduceOp[catch_op]);
18631864
Node *mem1 = (Node*)1;
18641865
debug_only(Node *save_mem_node = _mem_node;)
@@ -1896,24 +1897,24 @@ uint Matcher::ReduceInst_Interior( State *s, int rule, Node *&mem, MachNode *mac
18961897
}
18971898
// Operand type to catch childs result
18981899
// This is what my child will give me.
1899-
int opnd_class_instance = newstate->_rule[op];
1900+
int opnd_class_instance = newstate->rule(op);
19001901
// Choose between operand class or not.
19011902
// This is what I will receive.
19021903
int catch_op = (op >= FIRST_OPERAND_CLASS && op < NUM_OPERANDS) ? opnd_class_instance : op;
19031904
// New rule for child. Chase operand classes to get the actual rule.
1904-
int newrule = newstate->_rule[catch_op];
1905+
int newrule = newstate->rule(catch_op);
19051906

1906-
if( newrule < NUM_OPERANDS ) { // Operand/operandClass or internalOp/instruction?
1907+
if (newrule < NUM_OPERANDS) { // Operand/operandClass or internalOp/instruction?
19071908
// Operand/operandClass
19081909
// Insert operand into array of operands for this instruction
19091910
mach->_opnds[num_opnds++] = newstate->MachOperGenerator(opnd_class_instance);
1910-
ReduceOper( newstate, newrule, mem, mach );
1911+
ReduceOper(newstate, newrule, mem, mach);
19111912

19121913
} else { // Child is internal operand or new instruction
1913-
if( newrule < _LAST_MACH_OPER ) { // internal operand or instruction?
1914+
if (newrule < _LAST_MACH_OPER) { // internal operand or instruction?
19141915
// internal operand --> call ReduceInst_Interior
19151916
// Interior of complex instruction. Do nothing but recurse.
1916-
num_opnds = ReduceInst_Interior( newstate, newrule, mem, mach, num_opnds );
1917+
num_opnds = ReduceInst_Interior(newstate, newrule, mem, mach, num_opnds);
19171918
} else {
19181919
// instruction --> call build operand( ) to catch result
19191920
// --> ReduceInst( newrule )
@@ -1965,16 +1966,17 @@ void Matcher::ReduceOper( State *s, int rule, Node *&mem, MachNode *mach ) {
19651966
}
19661967
}
19671968

1968-
for( uint i=0; kid != NULL && i<2; kid = s->_kids[1], i++ ) { // binary tree
1969+
for (uint i = 0; kid != NULL && i < 2; kid = s->_kids[1], i++) { // binary tree
19691970
int newrule;
1970-
if( i == 0)
1971-
newrule = kid->_rule[_leftOp[rule]];
1972-
else
1973-
newrule = kid->_rule[_rightOp[rule]];
1971+
if( i == 0) {
1972+
newrule = kid->rule(_leftOp[rule]);
1973+
} else {
1974+
newrule = kid->rule(_rightOp[rule]);
1975+
}
19741976

1975-
if( newrule < _LAST_MACH_OPER ) { // Operand or instruction?
1977+
if (newrule < _LAST_MACH_OPER) { // Operand or instruction?
19761978
// Internal operand; recurse but do nothing else
1977-
ReduceOper( kid, newrule, mem, mach );
1979+
ReduceOper(kid, newrule, mem, mach);
19781980

19791981
} else { // Child is a new instruction
19801982
// Reduce the instruction, and add a direct pointer from this
@@ -2808,15 +2810,12 @@ bool Matcher::branches_to_uncommon_trap(const Node *n) {
28082810

28092811
//=============================================================================
28102812
//---------------------------State---------------------------------------------
2811-
State::State(void) {
2813+
State::State(void) : _rule() {
28122814
#ifdef ASSERT
28132815
_id = 0;
28142816
_kids[0] = _kids[1] = (State*)(intptr_t) CONST64(0xcafebabecafebabe);
28152817
_leaf = (Node*)(intptr_t) CONST64(0xbaadf00dbaadf00d);
2816-
//memset(_cost, -1, sizeof(_cost));
2817-
//memset(_rule, -1, sizeof(_rule));
28182818
#endif
2819-
memset(_valid, 0, sizeof(_valid));
28202819
}
28212820

28222821
#ifdef ASSERT
@@ -2837,25 +2836,30 @@ void State::dump() {
28372836
}
28382837

28392838
void State::dump(int depth) {
2840-
for( int j = 0; j < depth; j++ )
2839+
for (int j = 0; j < depth; j++) {
28412840
tty->print(" ");
2841+
}
28422842
tty->print("--N: ");
28432843
_leaf->dump();
28442844
uint i;
2845-
for( i = 0; i < _LAST_MACH_OPER; i++ )
2845+
for (i = 0; i < _LAST_MACH_OPER; i++) {
28462846
// Check for valid entry
2847-
if( valid(i) ) {
2848-
for( int j = 0; j < depth; j++ )
2847+
if (valid(i)) {
2848+
for (int j = 0; j < depth; j++) {
28492849
tty->print(" ");
2850-
assert(_cost[i] != max_juint, "cost must be a valid value");
2851-
assert(_rule[i] < _last_Mach_Node, "rule[i] must be valid rule");
2852-
tty->print_cr("%s %d %s",
2853-
ruleName[i], _cost[i], ruleName[_rule[i]] );
28542850
}
2851+
assert(cost(i) != max_juint, "cost must be a valid value");
2852+
assert(rule(i) < _last_Mach_Node, "rule[i] must be valid rule");
2853+
tty->print_cr("%s %d %s",
2854+
ruleName[i], cost(i), ruleName[rule(i)] );
2855+
}
2856+
}
28552857
tty->cr();
28562858

2857-
for( i=0; i<2; i++ )
2858-
if( _kids[i] )
2859-
_kids[i]->dump(depth+1);
2859+
for (i = 0; i < 2; i++) {
2860+
if (_kids[i]) {
2861+
_kids[i]->dump(depth + 1);
2862+
}
2863+
}
28602864
}
28612865
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.