8326135: Enhance adlc to report unused operands

Reviewed-by: kvn, vlivanov
This commit is contained in:
Kuai Wei 2024-02-28 08:44:49 +00:00 committed by Julian Waters
parent 3b90ddfefe
commit 1ab6bd434f
9 changed files with 305 additions and 8 deletions

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 1997, 2024, 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
@ -24,6 +24,7 @@
// archDesc.cpp - Internal format for architecture definition
#include <unordered_set>
#include "adlc.hpp"
static FILE *errfile = stderr;
@ -684,6 +685,98 @@ bool ArchDesc::verify() {
return true;
}
class MarkUsageFormClosure : public FormClosure {
private:
ArchDesc* _ad;
std::unordered_set<Form*> *_visited;
public:
MarkUsageFormClosure(ArchDesc* ad, std::unordered_set<Form*> *visit_map) {
_ad = ad;
_visited = visit_map;
}
virtual ~MarkUsageFormClosure() = default;
virtual void do_form(Form *form) {
if (_visited->find(form) == _visited->end()) {
_visited->insert(form);
form->forms_do(this);
}
}
virtual void do_form_by_name(const char* name) {
const Form* form = _ad->globalNames()[name];
if (form) {
do_form(const_cast<Form*>(form));
return;
}
RegisterForm* regs = _ad->get_registers();
if (regs->getRegClass(name)) {
do_form(regs->getRegClass(name));
return;
}
}
};
// check unused operands
bool ArchDesc::check_usage() {
std::unordered_set<Form*> visited;
MarkUsageFormClosure callback(this, &visited);
_instructions.reset();
// iterate all instruction to mark used form
InstructForm* instr;
for ( ; (instr = (InstructForm*)_instructions.iter()) != nullptr; ) {
callback.do_form(instr);
}
// these forms are coded in OperandForm::is_user_name_for_sReg
// it may happen no instruction use these operands, like stackSlotP in aarch64,
// but we can not desclare they are useless.
callback.do_form_by_name("stackSlotI");
callback.do_form_by_name("stackSlotP");
callback.do_form_by_name("stackSlotD");
callback.do_form_by_name("stackSlotF");
callback.do_form_by_name("stackSlotL");
// sReg* are initial created by adlc in ArchDesc::initBaseOpTypes()
// In ARM, no definition or usage in adfile, but they are reported as unused
callback.do_form_by_name("sRegI");
callback.do_form_by_name("sRegP");
callback.do_form_by_name("sRegD");
callback.do_form_by_name("sRegF");
callback.do_form_by_name("sRegL");
// special generic vector operands only used in Matcher::pd_specialize_generic_vector_operand
#if defined(AARCH64)
callback.do_form_by_name("vecA");
callback.do_form_by_name("vecD");
callback.do_form_by_name("vecX");
#elif defined(AMD64)
callback.do_form_by_name("vecS");
callback.do_form_by_name("vecD");
callback.do_form_by_name("vecX");
callback.do_form_by_name("vecY");
callback.do_form_by_name("vecZ");
callback.do_form_by_name("legVecS");
callback.do_form_by_name("legVecD");
callback.do_form_by_name("legVecX");
callback.do_form_by_name("legVecY");
callback.do_form_by_name("legVecZ");
#endif
int cnt = 0;
_operands.reset();
OperandForm* operand;
for ( ; (operand = (OperandForm*)_operands.iter()) != nullptr; ) {
if(visited.find(operand) == visited.end() && !operand->ideal_only()) {
fprintf(stderr, "\nWarning: unused operand (%s)", operand->_ident);
cnt++;
}
}
if (cnt) fprintf(stderr, "\n-------Warning: total %d unused operands\n", cnt);
return true;
}
void ArchDesc::dump() {
_pre_header.dump();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
@ -226,6 +226,7 @@ public:
inline void getForm(EncodeForm **ptr) { *ptr = _encode; }
bool verify();
bool check_usage();
void dump();
// Helper utility that gets MatchList components from inside MatchRule

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
@ -362,6 +362,15 @@ void FormDict::dump() {
_form.print(dumpkey, dumpform);
}
void FormDict::forms_do(FormClosure* f) {;
DictI iter(&_form);
for( ; iter.test(); ++iter ) {
Form* form = (Form*) iter._value;
assert(form != nullptr, "sanity");
f->do_form(form);
}
}
//------------------------------SourceForm-------------------------------------
SourceForm::SourceForm(char* code) : _code(code) { }; // Constructor
SourceForm::~SourceForm() {
@ -374,3 +383,11 @@ void SourceForm::dump() { // Debug printer
void SourceForm::output(FILE *fp) {
fprintf(fp,"\n//%s\n%s\n",classname(),(_code?_code:""));
}
void FormClosure::do_form(Form* form) {
assert(false, "should not reach here");
}
void FormClosure::do_form_by_name(const char* name) {
assert(false, "should not reach here");
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
@ -58,6 +58,7 @@ class Flag;
class RewriteRule;
class ConstructRule;
class FormatRule;
class FormClosure;
class Peephole;
class EncClass;
class Interface;
@ -114,6 +115,8 @@ public:
const Form *operator [](const char *name) const; // Do a lookup
void dump();
// iterate child forms recursively
void forms_do(FormClosure *f);
};
// ***** Master Class for ADL Parser Forms *****
@ -163,6 +166,9 @@ public:
// Write info to output files
virtual void output(FILE *fp) { fprintf(fp,"Form Output"); }
// iterate child forms recursively
virtual void forms_do (FormClosure* f) { return; }
public:
// ADLC types, match the last character on ideal operands and instructions
enum DataType {
@ -255,6 +261,16 @@ public:
};
class FormClosure {
public:
FormClosure() = default;
virtual ~FormClosure() = default;
virtual void do_form(Form* form);
virtual void do_form_by_name(const char* name);
};
//------------------------------FormList---------------------------------------
class FormList {
private:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024, 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
@ -198,6 +198,20 @@ void RegisterForm::output(FILE *fp) { // Write info to output files
fprintf(fp,"-------------------- end RegisterForm --------------------\n");
}
void RegisterForm::forms_do(FormClosure *f) {
const char *name = nullptr;
if (_current_ac) f->do_form(_current_ac);
for(_rdefs.reset(); (name = _rdefs.iter()) != nullptr;) {
f->do_form((RegDef*)_regDef[name]);
}
for (_rclasses.reset(); (name = _rclasses.iter()) != nullptr;) {
f->do_form((RegClass*)_regClass[name]);
}
for (_aclasses.reset(); (name = _aclasses.iter()) != nullptr;) {
f->do_form((AllocClass*)_allocClass[name]);
}
}
//------------------------------RegDef-----------------------------------------
// Constructor
RegDef::RegDef(char *regname, char *callconv, char *c_conv, char * idealtype, char * encode, char * concrete)
@ -322,6 +336,13 @@ void RegClass::output(FILE *fp) { // Write info to output files
fprintf(fp,"--- done with entries for reg_class %s\n\n",_classid);
}
void RegClass::forms_do(FormClosure *f) {
const char *name = nullptr;
for( _regDefs.reset(); (name = _regDefs.iter()) != nullptr; ) {
f->do_form((RegDef*)_regDef[name]);
}
}
void RegClass::declare_register_masks(FILE* fp) {
const char* prefix = "";
const char* rc_name_to_upper = toUpper(_classid);
@ -436,6 +457,14 @@ void AllocClass::output(FILE *fp) { // Write info to output files
fprintf(fp,"--- done with entries for alloc_class %s\n\n",_classid);
}
void AllocClass::forms_do(FormClosure* f) {
const char *name;
for(_regDefs.reset(); (name = _regDefs.iter()) != nullptr;) {
f->do_form((RegDef*)_regDef[name]);
}
return;
}
//==============================Frame Handling=================================
//------------------------------FrameForm--------------------------------------
FrameForm::FrameForm() {
@ -706,6 +735,15 @@ void Peephole::output(FILE *fp) { // Write info to output files
if( _next ) _next->output(fp);
}
void Peephole::forms_do(FormClosure *f) {
if (_predicate) f->do_form(_predicate);
if (_match) f->do_form(_match);
if (_procedure) f->do_form(_procedure);
if (_constraint) f->do_form(_constraint);
if (_replace) f->do_form(_replace);
return;
}
//----------------------------PeepPredicate------------------------------------
PeepPredicate::PeepPredicate(const char* rule) : _rule(rule) {
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024, 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
@ -123,6 +123,7 @@ public:
void dump(); // Debug printer
void output(FILE *fp); // Write info to output files
virtual void forms_do(FormClosure* f);
};
//------------------------------RegDef-----------------------------------------
@ -199,6 +200,7 @@ public:
void dump(); // Debug printer
void output(FILE *fp); // Write info to output files
virtual void forms_do(FormClosure* f);
virtual bool has_stack_version() {
return _stack_or_reg;
@ -305,6 +307,11 @@ public:
char* condition_code() {
return _condition_code;
}
virtual void forms_do(FormClosure* f) {
if (_rclasses[0]) f->do_form(_rclasses[0]);
if (_rclasses[1]) f->do_form(_rclasses[1]);
}
};
//------------------------------AllocClass-------------------------------------
@ -325,6 +332,7 @@ public:
void dump(); // Debug printer
void output(FILE *fp); // Write info to output files
virtual void forms_do(FormClosure* f);
};
@ -568,6 +576,7 @@ public:
void dump(); // Debug printer
void output(FILE *fp); // Write info to output files
virtual void forms_do(FormClosure* f);
};
class PeepPredicate : public Form {

View File

@ -1498,6 +1498,24 @@ void InstructForm::output(FILE *fp) {
if (_peephole) _peephole->output(fp);
}
void InstructForm::forms_do(FormClosure *f) {
if (_cisc_spill_alternate) f->do_form(_cisc_spill_alternate);
if (_short_branch_form) f->do_form(_short_branch_form);
_localNames.forms_do(f);
if (_matrule) f->do_form(_matrule);
if (_opcode) f->do_form(_opcode);
if (_insencode) f->do_form(_insencode);
if (_constant) f->do_form(_constant);
if (_attribs) f->do_form(_attribs);
if (_predicate) f->do_form(_predicate);
_effects.forms_do(f);
if (_exprule) f->do_form(_exprule);
if (_rewrule) f->do_form(_rewrule);
if (_format) f->do_form(_format);
if (_peephole) f->do_form(_peephole);
assert(_components.count() == 0, "skip components");
}
void MachNodeForm::dump() {
output(stderr);
}
@ -1615,6 +1633,14 @@ void EncodeForm::output(FILE *fp) { // Write info to output files
}
fprintf(fp,"-------------------- end EncodeForm --------------------\n");
}
void EncodeForm::forms_do(FormClosure* f) {
const char *name;
for (_eclasses.reset(); (name = _eclasses.iter()) != nullptr;) {
f->do_form((EncClass*)_encClass[name]);
}
}
//------------------------------EncClass---------------------------------------
EncClass::EncClass(const char *name)
: _localNames(cmpstr,hashstr, Form::arena), _name(name) {
@ -1705,6 +1731,15 @@ void EncClass::output(FILE *fp) {
}
void EncClass::forms_do(FormClosure *f) {
_parameter_type.reset();
const char *type = _parameter_type.iter();
for ( ; type != nullptr ; type = _parameter_type.iter() ) {
f->do_form_by_name(type);
}
_localNames.forms_do(f);
}
//------------------------------Opcode-----------------------------------------
Opcode::Opcode(char *primary, char *secondary, char *tertiary)
: _primary(primary), _secondary(secondary), _tertiary(tertiary) {
@ -1835,6 +1870,15 @@ void InsEncode::output(FILE *fp) {
fprintf(fp,"\n");
}
void InsEncode::forms_do(FormClosure *f) {
_encoding.reset();
NameAndList *encoding = (NameAndList*)_encoding.iter();
for( ; encoding != nullptr; encoding = (NameAndList*)_encoding.iter() ) {
// just check name, other operands will be checked as instruction parameters
f->do_form_by_name(encoding->name());
}
}
//------------------------------Effect-----------------------------------------
static int effect_lookup(const char *name) {
if (!strcmp(name, "USE")) return Component::USE;
@ -1968,6 +2012,19 @@ void ExpandRule::output(FILE *fp) { // Write info to output files
}
}
void ExpandRule::forms_do(FormClosure *f) {
NameAndList *expand_instr = nullptr;
// Iterate over the instructions 'node' expands into
for(reset_instructions(); (expand_instr = iter_instructions()) != nullptr; ) {
f->do_form_by_name(expand_instr->name());
}
_newopers.reset();
const char* oper = _newopers.iter();
for(; oper != nullptr; oper = _newopers.iter()) {
f->do_form_by_name(oper);
}
}
//------------------------------RewriteRule------------------------------------
RewriteRule::RewriteRule(char* params, char* block)
: _tempParams(params), _tempBlock(block) { }; // Constructor
@ -1984,6 +2041,12 @@ void RewriteRule::output(FILE *fp) { // Write info to output files
(_tempBlock?_tempBlock:""));
}
void RewriteRule::forms_do(FormClosure *f) {
if (_condition) f->do_form(_condition);
if (_instrs) f->do_form(_instrs);
if (_opers) f->do_form(_opers);
}
//==============================MachNodes======================================
//------------------------------MachNodeForm-----------------------------------
@ -2066,6 +2129,13 @@ void OpClassForm::output(FILE *fp) {
fprintf(fp,"\n");
}
void OpClassForm::forms_do(FormClosure* f) {
const char *name;
for(_oplst.reset(); (name = _oplst.iter()) != nullptr;) {
f->do_form_by_name(name);
}
}
//==============================Operands=======================================
//------------------------------OperandForm------------------------------------
@ -2691,6 +2761,22 @@ void OperandForm::output(FILE *fp) {
if (_format) _format->dump();
}
void OperandForm::forms_do(FormClosure* f) {
if (_matrule) f->do_form(_matrule);
if (_interface) f->do_form(_interface);
if (_attribs) f->do_form(_attribs);
if (_predicate) f->do_form(_predicate);
if (_constraint) f->do_form(_constraint);
if (_construct) f->do_form(_construct);
if (_format) f->do_form(_format);
_localNames.forms_do(f);
const char* opclass = nullptr;
for ( _classes.reset(); (opclass = _classes.iter()) != nullptr; ) {
f->do_form_by_name(opclass);
}
assert(_components.count() == 0, "skip _compnets");
}
//------------------------------Constraint-------------------------------------
Constraint::Constraint(const char *func, const char *arg)
: _func(func), _arg(arg) {
@ -2712,6 +2798,10 @@ void Constraint::output(FILE *fp) { // Write info to output files
fprintf(fp,"Constraint: %s ( %s )\n", _func, _arg);
}
void Constraint::forms_do(FormClosure *f) {
f->do_form_by_name(_arg);
}
//------------------------------Predicate--------------------------------------
Predicate::Predicate(char *pr)
: _pred(pr) {
@ -3539,6 +3629,12 @@ void MatchNode::output(FILE *fp) {
}
}
void MatchNode::forms_do(FormClosure *f) {
f->do_form_by_name(_name);
if (_lChild) f->do_form(_lChild);
if (_rChild) f->do_form(_rChild);
}
int MatchNode::needs_ideal_memory_edge(FormDict &globals) const {
static const char *needs_ideal_memory_list[] = {
"StoreI","StoreL","StoreP","StoreN","StoreNKlass","StoreD","StoreF" ,
@ -3608,6 +3704,7 @@ int InstructForm::needs_base_oop_edge(FormDict &globals) const {
}
//-------------------------cisc spilling methods-------------------------------
// helper routines and methods for detecting cisc-spilling instructions
//-------------------------cisc_spill_merge------------------------------------
@ -4334,6 +4431,18 @@ void MatchRule::output(FILE *fp) {
fprintf(fp,"\n");
}
void MatchRule::forms_do(FormClosure* f) {
// keep sync with MatchNode::forms_do
f->do_form_by_name(_name);
if (_lChild) f->do_form(_lChild);
if (_rChild) f->do_form(_rChild);
// handle next rule
if (_next) {
f->do_form(_next);
}
}
//------------------------------Attribute--------------------------------------
Attribute::Attribute(char *id, char* val, int type)
: _ident(id), _val(val), _atype(type) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024, 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
@ -310,6 +310,7 @@ public:
virtual void dump(); // Debug printer
virtual void output(FILE *fp); // Write to output files
virtual void forms_do(FormClosure *f);
};
//------------------------------EncodeForm-------------------------------------
@ -333,6 +334,7 @@ public:
void dump(); // Debug printer
void output(FILE *fp); // Write info to output files
virtual void forms_do(FormClosure *f);
};
//------------------------------EncClass---------------------------------------
@ -377,6 +379,7 @@ public:
bool verify();
void dump();
void output(FILE *fp);
virtual void forms_do(FormClosure* f);
};
//------------------------------MachNode---------------------------------------
@ -468,6 +471,7 @@ public:
void dump();
void output(FILE *fp);
virtual void forms_do(FormClosure *f);
};
//------------------------------Effect-----------------------------------------
@ -515,6 +519,7 @@ public:
void dump(); // Debug printer
void output(FILE *fp); // Write info to output files
virtual void forms_do(FormClosure *f);
};
//---------------------------------Flag----------------------------------------
@ -554,6 +559,7 @@ public:
~RewriteRule(); // Destructor
void dump(); // Debug printer
void output(FILE *fp); // Write info to output files
virtual void forms_do(FormClosure* f);
};
@ -584,6 +590,7 @@ public:
virtual bool ideal_only() const;
virtual void dump(); // Debug printer
virtual void output(FILE *fp); // Write to output files
virtual void forms_do(FormClosure* f);
};
//------------------------------OperandForm------------------------------------
@ -711,6 +718,7 @@ public:
virtual void dump(); // Debug printer
virtual void output(FILE *fp); // Write to output files
virtual void forms_do(FormClosure* f);
};
//------------------------------Constraint-------------------------------------
@ -729,6 +737,7 @@ public:
void dump(); // Debug printer
void output(FILE *fp); // Write info to output files
virtual void forms_do(FormClosure* f);
};
//------------------------------Predicate--------------------------------------
@ -1014,6 +1023,7 @@ public:
void dump();
void output(FILE *fp);
virtual void forms_do(FormClosure* f);
};
//------------------------------MatchRule--------------------------------------
@ -1075,6 +1085,7 @@ public:
void dump();
void output_short(FILE *fp);
void output(FILE *fp);
virtual void forms_do(FormClosure* f);
};
//------------------------------Attribute--------------------------------------

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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
@ -186,6 +186,9 @@ int main(int argc, char *argv[])
// Verify that the results of the parse are consistent
AD.verify();
// Check defined operands are used
AD.check_usage();
// Prepare to generate the result files:
AD.generateMatchLists();
AD.identify_unique_operands();