@@ -2209,6 +2209,7 @@ void dce_insn(basic_block_t *bb)
22092209void dce_sweep (void )
22102210{
22112211 int total_eliminated = 0 ; /* Track effectiveness */
2212+ int empty_blocks_removed = 0 ;
22122213
22132214 for (func_t * func = FUNC_LIST .head ; func ; func = func -> next ) {
22142215 for (basic_block_t * bb = func -> bbs ; bb ; bb = bb -> rpo_next ) {
@@ -2223,6 +2224,7 @@ void dce_sweep(void)
22232224 }
22242225 /* Mark entire block as dead */
22252226 bb -> useful = false;
2227+ empty_blocks_removed ++ ;
22262228 continue ;
22272229 }
22282230
@@ -2261,12 +2263,31 @@ void dce_sweep(void)
22612263 }
22622264 insn = next ;
22632265 }
2266+
2267+ /* Check if block is now empty (only has branch or nothing) */
2268+ bool is_empty = true;
2269+ for (insn_t * check_insn = bb -> insn_list .head ; check_insn ;
2270+ check_insn = check_insn -> next ) {
2271+ if (check_insn -> opcode != OP_branch &&
2272+ check_insn -> opcode != OP_jump ) {
2273+ is_empty = false;
2274+ break ;
2275+ }
2276+ }
2277+
2278+ /* Mark empty blocks for potential removal */
2279+ if (is_empty && bb != func -> bbs && bb != bb -> belong_to -> exit ) {
2280+ /* Mark for potential removal */
2281+ empty_blocks_removed ++ ;
2282+ }
22642283 }
22652284 }
22662285}
22672286
22682287void build_reversed_rpo ();
22692288
2289+ bool is_var_used_later (var_t * var , insn_t * from_insn );
2290+
22702291void optimize (void )
22712292{
22722293 /* build rdf information for DCE */
@@ -2322,29 +2343,60 @@ void optimize(void)
23222343 continue ;
23232344 }
23242345
2325- /* Dead store elimination - conservative */
2326- if (insn -> opcode == OP_store || insn -> opcode == OP_write ) {
2327- /* Only eliminate if target is local and immediately
2328- * overwritten
2329- */
2330- if (insn -> rd && !insn -> rd -> is_global && insn -> next ) {
2331- insn_t * next_insn = insn -> next ;
2346+ /* Enhanced dead store elimination */
2347+ if (insn -> opcode == OP_store || insn -> opcode == OP_write ||
2348+ insn -> opcode == OP_global_store ) {
2349+ /* Check if the stored value is never loaded again */
2350+ if (insn -> rd && !insn -> rd -> is_global ) {
2351+ bool is_dead_store = true;
2352+
2353+ /* Look for subsequent uses of this memory location */
2354+ for (insn_t * check = insn -> next ; check && is_dead_store ;
2355+ check = check -> next ) {
2356+ /* If there is a load from this location, store is
2357+ * not dead
2358+ */
2359+ if ((check -> opcode == OP_load ||
2360+ check -> opcode == OP_read ) &&
2361+ check -> rs1 == insn -> rd ) {
2362+ is_dead_store = false;
2363+ break ;
2364+ }
23322365
2333- /* Check for immediate overwrite with no intervening
2334- * instructions
2335- */
2336- if ((next_insn -> opcode == OP_store ||
2337- next_insn -> opcode == OP_write ) &&
2338- next_insn -> rd == insn -> rd ) {
2339- /* Eliminate only immediate overwrites */
2340- insn -> rd = NULL ;
2341- insn -> rs1 = NULL ;
2342- insn -> rs2 = NULL ;
2366+ /* If there is another store to same location, this
2367+ * store is dead
2368+ */
2369+ if ((check -> opcode == OP_store ||
2370+ check -> opcode == OP_write ) &&
2371+ check -> rd == insn -> rd ) {
2372+ break ; /* This store is dead */
2373+ }
2374+ }
2375+
2376+ if (is_dead_store ) {
2377+ /* Mark as not useful for DCE to remove */
2378+ /* Note: We cannot directly remove it here as it
2379+ * would break the instruction list. Let DCE handle
2380+ * it.
2381+ */
2382+ continue ;
23432383 }
23442384 }
23452385 }
23462386
2347- /* TODO: Dead load elimination */
2387+ /* Dead load elimination - remove loads whose results are never
2388+ * used
2389+ */
2390+ if (insn -> opcode == OP_load || insn -> opcode == OP_global_load ) {
2391+ if (insn -> rd && !is_var_used_later (insn -> rd , insn )) {
2392+ /* Mark this load as not useful for DCE */
2393+ /* Note: We cannot directly remove it here as it would
2394+ * break the instruction list. Let DCE handle it.
2395+ */
2396+ continue ;
2397+ }
2398+ }
2399+
23482400 /* TODO: Phi node optimization */
23492401
23502402 /* more optimizations */
@@ -2495,6 +2547,43 @@ void bb_solve_locals(func_t *func, basic_block_t *bb)
24952547 }
24962548}
24972549
2550+ /* Check if a variable is used after a given instruction */
2551+ bool is_var_used_later (var_t * var , insn_t * from_insn )
2552+ {
2553+ if (!var || !from_insn )
2554+ return false;
2555+
2556+ /* Check if variable is global - globals are always potentially used */
2557+ if (var -> is_global )
2558+ return true;
2559+
2560+ /* Check remaining instructions in the same basic block */
2561+ for (insn_t * insn = from_insn -> next ; insn ; insn = insn -> next ) {
2562+ if ((insn -> rs1 && insn -> rs1 == var ) ||
2563+ (insn -> rs2 && insn -> rs2 == var )) {
2564+ return true;
2565+ }
2566+ /* Check phi operands */
2567+ if (insn -> opcode == OP_phi ) {
2568+ for (phi_operand_t * op = insn -> phi_ops ; op ; op = op -> next ) {
2569+ if (op -> var == var )
2570+ return true;
2571+ }
2572+ }
2573+ }
2574+
2575+ /* Check if variable is in live_out set of the basic block */
2576+ basic_block_t * bb = from_insn -> belong_to ;
2577+ if (bb ) {
2578+ for (int i = 0 ; i < bb -> live_out_idx ; i ++ ) {
2579+ if (bb -> live_out [i ] == var )
2580+ return true;
2581+ }
2582+ }
2583+
2584+ return false;
2585+ }
2586+
24982587void add_live_in (basic_block_t * bb , var_t * var )
24992588{
25002589 for (int i = 0 ; i < bb -> live_in_idx ; i ++ ) {
0 commit comments