1/* Combine stack adjustments. 2 Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 3 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 4 Free Software Foundation, Inc. 5 6This file is part of GCC. 7 8GCC is free software; you can redistribute it and/or modify it under 9the terms of the GNU General Public License as published by the Free 10Software Foundation; either version 3, or (at your option) any later 11version. 12 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14WARRANTY; without even the implied warranty of MERCHANTABILITY or 15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16for more details. 17 18You should have received a copy of the GNU General Public License 19along with GCC; see the file COPYING3. If not see 20<http://www.gnu.org/licenses/>. */ 21 22/* Track stack adjustments and stack memory references. Attempt to 23 reduce the number of stack adjustments by back-propagating across 24 the memory references. 25 26 This is intended primarily for use with targets that do not define 27 ACCUMULATE_OUTGOING_ARGS. It is of significantly more value to 28 targets that define PREFERRED_STACK_BOUNDARY more aligned than 29 STACK_BOUNDARY (e.g. x86), or if not all registers can be pushed 30 (e.g. x86 fp regs) which would ordinarily have to be implemented 31 as a sub/mov pair due to restrictions in calls.c. 32 33 Propagation stops when any of the insns that need adjusting are 34 (a) no longer valid because we've exceeded their range, (b) a 35 non-trivial push instruction, or (c) a call instruction. 36 37 Restriction B is based on the assumption that push instructions 38 are smaller or faster. If a port really wants to remove all 39 pushes, it should have defined ACCUMULATE_OUTGOING_ARGS. The 40 one exception that is made is for an add immediately followed 41 by a push. */ 42 43#include "config.h" 44#include "system.h" 45#include "coretypes.h" 46#include "tm.h" 47#include "rtl.h" 48#include "tm_p.h" 49#include "insn-config.h" 50#include "recog.h" 51#include "output.h" 52#include "regs.h" 53#include "hard-reg-set.h" 54#include "flags.h" 55#include "function.h" 56#include "expr.h" 57#include "basic-block.h" 58#include "df.h" 59#include "except.h" 60#include "toplev.h" 61#include "reload.h" 62#include "timevar.h" 63#include "tree-pass.h" 64 65 66/* Turn STACK_GROWS_DOWNWARD into a boolean. */ 67#ifdef STACK_GROWS_DOWNWARD 68#undef STACK_GROWS_DOWNWARD 69#define STACK_GROWS_DOWNWARD 1 70#else 71#define STACK_GROWS_DOWNWARD 0 72#endif 73 74/* This structure records two kinds of stack references between stack 75 adjusting instructions: stack references in memory addresses for 76 regular insns and all stack references for debug insns. */ 77 78struct csa_reflist 79{ 80 HOST_WIDE_INT sp_offset; 81 rtx insn, *ref; 82 struct csa_reflist *next; 83}; 84 85static int stack_memref_p (rtx); 86static rtx single_set_for_csa (rtx); 87static void free_csa_reflist (struct csa_reflist *); 88static struct csa_reflist *record_one_stack_ref (rtx, rtx *, 89 struct csa_reflist *); 90static int try_apply_stack_adjustment (rtx, struct csa_reflist *, 91 HOST_WIDE_INT, HOST_WIDE_INT); 92static void combine_stack_adjustments_for_block (basic_block); 93static int record_stack_refs (rtx *, void *); 94 95 96/* Main entry point for stack adjustment combination. */ 97 98static void 99combine_stack_adjustments (void) 100{ 101 basic_block bb; 102 103 FOR_EACH_BB (bb) 104 combine_stack_adjustments_for_block (bb); 105} 106 107/* Recognize a MEM of the form (sp) or (plus sp const). */ 108 109static int 110stack_memref_p (rtx x) 111{ 112 if (!MEM_P (x)) 113 return 0; 114 x = XEXP (x, 0); 115 116 if (x == stack_pointer_rtx) 117 return 1; 118 if (GET_CODE (x) == PLUS 119 && XEXP (x, 0) == stack_pointer_rtx 120 && CONST_INT_P (XEXP (x, 1))) 121 return 1; 122 123 return 0; 124} 125 126/* Recognize either normal single_set or the hack in i386.md for 127 tying fp and sp adjustments. */ 128 129static rtx 130single_set_for_csa (rtx insn) 131{ 132 int i; 133 rtx tmp = single_set (insn); 134 if (tmp) 135 return tmp; 136 137 if (!NONJUMP_INSN_P (insn) 138 || GET_CODE (PATTERN (insn)) != PARALLEL) 139 return NULL_RTX; 140 141 tmp = PATTERN (insn); 142 if (GET_CODE (XVECEXP (tmp, 0, 0)) != SET) 143 return NULL_RTX; 144 145 for (i = 1; i < XVECLEN (tmp, 0); ++i) 146 { 147 rtx this_rtx = XVECEXP (tmp, 0, i); 148 149 /* The special case is allowing a no-op set. */ 150 if (GET_CODE (this_rtx) == SET 151 && SET_SRC (this_rtx) == SET_DEST (this_rtx)) 152 ; 153 else if (GET_CODE (this_rtx) != CLOBBER 154 && GET_CODE (this_rtx) != USE) 155 return NULL_RTX; 156 } 157 158 return XVECEXP (tmp, 0, 0); 159} 160 161/* Free the list of csa_reflist nodes. */ 162 163static void 164free_csa_reflist (struct csa_reflist *reflist) 165{ 166 struct csa_reflist *next; 167 for (; reflist ; reflist = next) 168 { 169 next = reflist->next; 170 free (reflist); 171 } 172} 173 174/* Create a new csa_reflist node from the given stack reference. 175 It is already known that the reference is either a MEM satisfying the 176 predicate stack_memref_p or a REG representing the stack pointer. */ 177 178static struct csa_reflist * 179record_one_stack_ref (rtx insn, rtx *ref, struct csa_reflist *next_reflist) 180{ 181 struct csa_reflist *ml; 182 183 ml = XNEW (struct csa_reflist); 184 185 if (REG_P (*ref) || XEXP (*ref, 0) == stack_pointer_rtx) 186 ml->sp_offset = 0; 187 else 188 ml->sp_offset = INTVAL (XEXP (XEXP (*ref, 0), 1)); 189 190 ml->insn = insn; 191 ml->ref = ref; 192 ml->next = next_reflist; 193 194 return ml; 195} 196 197/* Attempt to apply ADJUST to the stack adjusting insn INSN, as well 198 as each of the memories and stack references in REFLIST. Return true 199 on success. */ 200 201static int 202try_apply_stack_adjustment (rtx insn, struct csa_reflist *reflist, 203 HOST_WIDE_INT new_adjust, HOST_WIDE_INT delta) 204{ 205 struct csa_reflist *ml; 206 rtx set; 207 208 set = single_set_for_csa (insn); 209 if (MEM_P (SET_DEST (set))) 210 validate_change (insn, &SET_DEST (set), 211 replace_equiv_address (SET_DEST (set), stack_pointer_rtx), 212 1); 213 else 214 validate_change (insn, &XEXP (SET_SRC (set), 1), GEN_INT (new_adjust), 1); 215 216 for (ml = reflist; ml ; ml = ml->next) 217 { 218 rtx new_addr = plus_constant (stack_pointer_rtx, ml->sp_offset - delta); 219 rtx new_val; 220 221 if (MEM_P (*ml->ref)) 222 new_val = replace_equiv_address_nv (*ml->ref, new_addr); 223 else if (GET_MODE (*ml->ref) == GET_MODE (stack_pointer_rtx)) 224 new_val = new_addr; 225 else 226 new_val = lowpart_subreg (GET_MODE (*ml->ref), new_addr, 227 GET_MODE (new_addr)); 228 validate_change (ml->insn, ml->ref, new_val, 1); 229 } 230 231 if (apply_change_group ()) 232 { 233 /* Succeeded. Update our knowledge of the stack references. */ 234 for (ml = reflist; ml ; ml = ml->next) 235 ml->sp_offset -= delta; 236 237 return 1; 238 } 239 else 240 return 0; 241} 242 243/* Called via for_each_rtx and used to record all stack memory and other 244 references in the insn and discard all other stack pointer references. */ 245struct record_stack_refs_data 246{ 247 rtx insn; 248 struct csa_reflist *reflist; 249}; 250 251static int 252record_stack_refs (rtx *xp, void *data) 253{ 254 rtx x = *xp; 255 struct record_stack_refs_data *d = 256 (struct record_stack_refs_data *) data; 257 if (!x) 258 return 0; 259 switch (GET_CODE (x)) 260 { 261 case MEM: 262 if (!reg_mentioned_p (stack_pointer_rtx, x)) 263 return -1; 264 /* We are not able to handle correctly all possible memrefs containing 265 stack pointer, so this check is necessary. */ 266 if (stack_memref_p (x)) 267 { 268 d->reflist = record_one_stack_ref (d->insn, xp, d->reflist); 269 return -1; 270 } 271 /* Try harder for DEBUG_INSNs, handle e.g. (mem (mem (sp + 16) + 4). */ 272 return !DEBUG_INSN_P (d->insn); 273 case REG: 274 /* ??? We want be able to handle non-memory stack pointer 275 references later. For now just discard all insns referring to 276 stack pointer outside mem expressions. We would probably 277 want to teach validate_replace to simplify expressions first. 278 279 We can't just compare with STACK_POINTER_RTX because the 280 reference to the stack pointer might be in some other mode. 281 In particular, an explicit clobber in an asm statement will 282 result in a QImode clobber. 283 284 In DEBUG_INSNs, we want to replace all occurrences, otherwise 285 they will cause -fcompare-debug failures. */ 286 if (REGNO (x) == STACK_POINTER_REGNUM) 287 { 288 if (!DEBUG_INSN_P (d->insn)) 289 return 1; 290 d->reflist = record_one_stack_ref (d->insn, xp, d->reflist); 291 return -1; 292 } 293 break; 294 default: 295 break; 296 } 297 return 0; 298} 299 300/* Adjust or create REG_FRAME_RELATED_EXPR note when merging a stack 301 adjustment into a frame related insn. */ 302 303static void 304adjust_frame_related_expr (rtx last_sp_set, rtx insn, 305 HOST_WIDE_INT this_adjust) 306{ 307 rtx note = find_reg_note (last_sp_set, REG_FRAME_RELATED_EXPR, NULL_RTX); 308 rtx new_expr = NULL_RTX; 309 310 if (note == NULL_RTX && RTX_FRAME_RELATED_P (insn)) 311 return; 312 313 if (note 314 && GET_CODE (XEXP (note, 0)) == SEQUENCE 315 && XVECLEN (XEXP (note, 0), 0) >= 2) 316 { 317 rtx expr = XEXP (note, 0); 318 rtx last = XVECEXP (expr, 0, XVECLEN (expr, 0) - 1); 319 int i; 320 321 if (GET_CODE (last) == SET 322 && RTX_FRAME_RELATED_P (last) == RTX_FRAME_RELATED_P (insn) 323 && SET_DEST (last) == stack_pointer_rtx 324 && GET_CODE (SET_SRC (last)) == PLUS 325 && XEXP (SET_SRC (last), 0) == stack_pointer_rtx 326 && CONST_INT_P (XEXP (SET_SRC (last), 1))) 327 { 328 XEXP (SET_SRC (last), 1) 329 = GEN_INT (INTVAL (XEXP (SET_SRC (last), 1)) + this_adjust); 330 return; 331 } 332 333 new_expr = gen_rtx_SEQUENCE (VOIDmode, 334 rtvec_alloc (XVECLEN (expr, 0) + 1)); 335 for (i = 0; i < XVECLEN (expr, 0); i++) 336 XVECEXP (new_expr, 0, i) = XVECEXP (expr, 0, i); 337 } 338 else 339 { 340 new_expr = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (2)); 341 if (note) 342 XVECEXP (new_expr, 0, 0) = XEXP (note, 0); 343 else 344 { 345 rtx expr = copy_rtx (single_set_for_csa (last_sp_set)); 346 347 XEXP (SET_SRC (expr), 1) 348 = GEN_INT (INTVAL (XEXP (SET_SRC (expr), 1)) - this_adjust); 349 RTX_FRAME_RELATED_P (expr) = 1; 350 XVECEXP (new_expr, 0, 0) = expr; 351 } 352 } 353 354 XVECEXP (new_expr, 0, XVECLEN (new_expr, 0) - 1) 355 = copy_rtx (single_set_for_csa (insn)); 356 RTX_FRAME_RELATED_P (XVECEXP (new_expr, 0, XVECLEN (new_expr, 0) - 1)) 357 = RTX_FRAME_RELATED_P (insn); 358 if (note) 359 XEXP (note, 0) = new_expr; 360 else 361 add_reg_note (last_sp_set, REG_FRAME_RELATED_EXPR, new_expr); 362} 363 364/* Subroutine of combine_stack_adjustments, called for each basic block. */ 365 366static void 367combine_stack_adjustments_for_block (basic_block bb) 368{ 369 HOST_WIDE_INT last_sp_adjust = 0; 370 rtx last_sp_set = NULL_RTX; 371 struct csa_reflist *reflist = NULL; 372 rtx insn, next, set; 373 struct record_stack_refs_data data; 374 bool end_of_block = false; 375 376 for (insn = BB_HEAD (bb); !end_of_block ; insn = next) 377 { 378 end_of_block = insn == BB_END (bb); 379 next = NEXT_INSN (insn); 380 381 if (! INSN_P (insn)) 382 continue; 383 384 set = single_set_for_csa (insn); 385 if (set) 386 { 387 rtx dest = SET_DEST (set); 388 rtx src = SET_SRC (set); 389 390 /* Find constant additions to the stack pointer. */ 391 if (dest == stack_pointer_rtx 392 && GET_CODE (src) == PLUS 393 && XEXP (src, 0) == stack_pointer_rtx 394 && CONST_INT_P (XEXP (src, 1))) 395 { 396 HOST_WIDE_INT this_adjust = INTVAL (XEXP (src, 1)); 397 398 /* If we've not seen an adjustment previously, record 399 it now and continue. */ 400 if (! last_sp_set) 401 { 402 last_sp_set = insn; 403 last_sp_adjust = this_adjust; 404 continue; 405 } 406 407 /* If not all recorded refs can be adjusted, or the 408 adjustment is now too large for a constant addition, 409 we cannot merge the two stack adjustments. 410 411 Also we need to be careful to not move stack pointer 412 such that we create stack accesses outside the allocated 413 area. We can combine an allocation into the first insn, 414 or a deallocation into the second insn. We can not 415 combine an allocation followed by a deallocation. 416 417 The only somewhat frequent occurrence of the later is when 418 a function allocates a stack frame but does not use it. 419 For this case, we would need to analyze rtl stream to be 420 sure that allocated area is really unused. This means not 421 only checking the memory references, but also all registers 422 or global memory references possibly containing a stack 423 frame address. 424 425 Perhaps the best way to address this problem is to teach 426 gcc not to allocate stack for objects never used. */ 427 428 /* Combine an allocation into the first instruction. */ 429 if (STACK_GROWS_DOWNWARD ? this_adjust <= 0 : this_adjust >= 0) 430 { 431 if (try_apply_stack_adjustment (last_sp_set, reflist, 432 last_sp_adjust + this_adjust, 433 this_adjust)) 434 { 435 if (RTX_FRAME_RELATED_P (last_sp_set)) 436 adjust_frame_related_expr (last_sp_set, insn, 437 this_adjust); 438 /* It worked! */ 439 delete_insn (insn); 440 last_sp_adjust += this_adjust; 441 continue; 442 } 443 } 444 445 /* Otherwise we have a deallocation. Do not combine with 446 a previous allocation. Combine into the second insn. */ 447 else if (STACK_GROWS_DOWNWARD 448 ? last_sp_adjust >= 0 : last_sp_adjust <= 0) 449 { 450 if (try_apply_stack_adjustment (insn, reflist, 451 last_sp_adjust + this_adjust, 452 -last_sp_adjust)) 453 { 454 /* It worked! */ 455 delete_insn (last_sp_set); 456 last_sp_set = insn; 457 last_sp_adjust += this_adjust; 458 free_csa_reflist (reflist); 459 reflist = NULL; 460 continue; 461 } 462 } 463 464 /* Combination failed. Restart processing from here. If 465 deallocation+allocation conspired to cancel, we can 466 delete the old deallocation insn. */ 467 if (last_sp_set && last_sp_adjust == 0) 468 delete_insn (last_sp_set); 469 free_csa_reflist (reflist); 470 reflist = NULL; 471 last_sp_set = insn; 472 last_sp_adjust = this_adjust; 473 continue; 474 } 475 476 /* Find a store with pre-(dec|inc)rement or pre-modify of exactly 477 the previous adjustment and turn it into a simple store. This 478 is equivalent to anticipating the stack adjustment so this must 479 be an allocation. */ 480 if (MEM_P (dest) 481 && ((STACK_GROWS_DOWNWARD 482 ? (GET_CODE (XEXP (dest, 0)) == PRE_DEC 483 && last_sp_adjust 484 == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest))) 485 : (GET_CODE (XEXP (dest, 0)) == PRE_INC 486 && last_sp_adjust 487 == -(HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (dest)))) 488 || ((STACK_GROWS_DOWNWARD 489 ? last_sp_adjust >= 0 : last_sp_adjust <= 0) 490 && GET_CODE (XEXP (dest, 0)) == PRE_MODIFY 491 && GET_CODE (XEXP (XEXP (dest, 0), 1)) == PLUS 492 && XEXP (XEXP (XEXP (dest, 0), 1), 0) 493 == stack_pointer_rtx 494 && GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1)) 495 == CONST_INT 496 && INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1)) 497 == -last_sp_adjust)) 498 && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx 499 && !reg_mentioned_p (stack_pointer_rtx, src) 500 && memory_address_p (GET_MODE (dest), stack_pointer_rtx) 501 && try_apply_stack_adjustment (insn, reflist, 0, 502 -last_sp_adjust)) 503 { 504 delete_insn (last_sp_set); 505 free_csa_reflist (reflist); 506 reflist = NULL; 507 last_sp_set = NULL_RTX; 508 last_sp_adjust = 0; 509 continue; 510 } 511 } 512 513 data.insn = insn; 514 data.reflist = reflist; 515 if (!CALL_P (insn) && last_sp_set 516 && !for_each_rtx (&PATTERN (insn), record_stack_refs, &data)) 517 { 518 reflist = data.reflist; 519 continue; 520 } 521 reflist = data.reflist; 522 523 /* Otherwise, we were not able to process the instruction. 524 Do not continue collecting data across such a one. */ 525 if (last_sp_set 526 && (CALL_P (insn) 527 || reg_mentioned_p (stack_pointer_rtx, PATTERN (insn)))) 528 { 529 if (last_sp_set && last_sp_adjust == 0) 530 delete_insn (last_sp_set); 531 free_csa_reflist (reflist); 532 reflist = NULL; 533 last_sp_set = NULL_RTX; 534 last_sp_adjust = 0; 535 } 536 } 537 538 if (last_sp_set && last_sp_adjust == 0) 539 delete_insn (last_sp_set); 540 541 if (reflist) 542 free_csa_reflist (reflist); 543} 544 545 546static bool 547gate_handle_stack_adjustments (void) 548{ 549 return (optimize > 0); 550} 551 552static unsigned int 553rest_of_handle_stack_adjustments (void) 554{ 555 cleanup_cfg (flag_crossjumping ? CLEANUP_CROSSJUMP : 0); 556 557 /* This is kind of a heuristic. We need to run combine_stack_adjustments 558 even for machines with possibly nonzero RETURN_POPS_ARGS 559 and ACCUMULATE_OUTGOING_ARGS. We expect that only ports having 560 push instructions will have popping returns. */ 561#ifndef PUSH_ROUNDING 562 if (!ACCUMULATE_OUTGOING_ARGS) 563#endif 564 { 565 df_note_add_problem (); 566 df_analyze (); 567 combine_stack_adjustments (); 568 } 569 return 0; 570} 571 572struct rtl_opt_pass pass_stack_adjustments = 573{ 574 { 575 RTL_PASS, 576 "csa", /* name */ 577 gate_handle_stack_adjustments, /* gate */ 578 rest_of_handle_stack_adjustments, /* execute */ 579 NULL, /* sub */ 580 NULL, /* next */ 581 0, /* static_pass_number */ 582 TV_COMBINE_STACK_ADJUST, /* tv_id */ 583 0, /* properties_required */ 584 0, /* properties_provided */ 585 0, /* properties_destroyed */ 586 0, /* todo_flags_start */ 587 TODO_df_finish | TODO_verify_rtl_sharing | 588 TODO_dump_func | 589 TODO_ggc_collect, /* todo_flags_finish */ 590 } 591}; 592