aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/rs6000/rs6000.c11
-rw-r--r--gcc/config/rs6000/rs6000.md38
-rw-r--r--gcc/integrate.c16
-rw-r--r--gcc/reload1.c14
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 < &reg_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