8306922: IR verification fails because IR dump is chopped up

Reviewed-by: chagedorn, thartmann
This commit is contained in:
Emanuel Peter 2023-06-26 06:11:32 +00:00
parent 8242c647b9
commit 9057b35033
8 changed files with 169 additions and 149 deletions

View File

@ -551,28 +551,37 @@ void Compile::print_compile_messages() {
#ifndef PRODUCT
void Compile::print_ideal_ir(const char* phase_name) {
ttyLocker ttyl;
// keep the following output all in one block
// This output goes directly to the tty, not the compiler log.
// To enable tools to match it up with the compilation activity,
// be sure to tag this tty output with the compile ID.
// Node dumping can cause a safepoint, which can break the tty lock.
// Buffer all node dumps, so that all safepoints happen before we lock.
ResourceMark rm;
stringStream ss;
if (_output == nullptr) {
ss.print_cr("AFTER: %s", phase_name);
// Print out all nodes in ascending order of index.
root()->dump_bfs(MaxNodeLimit, nullptr, "+S$", &ss);
} else {
// Dump the node blockwise if we have a scheduling
_output->print_scheduling(&ss);
}
// Check that the lock is not broken by a safepoint.
NoSafepointVerifier nsv;
ttyLocker ttyl;
if (xtty != nullptr) {
xtty->head("ideal compile_id='%d'%s compile_phase='%s'",
compile_id(),
is_osr_compilation() ? " compile_kind='osr'" : "",
phase_name);
}
if (_output == nullptr) {
tty->print_cr("AFTER: %s", phase_name);
// Print out all nodes in ascending order of index.
root()->dump_bfs(MaxNodeLimit, nullptr, "+S$");
} else {
// Dump the node blockwise if we have a scheduling
_output->print_scheduling();
}
if (xtty != nullptr) {
xtty->print("%s", ss.as_string()); // print to tty would use xml escape encoding
xtty->tail("ideal");
} else {
tty->print("%s", ss.as_string());
}
}
#endif
@ -4980,8 +4989,8 @@ bool Compile::randomized_select(int count) {
CloneMap& Compile::clone_map() { return _clone_map; }
void Compile::set_clone_map(Dict* d) { _clone_map._dict = d; }
void NodeCloneInfo::dump() const {
tty->print(" {%d:%d} ", idx(), gen());
void NodeCloneInfo::dump_on(outputStream* st) const {
st->print(" {%d:%d} ", idx(), gen());
}
void CloneMap::clone(Node* old, Node* nnn, int gen) {
@ -5028,11 +5037,11 @@ int CloneMap::max_gen() const {
return g;
}
void CloneMap::dump(node_idx_t key) const {
void CloneMap::dump(node_idx_t key, outputStream* st) const {
uint64_t val = value(key);
if (val != 0) {
NodeCloneInfo ni(val);
ni.dump();
ni.dump_on(st);
}
}

View File

@ -135,7 +135,7 @@ class NodeCloneInfo {
NodeCloneInfo(uint64_t idx_clone_orig) : _idx_clone_orig(idx_clone_orig) {}
NodeCloneInfo(node_idx_t x, int g) : _idx_clone_orig(0) { set(x, g); }
void dump() const;
void dump_on(outputStream* st) const;
};
class CloneMap {
@ -158,7 +158,7 @@ class CloneMap {
int max_gen() const;
void clone(Node* old, Node* nnn, int gen);
void verify_insert_and_clone(Node* old, Node* nnn, int gen);
void dump(node_idx_t key) const;
void dump(node_idx_t key, outputStream* st) const;
int clone_idx() const { return _clone_idx; }
void set_clone_idx(int x) { _clone_idx = x; }

View File

@ -1759,8 +1759,8 @@ Node* Node::find(const int idx, bool only_ctrl) {
class PrintBFS {
public:
PrintBFS(const Node* start, const int max_distance, const Node* target, const char* options)
: _start(start), _max_distance(max_distance), _target(target), _options(options),
PrintBFS(const Node* start, const int max_distance, const Node* target, const char* options, outputStream* st)
: _start(start), _max_distance(max_distance), _target(target), _options(options), _output(st),
_dcc(this), _info_uid(cmpkey, hashkey) {}
void run();
@ -1780,6 +1780,7 @@ private:
const int _max_distance;
const Node* _target;
const char* _options;
outputStream* _output;
// options
bool _traverse_inputs = false;
@ -1819,7 +1820,7 @@ private:
bool _print_blocks = false;
bool _print_old = false;
bool _dump_only = false;
static void print_options_help(bool print_examples);
void print_options_help(bool print_examples);
bool parse_options();
public:
@ -1836,9 +1837,9 @@ private:
// node info
static Node* old_node(const Node* n); // mach node -> prior IR node
static void print_node_idx(const Node* n); // to tty
static void print_block_id(const Block* b); // to tty
static void print_node_block(const Node* n); // to tty: _pre_order, head idx, _idom, _dom_depth
void print_node_idx(const Node* n);
void print_block_id(const Block* b);
void print_node_block(const Node* n); // _pre_order, head idx, _idom, _dom_depth
// traversal data structures
GrowableArray<const Node*> _worklist; // BFS queue
@ -1903,7 +1904,7 @@ void PrintBFS::run() {
// set up configuration for BFS and print
bool PrintBFS::configure() {
if (_max_distance < 0) {
tty->print("dump_bfs: max_distance must be non-negative!\n");
_output->print_cr("dump_bfs: max_distance must be non-negative!");
return false;
}
return parse_options();
@ -1941,7 +1942,7 @@ void PrintBFS::select() {
select_all();
} else {
if (find_info(_target) == nullptr) {
tty->print("Could not find target in BFS.\n");
_output->print_cr("Could not find target in BFS.");
return;
}
if (_all_paths) {
@ -2037,96 +2038,96 @@ void PrintBFS::print() {
print_node(n);
}
} else {
tty->print("No nodes to print.\n");
_output->print_cr("No nodes to print.");
}
}
void PrintBFS::print_options_help(bool print_examples) {
tty->print("Usage: node->dump_bfs(int max_distance, Node* target, char* options)\n");
tty->print("\n");
tty->print("Use cases:\n");
tty->print(" BFS traversal: no target required\n");
tty->print(" shortest path: set target\n");
tty->print(" all paths: set target and put 'A' in options\n");
tty->print(" detect loop: subcase of all paths, have start==target\n");
tty->print("\n");
tty->print("Arguments:\n");
tty->print(" this/start: staring point of BFS\n");
tty->print(" target:\n");
tty->print(" if null: simple BFS\n");
tty->print(" else: shortest path or all paths between this/start and target\n");
tty->print(" options:\n");
tty->print(" if null: same as \"cdmox@B\"\n");
tty->print(" else: use combination of following characters\n");
tty->print(" h: display this help info\n");
tty->print(" H: display this help info, with examples\n");
tty->print(" +: traverse in-edges (on if neither + nor -)\n");
tty->print(" -: traverse out-edges\n");
tty->print(" c: visit control nodes\n");
tty->print(" d: visit data nodes\n");
tty->print(" m: visit memory nodes\n");
tty->print(" o: visit other nodes\n");
tty->print(" x: visit mixed nodes\n");
tty->print(" C: boundary control nodes\n");
tty->print(" D: boundary data nodes\n");
tty->print(" M: boundary memory nodes\n");
tty->print(" O: boundary other nodes\n");
tty->print(" X: boundary mixed nodes\n");
tty->print(" #: display node category in color (not supported in all terminals)\n");
tty->print(" S: sort displayed nodes by node idx\n");
tty->print(" A: all paths (not just shortest path to target)\n");
tty->print(" @: print old nodes - before matching (if available)\n");
tty->print(" B: print scheduling blocks (if available)\n");
tty->print(" $: dump only, no header, no other columns\n");
tty->print("\n");
tty->print("recursively follow edges to nodes with permitted visit types,\n");
tty->print("on the boundary additionally display nodes allowed in boundary types\n");
tty->print("Note: the categories can be overlapping. For example a mixed node\n");
tty->print(" can contain control and memory output. Some from the other\n");
tty->print(" category are also control (Halt, Return, etc).\n");
tty->print("\n");
tty->print("output columns:\n");
tty->print(" dist: BFS distance to this/start\n");
tty->print(" apd: all paths distance (d_start + d_target)\n");
tty->print(" block: block identifier, based on _pre_order\n");
tty->print(" head: first node in block\n");
tty->print(" idom: head node of idom block\n");
tty->print(" depth: depth of block (_dom_depth)\n");
tty->print(" old: old IR node - before matching\n");
tty->print(" dump: node->dump()\n");
tty->print("\n");
tty->print("Note: if none of the \"cmdxo\" characters are in the options string\n");
tty->print(" then we set all of them.\n");
tty->print(" This allows for short strings like \"#\" for colored input traversal\n");
tty->print(" or \"-#\" for colored output traversal.\n");
_output->print_cr("Usage: node->dump_bfs(int max_distance, Node* target, char* options)");
_output->print_cr("");
_output->print_cr("Use cases:");
_output->print_cr(" BFS traversal: no target required");
_output->print_cr(" shortest path: set target");
_output->print_cr(" all paths: set target and put 'A' in options");
_output->print_cr(" detect loop: subcase of all paths, have start==target");
_output->print_cr("");
_output->print_cr("Arguments:");
_output->print_cr(" this/start: staring point of BFS");
_output->print_cr(" target:");
_output->print_cr(" if null: simple BFS");
_output->print_cr(" else: shortest path or all paths between this/start and target");
_output->print_cr(" options:");
_output->print_cr(" if null: same as \"cdmox@B\"");
_output->print_cr(" else: use combination of following characters");
_output->print_cr(" h: display this help info");
_output->print_cr(" H: display this help info, with examples");
_output->print_cr(" +: traverse in-edges (on if neither + nor -)");
_output->print_cr(" -: traverse out-edges");
_output->print_cr(" c: visit control nodes");
_output->print_cr(" d: visit data nodes");
_output->print_cr(" m: visit memory nodes");
_output->print_cr(" o: visit other nodes");
_output->print_cr(" x: visit mixed nodes");
_output->print_cr(" C: boundary control nodes");
_output->print_cr(" D: boundary data nodes");
_output->print_cr(" M: boundary memory nodes");
_output->print_cr(" O: boundary other nodes");
_output->print_cr(" X: boundary mixed nodes");
_output->print_cr(" #: display node category in color (not supported in all terminals)");
_output->print_cr(" S: sort displayed nodes by node idx");
_output->print_cr(" A: all paths (not just shortest path to target)");
_output->print_cr(" @: print old nodes - before matching (if available)");
_output->print_cr(" B: print scheduling blocks (if available)");
_output->print_cr(" $: dump only, no header, no other columns");
_output->print_cr("");
_output->print_cr("recursively follow edges to nodes with permitted visit types,");
_output->print_cr("on the boundary additionally display nodes allowed in boundary types");
_output->print_cr("Note: the categories can be overlapping. For example a mixed node");
_output->print_cr(" can contain control and memory output. Some from the other");
_output->print_cr(" category are also control (Halt, Return, etc).");
_output->print_cr("");
_output->print_cr("output columns:");
_output->print_cr(" dist: BFS distance to this/start");
_output->print_cr(" apd: all paths distance (d_outputart + d_target)");
_output->print_cr(" block: block identifier, based on _pre_order");
_output->print_cr(" head: first node in block");
_output->print_cr(" idom: head node of idom block");
_output->print_cr(" depth: depth of block (_dom_depth)");
_output->print_cr(" old: old IR node - before matching");
_output->print_cr(" dump: node->dump()");
_output->print_cr("");
_output->print_cr("Note: if none of the \"cmdxo\" characters are in the options string");
_output->print_cr(" then we set all of them.");
_output->print_cr(" This allows for short strings like \"#\" for colored input traversal");
_output->print_cr(" or \"-#\" for colored output traversal.");
if (print_examples) {
tty->print("\n");
tty->print("Examples:\n");
tty->print(" if->dump_bfs(10, 0, \"+cxo\")\n");
tty->print(" starting at some if node, traverse inputs recursively\n");
tty->print(" only along control (mixed and other can also be control)\n");
tty->print(" phi->dump_bfs(5, 0, \"-dxo\")\n");
tty->print(" starting at phi node, traverse outputs recursively\n");
tty->print(" only along data (mixed and other can also have data flow)\n");
tty->print(" find_node(385)->dump_bfs(3, 0, \"cdmox+#@B\")\n");
tty->print(" find inputs of node 385, up to 3 nodes up (+)\n");
tty->print(" traverse all nodes (cdmox), use colors (#)\n");
tty->print(" display old nodes and blocks, if they exist\n");
tty->print(" useful call to start with\n");
tty->print(" find_node(102)->dump_bfs(10, 0, \"dCDMOX-\")\n");
tty->print(" find non-data dependencies of a data node\n");
tty->print(" follow data node outputs until we find another category\n");
tty->print(" node as the boundary\n");
tty->print(" x->dump_bfs(10, y, 0)\n");
tty->print(" find shortest path from x to y, along any edge or node\n");
tty->print(" will not find a path if it is longer than 10\n");
tty->print(" useful to find how x and y are related\n");
tty->print(" find_node(741)->dump_bfs(20, find_node(746), \"c+\")\n");
tty->print(" find shortest control path between two nodes\n");
tty->print(" find_node(741)->dump_bfs(8, find_node(746), \"cdmox+A\")\n");
tty->print(" find all paths (A) between two nodes of length at most 8\n");
tty->print(" find_node(741)->dump_bfs(7, find_node(741), \"c+A\")\n");
tty->print(" find all control loops for this node\n");
_output->print_cr("");
_output->print_cr("Examples:");
_output->print_cr(" if->dump_bfs(10, 0, \"+cxo\")");
_output->print_cr(" starting at some if node, traverse inputs recursively");
_output->print_cr(" only along control (mixed and other can also be control)");
_output->print_cr(" phi->dump_bfs(5, 0, \"-dxo\")");
_output->print_cr(" starting at phi node, traverse outputs recursively");
_output->print_cr(" only along data (mixed and other can also have data flow)");
_output->print_cr(" find_node(385)->dump_bfs(3, 0, \"cdmox+#@B\")");
_output->print_cr(" find inputs of node 385, up to 3 nodes up (+)");
_output->print_cr(" traverse all nodes (cdmox), use colors (#)");
_output->print_cr(" display old nodes and blocks, if they exist");
_output->print_cr(" useful call to start with");
_output->print_cr(" find_node(102)->dump_bfs(10, 0, \"dCDMOX-\")");
_output->print_cr(" find non-data dependencies of a data node");
_output->print_cr(" follow data node outputs until we find another category");
_output->print_cr(" node as the boundary");
_output->print_cr(" x->dump_bfs(10, y, 0)");
_output->print_cr(" find shortest path from x to y, along any edge or node");
_output->print_cr(" will not find a path if it is longer than 10");
_output->print_cr(" useful to find how x and y are related");
_output->print_cr(" find_node(741)->dump_bfs(20, find_node(746), \"c+\")");
_output->print_cr(" find shortest control path between two nodes");
_output->print_cr(" find_node(741)->dump_bfs(8, find_node(746), \"cdmox+A\")");
_output->print_cr(" find all paths (A) between two nodes of length at most 8");
_output->print_cr(" find_node(741)->dump_bfs(7, find_node(741), \"c+A\")");
_output->print_cr(" find all control loops for this node");
}
}
@ -2198,8 +2199,8 @@ bool PrintBFS::parse_options() {
print_options_help(true);
return false;
default:
tty->print_cr("dump_bfs: Unrecognized option \'%c\'", _options[i]);
tty->print_cr("for help, run: find_node(0)->dump_bfs(0,0,\"H\")");
_output->print_cr("dump_bfs: Unrecognized option \'%c\'", _options[i]);
_output->print_cr("for help, run: find_node(0)->dump_bfs(0,0,\"H\")");
return false;
}
}
@ -2278,14 +2279,14 @@ void PrintBFS::print_node_idx(const Node* n) {
} else {
os::snprintf_checked(buf, sizeof(buf), "o%d", n->_idx); // old node
}
tty->print("%6s", buf);
_output->print("%6s", buf);
}
void PrintBFS::print_block_id(const Block* b) {
Compile* C = Compile::current();
char buf[30];
os::snprintf_checked(buf, sizeof(buf), "B%d", b->_pre_order);
tty->print("%7s", buf);
_output->print("%7s", buf);
}
void PrintBFS::print_node_block(const Node* n) {
@ -2294,19 +2295,19 @@ void PrintBFS::print_node_block(const Node* n) {
? C->cfg()->get_block_for_node(n)
: nullptr; // guard against old nodes
if (b == nullptr) {
tty->print(" _"); // Block
tty->print(" _"); // head
tty->print(" _"); // idom
tty->print(" _"); // depth
_output->print(" _"); // Block
_output->print(" _"); // head
_output->print(" _"); // idom
_output->print(" _"); // depth
} else {
print_block_id(b);
print_node_idx(b->head());
if (b->_idom) {
print_node_idx(b->_idom->head());
} else {
tty->print(" _"); // idom
_output->print(" _"); // idom
}
tty->print("%6d ", b->_dom_depth);
_output->print("%6d ", b->_dom_depth);
}
}
@ -2336,39 +2337,39 @@ void PrintBFS::print_header() const {
if (_dump_only) {
return; // no header in dump only mode
}
tty->print("dist"); // distance
_output->print("dist"); // distance
if (_all_paths) {
tty->print(" apd"); // all paths distance
_output->print(" apd"); // all paths distance
}
if (_print_blocks) {
tty->print(" [block head idom depth]"); // block
_output->print(" [block head idom depth]"); // block
}
if (_print_old) {
tty->print(" old"); // old node
_output->print(" old"); // old node
}
tty->print(" dump\n"); // node dump
tty->print("---------------------------------------------\n");
_output->print(" dump\n"); // node dump
_output->print_cr("---------------------------------------------");
}
void PrintBFS::print_node(const Node* n) {
if (_dump_only) {
n->dump("\n", false, tty, &_dcc);
n->dump("\n", false, _output, &_dcc);
return;
}
tty->print("%4d", find_info(n)->distance());// distance
_output->print("%4d", find_info(n)->distance());// distance
if (_all_paths) {
Info* info = find_info(n);
int apd = info->distance() + info->distance_from_target();
tty->print("%4d", apd); // all paths distance
_output->print("%4d", apd); // all paths distance
}
if (_print_blocks) {
print_node_block(n); // block
print_node_block(n); // block
}
if (_print_old) {
print_node_idx(old_node(n)); // old node
print_node_idx(old_node(n)); // old node
}
tty->print(" ");
n->dump("\n", false, tty, &_dcc); // node dump
_output->print(" ");
n->dump("\n", false, _output, &_dcc); // node dump
}
//------------------------------dump_bfs--------------------------------------
@ -2378,7 +2379,12 @@ void PrintBFS::print_node(const Node* n) {
// To find all options, run:
// find_node(0)->dump_bfs(0,0,"H")
void Node::dump_bfs(const int max_distance, Node* target, const char* options) const {
PrintBFS bfs(this, max_distance, target, options);
dump_bfs(max_distance, target, options, tty);
}
// Used to dump to stream.
void Node::dump_bfs(const int max_distance, Node* target, const char* options, outputStream* st) const {
PrintBFS bfs(this, max_distance, target, options, st);
bfs.run();
}
@ -2522,7 +2528,7 @@ void Node::dump(const char* suffix, bool mark, outputStream* st, DumpConfig* dc)
}
if (C->clone_map().value(_idx) != 0) {
C->clone_map().dump(_idx);
C->clone_map().dump(_idx, st);
}
// Dump node-specific info
dump_spec(st);

View File

@ -1215,7 +1215,8 @@ public:
public:
Node* find(int idx, bool only_ctrl = false); // Search the graph for the given idx.
Node* find_ctrl(int idx); // Search control ancestors for the given idx.
void dump_bfs(const int max_distance, Node* target, const char* options) const; // Print BFS traversal
void dump_bfs(const int max_distance, Node* target, const char* options, outputStream* st) const;
void dump_bfs(const int max_distance, Node* target, const char* options) const; // directly to tty
void dump_bfs(const int max_distance) const; // dump_bfs(max_distance, nullptr, nullptr)
class DumpConfig {
public:

View File

@ -2068,8 +2068,12 @@ void PhaseOutput::ScheduleAndBundle() {
#ifndef PRODUCT
if (C->trace_opto_output()) {
tty->print("\n---- After ScheduleAndBundle ----\n");
print_scheduling();
// Buffer and print all at once
ResourceMark rm;
stringStream ss;
ss.print("\n---- After ScheduleAndBundle ----\n");
print_scheduling(&ss);
tty->print("%s", ss.as_string());
}
#endif
}
@ -2077,14 +2081,18 @@ void PhaseOutput::ScheduleAndBundle() {
#ifndef PRODUCT
// Separated out so that it can be called directly from debugger
void PhaseOutput::print_scheduling() {
print_scheduling(tty);
}
void PhaseOutput::print_scheduling(outputStream* output_stream) {
for (uint i = 0; i < C->cfg()->number_of_blocks(); i++) {
tty->print("\nBB#%03d:\n", i);
output_stream->print("\nBB#%03d:\n", i);
Block* block = C->cfg()->get_block(i);
for (uint j = 0; j < block->number_of_nodes(); j++) {
Node* n = block->get_node(j);
OptoReg::Name reg = C->regalloc()->get_reg_first(n);
tty->print(" %-6s ", reg >= 0 && reg < REG_COUNT ? Matcher::regName[reg] : "");
n->dump();
output_stream->print(" %-6s ", reg >= 0 && reg < REG_COUNT ? Matcher::regName[reg] : "");
n->dump("\n", false, output_stream);
}
}
}

View File

@ -222,7 +222,8 @@ public:
void BuildOopMaps();
#ifndef PRODUCT
void print_scheduling();
void print_scheduling(outputStream* output_stream);
void print_scheduling(); // to tty for debugging
static void print_statistics();
#endif
};

View File

@ -69,8 +69,6 @@ compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-all
compiler/vectorapi/VectorLogicalOpIdentityTest.java 8302459 linux-x64,windows-x64
compiler/c2/irTests/TestVectorConditionalMove.java 8306922 generic-all
compiler/jvmci/TestUncaughtErrorInCompileMethod.java 8309073 generic-all
#############################################################################

View File

@ -43,10 +43,7 @@ public class TestVectorConditionalMove {
private static final Random RANDOM = Utils.getRandomInstance();
public static void main(String[] args) {
TestFramework.runWithFlags("-XX:-TieredCompilation",
"-XX:+UseCMoveUnconditionally",
"-XX:+UseVectorCmov",
"-XX:CompileCommand=compileonly,*.TestVectorConditionalMove.test*");
TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:+UseVectorCmov");
}
// Compare 2 values, and pick one of them