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 #include <ctype.h>
00062
00063 #include "defs.h"
00064 #include "util.h"
00065 #include "config.h"
00066 #include "config_targ_opt.h"
00067 #include "erglob.h"
00068 #include "tracing.h"
00069 #include "data_layout.h"
00070 #include "const.h"
00071 #include "wn.h"
00072 #include "import.h"
00073 #include "opt_alias_interface.h"
00074 #include "opt_alias_mgr.h"
00075 #include "be_symtab.h"
00076 #include "cgir.h"
00077 #include "cg.h"
00078 #include "void_list.h"
00079 #include "cg_dep_graph.h"
00080 #include "cg_spill.h"
00081 #include "cg_vector.h"
00082 #include "whirl2ops.h"
00083 #include "ti_errors.h"
00084 #include "w2op.h"
00085 #include "cgexp.h"
00086 #include "targ_proc_properties.h"
00087 #include "ti_bundle.h"
00088 #include "hb_sched.h"
00089 #include "hb_hazards.h"
00090 #include "bb.h"
00091 #include "op.h"
00092 #include "op_list.h"
00093 #include "calls.h"
00094 #include "cgtarget.h"
00095 #include "calls.h"
00096 #include "config_lno.h"
00097 #include "cg_region.h"
00098 #include "eh_region.h"
00099 #include "cg_sched_est.h"
00100
00101 UINT32 CGTARG_branch_taken_penalty;
00102 BOOL CGTARG_branch_taken_penalty_overridden = FALSE;
00103
00104 TOP CGTARG_Invert_Table[TOP_count+1];
00105 TOP CGTARG_Immed_To_Reg_Table[TOP_count+1];
00106
00107 OPCODE CGTARG_Assoc_Base_Opr_Table[TOP_count];
00108 mTOP CGTARG_Assoc_Base_Top_Table[TOP_count];
00109 mTOP CGTARG_Assoc_Base_Fnc_Table[TOP_count];
00110
00111 mTOP CGTARG_Inter_RegClass_Copy_Table[ISA_REGISTER_CLASS_MAX+1][ISA_REGISTER_CLASS_MAX+1][2];
00112
00113
00114 BOOL Trace_TD = FALSE;
00115 BOOL Trace_Eager = FALSE;
00116 extern BOOL Trace_Call_Exp;
00117
00118
00119 UINT32 CGTARG_Mem_Ref_Bytes(const OP *memop)
00120
00121
00122
00123
00124
00125 {
00126 const TOP topcode = OP_code(memop);
00127
00128 FmtAssert( false, ("Unknown mem ref bytes: %s", TOP_Name(topcode)) );
00129 return 0;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 BOOL
00141 CGTARG_Is_OP_Speculative(OP *op)
00142 {
00143 if (!OP_load(op)) return FALSE;
00144
00145
00146 if (CGTARG_Is_OP_Advanced_Load(op) || CGTARG_Is_OP_Speculative_Load(op))
00147 return TRUE;
00148
00149 return FALSE;
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 void CGTARG_Perform_THR_Code_Generation (OP *load_op, OP *chk_load,
00161 THR_TYPE type)
00162 {
00163 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 INT CGTARG_ARC_Sched_Latency(
00175 ARC *arc
00176 )
00177 {
00178 if ( ARC_kind(arc) == CG_DEP_PREBR &&
00179 PROC_has_same_cycle_branch_shadow() )
00180 return 0;
00181 else
00182 return ARC_latency(arc);
00183 }
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 BOOL
00195 CGTARG_Bundle_Slot_Available(TI_BUNDLE *bundle,
00196 OP *op,
00197 INT slot,
00198 ISA_EXEC_UNIT_PROPERTY *prop,
00199 BOOL stop_bit_reqd,
00200 const CG_GROUPING *grouping)
00201 {
00202 return FALSE;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 BOOL
00214 CGTARG_Bundle_Stop_Bit_Available(TI_BUNDLE *bundle, INT slot)
00215 {
00216
00217 if (TI_BUNDLE_stop_bit(bundle, slot)) return TRUE;
00218
00219 return TI_BUNDLE_Stop_Bit_Available(bundle, slot);
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 void
00231 CGTARG_Handle_Bundle_Hazard (OP *op,
00232 TI_BUNDLE *bundle,
00233 VECTOR *bundle_vector,
00234 BOOL can_fill,
00235 INT slot_pos,
00236 INT max_pos,
00237 BOOL stop_bit_reqd,
00238 ISA_EXEC_UNIT_PROPERTY prop)
00239 {
00240 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 void
00252 CGTARG_Handle_Errata_Hazard (OP *op, INT erratnum, INT ops_to_check)
00253 {
00254 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 static void
00271 Reduce_Fraction(INT frac[2])
00272 {
00273 INT i;
00274 static const INT primes[] = {2, 3, 5, 7, 11, 13};
00275 INT n = frac[0];
00276 INT d = frac[1];
00277 INT p = d;
00278
00279 if (d < -1 || d > 1) {
00280 for (i = sizeof(primes) / sizeof(primes[0]); ; p = primes[--i]) {
00281 while (n % p == 0 && d % p == 0) {
00282 n = n / p;
00283 d = d / p;
00284 }
00285 if (i == 0) break;
00286 }
00287 }
00288
00289 frac[0] = n;
00290 frac[1] = d;
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 static void
00312 Harmonic_Mean(
00313 INT mean[2],
00314 INT a,
00315 const INT a_rate[2],
00316 INT b,
00317 const INT b_rate[2]
00318 ) {
00319 if (a == 0) {
00320 mean[0] = b_rate[0];
00321 mean[1] = b_rate[1];
00322 } else if (b == 0) {
00323 mean[0] = a_rate[0];
00324 mean[1] = a_rate[1];
00325 } else {
00326 mean[1] = (a * a_rate[1] * b_rate[0])
00327 + (b * b_rate[1] * a_rate[0]);
00328 mean[0] = (a + b) * a_rate[0] * b_rate[0];
00329 Reduce_Fraction(mean);
00330 }
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 void CGTARG_Peak_Rate( PEAK_RATE_CLASS prc, PRC_INFO *info, INT ratio[2] )
00343 {
00344 ratio[0] = 1;
00345 ratio[1] = 1;
00346
00347 switch (prc) {
00348 case PRC_INST:
00349 ratio[0] = 4;
00350 break;
00351 case PRC_MADD:
00352 case PRC_MEMREF:
00353 ratio[0] = 2;
00354 break;
00355 case PRC_FLOP:
00356 case PRC_FADD:
00357 case PRC_FMUL:
00358 ratio[0] = 2;
00359 break;
00360 case PRC_IOP:
00361 ratio[0] = 2;
00362 break;
00363 default:
00364 ratio[0] = 2;
00365 break;
00366 }
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 #define Plural(i) ((i) != 1 ? "s" : "")
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 static INT
00392 Percent_Of_Peak(INT numer, INT denom, INT peak[2])
00393 {
00394 if (numer == 0) return 0;
00395 return (numer * peak[1] * 100) / ((denom * peak[0]) + peak[1] - 1);
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 void
00408 CGTARG_Print_PRC_INFO(
00409 FILE *file,
00410 PRC_INFO *info,
00411 INT32 ii,
00412 const char *prefix,
00413 const char *suffix
00414 )
00415 {
00416 char *s;
00417 INT madds_per_cycle[2];
00418 INT memrefs_per_cycle[2];
00419 INT flops_per_cycle[2];
00420 INT fadds_per_cycle[2];
00421 INT fmuls_per_cycle[2];
00422 INT iops_per_cycle[2];
00423 INT insts_per_cycle[2];
00424 INT insts = info->refs[PRC_INST];
00425 INT memrefs = info->refs[PRC_MEMREF];
00426 INT flops = info->refs[PRC_FLOP];
00427 INT madds = info->refs[PRC_MADD];
00428 INT fadds = info->refs[PRC_FADD];
00429 INT fmuls = info->refs[PRC_FMUL];
00430 INT iops = info->refs[PRC_IOP];
00431
00432 CGTARG_Peak_Rate(PRC_INST, info, insts_per_cycle);
00433 CGTARG_Peak_Rate(PRC_MEMREF, info, memrefs_per_cycle);
00434 CGTARG_Peak_Rate(PRC_FLOP, info, flops_per_cycle);
00435 CGTARG_Peak_Rate(PRC_MADD, info, madds_per_cycle);
00436 CGTARG_Peak_Rate(PRC_FADD, info, fadds_per_cycle);
00437 CGTARG_Peak_Rate(PRC_FMUL, info, fmuls_per_cycle);
00438 CGTARG_Peak_Rate(PRC_IOP, info, iops_per_cycle);
00439
00440 FmtAssert( madds == 0, ("madds != 0 ") );
00441
00442 if (flops != 0) {
00443 BOOL unbalanced_fpu = FALSE;
00444
00445 if ( madds_per_cycle[0] != 0 ) {
00446 fprintf(file,"%s%5d flop%1s (%3d%% of peak)%s",
00447 prefix,
00448 flops,
00449 Plural(flops),
00450 Percent_Of_Peak(flops, ii, flops_per_cycle),
00451 suffix);
00452 }
00453 else {
00454 fprintf(file,"%s%5d flop%1s (%3d%% of peak)%s",
00455 prefix,
00456 flops,
00457 Plural(flops),
00458 Percent_Of_Peak(flops, ii, flops_per_cycle),
00459 suffix);
00460 }
00461
00462 if ( unbalanced_fpu ) {
00463 INT fmuls2_per_cycle[2];
00464 INT fadds2_per_cycle[2];
00465 INT fadds2 = fadds + madds;
00466 INT fmuls2 = fmuls + madds;
00467
00468 Harmonic_Mean(fmuls2_per_cycle,
00469 fmuls, fmuls_per_cycle,
00470 madds, madds_per_cycle);
00471 Harmonic_Mean(fadds2_per_cycle,
00472 fadds, fadds_per_cycle,
00473 madds, madds_per_cycle);
00474
00475 fprintf(file,"%s%5d fmul%1s (%3d%% of peak)%s%s",
00476 prefix,
00477 fmuls2,
00478 Plural(fmuls2),
00479 Percent_Of_Peak(fmuls2, ii, fmuls2_per_cycle),
00480 madds_per_cycle[0] ? " (madds count as 1)" : "",
00481 suffix);
00482 fprintf(file,"%s%5d fadd%1s (%3d%% of peak)%s%s",
00483 prefix,
00484 fadds2,
00485 Plural(fadds2),
00486 Percent_Of_Peak(fadds2, ii, fadds2_per_cycle),
00487 madds_per_cycle[0] ? " (madds count as 1)" : "",
00488 suffix);
00489 }
00490 }
00491
00492 s = "";
00493 if (FALSE) {
00494 iops += memrefs;
00495 s = " (mem refs included)";
00496 }
00497
00498 fprintf(file,"%s%5d mem ref%1s (%3d%% of peak)%s"
00499 "%s%5d integer op%1s (%3d%% of peak)%s%s"
00500 "%s%5d instruction%1s (%3d%% of peak)%s",
00501 prefix,
00502 memrefs,
00503 Plural(memrefs),
00504 Percent_Of_Peak(memrefs, ii, memrefs_per_cycle),
00505 suffix,
00506 prefix,
00507 iops,
00508 Plural(iops),
00509 Percent_Of_Peak(iops, ii, iops_per_cycle),
00510 s,
00511 suffix,
00512 prefix,
00513 insts,
00514 Plural(insts),
00515 Percent_Of_Peak(insts, ii, insts_per_cycle),
00516 suffix);
00517 }
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 void
00530 CGTARG_Compute_PRC_INFO(
00531 BB *bb,
00532 PRC_INFO *info
00533 )
00534 {
00535 OP *op;
00536
00537 #ifdef __MINGW32__
00538 memset (info, 0, sizeof (PRC_INFO));
00539 #else
00540 bzero (info, sizeof (PRC_INFO));
00541 #endif
00542
00543 for ( op = BB_first_op(bb); op != NULL; op = OP_next(op) ) {
00544 INT num_insts = OP_Real_Ops (op);
00545
00546 if (num_insts == 0) continue;
00547
00548 info->refs[PRC_INST] += num_insts;
00549
00550 if( OP_memory(op) ){
00551 ++info->refs[PRC_MEMREF];
00552 }
00553
00554 if( OP_memory(op) ){
00555 ;
00556 }
00557 else if ( OP_flop(op) ) {
00558 BOOL is_single = (OP_result_size(op,0) == 32);
00559
00560 ++info->refs[PRC_FLOP];
00561 info->refs[PRC_FLOP_S] += is_single;
00562 if (OP_madd(op)) {
00563 ++info->refs[PRC_MADD];
00564 info->refs[PRC_MADD_S] += is_single;
00565 }
00566 else if (OP_fadd(op) || OP_fsub(op)) {
00567 ++info->refs[PRC_FADD];
00568 info->refs[PRC_FADD_S] += is_single;
00569 }
00570 else if (OP_fmul(op)) {
00571 ++info->refs[PRC_FMUL];
00572 info->refs[PRC_FMUL_S] += is_single;
00573 }
00574 }
00575 else {
00576 INT k;
00577
00578
00579
00580
00581
00582 if (OP_has_result(op) && TN_is_float(OP_result(op,0))) goto not_iop;
00583
00584 for (k = 0; k < OP_opnds(op); k++) {
00585 if (TN_is_float(OP_opnd(op,k))) goto not_iop;
00586 }
00587
00588 info->refs[PRC_IOP] += num_insts;
00589
00590 not_iop:
00591 ;
00592 }
00593 }
00594 }
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 void
00606 CGTARG_Branch_Info ( const OP *op,
00607 INT *tfirst,
00608 INT *tcount )
00609 {
00610 INT i;
00611 TN *tn;
00612
00613
00614 *tfirst = -1;
00615 *tcount = 0;
00616
00617
00618 for ( i = 0; ; i++ ) {
00619 if ( i >= OP_opnds(op) ) return;
00620 tn = OP_opnd(op,i);
00621 if ( tn != NULL && TN_is_label(tn) ) break;
00622 }
00623 *tfirst = i;
00624
00625
00626 *tcount = 1;
00627 for ( i++; i < OP_opnds(op); i++ ) {
00628 tn = OP_opnd(op,i);
00629 if ( tn == NULL || ! TN_is_label(tn) ) return;
00630 (*tcount)++;
00631 }
00632 return;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 BOOL
00645 CGTARG_Can_Be_Speculative( OP *op )
00646 {
00647 WN *wn;
00648 TN *sym_tn;
00649
00650
00651 if (Eager_Level == EAGER_NONE) return FALSE;
00652
00653
00654 if (OP_volatile(op)) return FALSE;
00655
00656 if (TOP_Can_Be_Speculative(OP_code(op))) return TRUE;
00657
00658 if (!OP_load(op)) return FALSE;
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 if (OP_no_alias(op)) goto scalar_load;
00671
00672
00673
00674
00675
00676 sym_tn = OP_opnd(op, OP_find_opnd_use(op,OU_base));
00677 if (TN_is_symbol(sym_tn) && !ST_is_weak_symbol(TN_var(sym_tn)))
00678 goto scalar_load;
00679
00680
00681
00682
00683
00684 if (
00685 ( (wn = Get_WN_From_Memory_OP(op))
00686 && Alias_Manager->Safe_to_speculate(wn))) goto scalar_load;
00687
00688
00689
00690
00691 if (CGTARG_Is_OP_Speculative(op)) goto scalar_load;
00692
00693
00694
00695
00696 return FALSE;
00697
00698
00699
00700
00701 scalar_load:
00702 return TRUE;
00703 }
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713 BOOL
00714 CGTARG_Is_OP_Speculative_Load( OP *memop )
00715 {
00716 return FALSE;
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727 BOOL
00728 CGTARG_Is_OP_Advanced_Load( OP *memop )
00729 {
00730 return FALSE;
00731 }
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741 BOOL
00742 CGTARG_Is_OP_Check_Load( OP *memop )
00743 {
00744 return FALSE;
00745 }
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756 BOOL
00757 CGTARG_OP_Defs_TN( OP *op, TN *tn )
00758 {
00759 return FALSE;
00760 }
00761
00762 BOOL
00763 CGTARG_OP_Refs_TN( OP *op, TN *tn )
00764 {
00765 return FALSE;
00766 }
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776 static MEM_POOL interference_pool;
00777 static VOID_LIST** writing;
00778
00779 static BOOL is_loop;
00780 static INT32 assumed_longest_latency = 40;
00781
00782
00783
00784
00785
00786
00787 static INT32 cycle_count;
00788
00789 static void (*make_interference)(void*,void*);
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 BOOL
00801 CGTARG_Interference_Required(void)
00802 {
00803 return FALSE;
00804 }
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 void
00815 CGTARG_Interference_Initialize( INT32 cycle_count_local, BOOL is_loop_local,
00816 void (*make_interference_local)(void*,void*) )
00817 {
00818 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
00819 }
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829 void
00830 CGTARG_Result_Live_Range( void* lrange, OP* op, INT32 offset )
00831 {
00832 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
00833 }
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843 void
00844 CGTARG_Operand_Live_Range( void* lrange, INT opnd, OP* op, INT32 offset )
00845 {
00846 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
00847 }
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857 void
00858 CGTARG_Interference_Finalize(void)
00859 {
00860 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
00861 }
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 BOOL
00873 CGTARG_Preg_Register_And_Class(
00874 WN_OFFSET preg,
00875 ISA_REGISTER_CLASS *p_rclass,
00876 REGISTER *p_reg
00877 )
00878 {
00879 ISA_REGISTER_CLASS rclass;
00880 INT regnum;
00881
00882
00883
00884 if (!Preg_Is_Dedicated(preg))
00885 return FALSE;
00886
00887 if (!Preg_Offset_Is_Int(preg) &&
00888 !Preg_Offset_Is_Float(preg) )
00889 return FALSE;
00890
00891
00892
00893
00894 if (Preg_Offset_Is_Int32(preg)) {
00895 rclass = ISA_REGISTER_CLASS_integer;
00896 if (Is_Return_Preg(preg))
00897 regnum = ABI_PROPERTY_integer_func_val_First_Register
00898 + preg - First_Int32_Preg_Return_Offset;
00899 else if (Is_Formal_Preg(preg))
00900 regnum = ABI_PROPERTY_integer_func_arg_First_Register
00901 + preg - First_Int32_Preg_Param_Offset;
00902 else
00903 return FALSE;
00904 }
00905 else if (Preg_Offset_Is_Float32(preg)) {
00906 rclass = ISA_REGISTER_CLASS_float;
00907 if (Is_Return_Preg(preg))
00908 regnum = ABI_PROPERTY_float_func_val_First_Register
00909 + preg - First_Float32_Preg_Return_Offset;
00910 else if (Is_Formal_Preg(preg))
00911 regnum = ABI_PROPERTY_float_func_arg_First_Register
00912 + preg - First_Float32_Preg_Param_Offset;
00913 else
00914 return FALSE;
00915 }
00916 else if (Preg_Offset_Is_Int64(preg)) {
00917 rclass = ISA_REGISTER_CLASS_integer64;
00918 if (Is_Return_Preg(preg))
00919 regnum = ABI_PROPERTY_integer64_func_val_First_Register
00920 + preg - First_Int64_Preg_Return_Offset;
00921 else if (Is_Formal_Preg(preg))
00922 regnum = ABI_PROPERTY_integer64_func_arg_First_Register
00923 + preg - First_Int64_Preg_Param_Offset;
00924 else
00925 return FALSE;
00926 }
00927 else if (Preg_Offset_Is_Float64(preg)) {
00928 rclass = ISA_REGISTER_CLASS_float64;
00929 if (Is_Return_Preg(preg))
00930 regnum = ABI_PROPERTY_float64_func_val_First_Register
00931 + preg - First_Float64_Preg_Return_Offset;
00932 else if (Is_Formal_Preg(preg))
00933 regnum = ABI_PROPERTY_float64_func_arg_First_Register
00934 + preg - First_Float64_Preg_Param_Offset;
00935 else
00936 return FALSE;
00937 }
00938 else {
00939 return FALSE;
00940 }
00941
00942
00943 for ( REGISTER reg = REGISTER_MIN;
00944 reg <= REGISTER_CLASS_last_register(rclass);
00945 reg++ )
00946 {
00947 if ( REGISTER_machine_id(rclass,reg) == regnum )
00948 {
00949 *p_reg = reg;
00950 *p_rclass = rclass;
00951 return TRUE;
00952 }
00953 }
00954
00955 FmtAssert(FALSE, ("failed to map preg %d", preg));
00956
00957 }
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968 void CGTARG_Compute_Branch_Parameters(INT32 *mispredict, INT32 *fixed, INT32 *brtaken, double *factor)
00969 {
00970 *mispredict = 4;
00971 *fixed = 4;
00972 *brtaken = 4;
00973 *factor = 1.0;
00974
00975
00976
00977
00978
00979
00980 if (CG_branch_mispredict_penalty >= 0)
00981 *mispredict= CG_branch_mispredict_penalty ;
00982
00983 if (CG_branch_mispredict_factor >= 0)
00984 *factor= CG_branch_mispredict_factor * (.01);
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 BOOL CGTARG_Can_Change_To_Brlikely(OP *xfer_op, TOP *new_opcode)
00997 {
00998 return FALSE;
00999 }
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010 INT32 CGTARG_Latency( TOP op )
01011 {
01012 FmtAssert( FALSE, ("NYI") );
01013 return 1;
01014 }
01015
01016 BOOL CGTARG_Is_Long_Latency(TOP op)
01017 {
01018 return ( CGTARG_Latency(op) > 2 );
01019 }
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029 VARIANT CGTARG_Analyze_Branch(
01030 OP *br,
01031 TN **tn1,
01032 TN **tn2)
01033 {
01034 OP *cmp;
01035 return CGTARG_Analyze_Compare (br, tn1, tn2, &cmp);
01036 }
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047 VARIANT CGTARG_Analyze_Compare(
01048 OP *br,
01049 TN **tn1,
01050 TN **tn2,
01051 OP **compare_op)
01052 {
01053 VARIANT variant = V_BR_NONE;
01054 *tn1 = NULL;
01055 *tn2 = NULL;
01056 *compare_op = NULL;
01057
01058 switch (OP_code(br)) {
01059 case TOP_bra_uni:
01060 return V_BR_ALWAYS;
01061 case TOP_bra_uni_p:
01062 case TOP_bra_uni_np:
01063 case TOP_bra_p:
01064 case TOP_bra_np:
01065 *tn1 = OP_opnd(br, OP_PREDICATE_OPND);
01066 variant = V_BR_P_TRUE;
01067 break;
01068 default:
01069 FmtAssert( FALSE, ("unexpected branch") );
01070 }
01071
01072
01073 DEF_KIND kind;
01074 *compare_op = TN_Reaching_Value_At_Op(*tn1, br, &kind, TRUE);
01075
01076 if (*compare_op == NULL) {
01077 DevWarn("no compare for branch in bb%d?", BB_id(OP_bb(br)));
01078 return variant;
01079 }
01080
01081 switch (OP_code(*compare_op)) {
01082 case TOP_setp_eq_s16:
01083 case TOP_setp_eq_s32:
01084 variant = V_BR_I4EQ;
01085 break;
01086 case TOP_setp_eq_s64:
01087 variant = V_BR_I8EQ;
01088 break;
01089 case TOP_setp_eq_u16:
01090 case TOP_setp_eq_u32:
01091 variant = V_BR_U4EQ;
01092 break;
01093 case TOP_setp_eq_u64:
01094 variant = V_BR_U8EQ;
01095 break;
01096 case TOP_setp_eq_f32:
01097 variant = V_BR_FEQ;
01098 break;
01099 case TOP_setp_eq_f64:
01100 variant = V_BR_DEQ;
01101 break;
01102 case TOP_setp_ne_s16:
01103 case TOP_setp_ne_s32:
01104 variant = V_BR_I4NE;
01105 break;
01106 case TOP_setp_ne_s64:
01107 variant = V_BR_I8NE;
01108 break;
01109 case TOP_setp_ne_u16:
01110 case TOP_setp_ne_u32:
01111 variant = V_BR_U4NE;
01112 break;
01113 case TOP_setp_ne_u64:
01114 variant = V_BR_U8NE;
01115 break;
01116 case TOP_setp_ne_f32:
01117 variant = V_BR_FNE;
01118 break;
01119 case TOP_setp_ne_f64:
01120 variant = V_BR_DNE;
01121 break;
01122 case TOP_setp_lt_s16:
01123 case TOP_setp_lt_s32:
01124 variant = V_BR_I4LT;
01125 break;
01126 case TOP_setp_lt_s64:
01127 variant = V_BR_I8LT;
01128 break;
01129 case TOP_setp_lt_u16:
01130 case TOP_setp_lt_u32:
01131 variant = V_BR_U4LT;
01132 break;
01133 case TOP_setp_lt_u64:
01134 variant = V_BR_U8LT;
01135 break;
01136 case TOP_setp_lt_f32:
01137 variant = V_BR_FLT;
01138 break;
01139 case TOP_setp_lt_f64:
01140 variant = V_BR_DLT;
01141 break;
01142 case TOP_setp_le_s16:
01143 case TOP_setp_le_s32:
01144 variant = V_BR_I4LE;
01145 break;
01146 case TOP_setp_le_s64:
01147 variant = V_BR_I8LE;
01148 break;
01149 case TOP_setp_le_u16:
01150 case TOP_setp_le_u32:
01151 variant = V_BR_U4LE;
01152 break;
01153 case TOP_setp_le_u64:
01154 variant = V_BR_U8LE;
01155 break;
01156 case TOP_setp_le_f32:
01157 variant = V_BR_FLE;
01158 break;
01159 case TOP_setp_le_f64:
01160 variant = V_BR_DLE;
01161 break;
01162 case TOP_setp_gt_s16:
01163 case TOP_setp_gt_s32:
01164 variant = V_BR_I4GT;
01165 break;
01166 case TOP_setp_gt_s64:
01167 variant = V_BR_I8GT;
01168 break;
01169 case TOP_setp_gt_u16:
01170 case TOP_setp_gt_u32:
01171 variant = V_BR_U4GT;
01172 break;
01173 case TOP_setp_gt_u64:
01174 variant = V_BR_U8GT;
01175 break;
01176 case TOP_setp_gt_f32:
01177 variant = V_BR_FGT;
01178 break;
01179 case TOP_setp_gt_f64:
01180 variant = V_BR_DGT;
01181 break;
01182 case TOP_setp_ge_s16:
01183 case TOP_setp_ge_s32:
01184 variant = V_BR_I4GE;
01185 break;
01186 case TOP_setp_ge_s64:
01187 variant = V_BR_I8GE;
01188 break;
01189 case TOP_setp_ge_u16:
01190 case TOP_setp_ge_u32:
01191 variant = V_BR_U4GE;
01192 break;
01193 case TOP_setp_ge_u64:
01194 variant = V_BR_U8GE;
01195 break;
01196 case TOP_setp_ge_f32:
01197 variant = V_BR_FGE;
01198 break;
01199 case TOP_setp_ge_f64:
01200 variant = V_BR_DGE;
01201 break;
01202 case TOP_setp_neu_f32:
01203 variant = V_BR_FUO;
01204 break;
01205 case TOP_setp_neu_f64:
01206 variant = V_BR_DUO;
01207 break;
01208 case TOP_not_pred:
01209 variant = V_BR_PNE;
01210 break;
01211 case TOP_mov_pred:
01212 variant = V_BR_PEQ;
01213 break;
01214 case TOP_xor_pred:
01215 if (OP_code(br) == TOP_bra_p) {
01216 variant = V_BR_PNE;
01217 } else if (OP_code(br) == TOP_bra_np) {
01218 variant = V_BR_PEQ;
01219 } else {
01220 FmtAssert(FALSE, ("incompatible branch op with xor compare"));
01221 }
01222 break;
01223 default:
01224 FmtAssert(FALSE, ("defining op not a recognized compare"));
01225 }
01226 *tn1 = OP_opnd(*compare_op, 0);
01227 *tn2 = OP_opnd(*compare_op, 1);
01228 return variant;
01229 }
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240 TOP
01241 CGTARG_Equiv_Nonindex_Memory_Op ( OP *op )
01242 {
01243 return TOP_UNDEFINED;
01244 }
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254 TOP
01255 CGTARG_Which_OP_Select ( UINT16 bit_size, BOOL is_float, BOOL is_fcc )
01256 {
01257 FmtAssert( FALSE, ( "CGTARG_Which_OP_Select: Unsupported Target") );
01258 return TOP_UNDEFINED;
01259 }
01260
01261
01262
01263
01264
01265
01266
01267 void
01268 Insert_Stop_Bits(BB *bb)
01269 {
01270 }
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280 INT32 CGTARG_Special_Min_II(BB* loop_body, BOOL trace)
01281 {
01282 return 0;
01283 }
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293 void
01294 Hardware_Workarounds(void)
01295 {
01296 }
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306 void CGTARG_Initialize(void)
01307 {
01308 #define Set_Inv_Table(a,b) \
01309 do { \
01310 CGTARG_Invert_Table[a] = b; \
01311 CGTARG_Invert_Table[b] = a; \
01312 } while( 0 )
01313
01314 #define Set_Immed_To_Reg_Table(a,b) \
01315 do { \
01316 CGTARG_Immed_To_Reg_Table[a] = b; \
01317 CGTARG_Immed_To_Reg_Table[b] = a; \
01318 } while( 0 )
01319
01320 INT32 i;
01321
01322
01323
01324 for(i = 0; i <= TOP_count; ++i) {
01325 CGTARG_Invert_Table[i] = TOP_UNDEFINED;
01326 CGTARG_Immed_To_Reg_Table[i] = TOP_UNDEFINED;
01327 }
01328
01329 for (i = 0; i <= ISA_REGISTER_CLASS_MAX; ++i) {
01330 INT j;
01331 for (j = 0; j <= ISA_REGISTER_CLASS_MAX; ++j) {
01332 CGTARG_Inter_RegClass_Copy_Table[i][j][FALSE] = TOP_UNDEFINED;
01333 CGTARG_Inter_RegClass_Copy_Table[i][j][TRUE] = TOP_UNDEFINED;
01334 }
01335 }
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348 CGTARG_Inter_RegClass_Copy_Table[ISA_REGISTER_CLASS_float]
01349 [ISA_REGISTER_CLASS_integer]
01350 [FALSE] = TOP_UNDEFINED;
01351 CGTARG_Inter_RegClass_Copy_Table[ISA_REGISTER_CLASS_float]
01352 [ISA_REGISTER_CLASS_integer]
01353 [TRUE] = TOP_UNDEFINED;
01354
01355 CGTARG_Inter_RegClass_Copy_Table[ISA_REGISTER_CLASS_integer]
01356 [ISA_REGISTER_CLASS_float]
01357 [FALSE] = TOP_UNDEFINED;
01358 CGTARG_Inter_RegClass_Copy_Table[ISA_REGISTER_CLASS_integer]
01359 [ISA_REGISTER_CLASS_float]
01360 [TRUE] = TOP_UNDEFINED;
01361
01362 #undef Set_Inv_Table
01363 #undef Set_Immed_To_Reg_Table
01364
01365 return;
01366 }
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377 void CGTARG_Load_From_Memory(TN *tn, ST *mem_loc, OPS *ops)
01378 {
01379 TYPE_ID mtype = TY_mtype(ST_type(mem_loc));
01380 Exp_Load(mtype, mtype, tn, mem_loc, 0, ops, 0);
01381 }
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392 void CGTARG_Store_To_Memory(TN *tn, ST *mem_loc, OPS *ops)
01393 {
01394 TYPE_ID mtype = TY_mtype(ST_type(mem_loc));
01395 Exp_Store(mtype, tn, mem_loc, 0, ops, 0);
01396 }
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407 void CGTARG_Init_Assoc_Base(void)
01408 {
01409 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01410 }
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421 INT CGTARG_Copy_Operand(OP *op)
01422 {
01423 const TOP opr = OP_code(op);
01424
01425 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01426
01427 if( OP_cond_move( op ) &&
01428 TNs_Are_Equivalent( OP_result(op,0), OP_opnd(op,0) ) ){
01429 return 0;
01430 }
01431
01432 return -1;
01433 }
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444 BOOL CGTARG_Can_Fit_Immediate_In_Add_Instruction (INT64 immed)
01445 {
01446 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01447
01448 }
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459 BOOL CGTARG_Can_Load_Immediate_In_Single_Instruction (INT64 immed)
01460 {
01461 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01462
01463 }
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476 void
01477 CGTARG_Predicate_OP(BB* bb, OP* op, TN* pred_tn)
01478 {
01479 if (OP_has_predicate(op)) {
01480 FmtAssert( FALSE, ( "CGTARG_Which_OP_Select: Unsupported Target") );
01481 }
01482 }
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492 BOOL
01493 CGTARG_Branches_On_True(OP* br_op, OP* cmp_op)
01494 {
01495 return FALSE;
01496 }
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508 TOP
01509 CGTARG_Parallel_Compare(OP* cmp_op, COMPARE_TYPE ctype)
01510 {
01511 return TOP_UNDEFINED;
01512 }
01513
01514
01515 static BOOL OP_Reads_Dedicated_TN( OP* op, TN* ded_tn )
01516 {
01517 for( int i = 0; i < OP_opnds(op); i++ ){
01518 TN* tmp_tn = CGTARG_Gen_Dedicated_Subclass_TN( op, i, FALSE );
01519 if( tmp_tn != NULL &&
01520 TNs_Are_Equivalent( tmp_tn, ded_tn ) )
01521 return TRUE;
01522 }
01523
01524 return FALSE;
01525 }
01526
01527
01528 static BOOL OP_Writes_Dedicated_TN( OP* op, TN* ded_tn )
01529 {
01530 for( int i = 0; i < OP_results(op); i++ ){
01531 TN* tmp_tn = CGTARG_Gen_Dedicated_Subclass_TN( op, i, TRUE );
01532 if( tmp_tn != NULL &&
01533 TNs_Are_Equivalent( tmp_tn, ded_tn ) )
01534 return TRUE;
01535 }
01536
01537 return FALSE;
01538 }
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549 BOOL CGTARG_Dependence_Required( OP* pred_op, OP* succ_op )
01550 {
01551 FmtAssert( OP_bb(pred_op) == OP_bb(succ_op), ("pred==succ NYI") );
01552
01553 FmtAssert( FALSE, ("NYI") );
01554
01555
01556
01557
01558
01559 if( PU_Has_Exc_Handler ){
01560
01561
01562
01563 if( BB_entry( OP_bb(pred_op) ) &&
01564 OP_store( pred_op ) &&
01565 OP_store( succ_op ) &&
01566 TN_is_save_reg( OP_opnd(pred_op,0) ) )
01567 return TRUE;
01568 }
01569
01570
01571
01572
01573 {
01574 for( ARC_LIST* arcs = OP_succs(pred_op);
01575 arcs != NULL;
01576 arcs = ARC_LIST_rest(arcs) ){
01577 ARC *arc = ARC_LIST_first(arcs);
01578 if( ARC_succ(arc) == succ_op )
01579 return FALSE;
01580 }
01581 }
01582
01583
01584
01585
01586 {
01587 if( OP_results(pred_op) > 0 &&
01588 TN_is_sp_reg( OP_result(pred_op,0) ) &&
01589 OP_store( succ_op ) )
01590 return TRUE;
01591 }
01592
01593
01594
01595
01596
01597
01598 {
01599 BB* bb = OP_bb( pred_op );
01600 if( BB_entry(bb) && !BB_handler(bb) ){
01601 if( pred_op == BB_entry_sp_adj_op(bb) )
01602 return TRUE;
01603 }
01604
01605 if( BB_exit(bb) ){
01606 if( succ_op == BB_exit_sp_adj_op(bb) )
01607 return TRUE;
01608 }
01609 }
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620 {
01621 for( int i = 0; i < OP_opnds(succ_op); i++ ){
01622 TN* tmp_tn = CGTARG_Gen_Dedicated_Subclass_TN( succ_op, i, FALSE );
01623 if( tmp_tn != NULL ){
01624
01625 if( OP_Writes_Dedicated_TN( pred_op, tmp_tn ) )
01626 return TRUE;
01627
01628
01629
01630
01631
01632
01633 if( !TN_is_dedicated( OP_opnd(succ_op,i) ) &&
01634 OP_Reads_Dedicated_TN( pred_op, tmp_tn ) )
01635 return TRUE;
01636 }
01637 }
01638
01639 for( int i = 0; i < OP_results(succ_op); i++ ){
01640 TN* tmp_tn = CGTARG_Gen_Dedicated_Subclass_TN( succ_op, i, TRUE );
01641 if( tmp_tn != NULL ){
01642
01643 if( OP_Writes_Dedicated_TN( pred_op, tmp_tn ) ||
01644 OP_Reads_Dedicated_TN( pred_op, tmp_tn ) ){
01645 return TRUE;
01646 }
01647 }
01648 }
01649 }
01650
01651
01652
01653
01654 return FALSE;
01655 }
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666 void
01667 CGTARG_Adjust_Latency(OP *pred_op, OP *succ_op, CG_DEP_KIND kind, UINT8 opnd, INT *latency)
01668 {
01669 }
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679 void
01680 CGTARG_Generate_Remainder_Branch(TN *trip_count, TN *label_tn,
01681 OPS *prolog_ops, OPS *body_ops)
01682 {
01683 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01684 }
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695 BOOL CGTARG_OP_is_counted_loop(OP *op)
01696 {
01697 return FALSE;
01698 }
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722 void
01723 CGTARG_Generate_Countdown_Loop ( TN *trip_count_tn,
01724 BB *tail,
01725 OPS *prolog_ops,
01726 OPS *body_ops,
01727 BOOL single_bb,
01728 LOOP_DESCR *loop )
01729 {
01730 OP *cmp, *incr, *op, *branch;
01731 BOOL cmp_found = FALSE, incr_found = FALSE;
01732 INT opnd, result;
01733
01734 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01735
01736 branch = BB_branch_op(tail);
01737 incr = cmp = NULL;
01738
01739
01740 return;
01741 }
01742
01743
01744
01745
01746 void CGTARG_LOOP_Optimize( LOOP_DESCR* loop )
01747 {
01748 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01749 }
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760 void
01761 CGTARG_Generate_Branch_Cloop(OP *br_op,
01762 TN *unrolled_trip_count,
01763 TN *trip_count_tn,
01764 INT32 ntimes,
01765 TN *label_tn,
01766 OPS *prolog_ops,
01767 OPS *body_ops)
01768 {
01769 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
01770 }
01771
01772 static TN* asm_constraint_tn[10];
01773 static ISA_REGISTER_SUBCLASS asm_constraint_sc[10];
01774 static char asm_constraint_name[10][8];
01775 static INT asm_constraint_index;
01776
01777
01778 void
01779 CGTARG_Init_Asm_Constraints (void)
01780 {
01781
01782 Setup_Output_Parameter_Locations (MTYPE_To_TY(MTYPE_I8));
01783 for (INT i = 0; i < 10; ++i) {
01784 asm_constraint_tn[i] = NULL;
01785 asm_constraint_sc[i] = ISA_REGISTER_SUBCLASS_UNDEFINED;
01786 asm_constraint_name[i][0] = '\0';
01787 }
01788 asm_constraint_index = 0;
01789 }
01790
01791
01792
01793
01794
01795 extern TN*
01796 CGTARG_TN_For_Asm_Operand (const char* constraint,
01797 const WN* load,
01798 TN* pref_tn,
01799 ISA_REGISTER_SUBCLASS* subclass,
01800 TYPE_ID type)
01801 {
01802
01803
01804
01805
01806 static const char* modifiers = "=&%";
01807 while (strchr(modifiers, *constraint))
01808 {
01809 constraint++;
01810 }
01811
01812
01813
01814
01815
01816
01817
01818 if (*constraint != 'm' && *constraint != 'g')
01819 {
01820 const char* m = constraint;
01821 while (*++m)
01822 {
01823 if (*m == 'm' || *m == 'g')
01824 {
01825 constraint = m;
01826 break;
01827 }
01828 }
01829 }
01830
01831 TN* ret_tn;
01832
01833
01834 if (isdigit(*constraint))
01835 {
01836
01837 INT prev_index = strtol(constraint, NULL, 10);
01838 if (prev_index < 0 || prev_index >= asm_constraint_index ||
01839 ! asm_constraint_tn[prev_index] ) {
01840 FmtAssert( FALSE, ("invalid matching constraint reference") );
01841 }
01842 ret_tn = asm_constraint_tn[prev_index];
01843 }
01844 else if (strchr("m", *constraint) || strchr("g", *constraint))
01845 {
01846 TYPE_ID rtype = (load != NULL ? WN_rtype(load) : MTYPE_I4);
01847 FmtAssert(MTYPE_is_integral(rtype),
01848 ("ASM operand does not satisfy its constraint %s", constraint));
01849
01850
01851 if (pref_tn) ret_tn = pref_tn;
01852 else {
01853 FmtAssert(load, ("no load for asm m constraint"));
01854 if (ST_class(WN_st(load)) == CLASS_PREG) {
01855
01856 load = TN_home(PREG_To_TN(WN_st(load),WN_load_offset(load)));
01857 }
01858 ret_tn = Gen_Symbol_TN (WN_st(load), 0, 0);
01859
01860
01861
01862
01863 if (strncmp(ST_name(WN_st(load)), "__cuda___T", 10) == 0) {
01864 OP *op;
01865 DevWarn("asm m param is __T temp, so replace with earlier def");
01866 FOR_ALL_OPS_OPs_REV(&New_OPs,op) {
01867 if (OP_store(op)) {
01868 TN *sym_tn = OP_opnd(op, OP_find_opnd_use(op,OU_base));
01869 if (TN_is_symbol(sym_tn) && TN_var(sym_tn) == WN_st(load)) {
01870 ret_tn = OP_opnd(op, OP_find_opnd_use(op,OU_storeval));
01871 if (TN_in_texture_mem(ret_tn) && TN_home(ret_tn) != NULL) {
01872 DevWarn("texture ret_tn");
01873 ret_tn = Gen_Symbol_TN (WN_st(TN_home(ret_tn)), 0, 0);
01874 break;
01875 }
01876 }
01877 }
01878 }
01879 }
01880 }
01881 }
01882 else if ((*constraint == 'h'))
01883 {
01884 TYPE_ID mtype = MTYPE_I2;
01885 if (load)
01886 mtype = WN_desc(load);
01887 FmtAssert(MTYPE_is_integral(mtype) && MTYPE_bit_size(mtype) == 16,
01888 ("ASM operand does not satisfy its constraint %s", constraint));
01889 ret_tn = (pref_tn ? pref_tn : Build_TN_Of_Mtype(mtype));
01890 }
01891 else if ((*constraint == 'r'))
01892 {
01893 TYPE_ID mtype = MTYPE_I4;
01894 if (load)
01895 mtype = WN_rtype(load);
01896 FmtAssert(MTYPE_is_integral(mtype) && MTYPE_bit_size(mtype) == 32,
01897 ("ASM operand does not satisfy its constraint %s", constraint));
01898 ret_tn = (pref_tn ? pref_tn : Build_TN_Of_Mtype(mtype));
01899 }
01900 else if ((*constraint == 'l'))
01901 {
01902 TYPE_ID mtype = MTYPE_I8;
01903 if (load)
01904 mtype = WN_rtype(load);
01905 FmtAssert(MTYPE_is_integral(mtype) && MTYPE_bit_size(mtype) == 64,
01906 ("ASM operand does not satisfy its constraint %s", constraint));
01907 ret_tn = (pref_tn ? pref_tn : Build_TN_Of_Mtype(mtype));
01908 }
01909 else if (*constraint == 'f')
01910 {
01911 TYPE_ID mtype = MTYPE_F4;
01912 if (load)
01913 mtype = WN_rtype(load);
01914 FmtAssert(MTYPE_is_float(mtype) && MTYPE_bit_size(mtype) == 32,
01915 ("ASM operand does not satisfy its constraint %s", constraint));
01916 ret_tn = (pref_tn ? pref_tn : Build_TN_Of_Mtype(mtype));
01917 }
01918 else if (*constraint == 'd')
01919 {
01920 TYPE_ID mtype = MTYPE_F8;
01921 if (load)
01922 mtype = WN_rtype(load);
01923 FmtAssert(MTYPE_is_float(mtype) && MTYPE_bit_size(mtype) == 64,
01924 ("ASM operand does not satisfy its constraint %s", constraint));
01925 ret_tn = (pref_tn ? pref_tn : Build_TN_Of_Mtype(mtype));
01926 }
01927 else if (*constraint == 'n')
01928 {
01929 FmtAssert(load && WN_operator(load) == OPR_INTCONST,
01930 ("Cannot find immediate operand for ASM"));
01931 ret_tn = Gen_Literal_TN(WN_const_val(load),
01932 MTYPE_byte_size(WN_rtype(load)));
01933 }
01934 else if (*constraint == 's')
01935 {
01936 ST *st;
01937 TY_IDX ty;
01938 INT64 offset;
01939 FmtAssert(load, ("no whirl for constraint s?"));
01940 if (WN_operator(load) == OPR_LDID
01941 && ST_class(WN_st(load)) == CLASS_PREG)
01942 {
01943
01944 load = TN_home(PREG_To_TN(WN_st(load),WN_load_offset(load)));
01945 }
01946 if (WN_operator(load)==OPR_LDID) {
01947 st = WN_st(load);
01948 offset = WN_offset(load);
01949 ty = WN_ty(load);
01950 }
01951 else if (WN_operator(load)==OPR_ILOAD
01952 && WN_operator(WN_kid0(load)) == OPR_ADD
01953 && WN_operator(WN_kid0(WN_kid0(load))) == OPR_LDA
01954 && WN_operator(WN_kid1(WN_kid0(load))) == OPR_INTCONST)
01955 {
01956
01957 st = WN_st(WN_kid0(WN_kid0(load)));
01958 offset = WN_const_val(WN_kid1(WN_kid0(load)));
01959 ty = WN_ty(load);
01960 }
01961 else if (WN_operator(load) == OPR_LDA) {
01962 st = WN_st(load);
01963 }
01964 else
01965 FmtAssert(FALSE, ("unexpected whirl for constraint s"));
01966
01967 if (ST_class(st) != CLASS_CONST) {
01968 INITV_IDX inv = ST_is_const_and_has_initv(st);
01969 FmtAssert(inv, ("s constraint operand not const initialized (%s)", ST_name(st)));
01970 if (INITV_kind(inv) == INITVKIND_BLOCK
01971 && TY_kind(ty) == KIND_POINTER)
01972 {
01973
01974 INT index = offset / TY_size(ty);
01975 inv = INITV_blk(inv);
01976 INT i;
01977 for (i = 0; i < index; ++i)
01978 inv = INITV_next(inv);
01979 }
01980 FmtAssert(INITV_kind(inv) == INITVKIND_SYMOFF, ("s constraint operand not a string?"));
01981 st = &St_Table[INITV_st(inv)];
01982 }
01983 FmtAssert(ST_class(st) == CLASS_CONST, ("s constraint operand not constant"));
01984 FmtAssert(TCON_ty(STC_val(st)) == MTYPE_STR, ("s constraint operand not a string"));
01985 ret_tn = Gen_Symbol_TN(st, 0, 0);
01986 }
01987 else
01988 {
01989 FmtAssert(FALSE, ("ASM constraint <%s> not supported", constraint));
01990 }
01991
01992 asm_constraint_tn[asm_constraint_index] = ret_tn;
01993 asm_constraint_index++;
01994
01995 return ret_tn;
01996 }
01997
01998
01999 static char *
02000 Get_TN_Assembly_Name (TN *tn)
02001 {
02002 return "moo";
02003 }
02004
02005 void
02006 CGTARG_TN_And_Name_For_Asm_Constraint (char *constraint, TYPE_ID mtype,
02007 TYPE_ID desc, TN **tn, char **name)
02008 {
02009 INT i;
02010 if (*constraint == '=') {
02011
02012 CGTARG_TN_And_Name_For_Asm_Constraint (constraint+1,
02013 mtype, desc, tn, name);
02014 return;
02015 }
02016 if (mtype == MTYPE_V) {
02017
02018 if (*constraint == 'f') mtype = MTYPE_F8;
02019 else mtype = MTYPE_I8;
02020 }
02021 switch (*constraint) {
02022 case 'r':
02023 case 'h':
02024 case 'l':
02025 FmtAssert(MTYPE_is_integral(mtype),
02026 ("ASM constraint is integer but parameter is not"));
02027 break;
02028 case 'f':
02029 case 'd':
02030 FmtAssert(MTYPE_is_float(mtype),
02031 ("ASM constraint is float but parameter is not"));
02032 break;
02033 case 'm':
02034 case 'g':
02035 break;
02036 case '0':
02037 case '1':
02038 case '2':
02039 case '3':
02040 case '4':
02041 case '5':
02042 case '6':
02043 case '7':
02044 case '8':
02045 case '9': {
02046 i = strtol(constraint, NULL, 10);
02047 if (i < 0 || i >= asm_constraint_index || ! asm_constraint_tn[i] ) {
02048 FmtAssert( FALSE, ("invalid matching constraint reference") );
02049 }
02050
02051 *tn = asm_constraint_tn[i];
02052 asm_constraint_tn[asm_constraint_index] = *tn;
02053
02054 *name = asm_constraint_name[i];
02055 strcpy(asm_constraint_name[asm_constraint_index],*name);
02056
02057 ++asm_constraint_index;
02058 return;
02059 }
02060 case 'i':
02061
02062 *tn = NULL;
02063 *name = NULL;
02064 return;
02065 default:
02066 FmtAssert(FALSE, ("ASM constraint <%s> not supported", constraint));
02067 }
02068 PLOC ploc = Get_Output_Parameter_Location (MTYPE_To_TY(mtype));
02069 *tn = PREG_To_TN (MTYPE_To_PREG(mtype), PLOC_reg(ploc));
02070 asm_constraint_tn[asm_constraint_index] = *tn;
02071 *name = Get_TN_Assembly_Name(*tn);
02072 if (*constraint == 'm' || *constraint == 'g') {
02073 sprintf(asm_constraint_name[asm_constraint_index], "[%s]",
02074 *name);
02075 } else {
02076 sprintf(asm_constraint_name[asm_constraint_index], "%s",
02077 *name);
02078 }
02079
02080 *name = asm_constraint_name[asm_constraint_index];
02081 ++asm_constraint_index;
02082 }
02083
02084
02085
02086
02087
02088
02089
02090 char CGTARG_Asm_Opnd_Modifiers[] = { 'r' };
02091 INT CGTARG_Num_Asm_Opnd_Modifiers = 1;
02092
02093 static const char* int_reg_names[3][16] = {
02094
02095 { "%al", "%bl", "%bpl", "%spl", "%dil", "%sil", "%dl", "%cl",
02096 "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" },
02097
02098 { "%ax", "%bx", "%bp", "%sp", "%di", "%si", "%dx", "%cx",
02099 "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" },
02100
02101 { "%eax", "%ebx", "%ebp", "%esp", "%edi", "%esi", "%edx", "%ecx",
02102 "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" },
02103 };
02104
02105 const char*
02106 CGTARG_Modified_Asm_Opnd_Name(char modifier, TN* tn, char *tn_name)
02107 {
02108 return tn_name;
02109
02110 if (TN_register_class(tn) == ISA_REGISTER_CLASS_float)
02111 return tn_name;
02112
02113 if (modifier == 'r') {
02114 if (TN_size(tn) == 8)
02115 return tn_name;
02116 else {
02117
02118 INT sub_reg_class = 2;
02119 if (TN_size(tn) == 2)
02120 sub_reg_class = 1;
02121 else if (TN_size(tn) == 1)
02122 sub_reg_class = 0;
02123 const ISA_REGISTER_CLASS rc = ISA_REGISTER_CLASS_integer;
02124 for( REGISTER reg = REGISTER_MIN; reg <= REGISTER_CLASS_last_register( rc ); reg++ ){
02125 const char* n = REGISTER_name( rc, reg );
02126 if( strcmp( n, tn_name ) == 0 ){
02127 const char *regname;
02128 regname = int_reg_names[sub_reg_class][reg-REGISTER_MIN];
02129 return regname;
02130 }
02131 }
02132 }
02133 }
02134 else {
02135 FmtAssert(FALSE, ("Unknown ASM operand modifier '%c'", modifier));
02136 }
02137
02138 }
02139
02140
02141
02142
02143
02144
02145
02146
02147
02148 TN* CGTARG_Process_Asm_m_constraint( WN* load, void** offset, OPS* ops )
02149 {
02150 Is_True( load != NULL, ("Asm_m_constraint: load is NULL") );
02151 TN* asm_opnd = NULL;
02152
02153 if( WN_operator(load) == OPR_LDA ){
02154 OP* lda_op = OPS_last( ops );
02155 asm_opnd = OP_iadd(lda_op) ? OP_opnd( lda_op, 1 ) : OP_opnd( lda_op, 0 );
02156 OPS_Remove_Op( ops, lda_op );
02157
02158 } else if( WN_operator(load) == OPR_ADD ){
02159 OP* add_op = OPS_last( ops );
02160 TN* ofst_tn = OP_opnd( add_op, 1 );
02161
02162 if( !TN_is_constant(ofst_tn) )
02163 return NULL;
02164
02165 *offset = (void*)Gen_Literal_TN( TN_value(ofst_tn), 4 );
02166
02167 asm_opnd = OP_opnd( add_op, 0 );
02168 OPS_Remove_Op( ops, add_op );
02169
02170
02171
02172
02173
02174 OP* ld_op = OPS_last(ops);
02175 if( ld_op != NULL &&
02176 OP_load(ld_op) &&
02177 OP_result(ld_op,0) == asm_opnd ){
02178
02179 for( OP* prev_ld = OP_prev(ld_op);
02180 prev_ld != NULL;
02181 prev_ld = OP_prev(prev_ld) ){
02182
02183 if( OP_store(prev_ld) )
02184 break;
02185
02186 if( OP_load(prev_ld) &&
02187 OP_opnds(prev_ld) == OP_opnds(ld_op) ){
02188 bool match = true;
02189 for( int i = 0; i < OP_opnds(ld_op); i++ ){
02190 if( OP_opnd(prev_ld,i) != OP_opnd(ld_op,i) ){
02191 match = false;
02192 break;
02193 }
02194 }
02195
02196 if( match ){
02197 OPS_Remove_Op( ops, ld_op );
02198 asm_opnd = OP_result( prev_ld, 0 );
02199 break;
02200 }
02201 }
02202 }
02203 }
02204
02205 } else if( WN_operator(load) == OPR_LDID ){
02206 ;
02207
02208 } else {
02209 DevWarn( "Asm_m_constraint: Unsupported opcode (%s)",
02210 OPCODE_name(WN_opcode(load)) );
02211 return NULL;
02212 }
02213
02214 return asm_opnd;
02215 }
02216
02217
02218
02219
02220
02221
02222
02223 void
02224 CGTARG_Postprocess_Asm_String (char*)
02225 {
02226 }
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236 BOOL CGTARG_Unconditional_Compare(OP *op, TOP* uncond_ver)
02237 {
02238 return FALSE;
02239 }
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249 TOP CGTARG_Invert_Branch(BB* bb)
02250 {
02251 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
02252 return TOP_UNDEFINED;
02253 }
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264 void CGTARG_Init_OP_cond_def_kind(OP *op)
02265 {
02266 if( OP_has_predicate(op) ) {
02267 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
02268 } else {
02269 {
02270 Set_OP_cond_def_kind(op, OP_ALWAYS_UNC_DEF);
02271 }
02272 }
02273 }
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285 TOP CGTARG_Get_unc_Variant(TOP top)
02286 {
02287
02288 FmtAssert(FALSE,("NOT YET IMPLEMENTED"));
02289 return TOP_UNDEFINED;
02290 }
02291
02293
02294
02295
02296
02297 void
02298 Make_Branch_Conditional(BB *bb)
02299 {
02300 return;
02301 }
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312 BOOL
02313 CGTARG_Check_OP_For_HB_Suitability(OP *op)
02314 {
02315 switch(Eager_Level) {
02316 case EAGER_NONE:
02317 return FALSE;
02318 case EAGER_SAFE:
02319 if (OP_fadd(op) ||
02320 OP_fdiv(op) ||
02321 OP_fsub(op) ||
02322 OP_fmul(op) ||
02323 OP_load(op) ||
02324 OP_store(op) ||
02325 OP_prefetch(op) ||
02326
02327 OP_idiv(op) ||
02328 OP_imul(op) )
02329 return FALSE;
02330 else
02331 return TRUE;
02332 case EAGER_ARITH:
02333 if (OP_load(op) ||
02334 OP_store(op) ||
02335 OP_prefetch(op) ||
02336
02337 OP_fdiv(op) ||
02338 OP_idiv(op) ||
02339 OP_imul(op) )
02340 return FALSE;
02341 else
02342 return TRUE;
02343 case EAGER_DIVIDE:
02344 if (OP_load(op) ||
02345 OP_store(op) ||
02346 OP_prefetch(op) ||
02347 OP_idiv(op) ||
02348 OP_imul(op) )
02349 return FALSE;
02350 else
02351 return TRUE;
02352 case EAGER_MEMORY:
02353 case EAGER_OTHER:
02354 if (OP_idiv(op) ||
02355 OP_imul(op) )
02356 return FALSE;
02357 else
02358 return TRUE;
02359 default:
02360 FmtAssert(FALSE, ("Handle this case"));
02361 return FALSE;
02362 }
02363 }
02364
02365
02366 TN* CGTARG_Gen_Dedicated_Subclass_TN( OP* op, int idx, BOOL is_result )
02367 {
02368 const ISA_REGISTER_SUBCLASS subclass = is_result ?
02369 OP_result_reg_subclass( op, idx ) : OP_opnd_reg_subclass( op, idx );
02370 const REGISTER_SET subclass_regs = REGISTER_SUBCLASS_members(subclass);
02371
02372 if( REGISTER_SET_Size(subclass_regs) != 1 ){
02373 TN* tn = is_result ? OP_result( op, idx ) : OP_opnd( op, idx );
02374 return TN_is_dedicated(tn) ? tn : NULL;
02375 }
02376
02377 const REGISTER reg = REGISTER_SET_Choose(subclass_regs);
02378 const ISA_REGISTER_CLASS rc = REGISTER_SUBCLASS_register_class(subclass);
02379
02380 return Build_Dedicated_TN( rc, reg, 0 );
02381 }
02382
02383 ISA_LIT_CLASS
02384 Lit_Class_For_Mtype (TYPE_ID mtype)
02385 {
02386 switch (mtype) {
02387 case MTYPE_I1: return LC_i8;
02388 case MTYPE_U1: return LC_u8;
02389 case MTYPE_I2: return LC_i16;
02390 case MTYPE_U2: return LC_u16;
02391 case MTYPE_I4: return LC_i32;
02392 case MTYPE_U4: return LC_u32;
02393 case MTYPE_I8: return LC_i64;
02394 case MTYPE_U8: return LC_u64;
02395 case MTYPE_F4: return LC_f32;
02396 case MTYPE_F8: return LC_f64;
02397 default: return LC_UNDEFINED;
02398 }
02399 }
02400
02401 BOOL
02402 TN_Can_Use_Constant_Value (TN *tn, TYPE_ID mtype, INT64 *val)
02403 {
02404 #if 0
02405 if (!MTYPE_is_integral(mtype))
02406 return FALSE;
02407 #endif
02408 if (TN_has_value(tn))
02409 *val = TN_value(tn);
02410 else if (TN_is_rematerializable(tn) && WN_operator(TN_home(tn)) == OPR_INTCONST)
02411 *val = WN_const_val(TN_home(tn));
02412 else
02413 return FALSE;
02414
02415 return TRUE;
02416
02417
02418 return ISA_LC_Value_In_Class (*val, Lit_Class_For_Mtype(mtype));
02419 }
02420
02421 static REGISTER_SET avail_set[ISA_REGISTER_CLASS_MAX+1];
02422 static REGISTER last_reg_allocated[ISA_REGISTER_CLASS_MAX+1];
02423
02424 void
02425 Assign_Virtual_Register (TN *tn)
02426 {
02427 ISA_REGISTER_CLASS cl;
02428 REGISTER reg;
02429 if (TN_Is_Allocatable(tn) && TN_register(tn) == REGISTER_UNDEFINED) {
02430 cl = TN_register_class(tn);
02431 reg = REGISTER_SET_Choose(avail_set[cl]);
02432 FmtAssert(reg != REGISTER_UNDEFINED, ("ran out of registers in %s",
02433 ISA_REGISTER_CLASS_INFO_Name(ISA_REGISTER_CLASS_Info(cl))));
02434
02435 TN_Allocate_Register( tn, reg );
02436 last_reg_allocated[cl] = reg;
02437 if (Get_Trace(TP_ALLOC,1))
02438 fprintf(TFile, "assign reg %d to TN %d\n", reg, TN_number(tn));
02439 avail_set[cl] = REGISTER_SET_Difference1 (avail_set[cl], reg);
02440 }
02441 }
02442
02443
02444 void
02445 Assign_Virtual_Registers(void)
02446 {
02447 BB *bb;
02448 OP *op;
02449 TN *tn;
02450 ISA_REGISTER_CLASS cl;
02451 FOR_ALL_ISA_REGISTER_CLASS(cl) {
02452 avail_set[cl] = REGISTER_CLASS_allocatable(cl);
02453 last_reg_allocated[cl] = REGISTER_UNDEFINED;
02454 }
02455 for (bb = REGION_First_BB; bb != NULL; bb = BB_next(bb)) {
02456 FOR_ALL_BB_OPs (bb, op) {
02457 for (INT i = 0; i < OP_results(op); i++) {
02458 tn = OP_result(op,i);
02459 Assign_Virtual_Register(tn);
02460 }
02461 for (INT i = 0; i < OP_opnds(op); i++) {
02462 tn = OP_opnd(op,i);
02463 Assign_Virtual_Register(tn);
02464 }
02465 }
02466 }
02467 }
02468
02469 REGISTER
02470 Last_Reg_Allocated (ISA_REGISTER_CLASS cl)
02471 {
02472 return last_reg_allocated[cl];
02473 }
02474
02475
02476
02477 extern "C" void EH_Generate_Range_List(WN * pu) { }
02478 extern "C" void EH_Set_End_Label(EH_RANGE* p) { FmtAssert(FALSE, ("NYI")); }
02479 extern "C" void EH_Set_Start_Label(EH_RANGE* p) { FmtAssert(FALSE, ("NYI")); }
02480 extern "C" void EH_Set_Has_Call(EH_RANGE* p) { FmtAssert(FALSE, ("NYI")); }
02481 BOOL FREQ_freqs_computed = FALSE;
02482 OP_MAP _CG_LOOP_info_map = NULL;
02483 BB_MAP _cg_dep_op_info = NULL;
02484 INT32 EBO_Opt_Level_Default = 5;
02485 INT32 EBO_Opt_Level = 0;
02486 BOOL CG_LOOP_unroll_analysis = FALSE;
02487 UINT32 CG_LOOP_unrolled_size_max;
02488 UINT32 CG_LOOP_unroll_times_max;
02489 BOOL CG_LOOP_ooo_unroll_heuristics = FALSE;
02490 RID* Non_Transparent_RID (RID *rid) { return rid; }
02491 INT BB_REGION_Exit( BB *bb, RID *rid ) { return 0; }
02492 LABEL_IDX REGION_Exit_Whirl_Labels( WN *exit_whirl, BB *exit_bb, LABEL_IDX external_label, RID *rid ) { FmtAssert(FALSE, ("NYI")); return LABEL_IDX_ZERO; }
02493 CGRIN *CGRIN_Create( INT num_exits ) { return NULL; }
02494 void FREQ_Print_BB_Note(BB *bb, FILE *file) { }
02495 ST * CGSPILL_Get_TN_Spill_Location (TN *tn, CGSPILL_CLIENT client) { return NULL; }
02496 BOOL GRA_LIVE_TN_Live_Outof_BB (TN *tn, BB *bb) { FmtAssert(FALSE, ("NYI")); return FALSE; }
02497 BOOL GRA_LIVE_TN_Live_Into_BB (TN *tn, BB *bb) { FmtAssert(FALSE, ("NYI")); return FALSE; }
02498 void GRA_LIVE_Print_Liveness( BB *bp) { return; }
02499 void LRA_Estimate_Fat_Points (BB* bb, mINT8* fatpoint, INT* regs_in_use, MEM_POOL* pool) { FmtAssert(FALSE, ("NYI")); }
02500 void REG_LIVE_Prolog_Temps(BB *bb, OP *first, OP *last, REGISTER_SET *temps) { FmtAssert(FALSE, ("NYI")); }
02501 CGRIN* RID_Find_Cginfo( BB *bb) { FmtAssert(FALSE, ("NYI")); return NULL; }
02502 void HB_CFLOW_Remove_Block( BB *bp) { }
02503 void HB_CFLOW_Replace_Block(BB *b, BB *pred) {}
02504 void Setup_HB_bb_map(void) {};
02505 BOOL HB_CFLOW_Can_Merge_BBs(BB *b, BB *pred) {return FALSE;}
02506 BB_SET *FREQ_Find_Never_BBs(MEM_POOL *pool) { return NULL; }
02507 void GRA_LIVE_Add_Live_Use_GTN(BB*, TN*) { }
02508 void GRA_LIVE_Merge_Blocks(BB*, BB*, BB*) {}
02509 void GRA_LIVE_Compute_Liveness_For_BB(BB*) {}
02510 void GRA_LIVE_Compute_Local_Info(BB*) {}
02511 void GRA_LIVE_Region_Start(void) {}
02512 void GRA_LIVE_Region_Entry(BB*) {}
02513 void GRA_LIVE_Region_Exit(BB*) {}
02514 void GRA_LIVE_Region_Compute_Global_Live_Info(void) {}
02515 void EH_Prune_Range_List(void) {}
02516 void EH_Dump_INITOs (WN *, FILE *) {}
02517 void Rename_TNs_For_BB (BB *, TN_SET *, OP *rename_local_TN_op = NULL) {}
02518 void CG_Set_Is_Stack_Used() { Fail_FmtAssertion("NYI"); }
02519
02520 CG_SCHED_EST* CG_SCHED_EST_Create( BB *bb, MEM_POOL *pool, SCHED_EST_TYPE type)
02521 {
02522 CG_SCHED_EST *se = (CG_SCHED_EST*) MEM_POOL_Alloc(pool, sizeof(CG_SCHED_EST));
02523 se->contents = NULL;
02524 se->res_count = NULL;
02525 se->latency_to_map = NULL;
02526 se->order = NULL;
02527 se->use_dep_graph = FALSE;
02528 se->latency_to_map_dirty = FALSE;
02529 se->sched_cycles = BB_length(bb);
02530 return se;
02531 }
02532 UINT32 CG_SCHED_EST_Cycles(CG_SCHED_EST *se)
02533 {
02534 return se->sched_cycles;
02535 }
02536 void CG_SCHED_EST_Ignore_Op(CG_SCHED_EST *se, OP *op)
02537 {
02538 se->sched_cycles--;
02539 }
02540 void CG_SCHED_EST_Append_Scheds(CG_SCHED_EST *se, CG_SCHED_EST *other_se)
02541 {
02542 se->sched_cycles += other_se->sched_cycles;
02543 }
02544 void CG_SCHED_EST_Delete(CG_SCHED_EST *se) {}
02545
02546 #include "pqs_cg_stubs.h"