diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 11 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 38 | ||||
-rw-r--r-- | gcc/integrate.c | 16 | ||||
-rw-r--r-- | gcc/reload1.c | 14 |
4 files changed, 55 insertions, 24 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 47e9342..3d4683b 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1018,6 +1018,17 @@ print_operand (file, x, code) RS6000_OUTPUT_BASENAME (file, XSTR (x, 0)); return; + case 'A': + /* If X is a constant integer whose low-order 5 bits are zero, + write 'l'. Otherwise, write 'r'. This is a kludge to fix a bug + in the RS/6000 assembler where "sri" with a zero shift count + write a trash instruction. */ + if (GET_CODE (x) != CONST_INT && (INTVAL (x) & 31) == 0) + fprintf (file, "l"); + else + fprintf (file, "r"); + return; + case 0: if (GET_CODE (x) == REG) fprintf (file, "%s", reg_names[REGNO (x)]); diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 14c3edd..167363b 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -22,7 +22,7 @@ ;; Define an insn type attribute. This is used in function unit delay ;; computations. -(define_attr "type" "load,integer,fp,compare,delayed_compare,fpcompare" +(define_attr "type" "load,integer,fp,compare,delayed_compare,fpcompare,mtlr" (const_string "integer")) ;; Memory delivers its result in two cycles. @@ -40,6 +40,9 @@ ;; Floating-point comparisons take eight cycles. (define_function_unit "compare" 1 0 (eq_attr "type" "fpcompare") 8 0) + +;; Branches on LR cannot be done until five cycles after LR is set. +(define_function_unit "branch" 1 0 (eq_attr "type" "mtlr") 5 0) ;; Start with fixed-point load and store insns. Here we put only the more ;; complex forms. Basic data transfer is done later. @@ -328,7 +331,7 @@ (define_insn "" [(set (match_operand:SI 0 "gen_reg_operand" "=r") (if_then_else:SI (gt (match_operand:SI 1 "gen_reg_operand" "r") - (match_operand:SI 2 "reg_or_short_operand" "r")) + (match_operand:SI 2 "reg_or_short_operand" "rI")) (const_int 0) (minus:SI (match_dup 2) (match_dup 1))))] "" @@ -338,7 +341,7 @@ [(set (match_operand:CC 0 "cc_reg_operand" "=x") (compare:CC (if_then_else:SI (gt (match_operand:SI 1 "gen_reg_operand" "r") - (match_operand:SI 2 "reg_or_short_operand" "r")) + (match_operand:SI 2 "reg_or_short_operand" "rI")) (const_int 0) (minus:SI (match_dup 2) (match_dup 1))) (const_int 0))) @@ -351,7 +354,7 @@ [(set (match_operand:CC 3 "cc_reg_operand" "=x") (compare:CC (if_then_else:SI (gt (match_operand:SI 1 "gen_reg_operand" "r") - (match_operand:SI 2 "reg_or_short_operand" "r")) + (match_operand:SI 2 "reg_or_short_operand" "rI")) (const_int 0) (minus:SI (match_dup 2) (match_dup 1))) (const_int 0))) @@ -1277,6 +1280,8 @@ "rlinm. %0,%h1,%h2,%m3,%M3" [(set_attr "type" "delayed_compare")]) +;; The RS/6000 assembler mis-handles "sri x,x,0", so write that case as +;; "sli x,x,0". (define_insn "lshrsi3" [(set (match_operand:SI 0 "gen_reg_operand" "=r,r") (lshiftrt:SI (match_operand:SI 1 "gen_reg_operand" "r,r") @@ -1285,7 +1290,7 @@ "" "@ sre %0,%1,%2 - sri %0,%1,%h2") + s%A2i %0,%1,%h2") (define_insn "" [(set (match_operand:CC 0 "cc_reg_operand" "=x,x") @@ -1297,7 +1302,7 @@ "" "@ sre. %3,%1,%2 - sri. %3,%1,%h2" + s%A2i. %3,%1,%h2" [(set_attr "type" "delayed_compare")]) (define_insn "" @@ -1311,7 +1316,7 @@ "" "@ sre. %0,%1,%2 - sri. %0,%1,%h2" + s%A2i. %0,%1,%h2" [(set_attr "type" "delayed_compare")]) (define_insn "" @@ -1936,19 +1941,19 @@ sli %0,%L1,%h2\;cal %L0,0(0) sl%I2q %L0,%L1,%h2\;sll%I2q %0,%1,%h2 sl%I2q %L0,%L1,%h2\;sll%I2q %0,%1,%h2 - sl%I2q %L0,%L1,%h2\;sll%I2q %0,%1,%h2 ") + sl%I2q %L0,%L1,%h2\;sll%I2q %0,%1,%h2") (define_insn "lshrdi3" - [(set (match_operand:DI 0 "gen_reg_operand" "=r,r,r,&r") + [(set (match_operand:DI 0 "gen_reg_operand" "=&r,r,r,&r") (lshiftrt:DI (match_operand:DI 1 "gen_reg_operand" "r,r,0,r") (match_operand:SI 2 "reg_or_cint_operand" "M,i,r,r"))) (clobber (match_scratch:SI 3 "=X,q,q,q"))] "" "@ - cal %0,0(0)\;sri %L0,%1,%h2 - sr%I2q %L0,%L1,%2\;srl%I2q %0,%1,%2 - sr%I2q %L0,%L1,%2\;srl%I2q %0,%1,%2 - sr%I2q %L0,%L1,%2\;srl%I2q %0,%1,%2 ") + cal %0,0(0)\;s%A2i %L0,%1,%h2 + s%A2%I2q %L0,%L1,%2\;srl%I2q %0,%1,%2 + s%A2%I2q %L0,%L1,%2\;srl%I2q %0,%1,%2 + s%A2%I2q %L0,%L1,%2\;srl%I2q %0,%1,%2") ;; Shift by a variable amount is too complex to be worth open-coding. We ;; just handle shifts by constants. @@ -2007,8 +2012,8 @@ }") (define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r,r,*h") - (match_operand:SI 1 "input_operand" "r,m,r,I,J,*h,r"))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,r,r,r,*c*q,*l") + (match_operand:SI 1 "input_operand" "r,m,r,I,J,*h,r,r"))] "gen_reg_operand (operands[0], SImode) || gen_reg_operand (operands[1], SImode)" "@ @@ -2018,8 +2023,9 @@ cal %0,%1(0) cau %0,0,%u1 mf%1 %0 + mt%0 %1 mt%0 %1" - [(set_attr "type" "*,load,*,*,*,*,*")]) + [(set_attr "type" "*,load,*,*,*,*,*,mtlr")]) (define_insn "" [(set (match_operand:CC 2 "cc_reg_operand" "=x") diff --git a/gcc/integrate.c b/gcc/integrate.c index 3026203..05b1143 100644 --- a/gcc/integrate.c +++ b/gcc/integrate.c @@ -1775,14 +1775,14 @@ copy_rtx_and_substitute (orig, map) rounded = CEIL_ROUND (size, BIGGEST_ALIGNMENT / BITS_PER_UNIT); loc = plus_constant (loc, rounded); #endif - map->reg_map[regno] = force_operand (loc, 0); - map->const_equiv_map[regno] = loc; - map->const_age_map[regno] = CONST_AGE_PARM; + map->reg_map[regno] = temp = force_operand (loc, 0); + map->const_equiv_map[REGNO (temp)] = loc; + map->const_age_map[REGNO (temp)] = CONST_AGE_PARM; seq = gen_sequence (); end_sequence (); emit_insn_after (seq, map->insns_at_start); - return map->reg_map[regno]; + return temp; } else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM) { @@ -1794,14 +1794,14 @@ copy_rtx_and_substitute (orig, map) start_sequence (); loc = assign_stack_temp (BLKmode, size, 1); loc = XEXP (loc, 0); - map->reg_map[regno] = force_operand (loc, 0); - map->const_equiv_map[regno] = loc; - map->const_age_map[regno] = CONST_AGE_PARM; + map->reg_map[regno] = temp = force_operand (loc, 0); + map->const_equiv_map[REGNO (temp)] = loc; + map->const_age_map[REGNO (temp)] = CONST_AGE_PARM; seq = gen_sequence (); end_sequence (); emit_insn_after (seq, map->insns_at_start); - return map->reg_map[regno]; + return temp; } else if (REG_FUNCTION_VALUE_P (orig)) { diff --git a/gcc/reload1.c b/gcc/reload1.c index e26cefe..c6f46b1 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -1367,6 +1367,20 @@ reload (first, global, dumpfile) } } + /* See if anything that happened changes which eliminations are valid. + For example, on the Sparc, whether or not the frame pointer can + be eliminated can depend on what registers have been used. We need + not check some conditions again (such as flag_omit_frame_pointer) + since they can't have changed. */ + + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) + if ((ep->from == FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED) +#ifdef ELIMINABLE_REGS + || ! CAN_ELIMINATE (ep->from, ep->to) +#endif + ) + ep->can_eliminate = 0; + /* Look for the case where we have discovered that we can't replace register A with register B and that means that we will now be trying to replace register A with register C. This means we can |