00001 00002 // 00003 // Copyright (C) 2007, 2008 PathScale, LLC. All Rights Reserved. 00004 // 00005 // This program is free software; you can redistribute it and/or modify it 00006 // under the terms of version 2 of the GNU General Public License as 00007 // published by the Free Software Foundation. 00008 // 00009 // This program is distributed in the hope that it would be useful, but 00010 // WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 // 00013 // Further, this software is distributed without any warranty that it is 00014 // free of the rightful claim of any third person regarding infringement 00015 // or the like. Any license provided herein, whether implied or 00016 // otherwise, applies only to this software file. Patent licenses, if 00017 // any, provided herein do not apply to combinations of this program with 00018 // other software, or any other product whatsoever. 00019 // 00020 // You should have received a copy of the GNU General Public License along 00021 // with this program; if not, write the Free Software Foundation, Inc., 59 00022 // Temple Place - Suite 330, Boston MA 02111-1307, USA. 00024 00025 #define __STDC_LIMIT_MACROS 00026 #include <stdint.h> 00027 #include <stdlib.h> 00028 00029 #include "defs.h" 00030 #include "wn.h" 00031 #include "wn_util.h" 00032 #include "symtab.h" 00033 #include "config_ipa.h" 00034 #include "ipa_struct_opt.h" 00035 00036 Field_pos *Struct_field_layout = NULL; 00037 INT Struct_split_count = 0; 00038 00039 // Invalidate struct types that are either parameters or returned from 00040 // functions, or if a pointer to such types is a parameter or returned 00041 // from a function. 00042 void Traverse_PU_parameters (void) 00043 { 00044 for (INT puid = 1; puid < PU_Table_Size(); puid++) 00045 { 00046 TY_IDX type = TY_IDX_ZERO; 00047 TY_IDX prototype = PU_prototype (Pu_Table[puid]); 00048 TYLIST_IDX tylist = TY_tylist(prototype); 00049 00050 while ((type = Tylist_Table[tylist]) != 0) 00051 { 00052 if (TY_kind(type) == KIND_STRUCT) 00053 Set_TY_no_split(type); 00054 else if (TY_kind(type) == KIND_POINTER && 00055 TY_kind(TY_pointed(type)) == KIND_STRUCT) 00056 Set_TY_no_split(TY_pointed(type)); 00057 00058 tylist++; 00059 } 00060 } 00061 } 00062 00063 // Invalidate all child STRUCT types. 00064 static void invalidate_it (TY& ty) 00065 { 00066 // Don't traverse empty structs 00067 if (TY_size(ty) && ty.Fld()) 00068 { 00069 FLD_ITER fld_iter = Make_fld_iter(TY_fld(ty)); 00070 do 00071 { 00072 FLD_HANDLE fld(fld_iter); 00073 00074 TY_IDX idx = FLD_type(fld); 00075 if (TY_kind(idx) == KIND_STRUCT) 00076 invalidate_it (Ty_Table[idx]); 00077 } while (!FLD_last_field(fld_iter++)); 00078 } 00079 00080 Set_TY_no_split(ty); 00081 } 00082 00083 INT struct_field_count (TY_IDX ty_idx) 00084 { 00085 Is_True (Ty_Table[ty_idx].Fld() != 0, ("struct TY should have >0 fields")); 00086 FLD_ITER fld_iter = Make_fld_iter(TY_fld(ty_idx)); 00087 INT field_count = 0; 00088 do 00089 { 00090 field_count++; 00091 } while (!FLD_last_field(fld_iter++)); 00092 00093 return field_count; 00094 } 00095 00096 extern mUINT32 Struct_split_candidate_index; 00097 extern mUINT32 Struct_update_index; 00098 00099 // Traverse through type-table and invalidate any as necessary. 00100 void Traverse_TYs (void) 00101 { 00102 TY_TAB::iterator iter; 00103 00104 // First pass 00105 for (iter = Ty_tab.begin(); iter != Ty_tab.end(); iter++) 00106 { 00107 //TY_IDX ty = iter.Index(); 00108 TY& ty = *iter.Ptr(); 00109 if (TY_kind(ty) == KIND_STRUCT && !TY_no_split(ty)) 00110 { 00111 // Empty structs 00112 if (TY_size(ty) == 0 || ty.Fld() == 0) 00113 Set_TY_no_split(ty); 00114 else if (TY_is_union(ty)) 00115 Set_TY_no_split(ty); 00116 else 00117 { 00118 FLD_ITER fld_iter = Make_fld_iter(TY_fld(ty)); 00119 INT field_count = 0; 00120 do 00121 { 00122 FLD_HANDLE fld(fld_iter); 00123 TYPE_ID mtype = TY_mtype(FLD_type(fld)); 00124 field_count++; 00125 if (FLD_is_bit_field(fld) || FLD_begin_union(fld)) 00126 { 00127 Set_TY_no_split(ty); 00128 break; 00129 } 00130 if (IPA_Enable_Struct_Opt == 1 && 00131 ((mtype != MTYPE_U8 && mtype != MTYPE_C4) || 00132 TY_kind(FLD_type(fld)) == KIND_POINTER)) 00133 { 00134 Set_TY_no_split(ty); 00135 break; 00136 } 00137 if (FLD_last_field(fld)) 00138 break; 00139 } while (!FLD_last_field(fld_iter++)); 00140 00141 // Struct must have 2 fields. 00142 if (IPA_Enable_Struct_Opt == 1 && field_count != 2) 00143 Set_TY_no_split(ty); 00144 00145 if (IPA_Enable_Struct_Opt == 2 && field_count != 8) 00146 Set_TY_no_split(ty); 00147 } 00148 } 00149 00150 if (TY_kind(ty) == KIND_STRUCT && TY_no_split(ty)) 00151 invalidate_it (ty); 00152 } 00153 00154 // Second pass 00155 for (iter = Ty_tab.begin(); iter != Ty_tab.end(); iter++) 00156 { 00157 TY& ty = *iter.Ptr(); 00158 if (TY_kind(ty) == KIND_STRUCT && !TY_no_split(ty)) 00159 { 00160 Struct_split_candidate_index = iter.Index(); 00161 // Take only the first such struct TY. 00162 break; 00163 } 00164 } 00165 00166 if (!Struct_split_candidate_index) 00167 return; 00168 00169 // Third pass 00170 for (iter = Ty_tab.begin(); iter != Ty_tab.end(); iter++) 00171 { 00172 TY& ty = *iter.Ptr(); 00173 if (TY_kind(ty) == KIND_STRUCT) 00174 { 00175 // Empty struct, union 00176 if (TY_size(ty) == 0 || ty.Fld() == 0 || TY_is_union(ty)) 00177 continue; 00178 else 00179 { 00180 FLD_ITER fld_iter = Make_fld_iter(TY_fld(ty)); 00181 INT field_count = 0; 00182 do 00183 { 00184 FLD_HANDLE fld(fld_iter); 00185 field_count++; 00186 TY_IDX fldtype = FLD_type(fld); 00187 00188 if (TY_kind(fldtype) == KIND_POINTER && 00189 TY_IDX_index(TY_pointed(fldtype)) == Struct_split_candidate_index) 00190 { 00191 if (Struct_update_index) 00192 { 00193 // There can be at most 1 struct with at most 1 pointer to the 00194 // type being split. 00195 Struct_update_index = 0; 00196 Struct_split_candidate_index = 0; 00197 return; 00198 } 00199 Struct_update_index = iter.Index(); 00200 } 00201 00202 if (FLD_last_field(fld)) 00203 break; 00204 } while (!FLD_last_field(fld_iter++)); 00205 } 00206 } 00207 } 00208 00209 if (IPA_Enable_Struct_Opt == 1 && Struct_update_index == 0) 00210 Struct_split_candidate_index = 0; 00211 00212 if (Struct_split_candidate_index) 00213 { 00214 INT field_count = struct_field_count (Struct_split_candidate_index<<8); 00215 00216 Struct_field_layout = 00217 (Field_pos *) malloc (field_count * sizeof(Field_pos)); 00218 00219 Struct_split_count = field_count; 00220 00221 // Relayout the struct into individual fields. 00222 for (INT i=0; i<field_count; i++) 00223 { 00224 Struct_field_layout[i].u.struct_id = i; 00225 Struct_field_layout[i].fld_id = 1; 00226 Struct_field_layout[i].st_idx = ST_IDX_ZERO; 00227 } 00228 } 00229 } 00230 00231 void IPA_struct_opt_legality (void) 00232 { 00233 Traverse_PU_parameters (); 00234 00235 // This function should be called after all type legality checks are done. 00236 Traverse_TYs (); 00237 }
1.5.6