Wed, 04 Feb 2009 11:44:57 -0800
6798785: Crash in OopFlow::build_oop_map: incorrect comparison of 64bit pointers
Reviewed-by: phh, kvn
duke@435 | 1 | /* |
duke@435 | 2 | * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
duke@435 | 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
duke@435 | 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
duke@435 | 21 | * have any questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
duke@435 | 25 | // FORMS.CPP - Definitions for ADL Parser Forms Classes |
duke@435 | 26 | #include "adlc.hpp" |
duke@435 | 27 | |
duke@435 | 28 | //==============================Register Allocation============================ |
duke@435 | 29 | int RegisterForm::_reg_ctr = 0; |
duke@435 | 30 | |
duke@435 | 31 | //------------------------------RegisterForm----------------------------------- |
duke@435 | 32 | // Constructor |
duke@435 | 33 | RegisterForm::RegisterForm() |
duke@435 | 34 | : _regDef(cmpstr,hashstr, Form::arena), |
duke@435 | 35 | _regClass(cmpstr,hashstr, Form::arena), |
duke@435 | 36 | _allocClass(cmpstr,hashstr, Form::arena) { |
duke@435 | 37 | } |
duke@435 | 38 | RegisterForm::~RegisterForm() { |
duke@435 | 39 | } |
duke@435 | 40 | |
duke@435 | 41 | // record a new register definition |
duke@435 | 42 | void RegisterForm::addRegDef(char *name, char *callingConv, char *c_conv, |
duke@435 | 43 | char *idealtype, char *encoding, char* concrete) { |
duke@435 | 44 | RegDef *regDef = new RegDef(name, callingConv, c_conv, idealtype, encoding, concrete); |
duke@435 | 45 | _rdefs.addName(name); |
duke@435 | 46 | _regDef.Insert(name,regDef); |
duke@435 | 47 | } |
duke@435 | 48 | |
duke@435 | 49 | // record a new register class |
duke@435 | 50 | RegClass *RegisterForm::addRegClass(const char *className) { |
duke@435 | 51 | RegClass *regClass = new RegClass(className); |
duke@435 | 52 | _rclasses.addName(className); |
duke@435 | 53 | _regClass.Insert(className,regClass); |
duke@435 | 54 | return regClass; |
duke@435 | 55 | } |
duke@435 | 56 | |
duke@435 | 57 | // record a new register class |
duke@435 | 58 | AllocClass *RegisterForm::addAllocClass(char *className) { |
duke@435 | 59 | AllocClass *allocClass = new AllocClass(className); |
duke@435 | 60 | _aclasses.addName(className); |
duke@435 | 61 | _allocClass.Insert(className,allocClass); |
duke@435 | 62 | return allocClass; |
duke@435 | 63 | } |
duke@435 | 64 | |
duke@435 | 65 | // Called after parsing the Register block. Record the register class |
duke@435 | 66 | // for spill-slots/regs. |
duke@435 | 67 | void RegisterForm::addSpillRegClass() { |
duke@435 | 68 | // Stack slots start at the next available even register number. |
duke@435 | 69 | _reg_ctr = (_reg_ctr+1) & ~1; |
duke@435 | 70 | const char *rc_name = "stack_slots"; |
duke@435 | 71 | RegClass *reg_class = new RegClass(rc_name); |
duke@435 | 72 | reg_class->_stack_or_reg = true; |
duke@435 | 73 | _rclasses.addName(rc_name); |
duke@435 | 74 | _regClass.Insert(rc_name,reg_class); |
duke@435 | 75 | } |
duke@435 | 76 | |
duke@435 | 77 | |
duke@435 | 78 | // Provide iteration over all register definitions |
duke@435 | 79 | // in the order used by the register allocator |
duke@435 | 80 | void RegisterForm::reset_RegDefs() { |
duke@435 | 81 | _current_ac = NULL; |
duke@435 | 82 | _aclasses.reset(); |
duke@435 | 83 | } |
duke@435 | 84 | |
duke@435 | 85 | RegDef *RegisterForm::iter_RegDefs() { |
duke@435 | 86 | // Check if we need to get the next AllocClass |
duke@435 | 87 | if ( _current_ac == NULL ) { |
duke@435 | 88 | const char *ac_name = _aclasses.iter(); |
duke@435 | 89 | if( ac_name == NULL ) return NULL; // No more allocation classes |
duke@435 | 90 | _current_ac = (AllocClass*)_allocClass[ac_name]; |
duke@435 | 91 | _current_ac->_regDefs.reset(); |
duke@435 | 92 | assert( _current_ac != NULL, "Name must match an allocation class"); |
duke@435 | 93 | } |
duke@435 | 94 | |
duke@435 | 95 | const char *rd_name = _current_ac->_regDefs.iter(); |
duke@435 | 96 | if( rd_name == NULL ) { |
duke@435 | 97 | // At end of this allocation class, check the next |
duke@435 | 98 | _current_ac = NULL; |
duke@435 | 99 | return iter_RegDefs(); |
duke@435 | 100 | } |
duke@435 | 101 | RegDef *reg_def = (RegDef*)_current_ac->_regDef[rd_name]; |
duke@435 | 102 | assert( reg_def != NULL, "Name must match a register definition"); |
duke@435 | 103 | return reg_def; |
duke@435 | 104 | } |
duke@435 | 105 | |
duke@435 | 106 | // return the register definition with name 'regName' |
duke@435 | 107 | RegDef *RegisterForm::getRegDef(const char *regName) { |
duke@435 | 108 | RegDef *regDef = (RegDef*)_regDef[regName]; |
duke@435 | 109 | return regDef; |
duke@435 | 110 | } |
duke@435 | 111 | |
duke@435 | 112 | // return the register class with name 'className' |
duke@435 | 113 | RegClass *RegisterForm::getRegClass(const char *className) { |
duke@435 | 114 | RegClass *regClass = (RegClass*)_regClass[className]; |
duke@435 | 115 | return regClass; |
duke@435 | 116 | } |
duke@435 | 117 | |
duke@435 | 118 | |
duke@435 | 119 | // Check that register classes are compatible with chunks |
duke@435 | 120 | bool RegisterForm::verify() { |
duke@435 | 121 | bool valid = true; |
duke@435 | 122 | |
duke@435 | 123 | // Verify Register Classes |
duke@435 | 124 | // check that each register class contains registers from one chunk |
duke@435 | 125 | const char *rc_name = NULL; |
duke@435 | 126 | _rclasses.reset(); |
duke@435 | 127 | while ( (rc_name = _rclasses.iter()) != NULL ) { |
duke@435 | 128 | // Check the chunk value for all registers in this class |
duke@435 | 129 | RegClass *reg_class = getRegClass(rc_name); |
duke@435 | 130 | assert( reg_class != NULL, "InternalError() no matching register class"); |
duke@435 | 131 | } // end of RegClasses |
duke@435 | 132 | |
duke@435 | 133 | // Verify that every register has been placed into an allocation class |
duke@435 | 134 | RegDef *reg_def = NULL; |
duke@435 | 135 | reset_RegDefs(); |
duke@435 | 136 | uint num_register_zero = 0; |
duke@435 | 137 | while ( (reg_def = iter_RegDefs()) != NULL ) { |
duke@435 | 138 | if( reg_def->register_num() == 0 ) ++num_register_zero; |
duke@435 | 139 | } |
duke@435 | 140 | if( num_register_zero > 1 ) { |
duke@435 | 141 | fprintf(stderr, |
duke@435 | 142 | "ERROR: More than one register has been assigned register-number 0.\n" |
duke@435 | 143 | "Probably because a register has not been entered into an allocation class.\n"); |
duke@435 | 144 | } |
duke@435 | 145 | |
duke@435 | 146 | return valid; |
duke@435 | 147 | } |
duke@435 | 148 | |
duke@435 | 149 | // Compute RegMask size |
duke@435 | 150 | int RegisterForm::RegMask_Size() { |
duke@435 | 151 | // Need at least this many words |
duke@435 | 152 | int words_for_regs = (_reg_ctr + 31)>>5; |
duke@435 | 153 | // Add a few for incoming & outgoing arguments to calls. |
duke@435 | 154 | // Round up to the next doubleword size. |
duke@435 | 155 | return (words_for_regs + 2 + 1) & ~1; |
duke@435 | 156 | } |
duke@435 | 157 | |
duke@435 | 158 | void RegisterForm::dump() { // Debug printer |
duke@435 | 159 | output(stderr); |
duke@435 | 160 | } |
duke@435 | 161 | |
duke@435 | 162 | void RegisterForm::output(FILE *fp) { // Write info to output files |
duke@435 | 163 | const char *name; |
duke@435 | 164 | fprintf(fp,"\n"); |
duke@435 | 165 | fprintf(fp,"-------------------- Dump RegisterForm --------------------\n"); |
duke@435 | 166 | for(_rdefs.reset(); (name = _rdefs.iter()) != NULL;) { |
duke@435 | 167 | ((RegDef*)_regDef[name])->output(fp); |
duke@435 | 168 | } |
duke@435 | 169 | fprintf(fp,"\n"); |
duke@435 | 170 | for (_rclasses.reset(); (name = _rclasses.iter()) != NULL;) { |
duke@435 | 171 | ((RegClass*)_regClass[name])->output(fp); |
duke@435 | 172 | } |
duke@435 | 173 | fprintf(fp,"\n"); |
duke@435 | 174 | for (_aclasses.reset(); (name = _aclasses.iter()) != NULL;) { |
duke@435 | 175 | ((AllocClass*)_allocClass[name])->output(fp); |
duke@435 | 176 | } |
duke@435 | 177 | fprintf(fp,"-------------------- end RegisterForm --------------------\n"); |
duke@435 | 178 | } |
duke@435 | 179 | |
duke@435 | 180 | //------------------------------RegDef----------------------------------------- |
duke@435 | 181 | // Constructor |
duke@435 | 182 | RegDef::RegDef(char *regname, char *callconv, char *c_conv, char * idealtype, char * encode, char * concrete) |
duke@435 | 183 | : _regname(regname), _callconv(callconv), _c_conv(c_conv), |
duke@435 | 184 | _idealtype(idealtype), |
duke@435 | 185 | _register_encode(encode), |
duke@435 | 186 | _concrete(concrete), |
duke@435 | 187 | _register_num(0) { |
duke@435 | 188 | |
duke@435 | 189 | // Chunk and register mask are determined by the register number |
duke@435 | 190 | // _register_num is set when registers are added to an allocation class |
duke@435 | 191 | } |
duke@435 | 192 | RegDef::~RegDef() { // Destructor |
duke@435 | 193 | } |
duke@435 | 194 | |
duke@435 | 195 | void RegDef::set_register_num(uint32 register_num) { |
duke@435 | 196 | _register_num = register_num; |
duke@435 | 197 | } |
duke@435 | 198 | |
duke@435 | 199 | // Bit pattern used for generating machine code |
duke@435 | 200 | const char* RegDef::register_encode() const { |
duke@435 | 201 | return _register_encode; |
duke@435 | 202 | } |
duke@435 | 203 | |
duke@435 | 204 | // Register number used in machine-independent code |
duke@435 | 205 | uint32 RegDef::register_num() const { |
duke@435 | 206 | return _register_num; |
duke@435 | 207 | } |
duke@435 | 208 | |
duke@435 | 209 | void RegDef::dump() { |
duke@435 | 210 | output(stderr); |
duke@435 | 211 | } |
duke@435 | 212 | |
duke@435 | 213 | void RegDef::output(FILE *fp) { // Write info to output files |
duke@435 | 214 | fprintf(fp,"RegDef: %s (%s) encode as %s using number %d\n", |
duke@435 | 215 | _regname, (_callconv?_callconv:""), _register_encode, _register_num); |
duke@435 | 216 | fprintf(fp,"\n"); |
duke@435 | 217 | } |
duke@435 | 218 | |
duke@435 | 219 | |
duke@435 | 220 | //------------------------------RegClass--------------------------------------- |
duke@435 | 221 | // Construct a register class into which registers will be inserted |
duke@435 | 222 | RegClass::RegClass(const char *classid) : _stack_or_reg(false), _classid(classid), _regDef(cmpstr,hashstr, Form::arena) { |
duke@435 | 223 | } |
duke@435 | 224 | |
duke@435 | 225 | // record a register in this class |
duke@435 | 226 | void RegClass::addReg(RegDef *regDef) { |
duke@435 | 227 | _regDefs.addName(regDef->_regname); |
duke@435 | 228 | _regDef.Insert((void*)regDef->_regname, regDef); |
duke@435 | 229 | } |
duke@435 | 230 | |
duke@435 | 231 | // Number of registers in class |
duke@435 | 232 | uint RegClass::size() const { |
duke@435 | 233 | return _regDef.Size(); |
duke@435 | 234 | } |
duke@435 | 235 | |
duke@435 | 236 | const RegDef *RegClass::get_RegDef(const char *rd_name) const { |
duke@435 | 237 | return (const RegDef*)_regDef[rd_name]; |
duke@435 | 238 | } |
duke@435 | 239 | |
duke@435 | 240 | void RegClass::reset() { |
duke@435 | 241 | _regDefs.reset(); |
duke@435 | 242 | } |
duke@435 | 243 | |
duke@435 | 244 | const char *RegClass::rd_name_iter() { |
duke@435 | 245 | return _regDefs.iter(); |
duke@435 | 246 | } |
duke@435 | 247 | |
duke@435 | 248 | RegDef *RegClass::RegDef_iter() { |
duke@435 | 249 | const char *rd_name = rd_name_iter(); |
duke@435 | 250 | RegDef *reg_def = rd_name ? (RegDef*)_regDef[rd_name] : NULL; |
duke@435 | 251 | return reg_def; |
duke@435 | 252 | } |
duke@435 | 253 | |
duke@435 | 254 | const RegDef* RegClass::find_first_elem() { |
duke@435 | 255 | const RegDef* first = NULL; |
duke@435 | 256 | const RegDef* def = NULL; |
duke@435 | 257 | |
duke@435 | 258 | reset(); |
duke@435 | 259 | while ((def = RegDef_iter()) != NULL) { |
duke@435 | 260 | if (first == NULL || def->register_num() < first->register_num()) { |
duke@435 | 261 | first = def; |
duke@435 | 262 | } |
duke@435 | 263 | } |
duke@435 | 264 | |
duke@435 | 265 | assert(first != NULL, "empty mask?"); |
duke@435 | 266 | return first;; |
duke@435 | 267 | } |
duke@435 | 268 | |
duke@435 | 269 | // Collect all the registers in this register-word. One bit per register. |
duke@435 | 270 | int RegClass::regs_in_word( int wordnum, bool stack_also ) { |
duke@435 | 271 | int word = 0; |
duke@435 | 272 | const char *name; |
duke@435 | 273 | for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) { |
duke@435 | 274 | int rnum = ((RegDef*)_regDef[name])->register_num(); |
duke@435 | 275 | if( (rnum >> 5) == wordnum ) |
duke@435 | 276 | word |= (1L<<(rnum&31)); |
duke@435 | 277 | } |
duke@435 | 278 | if( stack_also ) { |
duke@435 | 279 | // Now also collect stack bits |
duke@435 | 280 | for( int i = 0; i < 32; i++ ) |
duke@435 | 281 | if( wordnum*32+i >= RegisterForm::_reg_ctr ) |
duke@435 | 282 | word |= (1L<<i); |
duke@435 | 283 | } |
duke@435 | 284 | |
duke@435 | 285 | return word; |
duke@435 | 286 | } |
duke@435 | 287 | |
duke@435 | 288 | void RegClass::dump() { |
duke@435 | 289 | output(stderr); |
duke@435 | 290 | } |
duke@435 | 291 | |
duke@435 | 292 | void RegClass::output(FILE *fp) { // Write info to output files |
duke@435 | 293 | fprintf(fp,"RegClass: %s\n",_classid); |
duke@435 | 294 | const char *name; |
duke@435 | 295 | for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) { |
duke@435 | 296 | ((RegDef*)_regDef[name])->output(fp); |
duke@435 | 297 | } |
duke@435 | 298 | fprintf(fp,"--- done with entries for reg_class %s\n\n",_classid); |
duke@435 | 299 | } |
duke@435 | 300 | |
duke@435 | 301 | |
duke@435 | 302 | //------------------------------AllocClass------------------------------------- |
duke@435 | 303 | AllocClass::AllocClass(char *classid) : _classid(classid), _regDef(cmpstr,hashstr, Form::arena) { |
duke@435 | 304 | } |
duke@435 | 305 | |
duke@435 | 306 | // record a register in this class |
duke@435 | 307 | void AllocClass::addReg(RegDef *regDef) { |
duke@435 | 308 | assert( regDef != NULL, "Can not add a NULL to an allocation class"); |
duke@435 | 309 | regDef->set_register_num( RegisterForm::_reg_ctr++ ); |
duke@435 | 310 | // Add regDef to this allocation class |
duke@435 | 311 | _regDefs.addName(regDef->_regname); |
duke@435 | 312 | _regDef.Insert((void*)regDef->_regname, regDef); |
duke@435 | 313 | } |
duke@435 | 314 | |
duke@435 | 315 | void AllocClass::dump() { |
duke@435 | 316 | output(stderr); |
duke@435 | 317 | } |
duke@435 | 318 | |
duke@435 | 319 | void AllocClass::output(FILE *fp) { // Write info to output files |
duke@435 | 320 | fprintf(fp,"AllocClass: %s \n",_classid); |
duke@435 | 321 | const char *name; |
duke@435 | 322 | for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) { |
duke@435 | 323 | ((RegDef*)_regDef[name])->output(fp); |
duke@435 | 324 | } |
duke@435 | 325 | fprintf(fp,"--- done with entries for alloc_class %s\n\n",_classid); |
duke@435 | 326 | } |
duke@435 | 327 | |
duke@435 | 328 | //==============================Frame Handling================================= |
duke@435 | 329 | //------------------------------FrameForm-------------------------------------- |
duke@435 | 330 | FrameForm::FrameForm() { |
duke@435 | 331 | _frame_pointer = NULL; |
duke@435 | 332 | _c_frame_pointer = NULL; |
duke@435 | 333 | _alignment = NULL; |
duke@435 | 334 | _return_addr = NULL; |
duke@435 | 335 | _c_return_addr = NULL; |
duke@435 | 336 | _in_preserve_slots = NULL; |
duke@435 | 337 | _varargs_C_out_slots_killed = NULL; |
duke@435 | 338 | _calling_convention = NULL; |
duke@435 | 339 | _c_calling_convention = NULL; |
duke@435 | 340 | _return_value = NULL; |
duke@435 | 341 | _c_return_value = NULL; |
duke@435 | 342 | _interpreter_frame_pointer_reg = NULL; |
duke@435 | 343 | } |
duke@435 | 344 | |
duke@435 | 345 | FrameForm::~FrameForm() { |
duke@435 | 346 | } |
duke@435 | 347 | |
duke@435 | 348 | void FrameForm::dump() { |
duke@435 | 349 | output(stderr); |
duke@435 | 350 | } |
duke@435 | 351 | |
duke@435 | 352 | void FrameForm::output(FILE *fp) { // Write info to output files |
duke@435 | 353 | fprintf(fp,"\nFrame:\n"); |
duke@435 | 354 | } |
duke@435 | 355 | |
duke@435 | 356 | //==============================Scheduling===================================== |
duke@435 | 357 | //------------------------------PipelineForm----------------------------------- |
duke@435 | 358 | PipelineForm::PipelineForm() |
duke@435 | 359 | : _reslist () |
duke@435 | 360 | , _resdict (cmpstr, hashstr, Form::arena) |
duke@435 | 361 | , _classdict (cmpstr, hashstr, Form::arena) |
duke@435 | 362 | , _rescount (0) |
duke@435 | 363 | , _maxcycleused (0) |
duke@435 | 364 | , _stages () |
duke@435 | 365 | , _stagecnt (0) |
duke@435 | 366 | , _classlist () |
duke@435 | 367 | , _classcnt (0) |
duke@435 | 368 | , _noplist () |
duke@435 | 369 | , _nopcnt (0) |
duke@435 | 370 | , _variableSizeInstrs (false) |
duke@435 | 371 | , _branchHasDelaySlot (false) |
duke@435 | 372 | , _maxInstrsPerBundle (0) |
duke@435 | 373 | , _maxBundlesPerCycle (1) |
duke@435 | 374 | , _instrUnitSize (0) |
duke@435 | 375 | , _bundleUnitSize (0) |
duke@435 | 376 | , _instrFetchUnitSize (0) |
duke@435 | 377 | , _instrFetchUnits (0) { |
duke@435 | 378 | } |
duke@435 | 379 | PipelineForm::~PipelineForm() { |
duke@435 | 380 | } |
duke@435 | 381 | |
duke@435 | 382 | void PipelineForm::dump() { |
duke@435 | 383 | output(stderr); |
duke@435 | 384 | } |
duke@435 | 385 | |
duke@435 | 386 | void PipelineForm::output(FILE *fp) { // Write info to output files |
duke@435 | 387 | const char *res; |
duke@435 | 388 | const char *stage; |
duke@435 | 389 | const char *cls; |
duke@435 | 390 | const char *nop; |
duke@435 | 391 | int count = 0; |
duke@435 | 392 | |
duke@435 | 393 | fprintf(fp,"\nPipeline:"); |
duke@435 | 394 | if (_variableSizeInstrs) |
duke@435 | 395 | if (_instrUnitSize > 0) |
duke@435 | 396 | fprintf(fp," variable-sized instructions in %d byte units", _instrUnitSize); |
duke@435 | 397 | else |
duke@435 | 398 | fprintf(fp," variable-sized instructions"); |
duke@435 | 399 | else |
duke@435 | 400 | if (_instrUnitSize > 0) |
duke@435 | 401 | fprintf(fp," fixed-sized instructions of %d bytes", _instrUnitSize); |
duke@435 | 402 | else if (_bundleUnitSize > 0) |
duke@435 | 403 | fprintf(fp," fixed-sized bundles of %d bytes", _bundleUnitSize); |
duke@435 | 404 | else |
duke@435 | 405 | fprintf(fp," fixed-sized instructions"); |
duke@435 | 406 | if (_branchHasDelaySlot) |
duke@435 | 407 | fprintf(fp,", branch has delay slot"); |
duke@435 | 408 | if (_maxInstrsPerBundle > 0) |
duke@435 | 409 | fprintf(fp,", max of %d instruction%s in parallel", |
duke@435 | 410 | _maxInstrsPerBundle, _maxInstrsPerBundle > 1 ? "s" : ""); |
duke@435 | 411 | if (_maxBundlesPerCycle > 0) |
duke@435 | 412 | fprintf(fp,", max of %d bundle%s in parallel", |
duke@435 | 413 | _maxBundlesPerCycle, _maxBundlesPerCycle > 1 ? "s" : ""); |
duke@435 | 414 | if (_instrFetchUnitSize > 0 && _instrFetchUnits) |
duke@435 | 415 | fprintf(fp, ", fetch %d x % d bytes per cycle", _instrFetchUnits, _instrFetchUnitSize); |
duke@435 | 416 | |
duke@435 | 417 | fprintf(fp,"\nResource:"); |
duke@435 | 418 | for ( _reslist.reset(); (res = _reslist.iter()) != NULL; ) |
duke@435 | 419 | fprintf(fp," %s(0x%08x)", res, _resdict[res]->is_resource()->mask()); |
duke@435 | 420 | fprintf(fp,"\n"); |
duke@435 | 421 | |
duke@435 | 422 | fprintf(fp,"\nDescription:\n"); |
duke@435 | 423 | for ( _stages.reset(); (stage = _stages.iter()) != NULL; ) |
duke@435 | 424 | fprintf(fp," %s(%d)", stage, count++); |
duke@435 | 425 | fprintf(fp,"\n"); |
duke@435 | 426 | |
duke@435 | 427 | fprintf(fp,"\nClasses:\n"); |
duke@435 | 428 | for ( _classlist.reset(); (cls = _classlist.iter()) != NULL; ) |
duke@435 | 429 | _classdict[cls]->is_pipeclass()->output(fp); |
duke@435 | 430 | |
duke@435 | 431 | fprintf(fp,"\nNop Instructions:"); |
duke@435 | 432 | for ( _noplist.reset(); (nop = _noplist.iter()) != NULL; ) |
duke@435 | 433 | fprintf(fp, " \"%s\"", nop); |
duke@435 | 434 | fprintf(fp,"\n"); |
duke@435 | 435 | } |
duke@435 | 436 | |
duke@435 | 437 | |
duke@435 | 438 | //------------------------------ResourceForm----------------------------------- |
duke@435 | 439 | ResourceForm::ResourceForm(unsigned resmask) |
duke@435 | 440 | : _resmask(resmask) { |
duke@435 | 441 | } |
duke@435 | 442 | ResourceForm::~ResourceForm() { |
duke@435 | 443 | } |
duke@435 | 444 | |
duke@435 | 445 | ResourceForm *ResourceForm::is_resource() const { |
duke@435 | 446 | return (ResourceForm *)(this); |
duke@435 | 447 | } |
duke@435 | 448 | |
duke@435 | 449 | void ResourceForm::dump() { |
duke@435 | 450 | output(stderr); |
duke@435 | 451 | } |
duke@435 | 452 | |
duke@435 | 453 | void ResourceForm::output(FILE *fp) { // Write info to output files |
duke@435 | 454 | fprintf(fp, "resource: 0x%08x;\n", mask()); |
duke@435 | 455 | } |
duke@435 | 456 | |
duke@435 | 457 | |
duke@435 | 458 | //------------------------------PipeClassOperandForm---------------------------------- |
duke@435 | 459 | |
duke@435 | 460 | void PipeClassOperandForm::dump() { |
duke@435 | 461 | output(stderr); |
duke@435 | 462 | } |
duke@435 | 463 | |
duke@435 | 464 | void PipeClassOperandForm::output(FILE *fp) { // Write info to output files |
duke@435 | 465 | fprintf(stderr,"PipeClassOperandForm: %s", _stage); |
duke@435 | 466 | fflush(stderr); |
duke@435 | 467 | if (_more_instrs > 0) |
duke@435 | 468 | fprintf(stderr,"+%d", _more_instrs); |
duke@435 | 469 | fprintf(stderr," (%s)\n", _iswrite ? "write" : "read"); |
duke@435 | 470 | fflush(stderr); |
duke@435 | 471 | fprintf(fp,"PipeClassOperandForm: %s", _stage); |
duke@435 | 472 | if (_more_instrs > 0) |
duke@435 | 473 | fprintf(fp,"+%d", _more_instrs); |
duke@435 | 474 | fprintf(fp," (%s)\n", _iswrite ? "write" : "read"); |
duke@435 | 475 | } |
duke@435 | 476 | |
duke@435 | 477 | |
duke@435 | 478 | //------------------------------PipeClassResourceForm---------------------------------- |
duke@435 | 479 | |
duke@435 | 480 | void PipeClassResourceForm::dump() { |
duke@435 | 481 | output(stderr); |
duke@435 | 482 | } |
duke@435 | 483 | |
duke@435 | 484 | void PipeClassResourceForm::output(FILE *fp) { // Write info to output files |
duke@435 | 485 | fprintf(fp,"PipeClassResourceForm: %s at stage %s for %d cycles\n", |
duke@435 | 486 | _resource, _stage, _cycles); |
duke@435 | 487 | } |
duke@435 | 488 | |
duke@435 | 489 | |
duke@435 | 490 | //------------------------------PipeClassForm---------------------------------- |
duke@435 | 491 | PipeClassForm::PipeClassForm(const char *id, int num) |
duke@435 | 492 | : _ident(id) |
duke@435 | 493 | , _num(num) |
duke@435 | 494 | , _localNames(cmpstr, hashstr, Form::arena) |
duke@435 | 495 | , _localUsage(cmpstr, hashstr, Form::arena) |
duke@435 | 496 | , _has_fixed_latency(0) |
duke@435 | 497 | , _fixed_latency(0) |
duke@435 | 498 | , _instruction_count(0) |
duke@435 | 499 | , _has_multiple_bundles(false) |
duke@435 | 500 | , _has_branch_delay_slot(false) |
duke@435 | 501 | , _force_serialization(false) |
duke@435 | 502 | , _may_have_no_code(false) { |
duke@435 | 503 | } |
duke@435 | 504 | |
duke@435 | 505 | PipeClassForm::~PipeClassForm() { |
duke@435 | 506 | } |
duke@435 | 507 | |
duke@435 | 508 | PipeClassForm *PipeClassForm::is_pipeclass() const { |
duke@435 | 509 | return (PipeClassForm *)(this); |
duke@435 | 510 | } |
duke@435 | 511 | |
duke@435 | 512 | void PipeClassForm::dump() { |
duke@435 | 513 | output(stderr); |
duke@435 | 514 | } |
duke@435 | 515 | |
duke@435 | 516 | void PipeClassForm::output(FILE *fp) { // Write info to output files |
duke@435 | 517 | fprintf(fp,"PipeClassForm: #%03d", _num); |
duke@435 | 518 | if (_ident) |
duke@435 | 519 | fprintf(fp," \"%s\":", _ident); |
duke@435 | 520 | if (_has_fixed_latency) |
duke@435 | 521 | fprintf(fp," latency %d", _fixed_latency); |
duke@435 | 522 | if (_force_serialization) |
duke@435 | 523 | fprintf(fp, ", force serialization"); |
duke@435 | 524 | if (_may_have_no_code) |
duke@435 | 525 | fprintf(fp, ", may have no code"); |
duke@435 | 526 | fprintf(fp, ", %d instruction%s\n", InstructionCount(), InstructionCount() != 1 ? "s" : ""); |
duke@435 | 527 | } |
duke@435 | 528 | |
duke@435 | 529 | |
duke@435 | 530 | //==============================Peephole Optimization========================== |
duke@435 | 531 | int Peephole::_peephole_counter = 0; |
duke@435 | 532 | //------------------------------Peephole--------------------------------------- |
duke@435 | 533 | Peephole::Peephole() : _match(NULL), _constraint(NULL), _replace(NULL), _next(NULL) { |
duke@435 | 534 | _peephole_number = _peephole_counter++; |
duke@435 | 535 | } |
duke@435 | 536 | Peephole::~Peephole() { |
duke@435 | 537 | } |
duke@435 | 538 | |
duke@435 | 539 | // Append a peephole rule with the same root instruction |
duke@435 | 540 | void Peephole::append_peephole(Peephole *next_peephole) { |
duke@435 | 541 | if( _next == NULL ) { |
duke@435 | 542 | _next = next_peephole; |
duke@435 | 543 | } else { |
duke@435 | 544 | _next->append_peephole( next_peephole ); |
duke@435 | 545 | } |
duke@435 | 546 | } |
duke@435 | 547 | |
duke@435 | 548 | // Store the components of this peephole rule |
duke@435 | 549 | void Peephole::add_match(PeepMatch *match) { |
duke@435 | 550 | assert( _match == NULL, "fatal()" ); |
duke@435 | 551 | _match = match; |
duke@435 | 552 | } |
duke@435 | 553 | |
duke@435 | 554 | void Peephole::append_constraint(PeepConstraint *next_constraint) { |
duke@435 | 555 | if( _constraint == NULL ) { |
duke@435 | 556 | _constraint = next_constraint; |
duke@435 | 557 | } else { |
duke@435 | 558 | _constraint->append( next_constraint ); |
duke@435 | 559 | } |
duke@435 | 560 | } |
duke@435 | 561 | |
duke@435 | 562 | void Peephole::add_replace(PeepReplace *replace) { |
duke@435 | 563 | assert( _replace == NULL, "fatal()" ); |
duke@435 | 564 | _replace = replace; |
duke@435 | 565 | } |
duke@435 | 566 | |
duke@435 | 567 | // class Peephole accessor methods are in the declaration. |
duke@435 | 568 | |
duke@435 | 569 | |
duke@435 | 570 | void Peephole::dump() { |
duke@435 | 571 | output(stderr); |
duke@435 | 572 | } |
duke@435 | 573 | |
duke@435 | 574 | void Peephole::output(FILE *fp) { // Write info to output files |
duke@435 | 575 | fprintf(fp,"Peephole:\n"); |
duke@435 | 576 | if( _match != NULL ) _match->output(fp); |
duke@435 | 577 | if( _constraint != NULL ) _constraint->output(fp); |
duke@435 | 578 | if( _replace != NULL ) _replace->output(fp); |
duke@435 | 579 | // Output the next entry |
duke@435 | 580 | if( _next ) _next->output(fp); |
duke@435 | 581 | } |
duke@435 | 582 | |
duke@435 | 583 | //------------------------------PeepMatch-------------------------------------- |
duke@435 | 584 | PeepMatch::PeepMatch(char *rule) : _max_position(0), _rule(rule) { |
duke@435 | 585 | } |
duke@435 | 586 | PeepMatch::~PeepMatch() { |
duke@435 | 587 | } |
duke@435 | 588 | |
duke@435 | 589 | |
duke@435 | 590 | // Insert info into the match-rule |
duke@435 | 591 | void PeepMatch::add_instruction(int parent, int position, const char *name, |
duke@435 | 592 | int input) { |
duke@435 | 593 | if( position > _max_position ) _max_position = position; |
duke@435 | 594 | |
duke@435 | 595 | _parent.addName((char *)parent); |
duke@435 | 596 | _position.addName((char *)position); |
duke@435 | 597 | _instrs.addName(name); |
duke@435 | 598 | _input.addName((char *)input); |
duke@435 | 599 | } |
duke@435 | 600 | |
duke@435 | 601 | // Access info about instructions in the peep-match rule |
duke@435 | 602 | int PeepMatch::max_position() { |
duke@435 | 603 | return _max_position; |
duke@435 | 604 | } |
duke@435 | 605 | |
duke@435 | 606 | const char *PeepMatch::instruction_name(intptr_t position) { |
duke@435 | 607 | return _instrs.name(position); |
duke@435 | 608 | } |
duke@435 | 609 | |
duke@435 | 610 | // Iterate through all info on matched instructions |
duke@435 | 611 | void PeepMatch::reset() { |
duke@435 | 612 | _parent.reset(); |
duke@435 | 613 | _position.reset(); |
duke@435 | 614 | _instrs.reset(); |
duke@435 | 615 | _input.reset(); |
duke@435 | 616 | } |
duke@435 | 617 | |
duke@435 | 618 | void PeepMatch::next_instruction( intptr_t &parent, intptr_t &position, const char * &name, intptr_t &input ){ |
duke@435 | 619 | parent = (intptr_t)_parent.iter(); |
duke@435 | 620 | position = (intptr_t)_position.iter(); |
duke@435 | 621 | name = _instrs.iter(); |
duke@435 | 622 | input = (intptr_t)_input.iter(); |
duke@435 | 623 | } |
duke@435 | 624 | |
duke@435 | 625 | // 'true' if current position in iteration is a placeholder, not matched. |
duke@435 | 626 | bool PeepMatch::is_placeholder() { |
duke@435 | 627 | return _instrs.current_is_signal(); |
duke@435 | 628 | } |
duke@435 | 629 | |
duke@435 | 630 | |
duke@435 | 631 | void PeepMatch::dump() { |
duke@435 | 632 | output(stderr); |
duke@435 | 633 | } |
duke@435 | 634 | |
duke@435 | 635 | void PeepMatch::output(FILE *fp) { // Write info to output files |
duke@435 | 636 | fprintf(fp,"PeepMatch:\n"); |
duke@435 | 637 | } |
duke@435 | 638 | |
duke@435 | 639 | //------------------------------PeepConstraint--------------------------------- |
duke@435 | 640 | PeepConstraint::PeepConstraint(intptr_t left_inst, char *left_op, char *relation, |
duke@435 | 641 | intptr_t right_inst, char *right_op) |
duke@435 | 642 | : _left_inst(left_inst), _left_op(left_op), _relation(relation), |
duke@435 | 643 | _right_inst(right_inst), _right_op(right_op), _next(NULL) {} |
duke@435 | 644 | PeepConstraint::~PeepConstraint() { |
duke@435 | 645 | } |
duke@435 | 646 | |
duke@435 | 647 | // Check if constraints use instruction at position |
duke@435 | 648 | bool PeepConstraint::constrains_instruction(intptr_t position) { |
duke@435 | 649 | // Check local instruction constraints |
duke@435 | 650 | if( _left_inst == position ) return true; |
duke@435 | 651 | if( _right_inst == position ) return true; |
duke@435 | 652 | |
duke@435 | 653 | // Check remaining constraints in list |
duke@435 | 654 | if( _next == NULL ) return false; |
duke@435 | 655 | else return _next->constrains_instruction(position); |
duke@435 | 656 | } |
duke@435 | 657 | |
duke@435 | 658 | // Add another constraint |
duke@435 | 659 | void PeepConstraint::append(PeepConstraint *next_constraint) { |
duke@435 | 660 | if( _next == NULL ) { |
duke@435 | 661 | _next = next_constraint; |
duke@435 | 662 | } else { |
duke@435 | 663 | _next->append( next_constraint ); |
duke@435 | 664 | } |
duke@435 | 665 | } |
duke@435 | 666 | |
duke@435 | 667 | // Access the next constraint in the list |
duke@435 | 668 | PeepConstraint *PeepConstraint::next() { |
duke@435 | 669 | return _next; |
duke@435 | 670 | } |
duke@435 | 671 | |
duke@435 | 672 | |
duke@435 | 673 | void PeepConstraint::dump() { |
duke@435 | 674 | output(stderr); |
duke@435 | 675 | } |
duke@435 | 676 | |
duke@435 | 677 | void PeepConstraint::output(FILE *fp) { // Write info to output files |
duke@435 | 678 | fprintf(fp,"PeepConstraint:\n"); |
duke@435 | 679 | } |
duke@435 | 680 | |
duke@435 | 681 | //------------------------------PeepReplace------------------------------------ |
duke@435 | 682 | PeepReplace::PeepReplace(char *rule) : _rule(rule) { |
duke@435 | 683 | } |
duke@435 | 684 | PeepReplace::~PeepReplace() { |
duke@435 | 685 | } |
duke@435 | 686 | |
duke@435 | 687 | // Add contents of peepreplace |
duke@435 | 688 | void PeepReplace::add_instruction(char *root) { |
duke@435 | 689 | _instruction.addName(root); |
duke@435 | 690 | _operand_inst_num.add_signal(); |
duke@435 | 691 | _operand_op_name.add_signal(); |
duke@435 | 692 | } |
duke@435 | 693 | void PeepReplace::add_operand( int inst_num, char *inst_operand ) { |
duke@435 | 694 | _instruction.add_signal(); |
duke@435 | 695 | _operand_inst_num.addName((char*)inst_num); |
duke@435 | 696 | _operand_op_name.addName(inst_operand); |
duke@435 | 697 | } |
duke@435 | 698 | |
duke@435 | 699 | // Access contents of peepreplace |
duke@435 | 700 | void PeepReplace::reset() { |
duke@435 | 701 | _instruction.reset(); |
duke@435 | 702 | _operand_inst_num.reset(); |
duke@435 | 703 | _operand_op_name.reset(); |
duke@435 | 704 | } |
duke@435 | 705 | void PeepReplace::next_instruction(const char * &inst){ |
duke@435 | 706 | inst = _instruction.iter(); |
duke@435 | 707 | intptr_t inst_num = (intptr_t)_operand_inst_num.iter(); |
duke@435 | 708 | const char *inst_operand = _operand_op_name.iter(); |
duke@435 | 709 | } |
duke@435 | 710 | void PeepReplace::next_operand( intptr_t &inst_num, const char * &inst_operand ) { |
duke@435 | 711 | const char *inst = _instruction.iter(); |
duke@435 | 712 | inst_num = (intptr_t)_operand_inst_num.iter(); |
duke@435 | 713 | inst_operand = _operand_op_name.iter(); |
duke@435 | 714 | } |
duke@435 | 715 | |
duke@435 | 716 | |
duke@435 | 717 | |
duke@435 | 718 | void PeepReplace::dump() { |
duke@435 | 719 | output(stderr); |
duke@435 | 720 | } |
duke@435 | 721 | |
duke@435 | 722 | void PeepReplace::output(FILE *fp) { // Write info to output files |
duke@435 | 723 | fprintf(fp,"PeepReplace:\n"); |
duke@435 | 724 | } |