00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 #include <ctype.h>
00066
00067 #include "defs.h"
00068 #include "util.h"
00069 #include "config.h"
00070 #include "config_targ_opt.h"
00071 #include "erglob.h"
00072 #include "tracing.h"
00073 #include "data_layout.h"
00074 #include "const.h"
00075 #include "wn.h"
00076 #include "import.h"
00077 #include "opt_alias_interface.h"
00078 #include "opt_alias_mgr.h"
00079 #include "cgir.h"
00080 #include "cg.h"
00081 #include "void_list.h"
00082 #include "cg_dep_graph.h"
00083 #include "cg_spill.h"
00084 #include "cg_vector.h"
00085 #include "whirl2ops.h"
00086 #include "ti_errors.h"
00087 #include "ti_latency.h"
00088 #include "w2op.h"
00089 #include "cgexp.h"
00090 #include "cg_loop_recur.h"
00091 #include "targ_proc_properties.h"
00092 #include "ti_bundle.h"
00093 #include "hb_sched.h"
00094 #include "hb_hazards.h"
00095 #include "bb.h"
00096 #include "op.h"
00097 #include "op_list.h"
00098 #include "cg_grouping.h"
00099 #include "calls.h"
00100 #include "cgtarget.h"
00101 #include "calls.h"
00102 #include "cg_loop.h"
00103 #include "config_lno.h"
00104
00105 UINT32 CGTARG_branch_taken_penalty;
00106 BOOL CGTARG_branch_taken_penalty_overridden = FALSE;
00107
00108 TOP CGTARG_Invert_Table[TOP_count+1];
00109 TOP CGTARG_Immed_To_Reg_Table[TOP_count+1];
00110
00111 OPCODE CGTARG_Assoc_Base_Opr_Table[TOP_count];
00112 mTOP CGTARG_Assoc_Base_Top_Table[TOP_count];
00113 mTOP CGTARG_Assoc_Base_Fnc_Table[TOP_count];
00114
00115 mTOP CGTARG_Inter_RegClass_Copy_Table[ISA_REGISTER_CLASS_MAX+1][ISA_REGISTER_CLASS_MAX+1][2];
00116
00117
00118 BOOL Trace_TD = FALSE;
00119 BOOL Trace_Eager = FALSE;
00120 extern BOOL Trace_Call_Exp;
00121
00122
00123 UINT32 CGTARG_Mem_Ref_Bytes(const OP *memop)
00124
00125
00126
00127
00128
00129 {
00130 const TOP topcode = OP_code(memop);
00131
00132 if (TOP_is_vector_op(topcode)) {
00133 switch (topcode) {
00134 case TOP_stlps:
00135 case TOP_stlpsx:
00136 case TOP_stlpsxx:
00137 case TOP_stlps_n32:
00138 case TOP_stlpd:
00139 case TOP_stlpdx:
00140 case TOP_stlpdxx:
00141 case TOP_stlpd_n32:
00142 case TOP_ldlps:
00143 case TOP_ldlpsx:
00144 case TOP_ldlpsxx:
00145 case TOP_ldlps_n32:
00146 case TOP_ldlpd:
00147 case TOP_ldlpdx:
00148 case TOP_ldlpdxx:
00149 case TOP_ldlpd_n32:
00150 case TOP_sthps:
00151 case TOP_sthpsx:
00152 case TOP_sthpsxx:
00153 case TOP_sthpd:
00154 case TOP_sthpdx:
00155 case TOP_sthpdxx:
00156 case TOP_sthpd_n32:
00157 case TOP_ldhps:
00158 case TOP_ldhpsx:
00159 case TOP_ldhpsxx:
00160 case TOP_ldhpd:
00161 case TOP_ldhpdx:
00162 case TOP_ldhpdxx:
00163 case TOP_ldhpd_n32:
00164 return 8;
00165 default:
00166 return 16;
00167 }
00168 }
00169
00170
00171
00172
00173
00174 if (OP_flop(memop) &&
00175 !TOP_is_x87(topcode)) {
00176 switch (topcode) {
00177 case TOP_ldss:
00178 case TOP_ldss_n32:
00179 case TOP_ldssx:
00180 case TOP_ldssxx:
00181 case TOP_stssxx:
00182 case TOP_stss:
00183 case TOP_stss_n32:
00184 case TOP_stssx:
00185 case TOP_stntss:
00186 case TOP_stntssx:
00187 case TOP_stntssxx:
00188 case TOP_divxxxss:
00189 case TOP_addxxxss:
00190 case TOP_subxxxss:
00191 case TOP_mulxxxss:
00192 case TOP_comixss:
00193 case TOP_comixxss:
00194 case TOP_comixxxss:
00195 case TOP_divxss:
00196 case TOP_divxxss:
00197 case TOP_addxss:
00198 case TOP_subxss:
00199 case TOP_mulxss:
00200 case TOP_addxxss:
00201 case TOP_subxxss:
00202 case TOP_mulxxss:
00203 case TOP_cvtsi2ss_x:
00204 case TOP_cvtsi2ss_xx:
00205 case TOP_cvtsi2ss_xxx:
00206 return 4;
00207
00208 case TOP_ldsd:
00209 case TOP_ldsd_n32:
00210 case TOP_ldsdx:
00211 case TOP_ldsdxx:
00212 case TOP_stsdxx:
00213 case TOP_stsd:
00214 case TOP_stsd_n32:
00215 case TOP_stsdx:
00216 case TOP_stntsd:
00217 case TOP_stntsdx:
00218 case TOP_stntsdxx:
00219 case TOP_storelpd:
00220 case TOP_divxxxsd:
00221 case TOP_addxxxsd:
00222 case TOP_subxxxsd:
00223 case TOP_mulxxxsd:
00224 case TOP_comixsd:
00225 case TOP_comixxsd:
00226 case TOP_comixxxsd:
00227 case TOP_divxsd:
00228 case TOP_divxxsd:
00229 case TOP_addxsd:
00230 case TOP_subxsd:
00231 case TOP_mulxsd:
00232 case TOP_addxxsd:
00233 case TOP_subxxsd:
00234 case TOP_mulxxsd:
00235 case TOP_cvtsd2ss_x:
00236 case TOP_cvtsd2ss_xx:
00237 case TOP_cvtsd2ss_xxx:
00238 case TOP_cvtsi2sd_x:
00239 case TOP_cvtsi2sd_xx:
00240 case TOP_cvtsi2sd_xxx:
00241 case TOP_cvtsi2sdq_x:
00242 case TOP_cvtsi2sdq_xx:
00243 case TOP_cvtsi2sdq_xxx:
00244 case TOP_cvtsi2ssq_x:
00245 case TOP_cvtsi2ssq_xx:
00246 case TOP_cvtsi2ssq_xxx:
00247 return 8;
00248
00249 case TOP_lddqa:
00250 case TOP_lddqa_n32:
00251 case TOP_lddqu:
00252 case TOP_ldapd:
00253 case TOP_ldapd_n32:
00254 case TOP_ldaps:
00255 case TOP_ldaps_n32:
00256 case TOP_ldups:
00257 case TOP_ldups_n32:
00258 case TOP_ldupd:
00259 case TOP_ldupd_n32:
00260 case TOP_lddqax:
00261 case TOP_lddqux:
00262 case TOP_ldapdx:
00263 case TOP_ldapsx:
00264 case TOP_lddqaxx:
00265 case TOP_lddquxx:
00266 case TOP_ldapdxx:
00267 case TOP_ldapsxx:
00268 case TOP_fmovsldupx:
00269 case TOP_fmovshdupx:
00270 case TOP_fmovddupx:
00271 case TOP_fmovsldupxx:
00272 case TOP_fmovshdupxx:
00273 case TOP_fmovddupxx:
00274 case TOP_fmovsldupxxx:
00275 case TOP_fmovshdupxxx:
00276 case TOP_fmovddupxxx:
00277 case TOP_stdqa:
00278 case TOP_stdqa_n32:
00279 case TOP_stntpd:
00280 case TOP_stntps:
00281 case TOP_stdqu:
00282 case TOP_stdqax:
00283 case TOP_stntpdx:
00284 case TOP_stntpsx:
00285 case TOP_stdqux:
00286 case TOP_stdqaxx:
00287 case TOP_stntpdxx:
00288 case TOP_stntpsxx:
00289 case TOP_stdquxx:
00290 case TOP_staps:
00291 case TOP_staps_n32:
00292 case TOP_stapd:
00293 case TOP_stapd_n32:
00294 case TOP_stapsx:
00295 case TOP_stapdx:
00296 case TOP_stapsxx:
00297 case TOP_stapdxx:
00298 case TOP_storenti128:
00299 return 16;
00300
00301 case TOP_store64_fm:
00302 case TOP_store64_fm_n32:
00303 break;
00304
00305 default:
00306 FmtAssert(FALSE, ("CGTARG_Mem_Ref_Bytes: unknown SSE OP code"));
00307 }
00308 }
00309
00310 if( OP_store( memop ) ){
00311 const int opnd = OP_find_opnd_use( memop, OU_storeval );
00312 return OP_opnd_size( (OP*)memop, opnd ) / 8;
00313 }
00314
00315 switch (topcode){
00316 case TOP_xor8:
00317 case TOP_xorx8:
00318 case TOP_xorxx8:
00319 case TOP_xorxxx8:
00320 case TOP_and8:
00321 case TOP_andx8:
00322 case TOP_andxx8:
00323 case TOP_andxxx8:
00324 case TOP_cmp8:
00325 case TOP_cmpx8:
00326 case TOP_cmpxx8:
00327 case TOP_cmpxxx8:
00328 case TOP_cmpxi8:
00329 case TOP_cmpxxi8:
00330 case TOP_cmpxxxi8:
00331 case TOP_or8:
00332 case TOP_orx8:
00333 case TOP_orxx8:
00334 case TOP_orxxx8:
00335 case TOP_ld8_32_n32:
00336 case TOP_ldu8_32_n32:
00337 case TOP_ld8_32:
00338 case TOP_ldx8_32:
00339 case TOP_ldxx8_32:
00340 case TOP_ldu8_32:
00341 case TOP_ldxu8_32:
00342 case TOP_ldxxu8_32:
00343 case TOP_ld8_64:
00344 case TOP_ldx8_64:
00345 case TOP_ldxx8_64:
00346 case TOP_ldu8_64:
00347 case TOP_ldxu8_64:
00348 case TOP_ldxxu8_64:
00349 case TOP_ld8_abs:
00350 case TOP_lock_xadd8:
00351 return 1;
00352
00353 case TOP_xor16:
00354 case TOP_xorx16:
00355 case TOP_xorxx16:
00356 case TOP_xorxxx16:
00357 case TOP_and16:
00358 case TOP_andx16:
00359 case TOP_andxx16:
00360 case TOP_andxxx16:
00361 case TOP_cmp16:
00362 case TOP_cmpx16:
00363 case TOP_cmpxx16:
00364 case TOP_cmpxxx16:
00365 case TOP_cmpxi16:
00366 case TOP_cmpxxi16:
00367 case TOP_cmpxxxi16:
00368 case TOP_or16:
00369 case TOP_orx16:
00370 case TOP_orxx16:
00371 case TOP_orxxx16:
00372 case TOP_ld16_32_n32:
00373 case TOP_ldu16_32_n32:
00374 case TOP_ld16_32:
00375 case TOP_ldx16_32:
00376 case TOP_ldxx16_32:
00377 case TOP_ldu16_32:
00378 case TOP_ldxu16_32:
00379 case TOP_ldxxu16_32:
00380 case TOP_ld16_64:
00381 case TOP_ldx16_64:
00382 case TOP_ldxx16_64:
00383 case TOP_ldu16_64:
00384 case TOP_ldxu16_64:
00385 case TOP_ldxxu16_64:
00386 case TOP_fldcw:
00387 case TOP_filds:
00388 case TOP_ld16_abs:
00389 case TOP_lock_xadd16:
00390 return 2;
00391
00392 case TOP_xorx32:
00393 case TOP_xorxx32:
00394 case TOP_xorxxx32:
00395 case TOP_orx32:
00396 case TOP_orxx32:
00397 case TOP_orxxx32:
00398 case TOP_andx32:
00399 case TOP_andxx32:
00400 case TOP_andxxx32:
00401 case TOP_cmpx32:
00402 case TOP_cmpxx32:
00403 case TOP_cmpxxx32:
00404 case TOP_cmpxi32:
00405 case TOP_cmpxxi32:
00406 case TOP_cmpxxxi32:
00407 case TOP_testx32:
00408 case TOP_testxx32:
00409 case TOP_testxxx32:
00410 case TOP_ld32_n32:
00411 case TOP_ld32:
00412 case TOP_ldx32:
00413 case TOP_ldxx32:
00414 case TOP_ld32_64:
00415 case TOP_ldx32_64:
00416 case TOP_ldxx32_64:
00417 case TOP_ldss:
00418 case TOP_ldss_n32:
00419 case TOP_ldssx:
00420 case TOP_ldssxx:
00421 case TOP_addx32:
00422 case TOP_subx32:
00423 case TOP_addxx32:
00424 case TOP_subxx32:
00425 case TOP_addxxx32:
00426 case TOP_subxxx32:
00427 case TOP_addxss:
00428 case TOP_subxss:
00429 case TOP_addxxss:
00430 case TOP_subxxss:
00431 case TOP_addxxxss:
00432 case TOP_subxxxss:
00433 case TOP_mulxss:
00434 case TOP_mulxxss:
00435 case TOP_mulxxxss:
00436 case TOP_divxss:
00437 case TOP_divxxss:
00438 case TOP_divxxxss:
00439 case TOP_comixss:
00440 case TOP_comixxss:
00441 case TOP_comixxxss:
00442 case TOP_fildl:
00443 case TOP_flds:
00444 case TOP_flds_n32:
00445 case TOP_ld32_abs:
00446 case TOP_cvtsi2sd_x:
00447 case TOP_cvtsi2sd_xx:
00448 case TOP_cvtsi2sd_xxx:
00449 case TOP_cvtsi2ss_x:
00450 case TOP_cvtsi2ss_xx:
00451 case TOP_cvtsi2ss_xxx:
00452 case TOP_lock_add32:
00453 case TOP_lock_adc32:
00454 case TOP_lock_and32:
00455 case TOP_lock_or32:
00456 case TOP_lock_xor32:
00457 case TOP_lock_sub32:
00458 case TOP_lock_xadd32:
00459 return 4;
00460
00461 case TOP_xorx64:
00462 case TOP_xorxx64:
00463 case TOP_xorxxx64:
00464 case TOP_orx64:
00465 case TOP_orxx64:
00466 case TOP_orxxx64:
00467 case TOP_andx64:
00468 case TOP_andxx64:
00469 case TOP_andxxx64:
00470 case TOP_cmpx64:
00471 case TOP_cmpxx64:
00472 case TOP_cmpxxx64:
00473 case TOP_cmpxi64:
00474 case TOP_cmpxxi64:
00475 case TOP_cmpxxxi64:
00476 case TOP_testx64:
00477 case TOP_testxx64:
00478 case TOP_testxxx64:
00479 case TOP_ld64:
00480 case TOP_ldx64:
00481 case TOP_ldxx64:
00482 case TOP_ldsd_n32:
00483 case TOP_ldsd:
00484 case TOP_ldsdx:
00485 case TOP_ldsdxx:
00486 case TOP_ld64_2m:
00487 case TOP_ld64_2m_n32:
00488 case TOP_addx64:
00489 case TOP_subx64:
00490 case TOP_addxx64:
00491 case TOP_subxx64:
00492 case TOP_addxxx64:
00493 case TOP_subxxx64:
00494 case TOP_addxsd:
00495 case TOP_subxsd:
00496 case TOP_addxxsd:
00497 case TOP_subxxsd:
00498 case TOP_addxxxsd:
00499 case TOP_subxxxsd:
00500 case TOP_mulxsd:
00501 case TOP_mulxxsd:
00502 case TOP_mulxxxsd:
00503 case TOP_divxsd:
00504 case TOP_divxxsd:
00505 case TOP_divxxxsd:
00506 case TOP_comixsd:
00507 case TOP_comixxsd:
00508 case TOP_comixxxsd:
00509 case TOP_ijmpx:
00510 case TOP_ijmpxx:
00511 case TOP_ijmpxxx:
00512 case TOP_icallx:
00513 case TOP_icallxx:
00514 case TOP_icallxxx:
00515 case TOP_fildll:
00516 case TOP_fldl:
00517 case TOP_fldl_n32:
00518 case TOP_ld64_abs:
00519 case TOP_ld64_off:
00520 case TOP_cvtsd2ss_x:
00521 case TOP_cvtsd2ss_xx:
00522 case TOP_cvtsd2ss_xxx:
00523 case TOP_cvtsi2sdq_x:
00524 case TOP_cvtsi2sdq_xx:
00525 case TOP_cvtsi2sdq_xxx:
00526 case TOP_cvtsi2ssq_x:
00527 case TOP_cvtsi2ssq_xx:
00528 case TOP_cvtsi2ssq_xxx:
00529 case TOP_lock_add64:
00530 case TOP_lock_and64:
00531 case TOP_lock_or64:
00532 case TOP_lock_xor64:
00533 case TOP_lock_sub64:
00534 case TOP_lock_xadd64:
00535 case TOP_fmovsldupx:
00536 case TOP_fmovshdupx:
00537 case TOP_fmovddupx:
00538 case TOP_fmovsldupxx:
00539 case TOP_fmovshdupxx:
00540 case TOP_fmovddupxx:
00541 case TOP_fmovsldupxxx:
00542 case TOP_fmovshdupxxx:
00543 case TOP_fmovddupxxx:
00544 return 8;
00545
00546 case TOP_fldt:
00547 case TOP_fldt_n32:
00548 return 16;
00549 }
00550
00551 FmtAssert( false, ("Unknown mem ref bytes: %s", TOP_Name(topcode)) );
00552 return 0;
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 BOOL
00564 CGTARG_Is_OP_Speculative(OP *op)
00565 {
00566 if (!OP_load(op)) return FALSE;
00567
00568
00569 if (CGTARG_Is_OP_Advanced_Load(op) || CGTARG_Is_OP_Speculative_Load(op))
00570 return TRUE;
00571
00572 return FALSE;
00573 }
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 void CGTARG_Perform_THR_Code_Generation (OP *load_op, OP *chk_load,
00584 THR_TYPE type)
00585 {
00586 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 INT CGTARG_ARC_Sched_Latency(
00598 ARC *arc
00599 )
00600 {
00601 if ( ARC_kind(arc) == CG_DEP_PREBR &&
00602 PROC_has_same_cycle_branch_shadow() )
00603 return 0;
00604 else
00605 return ARC_latency(arc);
00606 }
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 BOOL
00618 CGTARG_Bundle_Slot_Available(TI_BUNDLE *bundle,
00619 OP *op,
00620 INT slot,
00621 ISA_EXEC_UNIT_PROPERTY *prop,
00622 BOOL stop_bit_reqd,
00623 const CG_GROUPING *grouping)
00624 {
00625 return FALSE;
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 BOOL
00637 CGTARG_Bundle_Stop_Bit_Available(TI_BUNDLE *bundle, INT slot)
00638 {
00639
00640 if (TI_BUNDLE_stop_bit(bundle, slot)) return TRUE;
00641
00642 return TI_BUNDLE_Stop_Bit_Available(bundle, slot);
00643 }
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 void
00654 CGTARG_Handle_Bundle_Hazard (OP *op,
00655 TI_BUNDLE *bundle,
00656 VECTOR *bundle_vector,
00657 BOOL can_fill,
00658 INT slot_pos,
00659 INT max_pos,
00660 BOOL stop_bit_reqd,
00661 ISA_EXEC_UNIT_PROPERTY prop)
00662 {
00663 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
00664 }
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 void
00675 CGTARG_Handle_Errata_Hazard (OP *op, INT erratnum, INT ops_to_check)
00676 {
00677 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 static void
00694 Reduce_Fraction(INT frac[2])
00695 {
00696 INT i;
00697 static const INT primes[] = {2, 3, 5, 7, 11, 13};
00698 INT n = frac[0];
00699 INT d = frac[1];
00700 INT p = d;
00701
00702 if (d < -1 || d > 1) {
00703 for (i = sizeof(primes) / sizeof(primes[0]); ; p = primes[--i]) {
00704 while (n % p == 0 && d % p == 0) {
00705 n = n / p;
00706 d = d / p;
00707 }
00708 if (i == 0) break;
00709 }
00710 }
00711
00712 frac[0] = n;
00713 frac[1] = d;
00714 }
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734 static void
00735 Harmonic_Mean(
00736 INT mean[2],
00737 INT a,
00738 const INT a_rate[2],
00739 INT b,
00740 const INT b_rate[2]
00741 ) {
00742 if (a == 0) {
00743 mean[0] = b_rate[0];
00744 mean[1] = b_rate[1];
00745 } else if (b == 0) {
00746 mean[0] = a_rate[0];
00747 mean[1] = a_rate[1];
00748 } else {
00749 mean[1] = (a * a_rate[1] * b_rate[0])
00750 + (b * b_rate[1] * a_rate[0]);
00751 mean[0] = (a + b) * a_rate[0] * b_rate[0];
00752 Reduce_Fraction(mean);
00753 }
00754 }
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765 void CGTARG_Peak_Rate( PEAK_RATE_CLASS prc, PRC_INFO *info, INT ratio[2] )
00766 {
00767 ratio[0] = 1;
00768 ratio[1] = 1;
00769
00770 switch (prc) {
00771 case PRC_INST:
00772 ratio[0] = 4;
00773 break;
00774 case PRC_MADD:
00775 case PRC_MEMREF:
00776 ratio[0] = 2;
00777 break;
00778 case PRC_FLOP:
00779 case PRC_FADD:
00780 case PRC_FMUL:
00781 ratio[0] = 2;
00782 break;
00783 case PRC_IOP:
00784 ratio[0] = 2;
00785 break;
00786 default:
00787 ratio[0] = 2;
00788 break;
00789 }
00790 }
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 #define Plural(i) ((i) != 1 ? "s" : "")
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 static INT
00815 Percent_Of_Peak(INT numer, INT denom, INT peak[2])
00816 {
00817 if (numer == 0) return 0;
00818 return (numer * peak[1] * 100) / ((denom * peak[0]) + peak[1] - 1);
00819 }
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830 void
00831 CGTARG_Print_PRC_INFO(
00832 FILE *file,
00833 PRC_INFO *info,
00834 INT32 ii,
00835 const char *prefix,
00836 const char *suffix
00837 )
00838 {
00839 const char *s;
00840 INT madds_per_cycle[2];
00841 INT memrefs_per_cycle[2];
00842 INT flops_per_cycle[2];
00843 INT fadds_per_cycle[2];
00844 INT fmuls_per_cycle[2];
00845 INT iops_per_cycle[2];
00846 INT insts_per_cycle[2];
00847 INT insts = info->refs[PRC_INST];
00848 INT memrefs = info->refs[PRC_MEMREF];
00849 INT flops = info->refs[PRC_FLOP];
00850 INT madds = info->refs[PRC_MADD];
00851 INT fadds = info->refs[PRC_FADD];
00852 INT fmuls = info->refs[PRC_FMUL];
00853 INT iops = info->refs[PRC_IOP];
00854
00855 CGTARG_Peak_Rate(PRC_INST, info, insts_per_cycle);
00856 CGTARG_Peak_Rate(PRC_MEMREF, info, memrefs_per_cycle);
00857 CGTARG_Peak_Rate(PRC_FLOP, info, flops_per_cycle);
00858 CGTARG_Peak_Rate(PRC_MADD, info, madds_per_cycle);
00859 CGTARG_Peak_Rate(PRC_FADD, info, fadds_per_cycle);
00860 CGTARG_Peak_Rate(PRC_FMUL, info, fmuls_per_cycle);
00861 CGTARG_Peak_Rate(PRC_IOP, info, iops_per_cycle);
00862
00863 FmtAssert( madds == 0, ("madds != 0 ") );
00864
00865 if (flops != 0) {
00866 BOOL unbalanced_fpu = FALSE;
00867
00868 if ( madds_per_cycle[0] != 0 ) {
00869 fprintf(file,"%s%5d flop%1s (%3d%% of peak)%s",
00870 prefix,
00871 flops,
00872 Plural(flops),
00873 Percent_Of_Peak(flops, ii, flops_per_cycle),
00874 suffix);
00875 }
00876 else {
00877 fprintf(file,"%s%5d flop%1s (%3d%% of peak)%s",
00878 prefix,
00879 flops,
00880 Plural(flops),
00881 Percent_Of_Peak(flops, ii, flops_per_cycle),
00882 suffix);
00883 }
00884
00885 if ( unbalanced_fpu ) {
00886 INT fmuls2_per_cycle[2];
00887 INT fadds2_per_cycle[2];
00888 INT fadds2 = fadds + madds;
00889 INT fmuls2 = fmuls + madds;
00890
00891 Harmonic_Mean(fmuls2_per_cycle,
00892 fmuls, fmuls_per_cycle,
00893 madds, madds_per_cycle);
00894 Harmonic_Mean(fadds2_per_cycle,
00895 fadds, fadds_per_cycle,
00896 madds, madds_per_cycle);
00897
00898 fprintf(file,"%s%5d fmul%1s (%3d%% of peak)%s%s",
00899 prefix,
00900 fmuls2,
00901 Plural(fmuls2),
00902 Percent_Of_Peak(fmuls2, ii, fmuls2_per_cycle),
00903 madds_per_cycle[0] ? " (madds count as 1)" : "",
00904 suffix);
00905 fprintf(file,"%s%5d fadd%1s (%3d%% of peak)%s%s",
00906 prefix,
00907 fadds2,
00908 Plural(fadds2),
00909 Percent_Of_Peak(fadds2, ii, fadds2_per_cycle),
00910 madds_per_cycle[0] ? " (madds count as 1)" : "",
00911 suffix);
00912 }
00913 }
00914
00915 s = "";
00916 if (FALSE) {
00917 iops += memrefs;
00918 s = " (mem refs included)";
00919 }
00920
00921 fprintf(file,"%s%5d mem ref%1s (%3d%% of peak)%s"
00922 "%s%5d integer op%1s (%3d%% of peak)%s%s"
00923 "%s%5d instruction%1s (%3d%% of peak)%s",
00924 prefix,
00925 memrefs,
00926 Plural(memrefs),
00927 Percent_Of_Peak(memrefs, ii, memrefs_per_cycle),
00928 suffix,
00929 prefix,
00930 iops,
00931 Plural(iops),
00932 Percent_Of_Peak(iops, ii, iops_per_cycle),
00933 s,
00934 suffix,
00935 prefix,
00936 insts,
00937 Plural(insts),
00938 Percent_Of_Peak(insts, ii, insts_per_cycle),
00939 suffix);
00940 }
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 void
00953 CGTARG_Compute_PRC_INFO(
00954 BB *bb,
00955 PRC_INFO *info
00956 )
00957 {
00958 OP *op;
00959
00960 bzero (info, sizeof (PRC_INFO));
00961
00962 for ( op = BB_first_op(bb); op != NULL; op = OP_next(op) ) {
00963 INT num_insts = OP_Real_Ops (op);
00964
00965 if (num_insts == 0) continue;
00966
00967 info->refs[PRC_INST] += num_insts;
00968
00969 if( OP_memory(op) || OP_load_exe(op) ){
00970 ++info->refs[PRC_MEMREF];
00971 }
00972
00973 if( OP_memory(op) && !OP_load_exe(op) ){
00974 ;
00975 }
00976 else if ( OP_flop(op) ) {
00977 BOOL is_single = (OP_result_size(op,0) == 32);
00978
00979 ++info->refs[PRC_FLOP];
00980 info->refs[PRC_FLOP_S] += is_single;
00981 if (OP_madd(op)) {
00982 ++info->refs[PRC_MADD];
00983 info->refs[PRC_MADD_S] += is_single;
00984 }
00985 else if (OP_fadd(op) || OP_fsub(op)) {
00986 ++info->refs[PRC_FADD];
00987 info->refs[PRC_FADD_S] += is_single;
00988 }
00989 else if (OP_fmul(op)) {
00990 ++info->refs[PRC_FMUL];
00991 info->refs[PRC_FMUL_S] += is_single;
00992 }
00993 }
00994 else {
00995 INT k;
00996
00997
00998
00999
01000
01001 if (OP_has_result(op) && TN_is_float(OP_result(op,0))) goto not_iop;
01002
01003 for (k = 0; k < OP_opnds(op); k++) {
01004 if (TN_is_float(OP_opnd(op,k))) goto not_iop;
01005 }
01006
01007 info->refs[PRC_IOP] += num_insts;
01008
01009 not_iop:
01010 ;
01011 }
01012 }
01013 }
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024 void
01025 CGTARG_Branch_Info ( const OP *op,
01026 INT *tfirst,
01027 INT *tcount )
01028 {
01029 INT i;
01030 TN *tn;
01031
01032
01033 *tfirst = -1;
01034 *tcount = 0;
01035
01036
01037 for ( i = 0; ; i++ ) {
01038 if ( i >= OP_opnds(op) ) return;
01039 tn = OP_opnd(op,i);
01040 if ( tn != NULL && TN_is_label(tn) ) break;
01041 }
01042 *tfirst = i;
01043
01044
01045 *tcount = 1;
01046 for ( i++; i < OP_opnds(op); i++ ) {
01047 tn = OP_opnd(op,i);
01048 if ( tn == NULL || ! TN_is_label(tn) ) return;
01049 (*tcount)++;
01050 }
01051 return;
01052 }
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063 BOOL
01064 CGTARG_Can_Be_Speculative( OP *op )
01065 {
01066 WN *wn;
01067
01068
01069 if (Eager_Level == EAGER_NONE) return FALSE;
01070
01071
01072 if (OP_volatile(op)) return FALSE;
01073
01074
01075
01076
01077 if (!TOP_Can_Be_Speculative(OP_code(op))) return FALSE;
01078
01079 if (!OP_load(op)) return FALSE;
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091 if (OP_no_alias(op)) goto scalar_load;
01092
01093
01094
01095
01096
01097 if (TN_is_symbol(OP_opnd(op, 1)) &&
01098 !ST_is_weak_symbol(TN_var(OP_opnd(op, 1)))) goto scalar_load;
01099
01100
01101
01102
01103
01104 if (
01105 ( (wn = Get_WN_From_Memory_OP(op))
01106 && Alias_Manager->Safe_to_speculate(wn))) goto scalar_load;
01107
01108
01109
01110
01111 if (CGTARG_Is_OP_Speculative(op)) goto scalar_load;
01112
01113
01114
01115
01116 return FALSE;
01117
01118
01119
01120
01121 scalar_load:
01122 return TRUE;
01123 }
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133 BOOL
01134 CGTARG_Is_OP_Speculative_Load( OP *memop )
01135 {
01136 return FALSE;
01137 }
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147 BOOL
01148 CGTARG_Is_OP_Advanced_Load( OP *memop )
01149 {
01150 return FALSE;
01151 }
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161 BOOL
01162 CGTARG_Is_OP_Check_Load( OP *memop )
01163 {
01164 return FALSE;
01165 }
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176 BOOL
01177 CGTARG_OP_Defs_TN( OP *op, TN *tn )
01178 {
01179 return FALSE;
01180 }
01181
01182 BOOL
01183 CGTARG_OP_Refs_TN( OP *op, TN *tn )
01184 {
01185 return FALSE;
01186 }
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196 static MEM_POOL interference_pool;
01197 static VOID_LIST** writing;
01198
01199 static BOOL is_loop;
01200 static INT32 assumed_longest_latency = 40;
01201
01202
01203
01204
01205
01206
01207 static INT32 cycle_count;
01208
01209 static void (*make_interference)(void*,void*);
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221 static void
01222 Increase_Assumed_Longest_Latency(INT32 new_longest_latency )
01223 {
01224 DevWarn("Assumed longest latency should be at least %d",
01225 new_longest_latency);
01226 writing = TYPE_MEM_POOL_REALLOC_N(VOID_LIST*,&interference_pool,writing,
01227 cycle_count + assumed_longest_latency,
01228 cycle_count + new_longest_latency);
01229 assumed_longest_latency = new_longest_latency;
01230 }
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240 BOOL
01241 CGTARG_Interference_Required(void)
01242 {
01243 return FALSE;
01244 }
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254 void
01255 CGTARG_Interference_Initialize( INT32 cycle_count_local, BOOL is_loop_local,
01256 void (*make_interference_local)(void*,void*) )
01257 {
01258 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01259 }
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269 void
01270 CGTARG_Result_Live_Range( void* lrange, OP* op, INT32 offset )
01271 {
01272 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01273 }
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283 void
01284 CGTARG_Operand_Live_Range( void* lrange, INT opnd, OP* op, INT32 offset )
01285 {
01286 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01287 }
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297 void
01298 CGTARG_Interference_Finalize(void)
01299 {
01300 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01301 }
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312 BOOL
01313 CGTARG_Preg_Register_And_Class(
01314 WN_OFFSET preg,
01315 ISA_REGISTER_CLASS *p_rclass,
01316 REGISTER *p_reg
01317 )
01318 {
01319 ISA_REGISTER_CLASS rclass;
01320 INT regnum;
01321
01322
01323
01324 if (!Preg_Is_Dedicated(preg))
01325 return FALSE;
01326
01327 if (!Preg_Offset_Is_Int(preg) &&
01328 !Preg_Offset_Is_Float(preg) &&
01329 !Preg_Offset_Is_X87(preg) &&
01330 !Preg_Offset_Is_MMX(preg))
01331 return FALSE;
01332
01333
01334
01335
01336 if (Preg_Offset_Is_Int(preg)) {
01337 regnum = preg - Int_Preg_Min_Offset;
01338 rclass = ISA_REGISTER_CLASS_integer;
01339 }
01340 else if (Preg_Offset_Is_Float(preg)) {
01341 regnum = preg - Float_Preg_Min_Offset;
01342 rclass = ISA_REGISTER_CLASS_float;
01343 }
01344 else if (Preg_Offset_Is_X87(preg)) {
01345 regnum = preg - X87_Preg_Min_Offset;
01346 rclass = ISA_REGISTER_CLASS_x87;
01347 }
01348 else if (Preg_Offset_Is_MMX(preg)) {
01349 regnum = preg - MMX_Preg_Min_Offset;
01350 rclass = ISA_REGISTER_CLASS_mmx;
01351 }
01352 else if (preg == 0) {
01353 regnum = 0;
01354 rclass = ISA_REGISTER_CLASS_integer;
01355 }
01356 else {
01357 return FALSE;
01358 }
01359
01360
01361 for ( REGISTER reg = REGISTER_MIN;
01362 reg <= REGISTER_CLASS_last_register(rclass);
01363 reg++ )
01364 {
01365 if ( REGISTER_machine_id(rclass,reg) == regnum )
01366 {
01367 *p_reg = reg;
01368 *p_rclass = rclass;
01369 return TRUE;
01370 }
01371 }
01372
01373 FmtAssert(FALSE, ("failed to map preg %d", preg));
01374
01375 }
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386 void CGTARG_Compute_Branch_Parameters(INT32 *mispredict, INT32 *fixed, INT32 *brtaken, double *factor)
01387 {
01388 *mispredict = 0;
01389 *fixed = 0;
01390 *brtaken = 0;
01391 *factor = 0.0;
01392
01393 if (Is_Target_x86_64() )
01394 {
01395 *mispredict= 7; *fixed= 1; *brtaken= 1; *factor = 1.0;
01396 }
01397 else
01398 {
01399 FmtAssert(FALSE, ("invalid target"));
01400 }
01401
01402
01403
01404
01405
01406
01407 if (CG_branch_mispredict_penalty >= 0)
01408 *mispredict= CG_branch_mispredict_penalty ;
01409
01410 if (CG_branch_mispredict_factor >= 0)
01411 *factor= CG_branch_mispredict_factor * (.01);
01412 }
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423 BOOL CGTARG_Can_Change_To_Brlikely(OP *xfer_op, TOP *new_opcode)
01424 {
01425 return FALSE;
01426 }
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437 INT32 CGTARG_Latency( TOP op )
01438 {
01439 return ( TI_LATENCY_Result_Available_Cycle(op,0) -
01440 TI_LATENCY_Operand_Access_Cycle(op,0) );
01441 }
01442
01443 BOOL CGTARG_Is_Long_Latency(TOP op)
01444 {
01445 return ( CGTARG_Latency(op) > 2 );
01446 }
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456 VARIANT CGTARG_Analyze_Branch(
01457 OP *br,
01458 TN **tn1,
01459 TN **tn2)
01460 {
01461 OP* cmp_op = NULL;
01462
01463
01464 for( OP* op = OP_prev(br); op != NULL; op = OP_prev(op) ){
01465 if( TOP_is_change_rflags( OP_code(op) ) ){
01466 cmp_op = op;
01467 break;
01468 }
01469 }
01470
01471 #ifdef TARG_X8664
01472
01473
01474
01475 if (cmp_op == NULL) {
01476 Is_True(OP_code(br) == TOP_jnp,
01477 ("CGTARG_Analyze_Branch: unexpected branch OP code"));
01478 BBLIST *edge;
01479 BB *fall_thru_pred = BB_Fall_Thru_Predecessor(OP_bb(br));
01480 int preds = 0;
01481
01482
01483 FOR_ALL_BB_PREDS(OP_bb(br), edge) {
01484 BB *pred = BBLIST_item(edge);
01485 preds++;
01486
01487 for (OP* op = BB_last_op(pred); op != NULL; op = OP_prev(op)) {
01488 if (TOP_is_change_rflags(OP_code(op))) {
01489 Is_True(cmp_op == NULL,
01490 ("CGTARG_Analyze_Branch: found multiple cmp ops"));
01491 cmp_op = op;
01492 break;
01493 }
01494 }
01495 #if !defined(Is_True_On)
01496 if (cmp_op != NULL)
01497 break;
01498 #endif
01499 }
01500 Is_True(preds == 2,
01501 ("CGTARG_Analyze_Branch: unexpected number of pred BBs"));
01502 }
01503 #endif
01504
01505 FmtAssert( cmp_op != NULL, ("compare op is missing") );
01506
01507 if( OP_icmp( cmp_op ) ){
01508
01509
01510 *tn1 = OP_opnd( cmp_op, 0 );
01511 *tn2 = OP_opnd( cmp_op, 1 );
01512
01513 if( OP_code(cmp_op) == TOP_test32 ||
01514 OP_code(cmp_op) == TOP_test64 ||
01515 OP_code(cmp_op) == TOP_testi32 ||
01516 OP_code(cmp_op) == TOP_testi64 ){
01517 if( *tn1 == *tn2 )
01518 *tn2 = Gen_Literal_TN( 0, 4 );
01519 else
01520 return V_BR_NONE;
01521 }
01522 } else {
01523
01524 *tn1 = OP_result( cmp_op, 0 );
01525 *tn2 = Gen_Literal_TN( 0, 4 );
01526 }
01527
01528
01529
01530
01531 const bool is_64bit = OP_result_size(cmp_op,0) == 64;
01532
01533 switch( OP_code(br) ){
01534 case TOP_jge:
01535 return OP_flop(cmp_op) ? V_BR_DGE : ( is_64bit ? V_BR_I8GE : V_BR_I4GE );
01536
01537 case TOP_jae:
01538 return OP_flop(cmp_op) ? V_BR_DGE : ( is_64bit ? V_BR_U8GE : V_BR_U4GE );
01539
01540 case TOP_jg:
01541 return OP_flop(cmp_op) ? V_BR_DGT : ( is_64bit ? V_BR_I8GT : V_BR_I4GT );
01542
01543 case TOP_ja:
01544 return OP_flop(cmp_op) ? V_BR_DGT : ( is_64bit ? V_BR_U8GT : V_BR_U4GT );
01545
01546 case TOP_jle:
01547 return OP_flop(cmp_op) ? V_BR_DLE : ( is_64bit ? V_BR_I8LE : V_BR_I4LE );
01548
01549 case TOP_jbe:
01550 return OP_flop(cmp_op) ? V_BR_DLE : ( is_64bit ? V_BR_U8LE : V_BR_U4LE );
01551
01552 case TOP_jl:
01553 return OP_flop(cmp_op) ? V_BR_DLT : ( is_64bit ? V_BR_I8LT : V_BR_I4LT );
01554
01555 case TOP_jb:
01556 return OP_flop(cmp_op) ? V_BR_DLT : ( is_64bit ? V_BR_U8LT : V_BR_U4LT );
01557
01558 case TOP_je:
01559 return OP_flop(cmp_op) ? V_BR_DEQ : ( is_64bit ? V_BR_U8EQ : V_BR_U4EQ );
01560
01561 case TOP_jne:
01562 return OP_flop(cmp_op) ? V_BR_DNE : ( is_64bit ? V_BR_U8NE : V_BR_U4NE );
01563
01564 case TOP_jp:
01565 case TOP_jnp:
01566
01567
01568 return V_BR_NONE;
01569
01570 case TOP_js:
01571 Is_True(!OP_flop(cmp_op), ("CGTARG_Analyze_Branch: unexpected conditional branch %s for floating point\n", TOP_Name(OP_code(br))));
01572 return ( is_64bit ? V_BR_I8LT0 : V_BR_I4LT0 );
01573
01574 case TOP_jns:
01575 Is_True(!OP_flop(cmp_op), ("CGTARG_Analyze_Branch: unexpected conditional branch %s for floating point\n", TOP_Name(OP_code(br))));
01576 return ( is_64bit ? V_BR_I8GE0 : V_BR_I4GE0 );
01577
01578 default:
01579 FmtAssert( false, ("unexpected conditional branch %s\n", TOP_Name(OP_code(br))) );
01580 break;
01581 }
01582
01583 return V_BR_NONE;
01584 }
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595 VARIANT CGTARG_Analyze_Compare(
01596 OP *br,
01597 TN **tn1,
01598 TN **tn2,
01599 OP **compare_op)
01600 {
01601 TN* cond_tn1 = NULL;
01602 TN* cond_tn2 = NULL;
01603
01604
01605
01606 VARIANT variant = CGTARG_Analyze_Branch(br, &cond_tn1, &cond_tn2);
01607
01608
01609
01610
01611
01612 for( OP* op = OP_prev(br); op != NULL; op = OP_prev(op) ){
01613 if( TOP_is_change_rflags( OP_code(op) ) ){
01614 if( OP_icmp( op ) )
01615 *compare_op = op;
01616 break;
01617 }
01618 }
01619
01620 *tn1 = cond_tn1;
01621 *tn2 = cond_tn2;
01622
01623 return variant;
01624 }
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635 TOP
01636 CGTARG_Equiv_Nonindex_Memory_Op ( OP *op )
01637 {
01638 return TOP_UNDEFINED;
01639 }
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649 TOP
01650 CGTARG_Which_OP_Select ( UINT16 bit_size, BOOL is_float, BOOL is_fcc )
01651 {
01652 FmtAssert( FALSE, ( "CGTARG_Which_OP_Select: Unsupported Target") );
01653 return TOP_UNDEFINED;
01654 }
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664 static BOOL
01665 Is_OP_fp_op1(OP *op)
01666 {
01667 return FALSE;
01668 }
01669
01670
01671
01672
01673
01674
01675
01676 void
01677 Insert_Stop_Bits(BB *bb)
01678 {
01679 }
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689 INT32 CGTARG_Special_Min_II(BB* loop_body, BOOL trace)
01690 {
01691 return 0;
01692 }
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702 void
01703 Hardware_Workarounds(void)
01704 {
01705 }
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715 void CGTARG_Initialize(void)
01716 {
01717 #define Set_Inv_Table(a,b) \
01718 do { \
01719 CGTARG_Invert_Table[a] = b; \
01720 CGTARG_Invert_Table[b] = a; \
01721 } while( 0 )
01722
01723 #define Set_Immed_To_Reg_Table(a,b) \
01724 do { \
01725 CGTARG_Immed_To_Reg_Table[a] = b; \
01726 CGTARG_Immed_To_Reg_Table[b] = a; \
01727 } while( 0 )
01728
01729 INT32 i;
01730
01731
01732
01733 for(i = 0; i <= TOP_count; ++i) {
01734 CGTARG_Invert_Table[i] = TOP_UNDEFINED;
01735 CGTARG_Immed_To_Reg_Table[i] = TOP_UNDEFINED;
01736 }
01737
01738 for (i = 0; i <= ISA_REGISTER_CLASS_MAX; ++i) {
01739 INT j;
01740 for (j = 0; j <= ISA_REGISTER_CLASS_MAX; ++j) {
01741 CGTARG_Inter_RegClass_Copy_Table[i][j][FALSE] = TOP_UNDEFINED;
01742 CGTARG_Inter_RegClass_Copy_Table[i][j][TRUE] = TOP_UNDEFINED;
01743 }
01744 }
01745
01746
01747
01748 Set_Inv_Table( TOP_addss, TOP_subss );
01749 Set_Inv_Table( TOP_addsd, TOP_subsd );
01750 Set_Inv_Table( TOP_add32, TOP_sub32 );
01751 Set_Inv_Table( TOP_add64, TOP_sub64 );
01752
01753 Set_Inv_Table( TOP_cmovb, TOP_cmovae );
01754 Set_Inv_Table( TOP_cmove, TOP_cmovne );
01755 Set_Inv_Table( TOP_cmovbe, TOP_cmova );
01756 Set_Inv_Table( TOP_cmovl, TOP_cmovge );
01757 Set_Inv_Table( TOP_cmovle, TOP_cmovg );
01758
01759 Set_Inv_Table( TOP_jb, TOP_jae );
01760 Set_Inv_Table( TOP_je, TOP_jne );
01761 Set_Inv_Table( TOP_jbe, TOP_ja );
01762 Set_Inv_Table( TOP_jge, TOP_jl );
01763 Set_Inv_Table( TOP_jle, TOP_jg );
01764
01765 Set_Inv_Table( TOP_setb, TOP_setae );
01766 Set_Inv_Table( TOP_sete, TOP_setne );
01767 Set_Inv_Table( TOP_setbe, TOP_seta );
01768 Set_Inv_Table( TOP_setge, TOP_setl );
01769 Set_Inv_Table( TOP_setle, TOP_setg );
01770
01771
01772
01773 Set_Immed_To_Reg_Table( TOP_addi32, TOP_add32 );
01774 Set_Immed_To_Reg_Table( TOP_addi64, TOP_add64 );
01775 Set_Immed_To_Reg_Table( TOP_andi32, TOP_and32 );
01776 Set_Immed_To_Reg_Table( TOP_andi64, TOP_and64 );
01777 Set_Immed_To_Reg_Table( TOP_ori32, TOP_or32 );
01778 Set_Immed_To_Reg_Table( TOP_ori64, TOP_or64 );
01779 Set_Immed_To_Reg_Table( TOP_xori32, TOP_xor32 );
01780 Set_Immed_To_Reg_Table( TOP_xori64, TOP_xor64 );
01781 Set_Immed_To_Reg_Table( TOP_cmpi32, TOP_cmp32 );
01782 Set_Immed_To_Reg_Table( TOP_cmpi64, TOP_cmp64 );
01783 Set_Immed_To_Reg_Table( TOP_imuli32,TOP_imul32 );
01784 Set_Immed_To_Reg_Table( TOP_imuli64,TOP_imul64 );
01785
01786
01787
01788
01789 CGTARG_Inter_RegClass_Copy_Table[ISA_REGISTER_CLASS_float]
01790 [ISA_REGISTER_CLASS_integer]
01791 [FALSE] = TOP_UNDEFINED;
01792 CGTARG_Inter_RegClass_Copy_Table[ISA_REGISTER_CLASS_float]
01793 [ISA_REGISTER_CLASS_integer]
01794 [TRUE] = TOP_UNDEFINED;
01795
01796 CGTARG_Inter_RegClass_Copy_Table[ISA_REGISTER_CLASS_integer]
01797 [ISA_REGISTER_CLASS_float]
01798 [FALSE] = TOP_UNDEFINED;
01799 CGTARG_Inter_RegClass_Copy_Table[ISA_REGISTER_CLASS_integer]
01800 [ISA_REGISTER_CLASS_float]
01801 [TRUE] = TOP_UNDEFINED;
01802
01803 #undef Set_Inv_Table
01804 #undef Set_Immed_To_Reg_Table
01805
01806 return;
01807 }
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818 void CGTARG_Load_From_Memory(TN *tn, ST *mem_loc, OPS *ops)
01819 {
01820 TYPE_ID mtype = TY_mtype(ST_type(mem_loc));
01821 Exp_Load(mtype, mtype, tn, mem_loc, 0, ops, 0);
01822 }
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833 void CGTARG_Store_To_Memory(TN *tn, ST *mem_loc, OPS *ops)
01834 {
01835 TYPE_ID mtype = TY_mtype(ST_type(mem_loc));
01836 Exp_Store(mtype, tn, mem_loc, 0, ops, 0);
01837 }
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848 void CGTARG_Init_Assoc_Base(void)
01849 {
01850 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01851 }
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862 INT CGTARG_Copy_Operand(OP *op)
01863 {
01864 const TOP opr = OP_code(op);
01865
01866 switch( opr ){
01867 case TOP_addi32:
01868 case TOP_addi64:
01869 case TOP_subi32:
01870 case TOP_subi64:
01871 case TOP_sari32:
01872 case TOP_sari64:
01873 case TOP_shli32:
01874 case TOP_shli64:
01875 case TOP_shri32:
01876 case TOP_shri64:
01877 case TOP_lea32:
01878 case TOP_lea64:
01879 if (TN_has_value(OP_opnd(op,1)) && TN_value(OP_opnd(op,1)) == 0)
01880 return 0;
01881 break;
01882
01883 case TOP_andi32:
01884 case TOP_andi64:
01885 {
01886 TN *src1 = OP_opnd( op, 1 );
01887 if (TN_is_constant(src1)) {
01888 INT64 val;
01889 if (TN_has_value(src1))
01890 val = TN_value(src1);
01891 else FmtAssert(FALSE,("unexpected constant in CGTARG_Copy_Operand"));
01892 if (val == -1)
01893 return 0;
01894 }
01895 break;
01896 }
01897
01898 case TOP_movabsq:
01899 case TOP_ldc32:
01900 case TOP_ldc64:
01901 {
01902 TN* opnd = OP_opnd( op, 0 );
01903 if( TN_has_value( opnd ) ){
01904 return 0;
01905 }
01906 }
01907 break;
01908
01909 case TOP_mov64:
01910 case TOP_movsd:
01911 case TOP_movss:
01912 case TOP_movdq:
01913 case TOP_movapd:
01914 case TOP_movaps:
01915 case TOP_fmov:
01916 case TOP_mov64_m:
01917 case TOP_movm_2i32:
01918 case TOP_movm_2i64:
01919 case TOP_movi32_2m:
01920 case TOP_movi64_2m:
01921 return 0;
01922
01923 case TOP_mov32:
01924 if( TN_size(OP_result(op,0)) == TN_size(OP_opnd(op,0)) )
01925 return 0;
01926 break;
01927
01928 case TOP_ori32:
01929 case TOP_ori64:
01930 case TOP_xori32:
01931 case TOP_xori64:
01932 {
01933 TN *src1 = OP_opnd( op, 1 );
01934 if (TN_is_constant(src1)) {
01935 INT64 val;
01936 if (TN_has_value(src1))
01937 val = TN_value(src1);
01938 else FmtAssert(FALSE,("unexpected constant in CGTARG_Copy_Operand"));
01939 if (val == 0)
01940 return 0;
01941 }
01942 break;
01943 }
01944 }
01945
01946 if (OP_copy(op)) {
01947 if (opr == TOP_add32 || opr == TOP_add64 ||
01948 opr == TOP_or32 || opr == TOP_or64 ||
01949 opr == TOP_mov32 || opr== TOP_mov64 ||
01950 opr == TOP_movsd || opr == TOP_movss ||
01951 opr == TOP_fmov )
01952 return 0;
01953 }
01954
01955 if( OP_cond_move( op ) &&
01956 TNs_Are_Equivalent( OP_result(op,0), OP_opnd(op,0) ) ){
01957 return 0;
01958 }
01959
01960 return -1;
01961 }
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972 BOOL CGTARG_Can_Fit_Immediate_In_Add_Instruction (INT64 immed)
01973 {
01974 return ISA_LC_Value_In_Class (immed, LC_simm32);
01975 }
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986 BOOL CGTARG_Can_Load_Immediate_In_Single_Instruction (INT64 immed)
01987 {
01988 return ISA_LC_Value_In_Class (immed, LC_simm32);
01989 }
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002 void
02003 CGTARG_Predicate_OP(BB* bb, OP* op, TN* pred_tn)
02004 {
02005 if (OP_has_predicate(op)) {
02006 FmtAssert( FALSE, ( "CGTARG_Which_OP_Select: Unsupported Target") );
02007 }
02008 }
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018 BOOL
02019 CGTARG_Branches_On_True(OP* br_op, OP* cmp_op)
02020 {
02021 return FALSE;
02022 }
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034 TOP
02035 CGTARG_Parallel_Compare(OP* cmp_op, COMPARE_TYPE ctype)
02036 {
02037 return TOP_UNDEFINED;
02038 }
02039
02040
02041 static BOOL OP_Reads_Dedicated_TN( OP* op, TN* ded_tn )
02042 {
02043 for( int i = 0; i < OP_opnds(op); i++ ){
02044 TN* tmp_tn = CGTARG_Gen_Dedicated_Subclass_TN( op, i, FALSE );
02045 if( tmp_tn != NULL &&
02046 TNs_Are_Equivalent( tmp_tn, ded_tn ) )
02047 return TRUE;
02048 }
02049
02050 return FALSE;
02051 }
02052
02053
02054 static BOOL OP_Writes_Dedicated_TN( OP* op, TN* ded_tn )
02055 {
02056 for( int i = 0; i < OP_results(op); i++ ){
02057 TN* tmp_tn = CGTARG_Gen_Dedicated_Subclass_TN( op, i, TRUE );
02058 if( tmp_tn != NULL &&
02059 TNs_Are_Equivalent( tmp_tn, ded_tn ) )
02060 return TRUE;
02061 }
02062
02063 return FALSE;
02064 }
02065
02066
02067 static BOOL OP_is_lea( OP* op )
02068 {
02069 const TOP top = OP_code(op);
02070
02071 return ( top == TOP_lea32 || top == TOP_lea64 ||
02072 top == TOP_leax32 || top == TOP_leax64 ||
02073 top == TOP_leaxx32 || top == TOP_leaxx64 );
02074 }
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084 BOOL CGTARG_Dependence_Required( OP* pred_op, OP* succ_op )
02085 {
02086 FmtAssert( OP_bb(pred_op) == OP_bb(succ_op), ("NYI") );
02087
02088
02089
02090
02091
02092
02093 if( PU_Has_Exc_Handler ){
02094
02095
02096
02097 if( BB_entry( OP_bb(pred_op) ) &&
02098 OP_store( pred_op ) &&
02099 OP_store( succ_op ) &&
02100 TN_is_save_reg( OP_opnd(pred_op,0) ) )
02101 return TRUE;
02102 }
02103
02104
02105
02106
02107 {
02108 for( ARC_LIST* arcs = OP_succs(pred_op);
02109 arcs != NULL;
02110 arcs = ARC_LIST_rest(arcs) ){
02111 ARC *arc = ARC_LIST_first(arcs);
02112 if( ARC_succ(arc) == succ_op )
02113 return FALSE;
02114 }
02115 }
02116
02117
02118
02119
02120 {
02121 if( OP_results(pred_op) > 0 &&
02122 TN_is_sp_reg( OP_result(pred_op,0) ) &&
02123 OP_store( succ_op ) )
02124 return TRUE;
02125 }
02126
02127
02128
02129 {
02130 if( TOP_is_unknown_memdata( OP_code(pred_op) ) ){
02131 if( OP_memory( succ_op ) ||
02132 OP_load_exe( succ_op ) ||
02133 TOP_is_unknown_memdata( OP_code(succ_op) ) )
02134 return TRUE;
02135 }
02136
02137 if( TOP_is_unknown_memdata( OP_code(succ_op) ) ){
02138 if( OP_memory( pred_op ) ||
02139 OP_load_exe( pred_op ) ||
02140 TOP_is_unknown_memdata( OP_code(pred_op) ) )
02141 return TRUE;
02142 }
02143 }
02144
02145
02146
02147
02148
02149
02150 {
02151 BB* bb = OP_bb( pred_op );
02152 if( BB_entry(bb) && !BB_handler(bb) ){
02153 if( pred_op == BB_entry_sp_adj_op(bb) )
02154 return TRUE;
02155 }
02156
02157 if( BB_exit(bb) ){
02158 if( succ_op == BB_exit_sp_adj_op(bb) )
02159 return TRUE;
02160 }
02161 }
02162
02163
02164
02165
02166
02167 {
02168 if (TOP_is_change_x87_cw(OP_code(pred_op)) &&
02169 (TOP_is_read_x87_cw(OP_code(succ_op)) ||
02170 TOP_is_x87(OP_code(succ_op))))
02171 return TRUE;
02172
02173 if ((TOP_is_read_x87_cw(OP_code(pred_op)) ||
02174 TOP_is_x87(OP_code(pred_op))) &&
02175 TOP_is_change_x87_cw(OP_code(succ_op)))
02176 return TRUE;
02177 }
02178
02179
02180 {
02181 BOOL pred_is_x87_mmx = (OP_x87(pred_op) || OP_mmx(pred_op)) ? TRUE : FALSE;
02182 BOOL succ_is_x87_mmx = (OP_x87(succ_op) || OP_mmx(succ_op)) ? TRUE : FALSE;
02183 if ((OP_code(pred_op) == TOP_emms && succ_is_x87_mmx) ||
02184 (OP_code(succ_op) == TOP_emms && pred_is_x87_mmx))
02185 return TRUE;
02186 }
02187
02188
02189
02190
02191
02192
02193 {
02194 const BOOL pred_is_lea = OP_is_lea( pred_op );
02195 const BOOL succ_is_lea = OP_is_lea( succ_op );
02196
02197 if( TOP_is_change_rflags( OP_code(pred_op) ) || pred_is_lea ){
02198 if( OP_icmp( succ_op ) || OP_reads_rflags( succ_op ) )
02199 return TRUE;
02200
02201
02202
02203 if( OP_code(succ_op) == TOP_neg32 || OP_code(succ_op) == TOP_neg64 ){
02204 for( ARC_LIST* arcs = OP_succs(succ_op); arcs != NULL; arcs = ARC_LIST_rest(arcs) ){
02205 ARC* arc = ARC_LIST_first(arcs);
02206 OP* op = ARC_succ(arc);
02207 const TOP top = OP_code( op );
02208
02209 if( ( TOP_is_cond_set(top) || TOP_is_cond_move(top) ) &&
02210 TNs_Are_Equivalent( OP_result(op,0), OP_result(succ_op,0) ) )
02211 return TRUE;
02212 }
02213 }
02214 }
02215
02216
02217
02218
02219 if( TOP_is_change_rflags( OP_code(succ_op) ) || succ_is_lea ){
02220 if( OP_reads_rflags( pred_op ) )
02221 return TRUE;
02222 }
02223 }
02224
02225
02226
02227
02228
02229
02230 {
02231 for( int i = 0; i < OP_opnds(succ_op); i++ ){
02232 TN* tmp_tn = CGTARG_Gen_Dedicated_Subclass_TN( succ_op, i, FALSE );
02233 if( tmp_tn != NULL ){
02234
02235 if( OP_Writes_Dedicated_TN( pred_op, tmp_tn ) )
02236 return TRUE;
02237
02238
02239
02240
02241
02242
02243 if (OP_Reads_Dedicated_TN(pred_op, tmp_tn)) {
02244
02245
02246 if (!TN_is_dedicated(OP_opnd(succ_op, i)))
02247 return TRUE;
02248
02249
02250
02251 else if (TN_register(OP_opnd(succ_op, i)) != TN_register(tmp_tn))
02252 return TRUE;
02253 }
02254 }
02255 }
02256
02257 for( int i = 0; i < OP_results(succ_op); i++ ){
02258 TN* tmp_tn = CGTARG_Gen_Dedicated_Subclass_TN( succ_op, i, TRUE );
02259 if( tmp_tn != NULL ){
02260
02261 if( OP_Writes_Dedicated_TN( pred_op, tmp_tn ) ||
02262 OP_Reads_Dedicated_TN( pred_op, tmp_tn ) ){
02263 return TRUE;
02264 }
02265 }
02266 }
02267 }
02268
02269
02270
02271 {
02272 if (OP_code(succ_op) == TOP_savexmms)
02273 return TRUE;
02274
02275 if (OP_code(succ_op) == TOP_leave)
02276 return TRUE;
02277
02278
02279
02280 if( OP_computes_got( pred_op ) ||
02281 OP_computes_got( succ_op ) )
02282 return TRUE;
02283 }
02284
02285
02286
02287 {
02288 if( TOP_is_change_rflags( OP_code(pred_op) ) &&
02289 TOP_is_change_rflags( OP_code(succ_op) ) ){
02290 for( OP* next = OP_next(succ_op); next != NULL; next = OP_next(next) ){
02291 if( OP_reads_rflags(next) )
02292 return TRUE;
02293 if( TOP_is_change_rflags( OP_code(next) ) )
02294 break;
02295 }
02296 }
02297 }
02298
02299 return FALSE;
02300 }
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311 void
02312 CGTARG_Adjust_Latency(OP *pred_op, OP *succ_op, CG_DEP_KIND kind, UINT8 opnd, INT *latency)
02313 {
02314
02315 if (CG_ptr_load_use_latency != 0 &&
02316 kind == CG_DEP_REGIN &&
02317 (OP_load(pred_op) ||
02318
02319 OP_load_exe(pred_op)) &&
02320
02321 (OP_load(succ_op) ||
02322 OP_store(succ_op) ||
02323 OP_load_exe(succ_op) ||
02324 OP_load_exe_store(succ_op))) {
02325 int base_idx = OP_find_opnd_use(succ_op, OU_base);
02326 int index_idx = OP_find_opnd_use(succ_op, OU_index);
02327 if (opnd == base_idx ||
02328 opnd == index_idx) {
02329 *latency = MAX(*latency,
02330 TI_LATENCY_Result_Available_Cycle(OP_code(pred_op), 0)
02331 + CG_ptr_load_use_latency);
02332 }
02333 }
02334 }
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344 void
02345 CGTARG_Generate_Remainder_Branch(TN *trip_count, TN *label_tn,
02346 OPS *prolog_ops, OPS *body_ops)
02347 {
02348 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
02349 }
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360 BOOL CGTARG_OP_is_counted_loop(OP *op)
02361 {
02362 return FALSE;
02363 }
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379 static BOOL
02380 Loop_Countsdown_Xformed ( BB* bb )
02381 {
02382 OP* op;
02383
02384 if ( OP_code( BB_branch_op( bb ) ) != TOP_jne )
02385 return TRUE;
02386
02387
02388
02389 for ( op = BB_branch_op( bb ); op != NULL; op = op->prev )
02390 if ( TOP_is_change_rflags( OP_code( op ) ) )
02391 break;
02392 if ( op == NULL ||
02393 ( OP_code( op ) == TOP_dec32 &&
02394 OP_code( op ) == TOP_dec64 ) )
02395 return TRUE;
02396
02397 return FALSE;
02398 }
02399
02400 extern BOOL TN_live_out_of( TN*, BB* );
02401
02402 static BOOL CGTARG_live_out_of ( TN* tn, BB* tail, LOOP_DESCR *loop )
02403 {
02404 BB* bb;
02405 OP* op;
02406 INT opnd, result;
02407
02408 if ( TN_live_out_of( tn, tail ) ) {
02409 if ( TN_live_out_of( tn, BB_next( tail ) ) )
02410 return TRUE;
02411
02412 FOR_ALL_BB_SET_members( LOOP_DESCR_bbset(loop), bb ) {
02413 if (bb == tail)
02414 break;
02415 FOR_ALL_BB_OPs ( bb, op ) {
02416 for ( opnd = 0; opnd < OP_opnds( op ); opnd ++ )
02417 if ( OP_opnd( op, opnd ) == tn )
02418 return TRUE;
02419 for ( result = 0; result < OP_results( op ); result ++ )
02420 if ( OP_result( op, result ) == tn )
02421 return TRUE;
02422 }
02423 }
02424 }
02425
02426 return FALSE;
02427 }
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451 void
02452 CGTARG_Generate_Countdown_Loop ( TN *trip_count_tn,
02453 BB *tail,
02454 OPS *prolog_ops,
02455 OPS *body_ops,
02456 BOOL single_bb,
02457 LOOP_DESCR *loop )
02458 {
02459 OP *cmp, *incr, *op, *branch;
02460 BOOL cmp_found = FALSE, incr_found = FALSE;
02461 INT opnd, result;
02462
02463 if (!CG_LOOP_cloop)
02464 return;
02465
02466 if (Loop_Countsdown_Xformed(tail))
02467 return;
02468
02469 branch = BB_branch_op(tail);
02470 incr = cmp = NULL;
02471
02472
02473
02474 for ( op = branch->prev; op != NULL; op = op->prev ) {
02475 if (!cmp_found) {
02476
02477 if (OP_code(op) == TOP_test32 || OP_code(op) == TOP_test64)
02478 return;
02479
02480 if (OP_code(op) == TOP_cmp32 || OP_code(op) == TOP_cmp64) {
02481 cmp_found = TRUE;
02482 cmp = op;
02483 }
02484 }
02485
02486 if ( !incr_found && cmp_found &&
02487 ( OP_code( op ) == TOP_addi32 ||
02488 OP_code( op ) == TOP_addi64 ) &&
02489 OP_opnd( op, 0 ) == OP_result( op, 0 ) &&
02490 ( OP_result( op, 0 ) == OP_opnd( cmp, 0 ) ||
02491 OP_result( op, 0 ) == OP_opnd( cmp, 1 ) ) &&
02492 !CGTARG_live_out_of( OP_result( op, 0 ), tail, loop ) &&
02493 TN_is_constant( OP_opnd( op, 1 ) ) &&
02494 TN_value( OP_opnd ( op, 1 ) ) == 1 ) {
02495 incr_found = TRUE;
02496 incr = op;
02497 }
02498 }
02499
02500 if (!incr_found || !cmp_found)
02501 return;
02502
02503
02504
02505 TN *incr_result = OP_result(incr, 0);
02506 for (op = branch->prev; op != NULL; op = op->prev) {
02507 if (op == cmp || op == incr)
02508 continue;
02509
02510 if (OP_result(op, 0 ) == OP_opnd(cmp, 0) ||
02511 OP_result(op, 0 ) == OP_opnd(cmp, 1))
02512 return;
02513
02514
02515
02516 if (TOP_is_store(OP_code(op)) &&
02517 (OP_opnd(op, 0) == OP_opnd(cmp, 0) ||
02518 OP_opnd(op, 0) == OP_opnd(cmp, 1)))
02519 return;
02520
02521 for (opnd = 0; opnd < OP_opnds(op); opnd++)
02522 if (OP_opnd(op, opnd) == incr_result)
02523 return;
02524
02525 for (result = 0; result < OP_results(op); result++)
02526 if (OP_result(op, result ) == incr_result)
02527 return;
02528 }
02529
02530
02531
02532
02533
02534 INT32 trip_size = TN_size(trip_count_tn);
02535 TN *lc_tn_tmp;
02536 TN* lc_tn = Gen_Register_TN (ISA_REGISTER_CLASS_integer,
02537 trip_size);
02538
02539 if (TN_is_constant(trip_count_tn)) {
02540 lc_tn_tmp = Gen_Literal_TN(TN_value(trip_count_tn),
02541 trip_size);
02542 } else {
02543 lc_tn_tmp = trip_count_tn;
02544 }
02545
02546
02547 if (TN_is_constant(lc_tn_tmp)) {
02548 TN *tmp_tn = Gen_Register_TN (ISA_REGISTER_CLASS_integer,
02549 trip_size);
02550 Exp_COPY(tmp_tn, lc_tn_tmp, prolog_ops);
02551 lc_tn_tmp = tmp_tn;
02552 }
02553
02554 Exp_COPY(lc_tn, lc_tn_tmp, prolog_ops);
02555
02556
02557 Build_OP( OP_code( cmp ) == TOP_cmp32 ? TOP_dec32 : TOP_dec64,
02558 lc_tn, lc_tn, body_ops );
02559 if ( single_bb ) {
02560 CG_LOOP_Init_Op( OPS_last( body_ops ) );
02561 Set_OP_omega( OPS_last( body_ops ), 0, 1 );
02562 }
02563 Build_OP ( OP_code( branch ), OP_opnd( branch, 0 ),
02564 OP_opnd( branch, 1 ), body_ops );
02565 if ( single_bb ) {
02566 CG_LOOP_Init_Op( OPS_last( body_ops ) );
02567 Set_OP_omega( OPS_last( body_ops ), 0, OP_omega( branch, 0));
02568 Set_OP_omega( OPS_last( body_ops ), 1, OP_omega( branch, 1));
02569 }
02570
02571
02572 BB_Remove_Op( tail, incr );
02573 BB_Remove_Op( tail, cmp );
02574 BB_Remove_Op( tail, branch );
02575
02576 return;
02577 }
02578
02579 STACK<OP*> Working_Set(Malloc_Mem_Pool);
02580
02581 static inline TN* OP_opnd_use( OP* op, ISA_OPERAND_USE use )
02582 {
02583 const int indx = OP_find_opnd_use( op, use );
02584 return ( indx >= 0 ) ? OP_opnd( op, indx ) : NULL;
02585 }
02586
02587 static TOP Movnti_Top(TOP old_top)
02588 {
02589 switch(old_top){
02590 case TOP_stapd: return TOP_stntpd; break;
02591 case TOP_stapdx: return TOP_stntpdx; break;
02592 case TOP_stapdxx: return TOP_stntpdxx; break;
02593 case TOP_staps: return TOP_stntps; break;
02594 case TOP_stapsx: return TOP_stntpsx; break;
02595 case TOP_stapsxx: return TOP_stntpsxx; break;
02596 case TOP_stdqa: return TOP_stntpd; break;
02597 case TOP_stdqax: return TOP_stntpdx; break;
02598 case TOP_stdqaxx: return TOP_stntpdxx; break;
02599
02600 case TOP_store32: return TOP_storenti32; break;
02601 case TOP_storex32: return TOP_storentix32; break;
02602 case TOP_storexx32: return TOP_storentixx32; break;
02603
02604 case TOP_store64: return TOP_storenti64; break;
02605 case TOP_storex64: return TOP_storentix64; break;
02606 case TOP_storexx64: return TOP_storentixx64; break;
02607
02608 case TOP_stss: return TOP_stntss; break;
02609 case TOP_stssx: return TOP_stntssx; break;
02610 case TOP_stssxx: return TOP_stntssxx; break;
02611 case TOP_stsd: return TOP_stntsd; break;
02612 case TOP_stsdx: return TOP_stntsdx; break;
02613 case TOP_stsdxx: return TOP_stntsdxx; break;
02614 }
02615 FmtAssert(FALSE,("Non-Temporal Store: not supported!"));
02616 return TOP_UNDEFINED;
02617 }
02618
02619
02620
02621 BOOL Op_In_Working_Set ( OP* op )
02622 {
02623
02624 struct ADDRESS_COMPONENT {
02625 TN* index;
02626 TN* base;
02627 TN* offset;
02628 TN* scale;
02629 } a, b;
02630
02631 bzero( &a, sizeof(a) );
02632 a.scale = OP_opnd_use( op, OU_scale );
02633 a.base = OP_opnd_use( op, OU_base );
02634 a.index = OP_opnd_use( op, OU_index );
02635 a.offset = OP_opnd_use( op, OU_offset );
02636 if (a.scale == NULL)
02637 a.scale = Gen_Literal_TN( 1, 4 );
02638
02639 for (INT i = 0; i < Working_Set.Elements(); i++) {
02640 OP* last = Working_Set.Top_nth(i);
02641
02642 bzero( &b, sizeof(b) );
02643 b.scale = OP_opnd_use( last, OU_scale );
02644 b.base = OP_opnd_use( last, OU_base );
02645 b.index = OP_opnd_use( last, OU_index );
02646 b.offset = OP_opnd_use( last, OU_offset );
02647 if (b.scale == NULL)
02648 b.scale = Gen_Literal_TN(1, 4);
02649
02650 if (((a.base && b.base && TNs_Are_Equivalent(b.base, a.base)) ||
02651 (!a.base && !b.base)) &&
02652 ((a.index && b.index && TNs_Are_Equivalent(b.index, a.index)) ||
02653 (!a.index && !b.index)) &&
02654 TN_value(b.offset) == TN_value(a.offset) &&
02655 TN_value(b.scale) == TN_value(a.scale))
02656 return TRUE;
02657 }
02658
02659 Working_Set.Push(op);
02660 return FALSE;
02661 }
02662
02663
02664
02665
02666 void CGTARG_LOOP_Optimize( LOOP_DESCR* loop )
02667 {
02668 if(CG_movnti==0) return;
02669
02670 UINT32 trip_count = 0;
02671 TN* trip_count_tn = CG_LOOP_Trip_Count(loop);
02672 BB* body = LOOP_DESCR_loophead(loop);
02673
02674 if( trip_count_tn != NULL &&
02675 TN_is_constant(trip_count_tn) ){
02676 trip_count = TN_value( trip_count_tn );
02677
02678 } else {
02679 const ANNOTATION* annot = ANNOT_Get(BB_annotations(body), ANNOT_LOOPINFO);
02680 const LOOPINFO* info = ANNOT_loopinfo(annot);
02681
02682 trip_count = WN_loop_trip_est(LOOPINFO_wn(info));
02683 }
02684
02685 OP* op = NULL;
02686 INT64 size = 0;
02687
02688 Working_Set.Clear();
02689
02690
02691
02692
02693 FOR_ALL_BB_OPs_FWD( body, op ){
02694 if(((OP_store( op ) && !TOP_is_nt_store(OP_code(op))) ||
02695 OP_load(op) ) &&
02696 !Op_In_Working_Set(op)){
02697 size += CGTARG_Mem_Ref_Bytes(op);
02698 }
02699 }
02700
02701 size *= trip_count;
02702
02703 const INT64 cache_size = CG_movnti * 1024;
02704
02705 if( size < cache_size )
02706 return;
02707 #if 0 //temporarily disable changeset of bug 11853 for bug 12036
02708 BOOL dep_graph_computed = FALSE;
02709 #endif
02710 FOR_ALL_BB_OPs_FWD( body, op ){
02711 if( OP_prefetch( op ) ){
02712
02713
02714
02715
02716
02717 const ISA_ENUM_CLASS_VALUE pfhint = TN_enum( OP_opnd(op,0) );
02718 if( pfhint == ECV_pfhint_L1_store )
02719 OP_Change_To_Noop( op );
02720
02721
02722
02723
02724 else if ( pfhint == ECV_pfhint_L1_L2_load && LNO_Prefetch_Ahead == 2 ) {
02725 INT opnd_num = OP_find_opnd_use(op, OU_offset);
02726 if (opnd_num >= 0 &&
02727 TN_has_value(OP_opnd(op, opnd_num))) {
02728 TN *tn = OP_opnd(op, opnd_num);
02729 Set_OP_opnd(op, opnd_num,
02730 Gen_Literal_TN(TN_value(tn) + 64*8, TN_size(tn)));
02731 }
02732 }
02733
02734 if ( pfhint == ECV_pfhint_L1_L2_load ) {
02735 switch(OP_code(op)) {
02736 case TOP_prefetcht0: OP_Change_Opcode(op, TOP_prefetchnta); break;
02737 case TOP_prefetcht0x: OP_Change_Opcode(op, TOP_prefetchntax); break;
02738 case TOP_prefetcht0xx: OP_Change_Opcode(op, TOP_prefetchntaxx); break;
02739 case TOP_prefetchnta:
02740 case TOP_prefetchntax:
02741 case TOP_prefetchntaxx: break;
02742 default: FmtAssert(FALSE, ("NYI"));
02743 }
02744 }
02745
02746 continue;
02747 }
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761 #if 0
02762 BOOL skip = FALSE;
02763 if (TOP_is_vector_op(OP_code(op)) &&
02764 ((OP_store(op) &&
02765 !TOP_is_nt_store(OP_code(op))))) {
02766 ARC_LIST *arcs;
02767 if (dep_graph_computed == FALSE) {
02768 CG_DEP_Compute_Graph(body, NO_ASSIGNED_REG_DEPS, NON_CYCLIC,
02769 INCLUDE_MEMREAD_ARCS, INCLUDE_MEMIN_ARCS,
02770 NO_CONTROL_ARCS, NULL );
02771 dep_graph_computed = TRUE;
02772 }
02773 for (arcs = OP_preds(op); arcs != NULL; arcs = ARC_LIST_rest(arcs)) {
02774 ARC *arc = ARC_LIST_first(arcs);
02775 if (ARC_kind(arc) == CG_DEP_MEMIN ||
02776 ARC_kind(arc) == CG_DEP_MEMANTI) {
02777 skip = TRUE;
02778 break;
02779 }
02780 }
02781 if (skip == TRUE)
02782 continue;
02783
02784 for (arcs = OP_succs(op); arcs != NULL; arcs = ARC_LIST_rest(arcs)) {
02785 ARC *arc = ARC_LIST_first(arcs);
02786 if (ARC_kind(arc) == CG_DEP_MEMIN ||
02787 ARC_kind(arc) == CG_DEP_MEMANTI) {
02788 skip = TRUE;
02789 break;
02790 }
02791 }
02792 if (skip == TRUE)
02793 continue;
02794 }
02795 #endif
02796 TOP new_top = TOP_UNDEFINED;
02797 switch( OP_code(op) ){
02798
02799 case TOP_staps:
02800 case TOP_stapsx:
02801 case TOP_stapsxx: {
02802 new_top = Movnti_Top(OP_code(op));
02803 break;
02804 }
02805
02806 case TOP_stapd:
02807 case TOP_stapdx:
02808 case TOP_stapdxx:
02809 case TOP_stdqa:
02810 case TOP_stdqax:
02811 case TOP_stdqaxx:
02812 case TOP_store32:
02813 case TOP_storex32:
02814 case TOP_storexx32:
02815 case TOP_store64:
02816 case TOP_storex64:
02817 case TOP_storexx64: {
02818
02819 if(Is_Target_SSE2() && TOP_is_vector_op(OP_code(op)))
02820 new_top = Movnti_Top(OP_code(op));
02821 break;
02822 }
02823
02824 case TOP_stss:
02825 case TOP_stssx:
02826 case TOP_stssxx:
02827 case TOP_stsd:
02828 case TOP_stsdx:
02829 case TOP_stsdxx: {
02830 if(Is_Target_SSE4a())
02831 new_top = Movnti_Top(OP_code(op));
02832 break;
02833 }
02834 }
02835
02836 if( new_top != TOP_UNDEFINED )
02837 OP_Change_Opcode( op, new_top );
02838 }
02839 #if 0 //temporarily disable the changeset of bug 11853 for bug 12036
02840 if (dep_graph_computed == TRUE)
02841 CG_DEP_Delete_Graph(body);
02842 #endif
02843 }
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854 void
02855 CGTARG_Generate_Branch_Cloop(OP *br_op,
02856 TN *unrolled_trip_count,
02857 TN *trip_count_tn,
02858 INT32 ntimes,
02859 TN *label_tn,
02860 OPS *prolog_ops,
02861 OPS *body_ops)
02862 {
02863 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
02864 }
02865
02866 static TN* asm_constraint_tn[10];
02867 static ISA_REGISTER_SUBCLASS asm_constraint_sc[10];
02868 static char asm_constraint_name[10][8];
02869 static INT asm_constraint_index;
02870
02871
02872 void
02873 CGTARG_Init_Asm_Constraints (void)
02874 {
02875
02876 Setup_Output_Parameter_Locations (MTYPE_To_TY(MTYPE_I8));
02877 for (INT i = 0; i < 10; ++i) {
02878 asm_constraint_tn[i] = NULL;
02879 asm_constraint_sc[i] = ISA_REGISTER_SUBCLASS_UNDEFINED;
02880 asm_constraint_name[i][0] = '\0';
02881 }
02882 asm_constraint_index = 0;
02883 }
02884
02885 #define CONST_OK_FOR_LETTER(VALUE, C) \
02886 ((C) == 'I' ? (VALUE) >= 0 && (VALUE) <= 31 \
02887 : (C) == 'J' ? (VALUE) >= 0 && (VALUE) <= 63 \
02888 : (C) == 'K' ? (VALUE) >= -128 && (VALUE) <= 127 \
02889 : (C) == 'L' ? (VALUE) == 0xff || (VALUE) == 0xffff \
02890 : (C) == 'M' ? (VALUE) >= 0 && (VALUE) <= 3 \
02891 : (C) == 'N' ? (VALUE) >= 0 && (VALUE) <= 255 \
02892 : (C) == 'i' ? ((VALUE) >> 32) == 0 || ((VALUE) >> 32) == -1 \
02893 : (C) == 'n' ? 1 \
02894 : 0)
02895
02896
02897
02898
02899
02900 extern TN*
02901 CGTARG_TN_For_Asm_Operand (const char* constraint,
02902 const WN* load,
02903 TN* pref_tn,
02904 ISA_REGISTER_SUBCLASS* subclass,
02905 TYPE_ID type)
02906 {
02907
02908
02909
02910
02911 static const char* modifiers = "=&%";
02912 while (strchr(modifiers, *constraint))
02913 {
02914 constraint++;
02915 }
02916
02917 const char* initial_constraint = constraint;
02918
02919
02920
02921
02922
02923
02924
02925 if (*constraint != 'm' && *constraint != 'g')
02926 {
02927 const char* m = constraint;
02928 while (*++m)
02929 {
02930 if (*m == 'm' || *m == 'g')
02931 {
02932 constraint = m;
02933 break;
02934 }
02935 }
02936 }
02937
02938
02939
02940 static const char* immediates = "inIJKLMNO";
02941
02942
02943 static const char* hash = "#";
02944 if (!strstr(constraint, hash)) {
02945 while (strchr(immediates, *constraint) && *(constraint+1))
02946 {
02947 constraint++;
02948 }
02949 }
02950
02951
02952
02953
02954
02955
02956
02957 const char * found_immediate = initial_constraint;
02958 while (!strchr(immediates, *found_immediate) && *(found_immediate+1))
02959 {
02960 found_immediate++;
02961 }
02962
02963
02964 if (strchr(immediates, *found_immediate) &&
02965 WN_operator(load) == OPR_INTCONST)
02966 constraint = found_immediate;
02967
02968 TN* ret_tn;
02969 BOOL first = FALSE, second = FALSE, third = FALSE, fourth = FALSE;
02970
02971
02972 if (strchr(immediates, *constraint))
02973 {
02974 if (load && WN_operator(load)==OPR_LDID && WN_class(load)==CLASS_PREG)
02975 {
02976
02977 load = Preg_Is_Rematerializable(WN_load_offset(load), NULL);
02978 }
02979 FmtAssert(load && (WN_operator(load) == OPR_INTCONST ||
02980 (WN_operator(load) == OPR_LDA &&
02981 ST_sym_class(WN_st(load)) == CLASS_CONST)),
02982 ("Cannot find immediate operand for ASM"));
02983 if (WN_operator(load) == OPR_INTCONST)
02984 {
02985 ret_tn = Gen_Literal_TN(WN_const_val(load),
02986 MTYPE_bit_size(WN_rtype(load))/8);
02987
02988 FmtAssert(CONST_OK_FOR_LETTER(WN_const_val(load), *constraint),
02989 ("The value of immediate operand supplied is not within expected range."));
02990 }
02991 else
02992 {
02993
02994 ST * base;
02995 INT64 ofst;
02996
02997 Allocate_Object (WN_st(load));
02998 Base_Symbol_And_Offset (WN_st(load), &base, &ofst);
02999 ret_tn = Gen_Symbol_TN(base, ofst, 0);
03000 }
03001 }
03002
03003 else if (isdigit(*constraint))
03004 {
03005
03006 INT prev_index = strtol(constraint, NULL, 10);
03007 if (prev_index < 0 || prev_index >= asm_constraint_index ||
03008 ! asm_constraint_tn[prev_index] ) {
03009 FmtAssert( FALSE, ("invalid matching constraint reference") );
03010 }
03011 ret_tn = asm_constraint_tn[prev_index];
03012 }
03013 else if (strchr("m", *constraint) || strchr("g", *constraint))
03014 {
03015 TYPE_ID rtype = (load != NULL ? WN_rtype(load) : MTYPE_I4);
03016 FmtAssert(MTYPE_is_integral(rtype),
03017 ("ASM operand does not satisfy its constraint"));
03018 ret_tn = (pref_tn ? pref_tn : Build_TN_Of_Mtype(rtype));
03019 }
03020 else if ((*constraint == 'r') || (*constraint == 'a') ||
03021 (*constraint == 'b') || (*constraint == 'v') ||
03022 (*constraint == 'h') || (*constraint == 'l') ||
03023 (*constraint == 'd') || (*constraint == 'c') ||
03024 (*constraint == 'S') || (*constraint == 'D') ||
03025 (*constraint == 'A') || (*constraint == 'q') ||
03026 (*constraint == 'Q') ||
03027 (*constraint == 'Z') ||
03028 (*constraint == 'e' && *(constraint+1) == 'r'))
03029 {
03030 TYPE_ID rtype;
03031
03032 if (load != NULL) {
03033
03034 rtype = (WN_desc(load) == MTYPE_V) ? WN_rtype(load) : WN_desc(load);
03035 if (WN_operator(load) == OPR_CVTL) {
03036 switch (WN_cvtl_bits(load)) {
03037
03038 case 32: rtype = MTYPE_U4; break;
03039 case 16: rtype = MTYPE_U2; break;
03040 case 8: rtype = MTYPE_U1; break;
03041 default: FmtAssert(FALSE, ("NYI"));
03042 }
03043 }
03044 else if (WN_operator(load) == OPR_CVT ||
03045
03046
03047 (WN_operator(load) == OPR_LDID &&
03048 WN_desc(load) == MTYPE_U4))
03049 rtype = WN_rtype(load);
03050 } else {
03051
03052
03053 rtype = type ;
03054 }
03055 if (pref_tn)
03056 ret_tn = pref_tn;
03057 else if ((*constraint == 'a') || (*constraint == 'b') ||
03058 (*constraint == 'c') || (*constraint == 'd') ||
03059 (*constraint == 'S') || (*constraint == 'D') ||
03060 (*constraint == 'A')) {
03061 REGISTER reg;
03062 switch (*constraint) {
03063 case 'a': reg = RAX; break;
03064 case 'b': reg = RBX; break;
03065 case 'c': reg = RCX; break;
03066 case 'd': reg = RDX; break;
03067 case 'S': reg = RSI; break;
03068 case 'D': reg = RDI; break;
03069
03070 case 'A': reg = RAX; break;
03071 }
03072 ret_tn = Build_Dedicated_TN(ISA_REGISTER_CLASS_integer, reg,
03073
03074
03075
03076 MTYPE_byte_size(rtype));
03077 } else
03078 ret_tn = Build_TN_Of_Mtype(rtype);
03079
03080 if (*constraint == 'q' || *constraint == 'Q') {
03081
03082
03083
03084
03085
03086 *subclass = ISA_REGISTER_SUBCLASS_m32_8bit_regs;
03087 }
03088 }
03089 else if (*constraint == 't' || *constraint == 'u')
03090 {
03091
03092
03093
03094 ret_tn = (pref_tn ? pref_tn : Build_TN_Of_Mtype(MTYPE_FQ));
03095 }
03096 else if (*constraint == 'f')
03097 {
03098 FmtAssert(FALSE, ("Asm constraint <f> requires x87 implementation"));
03099 ret_tn = (pref_tn ? pref_tn : Build_TN_Of_Mtype(MTYPE_F4));
03100 }
03101 else if (*constraint == 'x')
03102 {
03103 TYPE_ID mtype = MTYPE_F4;
03104 if (load)
03105 mtype = WN_rtype(load);
03106 ret_tn = (pref_tn ? pref_tn : Build_TN_Of_Mtype(mtype));
03107 }
03108 else if (*constraint == 'X')
03109 {
03110 TYPE_ID mtype = MTYPE_I4;
03111 if (load)
03112 mtype = WN_rtype(load);
03113 ret_tn = (pref_tn ? pref_tn : Build_TN_Of_Mtype(mtype));
03114 }
03115 else if (*constraint == 'Y')
03116 {
03117 TYPE_ID mtype = MTYPE_F8;
03118 if (load)
03119 mtype = WN_rtype(load);
03120 ret_tn = (pref_tn ? pref_tn : Build_TN_Of_Mtype(mtype));
03121 }
03122 else if (*constraint == 'y')
03123 {
03124 if(Is_Target_32bit())
03125 ret_tn = (pref_tn ? pref_tn : Build_RCLASS_TN(ISA_REGISTER_CLASS_mmx));
03126 else
03127 ret_tn = (pref_tn ? pref_tn : Build_RCLASS_TN(ISA_REGISTER_CLASS_float));
03128 }
03129 else
03130 {
03131 FmtAssert(FALSE, ("ASM constraint <%s> not supported", constraint));
03132 }
03133
03134 asm_constraint_tn[asm_constraint_index] = ret_tn;
03135 asm_constraint_index++;
03136
03137 return ret_tn;
03138 }
03139
03140
03141 static const char *
03142 Get_TN_Assembly_Name (TN *tn)
03143 {
03144 return "moo";
03145 }
03146
03147 void
03148 CGTARG_TN_And_Name_For_Asm_Constraint (char *constraint, TYPE_ID mtype,
03149 TYPE_ID desc, TN **tn, const char **name)
03150 {
03151 INT i;
03152 if (*constraint == '=') {
03153
03154 CGTARG_TN_And_Name_For_Asm_Constraint (constraint+1,
03155 mtype, desc, tn, name);
03156 return;
03157 }
03158 if (mtype == MTYPE_V) {
03159
03160 if (*constraint == 'f') mtype = MTYPE_F8;
03161 else mtype = MTYPE_I8;
03162 }
03163 switch (*constraint) {
03164 case 'r':
03165 FmtAssert(MTYPE_is_integral(mtype),
03166 ("ASM constraint is integer but parameter is not"));
03167 break;
03168 case 'f':
03169 FmtAssert(MTYPE_is_float(mtype),
03170 ("ASM constraint is float but parameter is not"));
03171 break;
03172 case 'm':
03173 case 'g':
03174 break;
03175 case '0':
03176 case '1':
03177 case '2':
03178 case '3':
03179 case '4':
03180 case '5':
03181 case '6':
03182 case '7':
03183 case '8':
03184 case '9': {
03185 i = strtol(constraint, NULL, 10);
03186 if (i < 0 || i >= asm_constraint_index || ! asm_constraint_tn[i] ) {
03187 FmtAssert( FALSE, ("invalid matching constraint reference") );
03188 }
03189
03190 *tn = asm_constraint_tn[i];
03191 asm_constraint_tn[asm_constraint_index] = *tn;
03192
03193 *name = asm_constraint_name[i];
03194 strcpy(asm_constraint_name[asm_constraint_index],*name);
03195
03196 ++asm_constraint_index;
03197 return;
03198 }
03199 case 'i':
03200
03201 *tn = NULL;
03202 *name = NULL;
03203 return;
03204 default:
03205 FmtAssert(FALSE, ("ASM constraint <%s> not supported", constraint));
03206 }
03207 PLOC ploc = Get_Output_Parameter_Location (MTYPE_To_TY(mtype));
03208 *tn = PREG_To_TN (MTYPE_To_PREG(mtype), PLOC_reg(ploc));
03209 asm_constraint_tn[asm_constraint_index] = *tn;
03210 *name = Get_TN_Assembly_Name(*tn);
03211 if (*constraint == 'm' || *constraint == 'g') {
03212 sprintf(asm_constraint_name[asm_constraint_index], "[%s]",
03213 *name);
03214 } else {
03215 sprintf(asm_constraint_name[asm_constraint_index], "%s",
03216 *name);
03217 }
03218
03219 *name = asm_constraint_name[asm_constraint_index];
03220 ++asm_constraint_index;
03221 }
03222
03223
03224
03225
03226
03227
03228
03229 char CGTARG_Asm_Opnd_Modifiers[] = { 'r' };
03230 INT CGTARG_Num_Asm_Opnd_Modifiers = 1;
03231
03232 static const char* int_reg_names[3][16] = {
03233
03234 { "%al", "%bl", "%bpl", "%spl", "%dil", "%sil", "%dl", "%cl",
03235 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" },
03236
03237 { "%ax", "%bx", "%bp", "%sp", "%di", "%si", "%dx", "%cx",
03238 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" },
03239
03240 { "%eax", "%ebx", "%ebp", "%esp", "%edi", "%esi", "%edx", "%ecx",
03241 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" },
03242 };
03243
03244 const char*
03245 CGTARG_Modified_Asm_Opnd_Name(char modifier, TN* tn, char *tn_name)
03246 {
03247 if (TN_register_class(tn) == ISA_REGISTER_CLASS_float ||
03248 TN_register_class(tn) == ISA_REGISTER_CLASS_x87)
03249 return tn_name;
03250
03251 if (modifier == 'r') {
03252 if (TN_size(tn) == 8)
03253 return tn_name;
03254 else {
03255
03256 INT sub_reg_class = 2;
03257 if (TN_size(tn) == 2)
03258 sub_reg_class = 1;
03259 else if (TN_size(tn) == 1)
03260 sub_reg_class = 0;
03261 const ISA_REGISTER_CLASS rc = ISA_REGISTER_CLASS_integer;
03262 for( REGISTER reg = REGISTER_MIN; reg <= REGISTER_CLASS_last_register( rc ); reg++ ){
03263 const char* n = REGISTER_name( rc, reg );
03264 if( strcmp( n, tn_name ) == 0 ){
03265 const char *regname;
03266 regname = int_reg_names[sub_reg_class][reg-REGISTER_MIN];
03267 return regname;
03268 }
03269 }
03270 }
03271 }
03272 else {
03273 FmtAssert(FALSE, ("Unknown ASM operand modifier '%c'", modifier));
03274 }
03275
03276 }
03277
03278
03279
03280
03281
03282
03283
03284
03285
03286 TN* CGTARG_Process_Asm_m_constraint( WN* load, void** offset, OPS* ops )
03287 {
03288 Is_True( load != NULL, ("Asm_m_constraint: load is NULL") );
03289 TN* asm_opnd = NULL;
03290
03291 if( WN_operator(load) == OPR_LDA ){
03292 OP* lda_op = OPS_last( ops );
03293 asm_opnd = OP_iadd(lda_op) ? OP_opnd( lda_op, 1 ) : OP_opnd( lda_op, 0 );
03294 OPS_Remove_Op( ops, lda_op );
03295
03296 } else if( WN_operator(load) == OPR_ADD ){
03297 OP* add_op = OPS_last( ops );
03298 TN* ofst_tn = OP_opnd( add_op, 1 );
03299
03300 if( !TN_is_constant(ofst_tn) )
03301 return NULL;
03302
03303 *offset = (void*)Gen_Literal_TN( TN_value(ofst_tn), 4 );
03304
03305 asm_opnd = OP_opnd( add_op, 0 );
03306 OPS_Remove_Op( ops, add_op );
03307
03308
03309
03310
03311
03312 OP* ld_op = OPS_last(ops);
03313 if( ld_op != NULL &&
03314 OP_load(ld_op) &&
03315 OP_result(ld_op,0) == asm_opnd ){
03316
03317 for( OP* prev_ld = OP_prev(ld_op);
03318 prev_ld != NULL;
03319 prev_ld = OP_prev(prev_ld) ){
03320
03321 if( OP_store(prev_ld) )
03322 break;
03323
03324 if( OP_load(prev_ld) &&
03325 OP_opnds(prev_ld) == OP_opnds(ld_op) ){
03326 bool match = true;
03327 for( int i = 0; i < OP_opnds(ld_op); i++ ){
03328 if( OP_opnd(prev_ld,i) != OP_opnd(ld_op,i) ){
03329 match = false;
03330 break;
03331 }
03332 }
03333
03334 if( match ){
03335 OPS_Remove_Op( ops, ld_op );
03336 asm_opnd = OP_result( prev_ld, 0 );
03337 break;
03338 }
03339 }
03340 }
03341 }
03342
03343 } else if( WN_operator(load) == OPR_LDID ){
03344 ;
03345
03346 } else {
03347 DevWarn( "Asm_m_constraint: Unsupported opcode (%s)",
03348 OPCODE_name(WN_opcode(load)) );
03349 return NULL;
03350 }
03351
03352 return asm_opnd;
03353 }
03354
03355
03356
03357
03358
03359
03360
03361 void
03362 CGTARG_Postprocess_Asm_String (char*)
03363 {
03364 }
03365
03366
03367
03368
03369
03370
03371
03372
03373
03374 BOOL CGTARG_Unconditional_Compare(OP *op, TOP* uncond_ver)
03375 {
03376 return FALSE;
03377 }
03378
03379
03380
03381
03382
03383
03384
03385
03386
03387 TOP CGTARG_Invert_Branch(BB* bb)
03388 {
03389 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
03390 return TOP_UNDEFINED;
03391 }
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402 void CGTARG_Init_OP_cond_def_kind(OP *op)
03403 {
03404 if( OP_has_predicate(op) ) {
03405 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
03406 } else {
03407 {
03408 Set_OP_cond_def_kind(op, OP_ALWAYS_UNC_DEF);
03409 }
03410 }
03411 }
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423 TOP CGTARG_Get_unc_Variant(TOP top)
03424 {
03425
03426 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
03427 return TOP_UNDEFINED;
03428 }
03429
03431
03432
03433
03434
03435 void
03436 Make_Branch_Conditional(BB *bb)
03437 {
03438 return;
03439 }
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450 BOOL
03451 CGTARG_Check_OP_For_HB_Suitability(OP *op)
03452 {
03453 switch(Eager_Level) {
03454 case EAGER_NONE:
03455 return FALSE;
03456 case EAGER_SAFE:
03457 if (OP_fadd(op) ||
03458 OP_fdiv(op) ||
03459 OP_fsub(op) ||
03460 OP_fmul(op) ||
03461 OP_load(op) ||
03462 OP_store(op) ||
03463 OP_prefetch(op) ||
03464
03465 OP_idiv(op) ||
03466 OP_imul(op) )
03467 return FALSE;
03468 else
03469 return TRUE;
03470 case EAGER_ARITH:
03471 if (OP_load(op) ||
03472 OP_store(op) ||
03473 OP_prefetch(op) ||
03474
03475 OP_fdiv(op) ||
03476 OP_idiv(op) ||
03477 OP_imul(op) )
03478 return FALSE;
03479 else
03480 return TRUE;
03481 case EAGER_DIVIDE:
03482 if (OP_load(op) ||
03483 OP_store(op) ||
03484 OP_prefetch(op) ||
03485 OP_idiv(op) ||
03486 OP_imul(op) )
03487 return FALSE;
03488 else
03489 return TRUE;
03490 case EAGER_MEMORY:
03491 case EAGER_OTHER:
03492 if (OP_idiv(op) ||
03493 OP_imul(op) )
03494 return FALSE;
03495 else
03496 return TRUE;
03497 default:
03498 FmtAssert(FALSE, ("Handle this case"));
03499 return FALSE;
03500 }
03501 }
03502
03503
03504 TN* CGTARG_Gen_Dedicated_Subclass_TN( OP* op, int idx, BOOL is_result )
03505 {
03506 const ISA_REGISTER_SUBCLASS subclass = is_result ?
03507 OP_result_reg_subclass( op, idx ) : OP_opnd_reg_subclass( op, idx );
03508 const REGISTER_SET subclass_regs = REGISTER_SUBCLASS_members(subclass);
03509
03510 if( REGISTER_SET_Size(subclass_regs) != 1 ){
03511 TN* tn = is_result ? OP_result( op, idx ) : OP_opnd( op, idx );
03512 return TN_is_dedicated(tn) ? tn : NULL;
03513 }
03514
03515 const REGISTER reg = REGISTER_SET_Choose(subclass_regs);
03516 const ISA_REGISTER_CLASS rc = REGISTER_SUBCLASS_register_class(subclass);
03517
03518 return Build_Dedicated_TN( rc, reg, 0 );
03519 }
03520
03521
03522
03523 BOOL
03524 CGTARG_Is_Thread_Local_Memory_OP (OP* op)
03525 {
03526 TOP code = OP_code(op);
03527
03528 int base_opnd = TOP_Find_Operand_Use(code, OU_base);
03529 if (base_opnd != -1 &&
03530 TN_is_thread_seg_ptr(OP_opnd(op, base_opnd))) {
03531 return TRUE;
03532 }
03533
03534 int offset_opnd = TOP_Find_Operand_Use(code, OU_offset);
03535 if (offset_opnd != -1 &&
03536 (TN_relocs(OP_opnd(op, offset_opnd)) == TN_RELOC_X8664_TPOFF32 ||
03537 TN_relocs(OP_opnd(op, offset_opnd)) == TN_RELOC_X8664_TPOFF32_seg_reg)) {
03538 return TRUE;
03539 }
03540
03541 return FALSE;
03542 }