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
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 #include "config.h"
00155 #include "system.h"
00156 #include "coretypes.h"
00157 #include "tm.h"
00158 #include "tree.h"
00159 #include "rtl.h"
00160 #include "tm_p.h"
00161 #include "function.h"
00162 #include "insn-config.h"
00163 #include "regs.h"
00164 #include "hard-reg-set.h"
00165 #include "flags.h"
00166 #include "toplev.h"
00167 #include "recog.h"
00168 #include "output.h"
00169 #include "basic-block.h"
00170 #include "varray.h"
00171 #include "reload.h"
00172 #include "ggc.h"
00173 #include "timevar.h"
00174 #include "tree-pass.h"
00175 #include "target.h"
00176 #include "vecprim.h"
00177
00178 #ifdef STACK_REGS
00179
00180
00181
00182
00183
00184
00185
00186 static VEC(char,heap) *stack_regs_mentioned_data;
00187
00188 #define REG_STACK_SIZE (LAST_STACK_REG - FIRST_STACK_REG + 1)
00189
00190 int regstack_completed = 0;
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 typedef struct stack_def
00202 {
00203 int top;
00204 HARD_REG_SET reg_set;
00205 unsigned char reg[REG_STACK_SIZE];
00206 } *stack;
00207
00208
00209
00210
00211 typedef struct block_info_def
00212 {
00213 struct stack_def stack_in;
00214 struct stack_def stack_out;
00215 HARD_REG_SET out_reg_set;
00216 int done;
00217 int predecessors;
00218
00219 } *block_info;
00220
00221 #define BLOCK_INFO(B) ((block_info) (B)->aux)
00222
00223
00224 enum emit_where
00225 {
00226 EMIT_AFTER,
00227 EMIT_BEFORE
00228 };
00229
00230
00231 static basic_block current_block;
00232
00233
00234
00235
00236 static bool starting_stack_p;
00237
00238
00239 static rtx
00240 FP_mode_reg[LAST_STACK_REG+1-FIRST_STACK_REG][(int) MAX_MACHINE_MODE];
00241
00242 #define FP_MODE_REG(regno,mode) \
00243 (FP_mode_reg[(regno)-FIRST_STACK_REG][(int) (mode)])
00244
00245
00246 static rtx not_a_num;
00247
00248
00249
00250 static int stack_regs_mentioned_p (rtx pat);
00251 static void pop_stack (stack, int);
00252 static rtx *get_true_reg (rtx *);
00253
00254 static int check_asm_stack_operands (rtx);
00255 static int get_asm_operand_n_inputs (rtx);
00256 static rtx stack_result (tree);
00257 static void replace_reg (rtx *, int);
00258 static void remove_regno_note (rtx, enum reg_note, unsigned int);
00259 static int get_hard_regnum (stack, rtx);
00260 static rtx emit_pop_insn (rtx, stack, rtx, enum emit_where);
00261 static void swap_to_top(rtx, stack, rtx, rtx);
00262 static bool move_for_stack_reg (rtx, stack, rtx);
00263 static bool move_nan_for_stack_reg (rtx, stack, rtx);
00264 static int swap_rtx_condition_1 (rtx);
00265 static int swap_rtx_condition (rtx);
00266 static void compare_for_stack_reg (rtx, stack, rtx);
00267 static bool subst_stack_regs_pat (rtx, stack, rtx);
00268 static void subst_asm_stack_regs (rtx, stack);
00269 static bool subst_stack_regs (rtx, stack);
00270 static void change_stack (rtx, stack, stack, enum emit_where);
00271 static void print_stack (FILE *, stack);
00272 static rtx next_flags_user (rtx);
00273
00274
00275
00276 static int
00277 stack_regs_mentioned_p (rtx pat)
00278 {
00279 const char *fmt;
00280 int i;
00281
00282 if (STACK_REG_P (pat))
00283 return 1;
00284
00285 fmt = GET_RTX_FORMAT (GET_CODE (pat));
00286 for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--)
00287 {
00288 if (fmt[i] == 'E')
00289 {
00290 int j;
00291
00292 for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
00293 if (stack_regs_mentioned_p (XVECEXP (pat, i, j)))
00294 return 1;
00295 }
00296 else if (fmt[i] == 'e' && stack_regs_mentioned_p (XEXP (pat, i)))
00297 return 1;
00298 }
00299
00300 return 0;
00301 }
00302
00303
00304
00305 int
00306 stack_regs_mentioned (rtx insn)
00307 {
00308 unsigned int uid, max;
00309 int test;
00310
00311 if (! INSN_P (insn) || !stack_regs_mentioned_data)
00312 return 0;
00313
00314 uid = INSN_UID (insn);
00315 max = VEC_length (char, stack_regs_mentioned_data);
00316 if (uid >= max)
00317 {
00318 char *p;
00319 unsigned int old_max = max;
00320
00321
00322
00323 max = uid + uid / 20 + 1;
00324 VEC_safe_grow (char, heap, stack_regs_mentioned_data, max);
00325 p = VEC_address (char, stack_regs_mentioned_data);
00326 memset (&p[old_max], 0,
00327 sizeof (char) * (max - old_max));
00328 }
00329
00330 test = VEC_index (char, stack_regs_mentioned_data, uid);
00331 if (test == 0)
00332 {
00333
00334 test = stack_regs_mentioned_p (PATTERN (insn)) ? 1 : 2;
00335 VEC_replace (char, stack_regs_mentioned_data, uid, test);
00336 }
00337
00338 return test == 1;
00339 }
00340
00341 static rtx ix86_flags_rtx;
00342
00343 static rtx
00344 next_flags_user (rtx insn)
00345 {
00346
00347
00348
00349 while (insn != BB_END (current_block))
00350 {
00351 insn = NEXT_INSN (insn);
00352
00353 if (INSN_P (insn) && reg_mentioned_p (ix86_flags_rtx, PATTERN (insn)))
00354 return insn;
00355
00356 if (CALL_P (insn))
00357 return NULL_RTX;
00358 }
00359 return NULL_RTX;
00360 }
00361
00362
00363
00364 static void
00365 straighten_stack (rtx insn, stack regstack)
00366 {
00367 struct stack_def temp_stack;
00368 int top;
00369
00370
00371
00372
00373
00374 if (regstack->top <= 0)
00375 return;
00376
00377 COPY_HARD_REG_SET (temp_stack.reg_set, regstack->reg_set);
00378
00379 for (top = temp_stack.top = regstack->top; top >= 0; top--)
00380 temp_stack.reg[top] = FIRST_STACK_REG + temp_stack.top - top;
00381
00382 change_stack (insn, regstack, &temp_stack, EMIT_BEFORE);
00383 }
00384
00385
00386
00387 static void
00388 pop_stack (stack regstack, int regno)
00389 {
00390 int top = regstack->top;
00391
00392 CLEAR_HARD_REG_BIT (regstack->reg_set, regno);
00393 regstack->top--;
00394
00395 if (regstack->reg [top] != regno)
00396 {
00397 int i;
00398 for (i = regstack->top; i >= 0; i--)
00399 if (regstack->reg [i] == regno)
00400 {
00401 int j;
00402 for (j = i; j < top; j++)
00403 regstack->reg [j] = regstack->reg [j + 1];
00404 break;
00405 }
00406 }
00407 }
00408
00409
00410
00411
00412
00413 static rtx *
00414 get_true_reg (rtx *pat)
00415 {
00416 for (;;)
00417 switch (GET_CODE (*pat))
00418 {
00419 case SUBREG:
00420
00421
00422 {
00423 rtx subreg;
00424 if (FP_REG_P (subreg = SUBREG_REG (*pat)))
00425 {
00426 int regno_off = subreg_regno_offset (REGNO (subreg),
00427 GET_MODE (subreg),
00428 SUBREG_BYTE (*pat),
00429 GET_MODE (*pat));
00430 *pat = FP_MODE_REG (REGNO (subreg) + regno_off,
00431 GET_MODE (subreg));
00432 default:
00433 return pat;
00434 }
00435 }
00436 case FLOAT:
00437 case FIX:
00438 case FLOAT_EXTEND:
00439 pat = & XEXP (*pat, 0);
00440 break;
00441
00442 case FLOAT_TRUNCATE:
00443 if (!flag_unsafe_math_optimizations)
00444 return pat;
00445 pat = & XEXP (*pat, 0);
00446 break;
00447 }
00448 }
00449
00450
00451 static bool any_malformed_asm;
00452
00453
00454
00455
00456
00457 static int
00458 check_asm_stack_operands (rtx insn)
00459 {
00460 int i;
00461 int n_clobbers;
00462 int malformed_asm = 0;
00463 rtx body = PATTERN (insn);
00464
00465 char reg_used_as_output[FIRST_PSEUDO_REGISTER];
00466 char implicitly_dies[FIRST_PSEUDO_REGISTER];
00467 int alt;
00468
00469 rtx *clobber_reg = 0;
00470 int n_inputs, n_outputs;
00471
00472
00473
00474 extract_insn (insn);
00475 constrain_operands (1);
00476 alt = which_alternative;
00477
00478 preprocess_constraints ();
00479
00480 n_inputs = get_asm_operand_n_inputs (body);
00481 n_outputs = recog_data.n_operands - n_inputs;
00482
00483 if (alt < 0)
00484 {
00485 malformed_asm = 1;
00486
00487 PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
00488 return 0;
00489 }
00490
00491
00492 for (i = 0; i < recog_data.n_operands; i++)
00493 if (GET_CODE (recog_data.operand[i]) == SUBREG
00494 && REG_P (SUBREG_REG (recog_data.operand[i])))
00495 recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
00496
00497
00498
00499 n_clobbers = 0;
00500
00501 if (GET_CODE (body) == PARALLEL)
00502 {
00503 clobber_reg = alloca (XVECLEN (body, 0) * sizeof (rtx));
00504
00505 for (i = 0; i < XVECLEN (body, 0); i++)
00506 if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
00507 {
00508 rtx clobber = XVECEXP (body, 0, i);
00509 rtx reg = XEXP (clobber, 0);
00510
00511 if (GET_CODE (reg) == SUBREG && REG_P (SUBREG_REG (reg)))
00512 reg = SUBREG_REG (reg);
00513
00514 if (STACK_REG_P (reg))
00515 {
00516 clobber_reg[n_clobbers] = reg;
00517 n_clobbers++;
00518 }
00519 }
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529 memset (reg_used_as_output, 0, sizeof (reg_used_as_output));
00530 for (i = 0; i < n_outputs; i++)
00531 if (STACK_REG_P (recog_data.operand[i]))
00532 {
00533 if (reg_class_size[(int) recog_op_alt[i][alt].cl] != 1)
00534 {
00535 error_for_asm (insn, "output constraint %d must specify a single register", i);
00536 malformed_asm = 1;
00537 }
00538 else
00539 {
00540 int j;
00541
00542 for (j = 0; j < n_clobbers; j++)
00543 if (REGNO (recog_data.operand[i]) == REGNO (clobber_reg[j]))
00544 {
00545 error_for_asm (insn, "output constraint %d cannot be specified together with \"%s\" clobber",
00546 i, reg_names [REGNO (clobber_reg[j])]);
00547 malformed_asm = 1;
00548 break;
00549 }
00550 if (j == n_clobbers)
00551 reg_used_as_output[REGNO (recog_data.operand[i])] = 1;
00552 }
00553 }
00554
00555
00556
00557 for (i = FIRST_STACK_REG; i < LAST_STACK_REG + 1; i++)
00558 if (! reg_used_as_output[i])
00559 break;
00560
00561
00562 for (; i < LAST_STACK_REG + 1; i++)
00563 if (reg_used_as_output[i])
00564 break;
00565
00566 if (i != LAST_STACK_REG + 1)
00567 {
00568 error_for_asm (insn, "output regs must be grouped at top of stack");
00569 malformed_asm = 1;
00570 }
00571
00572
00573
00574
00575
00576 memset (implicitly_dies, 0, sizeof (implicitly_dies));
00577 for (i = n_outputs; i < n_outputs + n_inputs; i++)
00578 if (STACK_REG_P (recog_data.operand[i]))
00579 {
00580
00581
00582 int j;
00583
00584 for (j = 0; j < n_clobbers; j++)
00585 if (operands_match_p (clobber_reg[j], recog_data.operand[i]))
00586 break;
00587
00588 if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0)
00589 implicitly_dies[REGNO (recog_data.operand[i])] = 1;
00590 }
00591
00592
00593 for (i = FIRST_STACK_REG; i < LAST_STACK_REG + 1; i++)
00594 if (! implicitly_dies[i])
00595 break;
00596
00597
00598 for (; i < LAST_STACK_REG + 1; i++)
00599 if (implicitly_dies[i])
00600 break;
00601
00602 if (i != LAST_STACK_REG + 1)
00603 {
00604 error_for_asm (insn,
00605 "implicitly popped regs must be grouped at top of stack");
00606 malformed_asm = 1;
00607 }
00608
00609
00610
00611
00612
00613
00614
00615 for (i = n_outputs; i < n_outputs + n_inputs; i++)
00616 if (recog_op_alt[i][alt].matches == -1)
00617 {
00618 int j;
00619
00620 for (j = 0; j < n_outputs; j++)
00621 if (operands_match_p (recog_data.operand[j], recog_data.operand[i]))
00622 {
00623 error_for_asm (insn,
00624 "output operand %d must use %<&%> constraint", j);
00625 malformed_asm = 1;
00626 }
00627 }
00628
00629 if (malformed_asm)
00630 {
00631
00632 PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
00633 any_malformed_asm = true;
00634 return 0;
00635 }
00636
00637 return 1;
00638 }
00639
00640
00641
00642
00643
00644
00645 static int
00646 get_asm_operand_n_inputs (rtx body)
00647 {
00648 switch (GET_CODE (body))
00649 {
00650 case SET:
00651 gcc_assert (GET_CODE (SET_SRC (body)) == ASM_OPERANDS);
00652 return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body));
00653
00654 case ASM_OPERANDS:
00655 return ASM_OPERANDS_INPUT_LENGTH (body);
00656
00657 case PARALLEL:
00658 return get_asm_operand_n_inputs (XVECEXP (body, 0, 0));
00659
00660 default:
00661 gcc_unreachable ();
00662 }
00663 }
00664
00665
00666
00667
00668 static rtx
00669 stack_result (tree decl)
00670 {
00671 rtx result;
00672
00673
00674
00675 if (aggregate_value_p (DECL_RESULT (decl), decl))
00676 return 0;
00677
00678 result = DECL_RTL_IF_SET (DECL_RESULT (decl));
00679 if (result != 0)
00680 result = targetm.calls.function_value (TREE_TYPE (DECL_RESULT (decl)),
00681 decl, true);
00682
00683 return result != 0 && STACK_REG_P (result) ? result : 0;
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 static void
00696 replace_reg (rtx *reg, int regno)
00697 {
00698 gcc_assert (regno >= FIRST_STACK_REG);
00699 gcc_assert (regno <= LAST_STACK_REG);
00700 gcc_assert (STACK_REG_P (*reg));
00701
00702 gcc_assert (SCALAR_FLOAT_MODE_P (GET_MODE (*reg))
00703 || GET_MODE_CLASS (GET_MODE (*reg)) == MODE_COMPLEX_FLOAT);
00704
00705 *reg = FP_MODE_REG (regno, GET_MODE (*reg));
00706 }
00707
00708
00709
00710
00711 static void
00712 remove_regno_note (rtx insn, enum reg_note note, unsigned int regno)
00713 {
00714 rtx *note_link, this;
00715
00716 note_link = ®_NOTES (insn);
00717 for (this = *note_link; this; this = XEXP (this, 1))
00718 if (REG_NOTE_KIND (this) == note
00719 && REG_P (XEXP (this, 0)) && REGNO (XEXP (this, 0)) == regno)
00720 {
00721 *note_link = XEXP (this, 1);
00722 return;
00723 }
00724 else
00725 note_link = &XEXP (this, 1);
00726
00727 gcc_unreachable ();
00728 }
00729
00730
00731
00732
00733
00734 static int
00735 get_hard_regnum (stack regstack, rtx reg)
00736 {
00737 int i;
00738
00739 gcc_assert (STACK_REG_P (reg));
00740
00741 for (i = regstack->top; i >= 0; i--)
00742 if (regstack->reg[i] == REGNO (reg))
00743 break;
00744
00745 return i >= 0 ? (FIRST_STACK_REG + regstack->top - i) : -1;
00746 }
00747
00748
00749
00750
00751
00752
00753
00754
00755 static rtx
00756 emit_pop_insn (rtx insn, stack regstack, rtx reg, enum emit_where where)
00757 {
00758 rtx pop_insn, pop_rtx;
00759 int hard_regno;
00760
00761
00762
00763 if (COMPLEX_MODE_P (GET_MODE (reg)))
00764 {
00765 rtx reg1 = FP_MODE_REG (REGNO (reg), DFmode);
00766 rtx reg2 = FP_MODE_REG (REGNO (reg) + 1, DFmode);
00767
00768 pop_insn = NULL_RTX;
00769 if (get_hard_regnum (regstack, reg1) >= 0)
00770 pop_insn = emit_pop_insn (insn, regstack, reg1, where);
00771 if (get_hard_regnum (regstack, reg2) >= 0)
00772 pop_insn = emit_pop_insn (insn, regstack, reg2, where);
00773 gcc_assert (pop_insn);
00774 return pop_insn;
00775 }
00776
00777 hard_regno = get_hard_regnum (regstack, reg);
00778
00779 gcc_assert (hard_regno >= FIRST_STACK_REG);
00780
00781 pop_rtx = gen_rtx_SET (VOIDmode, FP_MODE_REG (hard_regno, DFmode),
00782 FP_MODE_REG (FIRST_STACK_REG, DFmode));
00783
00784 if (where == EMIT_AFTER)
00785 pop_insn = emit_insn_after (pop_rtx, insn);
00786 else
00787 pop_insn = emit_insn_before (pop_rtx, insn);
00788
00789 REG_NOTES (pop_insn)
00790 = gen_rtx_EXPR_LIST (REG_DEAD, FP_MODE_REG (FIRST_STACK_REG, DFmode),
00791 REG_NOTES (pop_insn));
00792
00793 regstack->reg[regstack->top - (hard_regno - FIRST_STACK_REG)]
00794 = regstack->reg[regstack->top];
00795 regstack->top -= 1;
00796 CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (reg));
00797
00798 return pop_insn;
00799 }
00800
00801
00802
00803
00804
00805
00806
00807
00808 static void
00809 emit_swap_insn (rtx insn, stack regstack, rtx reg)
00810 {
00811 int hard_regno;
00812 rtx swap_rtx;
00813 int tmp, other_reg;
00814 rtx i1;
00815 rtx i1set = NULL_RTX;
00816
00817 hard_regno = get_hard_regnum (regstack, reg);
00818
00819 if (hard_regno == FIRST_STACK_REG)
00820 return;
00821 if (hard_regno == -1)
00822 {
00823
00824
00825
00826
00827 gcc_assert (any_malformed_asm);
00828 regstack->reg[++regstack->top] = REGNO (reg);
00829 return;
00830 }
00831 gcc_assert (hard_regno >= FIRST_STACK_REG);
00832
00833 other_reg = regstack->top - (hard_regno - FIRST_STACK_REG);
00834
00835 tmp = regstack->reg[other_reg];
00836 regstack->reg[other_reg] = regstack->reg[regstack->top];
00837 regstack->reg[regstack->top] = tmp;
00838
00839
00840
00841 i1 = NULL;
00842 if (current_block && insn != BB_HEAD (current_block))
00843 {
00844 rtx tmp = PREV_INSN (insn);
00845 rtx limit = PREV_INSN (BB_HEAD (current_block));
00846 while (tmp != limit)
00847 {
00848 if (LABEL_P (tmp)
00849 || CALL_P (tmp)
00850 || NOTE_INSN_BASIC_BLOCK_P (tmp)
00851 || (NONJUMP_INSN_P (tmp)
00852 && stack_regs_mentioned (tmp)))
00853 {
00854 i1 = tmp;
00855 break;
00856 }
00857 tmp = PREV_INSN (tmp);
00858 }
00859 }
00860
00861 if (i1 != NULL_RTX
00862 && (i1set = single_set (i1)) != NULL_RTX)
00863 {
00864 rtx i1src = *get_true_reg (&SET_SRC (i1set));
00865 rtx i1dest = *get_true_reg (&SET_DEST (i1set));
00866
00867
00868
00869
00870 if (REG_P (i1dest) && REGNO (i1dest) == FIRST_STACK_REG
00871 && REG_P (i1src)
00872 && REGNO (i1src) == (unsigned) hard_regno - 1
00873 && find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX)
00874 return;
00875
00876
00877
00878
00879 if (REG_P (i1dest) && REGNO (i1dest) == (unsigned) hard_regno
00880 && REG_P (i1src) && REGNO (i1src) == FIRST_STACK_REG
00881 && find_regno_note (i1, REG_DEAD, FIRST_STACK_REG) == NULL_RTX)
00882 return;
00883 }
00884
00885
00886
00887
00888 if (current_block && starting_stack_p)
00889 {
00890 BLOCK_INFO (current_block)->stack_in = *regstack;
00891 starting_stack_p = false;
00892 return;
00893 }
00894
00895 swap_rtx = gen_swapxf (FP_MODE_REG (hard_regno, XFmode),
00896 FP_MODE_REG (FIRST_STACK_REG, XFmode));
00897
00898 if (i1)
00899 emit_insn_after (swap_rtx, i1);
00900 else if (current_block)
00901 emit_insn_before (swap_rtx, BB_HEAD (current_block));
00902 else
00903 emit_insn_before (swap_rtx, insn);
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915 static void
00916 swap_to_top (rtx insn, stack regstack, rtx src1, rtx src2)
00917 {
00918 struct stack_def temp_stack;
00919 int regno, j, k, temp;
00920
00921 temp_stack = *regstack;
00922
00923
00924 regno = get_hard_regnum (&temp_stack, src1);
00925 gcc_assert (regno >= 0);
00926 if (regno != FIRST_STACK_REG)
00927 {
00928 k = temp_stack.top - (regno - FIRST_STACK_REG);
00929 j = temp_stack.top;
00930
00931 temp = temp_stack.reg[k];
00932 temp_stack.reg[k] = temp_stack.reg[j];
00933 temp_stack.reg[j] = temp;
00934 }
00935
00936
00937 regno = get_hard_regnum (&temp_stack, src2);
00938 gcc_assert (regno >= 0);
00939 if (regno != FIRST_STACK_REG + 1)
00940 {
00941 k = temp_stack.top - (regno - FIRST_STACK_REG);
00942 j = temp_stack.top - 1;
00943
00944 temp = temp_stack.reg[k];
00945 temp_stack.reg[k] = temp_stack.reg[j];
00946 temp_stack.reg[j] = temp;
00947 }
00948
00949 change_stack (insn, regstack, &temp_stack, EMIT_BEFORE);
00950 }
00951
00952
00953
00954
00955
00956 static bool
00957 move_for_stack_reg (rtx insn, stack regstack, rtx pat)
00958 {
00959 rtx *psrc = get_true_reg (&SET_SRC (pat));
00960 rtx *pdest = get_true_reg (&SET_DEST (pat));
00961 rtx src, dest;
00962 rtx note;
00963 bool control_flow_insn_deleted = false;
00964
00965 src = *psrc; dest = *pdest;
00966
00967 if (STACK_REG_P (src) && STACK_REG_P (dest))
00968 {
00969
00970
00971
00972 note = find_regno_note (insn, REG_DEAD, REGNO (src));
00973 if (note)
00974 {
00975 int i;
00976
00977
00978 gcc_assert (REGNO (src) != REGNO (dest));
00979
00980 for (i = regstack->top; i >= 0; i--)
00981 if (regstack->reg[i] == REGNO (src))
00982 break;
00983
00984
00985 gcc_assert (get_hard_regnum (regstack, dest) < FIRST_STACK_REG);
00986
00987
00988
00989 if (i < 0)
00990 return move_nan_for_stack_reg (insn, regstack, dest);
00991
00992
00993
00994
00995 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
00996 emit_pop_insn (insn, regstack, src, EMIT_AFTER);
00997 else
00998 {
00999 regstack->reg[i] = REGNO (dest);
01000 SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
01001 CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
01002 }
01003
01004 control_flow_insn_deleted |= control_flow_insn_p (insn);
01005 delete_insn (insn);
01006 return control_flow_insn_deleted;
01007 }
01008
01009
01010
01011
01012
01013
01014
01015
01016 if (REGNO (src) == REGNO (dest))
01017 {
01018 if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
01019 emit_pop_insn (insn, regstack, dest, EMIT_AFTER);
01020
01021 control_flow_insn_deleted |= control_flow_insn_p (insn);
01022 delete_insn (insn);
01023 return control_flow_insn_deleted;
01024 }
01025
01026
01027 gcc_assert (get_hard_regnum (regstack, dest) < FIRST_STACK_REG);
01028
01029 replace_reg (psrc, get_hard_regnum (regstack, src));
01030
01031 regstack->reg[++regstack->top] = REGNO (dest);
01032 SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
01033 replace_reg (pdest, FIRST_STACK_REG);
01034 }
01035 else if (STACK_REG_P (src))
01036 {
01037
01038
01039
01040
01041 emit_swap_insn (insn, regstack, src);
01042
01043 note = find_regno_note (insn, REG_DEAD, REGNO (src));
01044 if (note)
01045 {
01046 replace_reg (&XEXP (note, 0), FIRST_STACK_REG);
01047 regstack->top--;
01048 CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
01049 }
01050 else if ((GET_MODE (src) == XFmode)
01051 && regstack->top < REG_STACK_SIZE - 1)
01052 {
01053
01054
01055
01056
01057
01058
01059
01060 rtx push_rtx;
01061 rtx top_stack_reg = FP_MODE_REG (FIRST_STACK_REG, GET_MODE (src));
01062
01063 push_rtx = gen_movxf (top_stack_reg, top_stack_reg);
01064 emit_insn_before (push_rtx, insn);
01065 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, top_stack_reg,
01066 REG_NOTES (insn));
01067 }
01068
01069 replace_reg (psrc, FIRST_STACK_REG);
01070 }
01071 else
01072 {
01073 gcc_assert (STACK_REG_P (dest));
01074
01075
01076
01077
01078
01079
01080
01081 gcc_assert (get_hard_regnum (regstack, dest) < FIRST_STACK_REG);
01082
01083 gcc_assert (regstack->top < REG_STACK_SIZE);
01084
01085 regstack->reg[++regstack->top] = REGNO (dest);
01086 SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
01087 replace_reg (pdest, FIRST_STACK_REG);
01088 }
01089
01090 return control_flow_insn_deleted;
01091 }
01092
01093
01094
01095
01096 static bool
01097 move_nan_for_stack_reg (rtx insn, stack regstack, rtx dest)
01098 {
01099 rtx pat;
01100
01101 dest = FP_MODE_REG (REGNO (dest), SFmode);
01102 pat = gen_rtx_SET (VOIDmode, dest, not_a_num);
01103 PATTERN (insn) = pat;
01104 INSN_CODE (insn) = -1;
01105
01106 return move_for_stack_reg (insn, regstack, pat);
01107 }
01108
01109
01110
01111
01112
01113 static int
01114 swap_rtx_condition_1 (rtx pat)
01115 {
01116 const char *fmt;
01117 int i, r = 0;
01118
01119 if (COMPARISON_P (pat))
01120 {
01121 PUT_CODE (pat, swap_condition (GET_CODE (pat)));
01122 r = 1;
01123 }
01124 else
01125 {
01126 fmt = GET_RTX_FORMAT (GET_CODE (pat));
01127 for (i = GET_RTX_LENGTH (GET_CODE (pat)) - 1; i >= 0; i--)
01128 {
01129 if (fmt[i] == 'E')
01130 {
01131 int j;
01132
01133 for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
01134 r |= swap_rtx_condition_1 (XVECEXP (pat, i, j));
01135 }
01136 else if (fmt[i] == 'e')
01137 r |= swap_rtx_condition_1 (XEXP (pat, i));
01138 }
01139 }
01140
01141 return r;
01142 }
01143
01144 static int
01145 swap_rtx_condition (rtx insn)
01146 {
01147 rtx pat = PATTERN (insn);
01148
01149
01150
01151 if (GET_CODE (pat) == SET
01152 && REG_P (SET_DEST (pat))
01153 && REGNO (SET_DEST (pat)) == FLAGS_REG)
01154 {
01155 insn = next_flags_user (insn);
01156 if (insn == NULL_RTX)
01157 return 0;
01158 pat = PATTERN (insn);
01159 }
01160
01161
01162
01163
01164
01165 if (GET_CODE (pat) == SET
01166 && GET_CODE (SET_SRC (pat)) == UNSPEC
01167 && XINT (SET_SRC (pat), 1) == UNSPEC_FNSTSW)
01168 {
01169 rtx dest = SET_DEST (pat);
01170
01171
01172
01173 while (insn != BB_END (current_block))
01174 {
01175 insn = NEXT_INSN (insn);
01176 if (INSN_P (insn) && reg_mentioned_p (dest, insn))
01177 break;
01178 if (CALL_P (insn))
01179 return 0;
01180 }
01181
01182
01183 if (insn == BB_END (current_block))
01184 return 0;
01185
01186
01187
01188
01189 pat = PATTERN (insn);
01190 if (GET_CODE (pat) != SET
01191 || GET_CODE (SET_SRC (pat)) != UNSPEC
01192 || XINT (SET_SRC (pat), 1) != UNSPEC_SAHF
01193 || ! dead_or_set_p (insn, dest))
01194 return 0;
01195
01196
01197 insn = next_flags_user (insn);
01198 if (insn == NULL_RTX)
01199 return 0;
01200 pat = PATTERN (insn);
01201 }
01202
01203 if (swap_rtx_condition_1 (pat))
01204 {
01205 int fail = 0;
01206 INSN_CODE (insn) = -1;
01207 if (recog_memoized (insn) == -1)
01208 fail = 1;
01209
01210
01211 else if (! dead_or_set_p (insn, ix86_flags_rtx))
01212 {
01213 insn = next_flags_user (insn);
01214 if (!insn || !swap_rtx_condition (insn))
01215 fail = 1;
01216 }
01217 if (fail)
01218 {
01219 swap_rtx_condition_1 (pat);
01220 return 0;
01221 }
01222 return 1;
01223 }
01224 return 0;
01225 }
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235 static void
01236 compare_for_stack_reg (rtx insn, stack regstack, rtx pat_src)
01237 {
01238 rtx *src1, *src2;
01239 rtx src1_note, src2_note;
01240
01241 src1 = get_true_reg (&XEXP (pat_src, 0));
01242 src2 = get_true_reg (&XEXP (pat_src, 1));
01243
01244
01245
01246 if ((! STACK_REG_P (*src1)
01247 || (STACK_REG_P (*src2)
01248 && get_hard_regnum (regstack, *src2) == FIRST_STACK_REG))
01249 && swap_rtx_condition (insn))
01250 {
01251 rtx temp;
01252 temp = XEXP (pat_src, 0);
01253 XEXP (pat_src, 0) = XEXP (pat_src, 1);
01254 XEXP (pat_src, 1) = temp;
01255
01256 src1 = get_true_reg (&XEXP (pat_src, 0));
01257 src2 = get_true_reg (&XEXP (pat_src, 1));
01258
01259 INSN_CODE (insn) = -1;
01260 }
01261
01262
01263
01264 src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
01265
01266 if (STACK_REG_P (*src2))
01267 src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
01268 else
01269 src2_note = NULL_RTX;
01270
01271 emit_swap_insn (insn, regstack, *src1);
01272
01273 replace_reg (src1, FIRST_STACK_REG);
01274
01275 if (STACK_REG_P (*src2))
01276 replace_reg (src2, get_hard_regnum (regstack, *src2));
01277
01278 if (src1_note)
01279 {
01280 pop_stack (regstack, REGNO (XEXP (src1_note, 0)));
01281 replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
01282 }
01283
01284
01285
01286
01287
01288 if (src2_note
01289 && ! (STACK_REG_P (*src1) && STACK_REG_P (*src2)
01290 && REGNO (*src1) == REGNO (*src2)))
01291 {
01292
01293
01294
01295
01296
01297 if (get_hard_regnum (regstack, XEXP (src2_note, 0)) == FIRST_STACK_REG
01298 && src1_note)
01299 {
01300 pop_stack (regstack, REGNO (XEXP (src2_note, 0)));
01301 replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG + 1);
01302 }
01303 else
01304 {
01305
01306
01307
01308
01309
01310
01311 remove_regno_note (insn, REG_DEAD, REGNO (XEXP (src2_note, 0)));
01312
01313 emit_pop_insn (insn, regstack, XEXP (src2_note, 0),
01314 EMIT_AFTER);
01315 }
01316 }
01317 }
01318
01319
01320
01321
01322
01323 static bool
01324 subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
01325 {
01326 rtx *dest, *src;
01327 bool control_flow_insn_deleted = false;
01328
01329 switch (GET_CODE (pat))
01330 {
01331 case USE:
01332
01333
01334 src = get_true_reg (&XEXP (pat, 0));
01335 if (STACK_REG_P (*src)
01336 && find_regno_note (insn, REG_DEAD, REGNO (*src)))
01337 {
01338 emit_pop_insn (insn, regstack, *src, EMIT_AFTER);
01339 return control_flow_insn_deleted;
01340 }
01341
01342 else
01343 gcc_assert (get_hard_regnum (regstack, *src) != -1);
01344 break;
01345
01346 case CLOBBER:
01347 {
01348 rtx note;
01349
01350 dest = get_true_reg (&XEXP (pat, 0));
01351 if (STACK_REG_P (*dest))
01352 {
01353 note = find_reg_note (insn, REG_DEAD, *dest);
01354
01355 if (pat != PATTERN (insn))
01356 {
01357
01358
01359
01360
01361
01362
01363
01364 if (note)
01365 emit_pop_insn (insn, regstack, *dest, EMIT_BEFORE);
01366 else
01367 {
01368 note = find_reg_note (insn, REG_UNUSED, *dest);
01369 gcc_assert (note);
01370 }
01371 remove_note (insn, note);
01372 replace_reg (dest, FIRST_STACK_REG + 1);
01373 }
01374 else
01375 {
01376
01377
01378
01379
01380
01381 if (!note)
01382 {
01383 rtx t = *dest;
01384 if (COMPLEX_MODE_P (GET_MODE (t)))
01385 {
01386 rtx u = FP_MODE_REG (REGNO (t) + 1, SFmode);
01387 if (get_hard_regnum (regstack, u) == -1)
01388 {
01389 rtx pat2 = gen_rtx_CLOBBER (VOIDmode, u);
01390 rtx insn2 = emit_insn_before (pat2, insn);
01391 control_flow_insn_deleted
01392 |= move_nan_for_stack_reg (insn2, regstack, u);
01393 }
01394 }
01395 if (get_hard_regnum (regstack, t) == -1)
01396 control_flow_insn_deleted
01397 |= move_nan_for_stack_reg (insn, regstack, t);
01398 }
01399 }
01400 }
01401 break;
01402 }
01403
01404 case SET:
01405 {
01406 rtx *src1 = (rtx *) 0, *src2;
01407 rtx src1_note, src2_note;
01408 rtx pat_src;
01409
01410 dest = get_true_reg (&SET_DEST (pat));
01411 src = get_true_reg (&SET_SRC (pat));
01412 pat_src = SET_SRC (pat);
01413
01414
01415 if (STACK_REG_P (*src)
01416 || (STACK_REG_P (*dest)
01417 && (REG_P (*src) || MEM_P (*src)
01418 || GET_CODE (*src) == CONST_DOUBLE)))
01419 {
01420 control_flow_insn_deleted |= move_for_stack_reg (insn, regstack, pat);
01421 break;
01422 }
01423
01424 switch (GET_CODE (pat_src))
01425 {
01426 case COMPARE:
01427 compare_for_stack_reg (insn, regstack, pat_src);
01428 break;
01429
01430 case CALL:
01431 {
01432 int count;
01433 for (count = hard_regno_nregs[REGNO (*dest)][GET_MODE (*dest)];
01434 --count >= 0;)
01435 {
01436 regstack->reg[++regstack->top] = REGNO (*dest) + count;
01437 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest) + count);
01438 }
01439 }
01440 replace_reg (dest, FIRST_STACK_REG);
01441 break;
01442
01443 case REG:
01444
01445 gcc_assert (*dest == cc0_rtx);
01446 src1 = src;
01447
01448
01449
01450 case FLOAT_TRUNCATE:
01451 case SQRT:
01452 case ABS:
01453 case NEG:
01454
01455
01456
01457
01458
01459 if (src1 == 0)
01460 src1 = get_true_reg (&XEXP (pat_src, 0));
01461
01462 emit_swap_insn (insn, regstack, *src1);
01463
01464 src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
01465
01466 if (STACK_REG_P (*dest))
01467 replace_reg (dest, FIRST_STACK_REG);
01468
01469 if (src1_note)
01470 {
01471 replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
01472 regstack->top--;
01473 CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1));
01474 }
01475
01476 replace_reg (src1, FIRST_STACK_REG);
01477 break;
01478
01479 case MINUS:
01480 case DIV:
01481
01482
01483
01484 case MULT:
01485 case PLUS:
01486
01487
01488
01489
01490
01491 src1 = get_true_reg (&XEXP (pat_src, 0));
01492 src2 = get_true_reg (&XEXP (pat_src, 1));
01493
01494
01495
01496 if (STACK_REG_P (*src1))
01497 src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
01498 else
01499 src1_note = NULL_RTX;
01500 if (STACK_REG_P (*src2))
01501 src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
01502 else
01503 src2_note = NULL_RTX;
01504
01505
01506
01507
01508 if (! STACK_REG_P (*src1) || ! STACK_REG_P (*src2))
01509 emit_swap_insn (insn, regstack, *dest);
01510 else
01511 {
01512
01513
01514
01515
01516 int src1_hard_regnum, src2_hard_regnum;
01517
01518 src1_hard_regnum = get_hard_regnum (regstack, *src1);
01519 src2_hard_regnum = get_hard_regnum (regstack, *src2);
01520 gcc_assert (src1_hard_regnum != -1);
01521 gcc_assert (src2_hard_regnum != -1);
01522
01523 if (src1_hard_regnum != FIRST_STACK_REG
01524 && src2_hard_regnum != FIRST_STACK_REG)
01525 emit_swap_insn (insn, regstack, *dest);
01526 }
01527
01528 if (STACK_REG_P (*src1))
01529 replace_reg (src1, get_hard_regnum (regstack, *src1));
01530 if (STACK_REG_P (*src2))
01531 replace_reg (src2, get_hard_regnum (regstack, *src2));
01532
01533 if (src1_note)
01534 {
01535 rtx src1_reg = XEXP (src1_note, 0);
01536
01537
01538
01539
01540
01541
01542
01543 if (REGNO (src1_reg) == regstack->reg[regstack->top])
01544 {
01545 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
01546 replace_reg (dest, get_hard_regnum (regstack, *dest));
01547 }
01548 else
01549 {
01550 int regno = get_hard_regnum (regstack, src1_reg);
01551
01552 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
01553 replace_reg (dest, regno);
01554
01555 regstack->reg[regstack->top - (regno - FIRST_STACK_REG)]
01556 = regstack->reg[regstack->top];
01557 }
01558
01559 CLEAR_HARD_REG_BIT (regstack->reg_set,
01560 REGNO (XEXP (src1_note, 0)));
01561 replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
01562 regstack->top--;
01563 }
01564 else if (src2_note)
01565 {
01566 rtx src2_reg = XEXP (src2_note, 0);
01567 if (REGNO (src2_reg) == regstack->reg[regstack->top])
01568 {
01569 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
01570 replace_reg (dest, get_hard_regnum (regstack, *dest));
01571 }
01572 else
01573 {
01574 int regno = get_hard_regnum (regstack, src2_reg);
01575
01576 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
01577 replace_reg (dest, regno);
01578
01579 regstack->reg[regstack->top - (regno - FIRST_STACK_REG)]
01580 = regstack->reg[regstack->top];
01581 }
01582
01583 CLEAR_HARD_REG_BIT (regstack->reg_set,
01584 REGNO (XEXP (src2_note, 0)));
01585 replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG);
01586 regstack->top--;
01587 }
01588 else
01589 {
01590 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
01591 replace_reg (dest, get_hard_regnum (regstack, *dest));
01592 }
01593
01594
01595 if (COMMUTATIVE_ARITH_P (pat_src)
01596 && REG_P (*src1) && REG_P (*src2)
01597 && REGNO (*src1) != REGNO (*dest))
01598 {
01599 int tmp = REGNO (*src1);
01600 replace_reg (src1, REGNO (*src2));
01601 replace_reg (src2, tmp);
01602 }
01603 break;
01604
01605 case UNSPEC:
01606 switch (XINT (pat_src, 1))
01607 {
01608 case UNSPEC_FIST:
01609
01610 case UNSPEC_FIST_FLOOR:
01611 case UNSPEC_FIST_CEIL:
01612
01613
01614
01615 src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
01616 emit_swap_insn (insn, regstack, *src1);
01617
01618 src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
01619
01620 if (STACK_REG_P (*dest))
01621 replace_reg (dest, FIRST_STACK_REG);
01622
01623 if (src1_note)
01624 {
01625 replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
01626 regstack->top--;
01627 CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (*src1));
01628 }
01629
01630 replace_reg (src1, FIRST_STACK_REG);
01631 break;
01632
01633 case UNSPEC_SIN:
01634 case UNSPEC_COS:
01635 case UNSPEC_FRNDINT:
01636 case UNSPEC_F2XM1:
01637
01638 case UNSPEC_FRNDINT_FLOOR:
01639 case UNSPEC_FRNDINT_CEIL:
01640 case UNSPEC_FRNDINT_TRUNC:
01641 case UNSPEC_FRNDINT_MASK_PM:
01642
01643
01644
01645 src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
01646
01647 emit_swap_insn (insn, regstack, *src1);
01648
01649
01650
01651 src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
01652 gcc_assert (!src1_note);
01653
01654 if (STACK_REG_P (*dest))
01655 replace_reg (dest, FIRST_STACK_REG);
01656
01657 replace_reg (src1, FIRST_STACK_REG);
01658 break;
01659
01660 case UNSPEC_FPATAN:
01661 case UNSPEC_FYL2X:
01662 case UNSPEC_FYL2XP1:
01663
01664
01665 src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
01666 src2 = get_true_reg (&XVECEXP (pat_src, 0, 1));
01667
01668 src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
01669 src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
01670
01671 swap_to_top (insn, regstack, *src1, *src2);
01672
01673 replace_reg (src1, FIRST_STACK_REG);
01674 replace_reg (src2, FIRST_STACK_REG + 1);
01675
01676 if (src1_note)
01677 replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
01678 if (src2_note)
01679 replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG + 1);
01680
01681
01682 CLEAR_HARD_REG_BIT (regstack->reg_set,
01683 regstack->reg[regstack->top]);
01684 CLEAR_HARD_REG_BIT (regstack->reg_set,
01685 regstack->reg[regstack->top - 1]);
01686 regstack->top -= 2;
01687
01688
01689 regstack->reg[++regstack->top] = REGNO (*dest);
01690 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
01691 replace_reg (dest, FIRST_STACK_REG);
01692 break;
01693
01694 case UNSPEC_FSCALE_FRACT:
01695 case UNSPEC_FPREM_F:
01696 case UNSPEC_FPREM1_F:
01697
01698
01699
01700 src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
01701 src2 = get_true_reg (&XVECEXP (pat_src, 0, 1));
01702
01703 src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
01704 src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
01705
01706
01707
01708 gcc_assert (!src1_note);
01709 gcc_assert (!src2_note);
01710
01711 swap_to_top (insn, regstack, *src1, *src2);
01712
01713
01714
01715 if (STACK_REG_P (*dest)) {
01716 regstack->reg[regstack->top] = REGNO (*dest);
01717 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
01718 replace_reg (dest, FIRST_STACK_REG);
01719 }
01720
01721 replace_reg (src1, FIRST_STACK_REG);
01722 replace_reg (src2, FIRST_STACK_REG + 1);
01723 break;
01724
01725 case UNSPEC_FSCALE_EXP:
01726 case UNSPEC_FPREM_U:
01727 case UNSPEC_FPREM1_U:
01728
01729
01730
01731 src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
01732 src2 = get_true_reg (&XVECEXP (pat_src, 0, 1));
01733
01734 src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
01735 src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
01736
01737
01738
01739 gcc_assert (!src1_note);
01740 gcc_assert (!src2_note);
01741
01742 swap_to_top (insn, regstack, *src1, *src2);
01743
01744
01745
01746 if (STACK_REG_P (*dest)) {
01747 regstack->reg[regstack->top - 1] = REGNO (*dest);
01748 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
01749 replace_reg (dest, FIRST_STACK_REG + 1);
01750 }
01751
01752 replace_reg (src1, FIRST_STACK_REG);
01753 replace_reg (src2, FIRST_STACK_REG + 1);
01754 break;
01755
01756 case UNSPEC_SINCOS_COS:
01757 case UNSPEC_TAN_ONE:
01758 case UNSPEC_XTRACT_FRACT:
01759
01760
01761
01762 src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
01763
01764 emit_swap_insn (insn, regstack, *src1);
01765
01766
01767
01768 src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
01769 gcc_assert (!src1_note);
01770
01771
01772
01773 if (STACK_REG_P (*dest)) {
01774 regstack->reg[regstack->top + 1] = REGNO (*dest);
01775 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
01776 replace_reg (dest, FIRST_STACK_REG);
01777 }
01778
01779 replace_reg (src1, FIRST_STACK_REG);
01780 break;
01781
01782 case UNSPEC_SINCOS_SIN:
01783 case UNSPEC_TAN_TAN:
01784 case UNSPEC_XTRACT_EXP:
01785
01786
01787
01788 src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
01789
01790 emit_swap_insn (insn, regstack, *src1);
01791
01792
01793
01794 src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
01795 gcc_assert (!src1_note);
01796
01797
01798
01799 if (STACK_REG_P (*dest)) {
01800 regstack->reg[regstack->top] = REGNO (*dest);
01801 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
01802 replace_reg (dest, FIRST_STACK_REG + 1);
01803
01804 regstack->top++;
01805 }
01806
01807 replace_reg (src1, FIRST_STACK_REG);
01808 break;
01809
01810 case UNSPEC_SAHF:
01811
01812
01813
01814 pat_src = XVECEXP (pat_src, 0, 0);
01815 gcc_assert (GET_CODE (pat_src) == UNSPEC);
01816 gcc_assert (XINT (pat_src, 1) == UNSPEC_FNSTSW);
01817
01818
01819 case UNSPEC_FNSTSW:
01820
01821
01822
01823
01824 pat_src = XVECEXP (pat_src, 0, 0);
01825 gcc_assert (GET_CODE (pat_src) == COMPARE);
01826
01827 compare_for_stack_reg (insn, regstack, pat_src);
01828 break;
01829
01830 default:
01831 gcc_unreachable ();
01832 }
01833 break;
01834
01835 case IF_THEN_ELSE:
01836
01837
01838 src1 = get_true_reg (&XEXP (pat_src, 1));
01839 src2 = get_true_reg (&XEXP (pat_src, 2));
01840
01841 src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
01842 src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
01843
01844
01845
01846
01847
01848
01849 if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG
01850 && REGNO (*dest) != regstack->reg[regstack->top])
01851 {
01852
01853
01854
01855 if ((REGNO (*src1) == regstack->reg[regstack->top]
01856 && src1_note)
01857 || (REGNO (*src2) == regstack->reg[regstack->top]
01858 && src2_note))
01859 {
01860 int idx1 = (get_hard_regnum (regstack, *src1)
01861 - FIRST_STACK_REG);
01862 int idx2 = (get_hard_regnum (regstack, *src2)
01863 - FIRST_STACK_REG);
01864
01865
01866
01867 regstack->reg[regstack->top - idx1] = REGNO (*src2);
01868 regstack->reg[regstack->top - idx2] = REGNO (*src1);
01869
01870
01871
01872 PUT_CODE (XEXP (pat_src, 0),
01873 reversed_comparison_code (XEXP (pat_src, 0), insn));
01874 }
01875 else
01876 emit_swap_insn (insn, regstack, *dest);
01877 }
01878
01879 {
01880 rtx src_note [3];
01881 int i;
01882
01883 src_note[0] = 0;
01884 src_note[1] = src1_note;
01885 src_note[2] = src2_note;
01886
01887 if (STACK_REG_P (*src1))
01888 replace_reg (src1, get_hard_regnum (regstack, *src1));
01889 if (STACK_REG_P (*src2))
01890 replace_reg (src2, get_hard_regnum (regstack, *src2));
01891
01892 for (i = 1; i <= 2; i++)
01893 if (src_note [i])
01894 {
01895 int regno = REGNO (XEXP (src_note[i], 0));
01896
01897
01898
01899
01900
01901 gcc_assert (regno != regstack->reg[regstack->top]);
01902 remove_regno_note (insn, REG_DEAD, regno);
01903 emit_pop_insn (insn, regstack, XEXP (src_note[i], 0),
01904 EMIT_AFTER);
01905 }
01906 }
01907
01908
01909
01910 if (get_hard_regnum (regstack, *dest) < FIRST_STACK_REG)
01911 regstack->reg[++regstack->top] = REGNO (*dest);
01912 SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
01913 replace_reg (dest, FIRST_STACK_REG);
01914 break;
01915
01916 default:
01917 gcc_unreachable ();
01918 }
01919 break;
01920 }
01921
01922 default:
01923 break;
01924 }
01925
01926 return control_flow_insn_deleted;
01927 }
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939 static void
01940 subst_asm_stack_regs (rtx insn, stack regstack)
01941 {
01942 rtx body = PATTERN (insn);
01943 int alt;
01944
01945 rtx *note_reg;
01946 rtx **note_loc;
01947 enum reg_note *note_kind;
01948
01949 rtx *clobber_reg = 0;
01950 rtx **clobber_loc = 0;
01951
01952 struct stack_def temp_stack;
01953 int n_notes;
01954 int n_clobbers;
01955 rtx note;
01956 int i;
01957 int n_inputs, n_outputs;
01958
01959 if (! check_asm_stack_operands (insn))
01960 return;
01961
01962
01963
01964
01965 extract_insn (insn);
01966 constrain_operands (1);
01967 alt = which_alternative;
01968
01969 preprocess_constraints ();
01970
01971 n_inputs = get_asm_operand_n_inputs (body);
01972 n_outputs = recog_data.n_operands - n_inputs;
01973
01974 gcc_assert (alt >= 0);
01975
01976
01977 for (i = 0; i < recog_data.n_operands; i++)
01978 if (GET_CODE (recog_data.operand[i]) == SUBREG
01979 && REG_P (SUBREG_REG (recog_data.operand[i])))
01980 {
01981 recog_data.operand_loc[i] = & SUBREG_REG (recog_data.operand[i]);
01982 recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
01983 }
01984
01985
01986
01987 for (i = 0, note = REG_NOTES (insn); note; note = XEXP (note, 1))
01988 i++;
01989
01990 note_reg = alloca (i * sizeof (rtx));
01991 note_loc = alloca (i * sizeof (rtx *));
01992 note_kind = alloca (i * sizeof (enum reg_note));
01993
01994 n_notes = 0;
01995 for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
01996 {
01997 rtx reg = XEXP (note, 0);
01998 rtx *loc = & XEXP (note, 0);
01999
02000 if (GET_CODE (reg) == SUBREG && REG_P (SUBREG_REG (reg)))
02001 {
02002 loc = & SUBREG_REG (reg);
02003 reg = SUBREG_REG (reg);
02004 }
02005
02006 if (STACK_REG_P (reg)
02007 && (REG_NOTE_KIND (note) == REG_DEAD
02008 || REG_NOTE_KIND (note) == REG_UNUSED))
02009 {
02010 note_reg[n_notes] = reg;
02011 note_loc[n_notes] = loc;
02012 note_kind[n_notes] = REG_NOTE_KIND (note);
02013 n_notes++;
02014 }
02015 }
02016
02017
02018
02019 n_clobbers = 0;
02020
02021 if (GET_CODE (body) == PARALLEL)
02022 {
02023 clobber_reg = alloca (XVECLEN (body, 0) * sizeof (rtx));
02024 clobber_loc = alloca (XVECLEN (body, 0) * sizeof (rtx *));
02025
02026 for (i = 0; i < XVECLEN (body, 0); i++)
02027 if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
02028 {
02029 rtx clobber = XVECEXP (body, 0, i);
02030 rtx reg = XEXP (clobber, 0);
02031 rtx *loc = & XEXP (clobber, 0);
02032
02033 if (GET_CODE (reg) == SUBREG && REG_P (SUBREG_REG (reg)))
02034 {
02035 loc = & SUBREG_REG (reg);
02036 reg = SUBREG_REG (reg);
02037 }
02038
02039 if (STACK_REG_P (reg))
02040 {
02041 clobber_reg[n_clobbers] = reg;
02042 clobber_loc[n_clobbers] = loc;
02043 n_clobbers++;
02044 }
02045 }
02046 }
02047
02048 temp_stack = *regstack;
02049
02050
02051
02052 for (i = n_outputs; i < n_outputs + n_inputs; i++)
02053 if (STACK_REG_P (recog_data.operand[i])
02054 && reg_class_subset_p (recog_op_alt[i][alt].cl,
02055 FLOAT_REGS)
02056 && recog_op_alt[i][alt].cl != FLOAT_REGS)
02057 {
02058
02059
02060
02061
02062
02063
02064
02065 int regno = get_hard_regnum (&temp_stack, recog_data.operand[i]);
02066
02067 gcc_assert (regno >= 0);
02068
02069 if ((unsigned int) regno != REGNO (recog_data.operand[i]))
02070 {
02071
02072
02073
02074
02075 int j, k, temp;
02076
02077 k = temp_stack.top - (regno - FIRST_STACK_REG);
02078 j = (temp_stack.top
02079 - (REGNO (recog_data.operand[i]) - FIRST_STACK_REG));
02080
02081 temp = temp_stack.reg[k];
02082 temp_stack.reg[k] = temp_stack.reg[j];
02083 temp_stack.reg[j] = temp;
02084 }
02085 }
02086
02087
02088
02089
02090 change_stack (insn, regstack, &temp_stack, EMIT_BEFORE);
02091
02092
02093
02094
02095 for (i = n_outputs; i < n_outputs + n_inputs; i++)
02096 if (STACK_REG_P (recog_data.operand[i]))
02097 {
02098 int regnum = get_hard_regnum (regstack, recog_data.operand[i]);
02099
02100 gcc_assert (regnum >= 0);
02101
02102 replace_reg (recog_data.operand_loc[i], regnum);
02103 }
02104
02105 for (i = 0; i < n_notes; i++)
02106 if (note_kind[i] == REG_DEAD)
02107 {
02108 int regnum = get_hard_regnum (regstack, note_reg[i]);
02109
02110 gcc_assert (regnum >= 0);
02111
02112 replace_reg (note_loc[i], regnum);
02113 }
02114
02115 for (i = 0; i < n_clobbers; i++)
02116 {
02117
02118
02119 int regnum = get_hard_regnum (regstack, clobber_reg[i]);
02120
02121 if (regnum >= 0)
02122 {
02123
02124
02125
02126
02127 *clobber_loc[i] = FP_MODE_REG (regnum, DFmode);
02128 }
02129 }
02130
02131
02132
02133 for (i = n_outputs; i < n_outputs + n_inputs; i++)
02134 if (STACK_REG_P (recog_data.operand[i]))
02135 {
02136
02137
02138 int j;
02139
02140 for (j = 0; j < n_clobbers; j++)
02141 if (operands_match_p (clobber_reg[j], recog_data.operand[i]))
02142 break;
02143
02144 if (j < n_clobbers || recog_op_alt[i][alt].matches >= 0)
02145 {
02146
02147
02148
02149
02150
02151
02152 CLEAR_HARD_REG_BIT (regstack->reg_set,
02153 regstack->reg[regstack->top]);
02154 regstack->top--;
02155 }
02156 }
02157
02158
02159
02160
02161
02162 for (i = LAST_STACK_REG; i >= FIRST_STACK_REG; i--)
02163 {
02164
02165 int j;
02166
02167 for (j = 0; j < n_outputs; j++)
02168 if (STACK_REG_P (recog_data.operand[j])
02169 && REGNO (recog_data.operand[j]) == (unsigned) i)
02170 {
02171 regstack->reg[++regstack->top] = i;
02172 SET_HARD_REG_BIT (regstack->reg_set, i);
02173 break;
02174 }
02175 }
02176
02177
02178
02179
02180
02181
02182
02183
02184 for (i = 0; i < n_outputs; i++)
02185 if (STACK_REG_P (recog_data.operand[i]))
02186 {
02187 int j;
02188
02189 for (j = 0; j < n_notes; j++)
02190 if (REGNO (recog_data.operand[i]) == REGNO (note_reg[j])
02191 && note_kind[j] == REG_UNUSED)
02192 {
02193 insn = emit_pop_insn (insn, regstack, recog_data.operand[i],
02194 EMIT_AFTER);
02195 break;
02196 }
02197 }
02198
02199 for (i = n_outputs; i < n_outputs + n_inputs; i++)
02200 if (STACK_REG_P (recog_data.operand[i]))
02201 {
02202 int j;
02203
02204 for (j = 0; j < n_notes; j++)
02205 if (REGNO (recog_data.operand[i]) == REGNO (note_reg[j])
02206 && note_kind[j] == REG_DEAD
02207 && TEST_HARD_REG_BIT (regstack->reg_set,
02208 REGNO (recog_data.operand[i])))
02209 {
02210 insn = emit_pop_insn (insn, regstack, recog_data.operand[i],
02211 EMIT_AFTER);
02212 break;
02213 }
02214 }
02215 }
02216
02217
02218
02219
02220
02221
02222
02223 static bool
02224 subst_stack_regs (rtx insn, stack regstack)
02225 {
02226 rtx *note_link, note;
02227 bool control_flow_insn_deleted = false;
02228 int i;
02229
02230 if (CALL_P (insn))
02231 {
02232 int top = regstack->top;
02233
02234
02235
02236
02237
02238 if (top >= 0)
02239 {
02240 straighten_stack (insn, regstack);
02241
02242
02243
02244 while (regstack->top >= 0)
02245 {
02246 CLEAR_HARD_REG_BIT (regstack->reg_set, FIRST_STACK_REG + regstack->top);
02247 regstack->top--;
02248 }
02249 }
02250 }
02251
02252
02253
02254
02255
02256
02257
02258 if (stack_regs_mentioned (insn))
02259 {
02260 int n_operands = asm_noperands (PATTERN (insn));
02261 if (n_operands >= 0)
02262 {
02263
02264
02265
02266
02267 subst_asm_stack_regs (insn, regstack);
02268 return control_flow_insn_deleted;
02269 }
02270
02271 if (GET_CODE (PATTERN (insn)) == PARALLEL)
02272 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
02273 {
02274 if (stack_regs_mentioned_p (XVECEXP (PATTERN (insn), 0, i)))
02275 {
02276 if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == CLOBBER)
02277 XVECEXP (PATTERN (insn), 0, i)
02278 = shallow_copy_rtx (XVECEXP (PATTERN (insn), 0, i));
02279 control_flow_insn_deleted
02280 |= subst_stack_regs_pat (insn, regstack,
02281 XVECEXP (PATTERN (insn), 0, i));
02282 }
02283 }
02284 else
02285 control_flow_insn_deleted
02286 |= subst_stack_regs_pat (insn, regstack, PATTERN (insn));
02287 }
02288
02289
02290
02291
02292 if (NOTE_P (insn) || INSN_DELETED_P (insn))
02293 return control_flow_insn_deleted;
02294
02295
02296
02297 if (CALL_P (insn)
02298 && find_reg_note (insn, REG_NORETURN, NULL))
02299 {
02300 regstack->top = -1;
02301 CLEAR_HARD_REG_SET (regstack->reg_set);
02302 return control_flow_insn_deleted;
02303 }
02304
02305
02306
02307
02308
02309
02310 note_link = ®_NOTES (insn);
02311 for (note = *note_link; note; note = XEXP (note, 1))
02312 if (REG_NOTE_KIND (note) == REG_UNUSED && STACK_REG_P (XEXP (note, 0)))
02313 {
02314 *note_link = XEXP (note, 1);
02315 insn = emit_pop_insn (insn, regstack, XEXP (note, 0), EMIT_AFTER);
02316 }
02317 else
02318 note_link = &XEXP (note, 1);
02319
02320 return control_flow_insn_deleted;
02321 }
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335 static void
02336 change_stack (rtx insn, stack old, stack new, enum emit_where where)
02337 {
02338 int reg;
02339 int update_end = 0;
02340
02341
02342
02343
02344 if (current_block
02345 && starting_stack_p
02346 && where == EMIT_BEFORE)
02347 {
02348 BLOCK_INFO (current_block)->stack_in = *new;
02349 starting_stack_p = false;
02350 *old = *new;
02351 return;
02352 }
02353
02354
02355
02356
02357 if (where == EMIT_AFTER)
02358 {
02359 if (current_block && BB_END (current_block) == insn)
02360 update_end = 1;
02361 insn = NEXT_INSN (insn);
02362 }
02363
02364
02365
02366
02367
02368
02369 if (new->top > 0)
02370 {
02371 bool slots[REG_STACK_SIZE];
02372 int pops[REG_STACK_SIZE];
02373 int next, dest, topsrc;
02374
02375
02376 for (reg = 0; reg <= new->top; reg++)
02377 slots[reg] = TEST_HARD_REG_BIT (new->reg_set, old->reg[reg]);
02378
02379
02380 topsrc = -1;
02381 for (reg = old->top; reg > new->top; reg--)
02382 if (TEST_HARD_REG_BIT (new->reg_set, old->reg[reg]))
02383 {
02384 dest = -1;
02385 for (next = 0; next <= new->top; next++)
02386 if (!slots[next] && new->reg[next] == old->reg[reg])
02387 {
02388
02389
02390 if (next == new->top)
02391 topsrc = reg;
02392 slots[next] = true;
02393 dest = next;
02394 break;
02395 }
02396 pops[reg] = dest;
02397 }
02398 else
02399 pops[reg] = reg;
02400
02401
02402
02403
02404
02405
02406 if (topsrc != -1)
02407 for (reg = 0; reg < new->top; reg++)
02408 if (!slots[reg])
02409 {
02410 pops[topsrc] = reg;
02411 slots[new->top] = false;
02412 slots[reg] = true;
02413 break;
02414 }
02415
02416
02417 next = new->top;
02418 for (reg = old->top; reg > new->top; reg--)
02419 {
02420 dest = pops[reg];
02421 if (dest == -1)
02422 {
02423
02424 while (slots[next])
02425 next--;
02426 dest = next--;
02427 }
02428 emit_pop_insn (insn, old, FP_MODE_REG (old->reg[dest], DFmode),
02429 EMIT_BEFORE);
02430 }
02431 }
02432 else
02433 {
02434
02435
02436
02437 int live, next;
02438
02439 live = 0;
02440 for (reg = 0; reg <= old->top; reg++)
02441 if (TEST_HARD_REG_BIT (new->reg_set, old->reg[reg]))
02442 live++;
02443
02444 next = live;
02445 while (old->top >= live)
02446 if (TEST_HARD_REG_BIT (new->reg_set, old->reg[old->top]))
02447 {
02448 while (TEST_HARD_REG_BIT (new->reg_set, old->reg[next]))
02449 next--;
02450 emit_pop_insn (insn, old, FP_MODE_REG (old->reg[next], DFmode),
02451 EMIT_BEFORE);
02452 }
02453 else
02454 emit_pop_insn (insn, old, FP_MODE_REG (old->reg[old->top], DFmode),
02455 EMIT_BEFORE);
02456 }
02457
02458 if (new->top == -2)
02459 {
02460
02461
02462
02463 new->top = old->top;
02464 memcpy (new->reg, old->reg, sizeof (new->reg));
02465 }
02466 else
02467 {
02468
02469
02470
02471
02472
02473
02474 GO_IF_HARD_REG_EQUAL (old->reg_set, new->reg_set, win);
02475 gcc_unreachable ();
02476 win:
02477 gcc_assert (old->top == new->top);
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488 if (new->top != -1)
02489 do
02490 {
02491
02492
02493
02494 while (old->reg[old->top] != new->reg[new->top])
02495 {
02496 for (reg = new->top; reg >= 0; reg--)
02497 if (new->reg[reg] == old->reg[old->top])
02498 break;
02499
02500 gcc_assert (reg != -1);
02501
02502 emit_swap_insn (insn, old,
02503 FP_MODE_REG (old->reg[reg], DFmode));
02504 }
02505
02506
02507
02508
02509
02510 for (reg = new->top; reg >= 0; reg--)
02511 if (new->reg[reg] != old->reg[reg])
02512 {
02513 emit_swap_insn (insn, old,
02514 FP_MODE_REG (old->reg[reg], DFmode));
02515 break;
02516 }
02517 } while (reg >= 0);
02518
02519
02520
02521 for (reg = old->top; reg >= 0; reg--)
02522 gcc_assert (old->reg[reg] == new->reg[reg]);
02523 }
02524
02525 if (update_end)
02526 BB_END (current_block) = PREV_INSN (insn);
02527 }
02528
02529
02530
02531 static void
02532 print_stack (FILE *file, stack s)
02533 {
02534 if (! file)
02535 return;
02536
02537 if (s->top == -2)
02538 fprintf (file, "uninitialized\n");
02539 else if (s->top == -1)
02540 fprintf (file, "empty\n");
02541 else
02542 {
02543 int i;
02544 fputs ("[ ", file);
02545 for (i = 0; i <= s->top; ++i)
02546 fprintf (file, "%d ", s->reg[i]);
02547 fputs ("]\n", file);
02548 }
02549 }
02550
02551
02552
02553
02554
02555
02556
02557
02558
02559 static int
02560 convert_regs_entry (void)
02561 {
02562 int inserted = 0;
02563 edge e;
02564 edge_iterator ei;
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
02576 {
02577 basic_block block = e->dest;
02578 block_info bi = BLOCK_INFO (block);
02579 int reg, top = -1;
02580
02581 for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; --reg)
02582 if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg))
02583 {
02584 rtx init;
02585
02586 bi->stack_in.reg[++top] = reg;
02587
02588 init = gen_rtx_SET (VOIDmode,
02589 FP_MODE_REG (FIRST_STACK_REG, SFmode),
02590 not_a_num);
02591 insert_insn_on_edge (init, e);
02592 inserted = 1;
02593 }
02594
02595 bi->stack_in.top = top;
02596 }
02597
02598 return inserted;
02599 }
02600
02601
02602
02603
02604 static void
02605 convert_regs_exit (void)
02606 {
02607 int value_reg_low, value_reg_high;
02608 stack output_stack;
02609 rtx retvalue;
02610
02611 retvalue = stack_result (current_function_decl);
02612 value_reg_low = value_reg_high = -1;
02613 if (retvalue)
02614 {
02615 value_reg_low = REGNO (retvalue);
02616 value_reg_high = value_reg_low
02617 + hard_regno_nregs[value_reg_low][GET_MODE (retvalue)] - 1;
02618 }
02619
02620 output_stack = &BLOCK_INFO (EXIT_BLOCK_PTR)->stack_in;
02621 if (value_reg_low == -1)
02622 output_stack->top = -1;
02623 else
02624 {
02625 int reg;
02626
02627 output_stack->top = value_reg_high - value_reg_low;
02628 for (reg = value_reg_low; reg <= value_reg_high; ++reg)
02629 {
02630 output_stack->reg[value_reg_high - reg] = reg;
02631 SET_HARD_REG_BIT (output_stack->reg_set, reg);
02632 }
02633 }
02634 }
02635
02636
02637
02638
02639 static void
02640 propagate_stack (edge e)
02641 {
02642 stack src_stack = &BLOCK_INFO (e->src)->stack_out;
02643 stack dest_stack = &BLOCK_INFO (e->dest)->stack_in;
02644 int reg;
02645
02646
02647
02648 dest_stack->top = -1;
02649 for (reg = 0; reg <= src_stack->top; ++reg)
02650 if (TEST_HARD_REG_BIT (dest_stack->reg_set, src_stack->reg[reg]))
02651 dest_stack->reg[++dest_stack->top] = src_stack->reg[reg];
02652 }
02653
02654
02655
02656
02657
02658
02659 static bool
02660 compensate_edge (edge e)
02661 {
02662 basic_block source = e->src, target = e->dest;
02663 stack target_stack = &BLOCK_INFO (target)->stack_in;
02664 stack source_stack = &BLOCK_INFO (source)->stack_out;
02665 struct stack_def regstack;
02666 int reg;
02667
02668 if (dump_file)
02669 fprintf (dump_file, "Edge %d->%d: ", source->index, target->index);
02670
02671 gcc_assert (target_stack->top != -2);
02672
02673
02674 if (target_stack->top == source_stack->top)
02675 {
02676 for (reg = target_stack->top; reg >= 0; --reg)
02677 if (target_stack->reg[reg] != source_stack->reg[reg])
02678 break;
02679
02680 if (reg == -1)
02681 {
02682 if (dump_file)
02683 fprintf (dump_file, "no changes needed\n");
02684 return false;
02685 }
02686 }
02687
02688 if (dump_file)
02689 {
02690 fprintf (dump_file, "correcting stack to ");
02691 print_stack (dump_file, target_stack);
02692 }
02693
02694
02695
02696 if (e->flags & EDGE_ABNORMAL_CALL)
02697 {
02698
02699
02700
02701
02702 gcc_assert (source_stack->top == 0 || source_stack->top == 1);
02703 gcc_assert (target_stack->top == -1);
02704 return false;
02705 }
02706
02707
02708
02709
02710 if (e->flags & EDGE_EH)
02711 {
02712 gcc_assert (target_stack->top == -1);
02713 return false;
02714 }
02715
02716
02717
02718
02719 gcc_assert (! (e->flags & EDGE_ABNORMAL));
02720
02721
02722 regstack = *source_stack;
02723
02724
02725
02726
02727
02728 if (EDGE_COUNT (source->succs) == 1)
02729 {
02730 current_block = source;
02731 change_stack (BB_END (source), ®stack, target_stack,
02732 (JUMP_P (BB_END (source)) ? EMIT_BEFORE : EMIT_AFTER));
02733 }
02734 else
02735 {
02736 rtx seq, after;
02737
02738 current_block = NULL;
02739 start_sequence ();
02740
02741
02742 after = emit_note (NOTE_INSN_DELETED);
02743
02744 change_stack (after, ®stack, target_stack, EMIT_BEFORE);
02745
02746 seq = get_insns ();
02747 end_sequence ();
02748
02749 insert_insn_on_edge (seq, e);
02750 return true;
02751 }
02752 return false;
02753 }
02754
02755
02756
02757
02758
02759 static bool
02760 compensate_edges (void)
02761 {
02762 bool inserted = false;
02763 basic_block bb;
02764
02765 starting_stack_p = false;
02766
02767 FOR_EACH_BB (bb)
02768 if (bb != ENTRY_BLOCK_PTR)
02769 {
02770 edge e;
02771 edge_iterator ei;
02772
02773 FOR_EACH_EDGE (e, ei, bb->succs)
02774 inserted |= compensate_edge (e);
02775 }
02776 return inserted;
02777 }
02778
02779
02780
02781
02782
02783
02784 static edge
02785 better_edge (edge e1, edge e2)
02786 {
02787 if (!e1)
02788 return e2;
02789
02790 if (EDGE_FREQUENCY (e1) > EDGE_FREQUENCY (e2))
02791 return e1;
02792 if (EDGE_FREQUENCY (e1) < EDGE_FREQUENCY (e2))
02793 return e2;
02794
02795 if (e1->count > e2->count)
02796 return e1;
02797 if (e1->count < e2->count)
02798 return e2;
02799
02800
02801
02802
02803 if (EDGE_CRITICAL_P (e1) != EDGE_CRITICAL_P (e2))
02804 return EDGE_CRITICAL_P (e1) ? e1 : e2;
02805
02806
02807 return (e1->src->index < e2->src->index) ? e1 : e2;
02808 }
02809
02810
02811
02812 static void
02813 convert_regs_1 (basic_block block)
02814 {
02815 struct stack_def regstack;
02816 block_info bi = BLOCK_INFO (block);
02817 int reg;
02818 rtx insn, next;
02819 bool control_flow_insn_deleted = false;
02820
02821 any_malformed_asm = false;
02822
02823
02824 if (bi->stack_in.top == -2)
02825 {
02826 edge e, beste = NULL;
02827 edge_iterator ei;
02828
02829
02830
02831 FOR_EACH_EDGE (e, ei, block->preds)
02832 if (BLOCK_INFO (e->src)->done)
02833 beste = better_edge (beste, e);
02834
02835 if (beste)
02836 propagate_stack (beste);
02837 else
02838 {
02839
02840 bi->stack_in.top = -1;
02841 for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; --reg)
02842 if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg))
02843 bi->stack_in.reg[++bi->stack_in.top] = reg;
02844 }
02845 }
02846
02847 if (dump_file)
02848 {
02849 fprintf (dump_file, "\nBasic block %d\nInput stack: ", block->index);
02850 print_stack (dump_file, &bi->stack_in);
02851 }
02852
02853
02854
02855 current_block = block;
02856 next = BB_HEAD (block);
02857 regstack = bi->stack_in;
02858 starting_stack_p = true;
02859
02860 do
02861 {
02862 insn = next;
02863 next = NEXT_INSN (insn);
02864
02865
02866 gcc_assert (next);
02867 if (insn == BB_END (block))
02868 next = NULL;
02869
02870
02871
02872 if (stack_regs_mentioned (insn)
02873 || CALL_P (insn))
02874 {
02875 if (dump_file)
02876 {
02877 fprintf (dump_file, " insn %d input stack: ",
02878 INSN_UID (insn));
02879 print_stack (dump_file, ®stack);
02880 }
02881 control_flow_insn_deleted |= subst_stack_regs (insn, ®stack);
02882 starting_stack_p = false;
02883 }
02884 }
02885 while (next);
02886
02887 if (dump_file)
02888 {
02889 fprintf (dump_file, "Expected live registers [");
02890 for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; ++reg)
02891 if (TEST_HARD_REG_BIT (bi->out_reg_set, reg))
02892 fprintf (dump_file, " %d", reg);
02893 fprintf (dump_file, " ]\nOutput stack: ");
02894 print_stack (dump_file, ®stack);
02895 }
02896
02897 insn = BB_END (block);
02898 if (JUMP_P (insn))
02899 insn = PREV_INSN (insn);
02900
02901
02902
02903
02904
02905 for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; ++reg)
02906 {
02907 if (TEST_HARD_REG_BIT (bi->out_reg_set, reg)
02908 && ! TEST_HARD_REG_BIT (regstack.reg_set, reg))
02909 {
02910 rtx set;
02911
02912 if (dump_file)
02913 fprintf (dump_file, "Emitting insn initializing reg %d\n", reg);
02914
02915 set = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, SFmode), not_a_num);
02916 insn = emit_insn_after (set, insn);
02917 control_flow_insn_deleted |= subst_stack_regs (insn, ®stack);
02918 }
02919 }
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938 if (control_flow_insn_deleted)
02939 purge_dead_edges (block);
02940
02941
02942
02943
02944 GO_IF_HARD_REG_EQUAL (regstack.reg_set, bi->out_reg_set, win);
02945 gcc_assert (any_malformed_asm);
02946 win:
02947 bi->stack_out = regstack;
02948 bi->done = true;
02949 }
02950
02951
02952
02953 static void
02954 convert_regs_2 (basic_block block)
02955 {
02956 basic_block *stack, *sp;
02957
02958
02959
02960
02961
02962 stack = XNEWVEC (basic_block, n_basic_blocks);
02963 sp = stack;
02964
02965 *sp++ = block;
02966
02967 do
02968 {
02969 edge e;
02970 edge_iterator ei;
02971
02972 block = *--sp;
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987 FOR_EACH_EDGE (e, ei, block->succs)
02988 if (! (e->flags & EDGE_DFS_BACK))
02989 {
02990 BLOCK_INFO (e->dest)->predecessors--;
02991 if (!BLOCK_INFO (e->dest)->predecessors)
02992 *sp++ = e->dest;
02993 }
02994
02995 convert_regs_1 (block);
02996 }
02997 while (sp != stack);
02998
02999 free (stack);
03000 }
03001
03002
03003
03004
03005
03006 static void
03007 convert_regs (void)
03008 {
03009 int inserted;
03010 basic_block b;
03011 edge e;
03012 edge_iterator ei;
03013
03014
03015 inserted = convert_regs_entry ();
03016
03017
03018 convert_regs_exit ();
03019 BLOCK_INFO (EXIT_BLOCK_PTR)->done = 1;
03020
03021
03022
03023
03024
03025
03026 FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
03027 convert_regs_2 (e->dest);
03028
03029
03030
03031 FOR_EACH_BB (b)
03032 {
03033 block_info bi = BLOCK_INFO (b);
03034
03035 if (! bi->done)
03036 convert_regs_2 (b);
03037 }
03038
03039 inserted |= compensate_edges ();
03040
03041 clear_aux_for_blocks ();
03042
03043 fixup_abnormal_edges ();
03044 if (inserted)
03045 commit_edge_insertions ();
03046
03047 if (dump_file)
03048 fputc ('\n', dump_file);
03049 }
03050
03051
03052
03053
03054
03055
03056
03057
03058
03059 static bool
03060 reg_to_stack (void)
03061 {
03062 basic_block bb;
03063 int i;
03064 int max_uid;
03065
03066
03067 if (stack_regs_mentioned_data != NULL)
03068 VEC_free (char, heap, stack_regs_mentioned_data);
03069
03070
03071
03072 for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
03073 if (regs_ever_live[i])
03074 break;
03075 if (i > LAST_STACK_REG)
03076 return false;
03077
03078
03079
03080
03081
03082 if (!optimize
03083 || ((flag_sched2_use_superblocks || flag_sched2_use_traces)
03084 && flag_schedule_insns_after_reload))
03085 {
03086 count_or_remove_death_notes (NULL, 1);
03087 life_analysis (PROP_DEATH_NOTES);
03088 }
03089 mark_dfs_back_edges ();
03090
03091
03092 alloc_aux_for_blocks (sizeof (struct block_info_def));
03093 FOR_EACH_BB (bb)
03094 {
03095 block_info bi = BLOCK_INFO (bb);
03096 edge_iterator ei;
03097 edge e;
03098 int reg;
03099
03100 FOR_EACH_EDGE (e, ei, bb->preds)
03101 if (!(e->flags & EDGE_DFS_BACK)
03102 && e->src != ENTRY_BLOCK_PTR)
03103 bi->predecessors++;
03104
03105
03106 bi->stack_in.top = -2;
03107
03108
03109 for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++)
03110 {
03111 if (REGNO_REG_SET_P (bb->il.rtl->global_live_at_end, reg))
03112 SET_HARD_REG_BIT (bi->out_reg_set, reg);
03113 if (REGNO_REG_SET_P (bb->il.rtl->global_live_at_start, reg))
03114 SET_HARD_REG_BIT (bi->stack_in.reg_set, reg);
03115 }
03116 }
03117
03118
03119 for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
03120 {
03121 enum machine_mode mode;
03122 for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
03123 mode != VOIDmode;
03124 mode = GET_MODE_WIDER_MODE (mode))
03125 FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
03126 for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT);
03127 mode != VOIDmode;
03128 mode = GET_MODE_WIDER_MODE (mode))
03129 FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
03130 }
03131
03132 ix86_flags_rtx = gen_rtx_REG (CCmode, FLAGS_REG);
03133
03134
03135
03136
03137
03138
03139
03140
03141 if (flag_pic)
03142 not_a_num = CONST0_RTX (SFmode);
03143 else
03144 {
03145 not_a_num = gen_lowpart (SFmode, GEN_INT (0x7fc00000));
03146 not_a_num = force_const_mem (SFmode, not_a_num);
03147 }
03148
03149
03150 max_uid = get_max_uid ();
03151 stack_regs_mentioned_data = VEC_alloc (char, heap, max_uid + 1);
03152 memset (VEC_address (char, stack_regs_mentioned_data),
03153 0, sizeof (char) * max_uid + 1);
03154
03155 convert_regs ();
03156
03157 free_aux_for_blocks ();
03158 return true;
03159 }
03160 #endif
03161
03162 static bool
03163 gate_handle_stack_regs (void)
03164 {
03165 #ifdef STACK_REGS
03166 return 1;
03167 #else
03168 return 0;
03169 #endif
03170 }
03171
03172
03173
03174 static unsigned int
03175 rest_of_handle_stack_regs (void)
03176 {
03177 #ifdef STACK_REGS
03178 if (reg_to_stack () && optimize)
03179 {
03180 regstack_completed = 1;
03181 if (cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK
03182 | (flag_crossjumping ? CLEANUP_CROSSJUMP : 0))
03183 && (flag_reorder_blocks || flag_reorder_blocks_and_partition))
03184 {
03185 reorder_basic_blocks (0);
03186 cleanup_cfg (CLEANUP_EXPENSIVE | CLEANUP_POST_REGSTACK);
03187 }
03188 }
03189 else
03190 regstack_completed = 1;
03191 #endif
03192 return 0;
03193 }
03194
03195 struct tree_opt_pass pass_stack_regs =
03196 {
03197 "stack",
03198 gate_handle_stack_regs,
03199 rest_of_handle_stack_regs,
03200 NULL,
03201 NULL,
03202 0,
03203 TV_REG_STACK,
03204 0,
03205 0,
03206 0,
03207 0,
03208 TODO_dump_func |
03209 TODO_ggc_collect,
03210 'k'
03211 };