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