aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2001-09-05 07:46:54 +0000
committerRichard Henderson <rth@redhat.com>2001-09-05 07:46:54 +0000
commit49fc6118bf8eb08073f328bfe33721dbbc1e70c6 (patch)
tree55b1a620876a17f773e34274fc2a7a1835180ccb
parentbc4b824049d8b075fbe8fd7478fcc33bdfd1af33 (diff)
* config/alpha/alpha.c (alpha_expand_mov, alpha_expand_mov_nobwx):
New functions split out of md file expanders. * config/alpha/alpha-protos.h: Declare them. * config/alpha/alpha.md (movqi, movhi, movsi, movdi): Use them. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@45399 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/alpha/alpha-protos.h2
-rw-r--r--gcc/config/alpha/alpha.c176
-rw-r--r--gcc/config/alpha/alpha.md308
4 files changed, 197 insertions, 296 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6059426da08..742e21efa99 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2001-09-05 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c (alpha_expand_mov, alpha_expand_mov_nobwx):
+ New functions split out of md file expanders.
+ * config/alpha/alpha-protos.h: Declare them.
+ * config/alpha/alpha.md (movqi, movhi, movsi, movdi): Use them.
+
2001-09-05 Neil Booth <neil@daikokuya.demon.co.uk>
* cppmacro.c (funlike_invocation_p): No need to restore context.
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index 6696a18be30..025f3af5e87 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -87,6 +87,8 @@ extern rtx alpha_emit_set_const PARAMS ((rtx, enum machine_mode,
HOST_WIDE_INT, int));
extern rtx alpha_emit_set_long_const PARAMS ((rtx, HOST_WIDE_INT,
HOST_WIDE_INT));
+extern bool alpha_expand_mov PARAMS ((enum machine_mode, rtx *));
+extern bool alpha_expand_mov_nobwx PARAMS ((enum machine_mode, rtx *));
extern void alpha_emit_floatuns PARAMS ((rtx[]));
extern rtx alpha_emit_conditional_branch PARAMS ((enum rtx_code));
extern rtx alpha_emit_setcc PARAMS ((enum rtx_code));
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index a7ed11691b1..ca4be61da34 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -1746,6 +1746,182 @@ alpha_emit_set_long_const (target, c1, c2)
return target;
}
+/* Expand a move instruction; return true if all work is done.
+ We don't handle non-bwx subword loads here. */
+
+bool
+alpha_expand_mov (mode, operands)
+ enum machine_mode mode;
+ rtx *operands;
+{
+ /* If the output is not a register, the input must be. */
+ if (GET_CODE (operands[0]) == MEM
+ && ! reg_or_0_operand (operands[1], mode))
+ operands[1] = force_reg (mode, operands[1]);
+
+ /* Early out for non-constants and valid constants. */
+ if (! CONSTANT_P (operands[1]) || input_operand (operands[1], mode))
+ return false;
+
+ /* Split large integers. */
+ if (GET_CODE (operands[1]) == CONST_INT
+ || GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ HOST_WIDE_INT i0, i1;
+ rtx temp;
+
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ i0 = INTVAL (operands[1]);
+ i1 = -(i0 < 0);
+ }
+ else if (HOST_BITS_PER_WIDE_INT >= 64)
+ {
+ i0 = CONST_DOUBLE_LOW (operands[1]);
+ i1 = -(i0 < 0);
+ }
+ else
+ {
+ i0 = CONST_DOUBLE_LOW (operands[1]);
+ i1 = CONST_DOUBLE_HIGH (operands[1]);
+ }
+
+ if (HOST_BITS_PER_WIDE_INT >= 64 || i1 == -(i0 < 0))
+ temp = alpha_emit_set_const (operands[0], mode, i0, 3);
+
+ if (!temp && TARGET_BUILD_CONSTANTS)
+ temp = alpha_emit_set_long_const (operands[0], i0, i1);
+
+ if (temp)
+ {
+ if (rtx_equal_p (operands[0], temp))
+ return true;
+ operands[1] = temp;
+ return false;
+ }
+ }
+
+ /* Otherwise we've nothing left but to drop the thing to memory. */
+ operands[1] = force_const_mem (DImode, operands[1]);
+ if (reload_in_progress)
+ {
+ emit_move_insn (operands[0], XEXP (operands[1], 0));
+ operands[1] = copy_rtx (operands[1]);
+ XEXP (operands[1], 0) = operands[0];
+ }
+ else
+ operands[1] = validize_mem (operands[1]);
+ return false;
+}
+
+/* Expand a non-bwx QImode or HImode move instruction;
+ return true if all work is done. */
+
+bool
+alpha_expand_mov_nobwx (mode, operands)
+ enum machine_mode mode;
+ rtx *operands;
+{
+ /* If the output is not a register, the input must be. */
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (mode, operands[1]);
+
+ /* Handle four memory cases, unaligned and aligned for either the input
+ or the output. The only case where we can be called during reload is
+ for aligned loads; all other cases require temporaries. */
+
+ if (GET_CODE (operands[1]) == MEM
+ || (GET_CODE (operands[1]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[1])) == MEM)
+ || (reload_in_progress && GET_CODE (operands[1]) == REG
+ && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
+ || (reload_in_progress && GET_CODE (operands[1]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[1])) == REG
+ && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER))
+ {
+ if (aligned_memory_operand (operands[1], mode))
+ {
+ if (reload_in_progress)
+ {
+ emit_insn ((mode == QImode
+ ? gen_reload_inqi_help
+ : gen_reload_inhi_help)
+ (operands[0], operands[1],
+ gen_rtx_REG (SImode, REGNO (operands[0]))));
+ }
+ else
+ {
+ rtx aligned_mem, bitnum;
+ rtx scratch = gen_reg_rtx (SImode);
+
+ get_aligned_mem (operands[1], &aligned_mem, &bitnum);
+
+ emit_insn ((mode == QImode
+ ? gen_aligned_loadqi
+ : gen_aligned_loadhi)
+ (operands[0], aligned_mem, bitnum, scratch));
+ }
+ }
+ else
+ {
+ /* Don't pass these as parameters since that makes the generated
+ code depend on parameter evaluation order which will cause
+ bootstrap failures. */
+
+ rtx temp1 = gen_reg_rtx (DImode);
+ rtx temp2 = gen_reg_rtx (DImode);
+ rtx seq = ((mode == QImode
+ ? gen_unaligned_loadqi
+ : gen_unaligned_loadhi)
+ (operands[0], get_unaligned_address (operands[1], 0),
+ temp1, temp2));
+
+ alpha_set_memflags (seq, operands[1]);
+ emit_insn (seq);
+ }
+ return true;
+ }
+
+ if (GET_CODE (operands[0]) == MEM
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == MEM)
+ || (reload_in_progress && GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
+ || (reload_in_progress && GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER))
+ {
+ if (aligned_memory_operand (operands[0], mode))
+ {
+ rtx aligned_mem, bitnum;
+ rtx temp1 = gen_reg_rtx (SImode);
+ rtx temp2 = gen_reg_rtx (SImode);
+
+ get_aligned_mem (operands[0], &aligned_mem, &bitnum);
+
+ emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
+ temp1, temp2));
+ }
+ else
+ {
+ rtx temp1 = gen_reg_rtx (DImode);
+ rtx temp2 = gen_reg_rtx (DImode);
+ rtx temp3 = gen_reg_rtx (DImode);
+ rtx seq = ((mode == QImode
+ ? gen_unaligned_storeqi
+ : gen_unaligned_storehi)
+ (get_unaligned_address (operands[0], 0),
+ operands[1], temp1, temp2, temp3));
+
+ alpha_set_memflags (seq, operands[0]);
+ emit_insn (seq);
+ }
+ return true;
+ }
+
+ return false;
+}
+
/* Generate an unsigned DImode to FP conversion. This is the same code
optabs would emit if we didn't have TFmode patterns.
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 3e7d4f52dc3..87458038c4b 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -4809,19 +4809,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:SI 1 "general_operand" ""))]
""
{
- if (GET_CODE (operands[0]) == MEM
- && ! reg_or_0_operand (operands[1], SImode))
- operands[1] = force_reg (SImode, operands[1]);
-
- if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode))
- ;
- else if (GET_CODE (operands[1]) == CONST_INT)
- {
- operands[1]
- = alpha_emit_set_const (operands[0], SImode, INTVAL (operands[1]), 3);
- if (rtx_equal_p (operands[0], operands[1]))
- DONE;
- }
+ if (alpha_expand_mov (SImode, operands))
+ DONE;
})
;; Split a load of a large constant into the appropriate two-insn
@@ -4901,68 +4890,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:DI 1 "general_operand" ""))]
""
{
- rtx tem;
-
- if (GET_CODE (operands[0]) == MEM
- && ! reg_or_0_operand (operands[1], DImode))
- operands[1] = force_reg (DImode, operands[1]);
-
- if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode))
- ;
- else if (GET_CODE (operands[1]) == CONST_INT
- && (tem = alpha_emit_set_const (operands[0], DImode,
- INTVAL (operands[1]), 3)) != 0)
- {
- if (rtx_equal_p (tem, operands[0]))
- DONE;
- else
- operands[1] = tem;
- }
- else if (CONSTANT_P (operands[1]))
- {
- if (TARGET_BUILD_CONSTANTS)
- {
- HOST_WIDE_INT i0, i1;
-
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- i0 = INTVAL (operands[1]);
- i1 = -(i0 < 0);
- }
- else if (GET_CODE (operands[1]) == CONST_DOUBLE)
- {
-#if HOST_BITS_PER_WIDE_INT >= 64
- i0 = CONST_DOUBLE_LOW (operands[1]);
- i1 = -(i0 < 0);
-#else
- i0 = CONST_DOUBLE_LOW (operands[1]);
- i1 = CONST_DOUBLE_HIGH (operands[1]);
-#endif
- }
- else
- abort();
-
- tem = alpha_emit_set_long_const (operands[0], i0, i1);
- if (rtx_equal_p (tem, operands[0]))
- DONE;
- else
- operands[1] = tem;
- }
- else
- {
- operands[1] = force_const_mem (DImode, operands[1]);
- if (reload_in_progress)
- {
- emit_move_insn (operands[0], XEXP (operands[1], 0));
- operands[1] = copy_rtx (operands[1]);
- XEXP (operands[1], 0) = operands[0];
- }
- else
- operands[1] = validize_mem (operands[1]);
- }
- }
- else
- abort ();
+ if (alpha_expand_mov (DImode, operands))
+ DONE;
})
;; Split a load of a large constant into the appropriate two-insn
@@ -5123,116 +5052,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:QI 1 "general_operand" ""))]
""
{
- if (TARGET_BWX)
- {
- if (GET_CODE (operands[0]) == MEM
- && ! reg_or_0_operand (operands[1], QImode))
- operands[1] = force_reg (QImode, operands[1]);
-
- if (GET_CODE (operands[1]) == CONST_INT
- && ! input_operand (operands[1], QImode))
- {
- operands[1] = alpha_emit_set_const (operands[0], QImode,
- INTVAL (operands[1]), 3);
-
- if (rtx_equal_p (operands[0], operands[1]))
- DONE;
- }
-
- goto def;
- }
-
- /* If the output is not a register, the input must be. */
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (QImode, operands[1]);
-
- /* Handle four memory cases, unaligned and aligned for either the input
- or the output. The only case where we can be called during reload is
- for aligned loads; all other cases require temporaries. */
-
- if (GET_CODE (operands[1]) == MEM
- || (GET_CODE (operands[1]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[1])) == MEM)
- || (reload_in_progress && GET_CODE (operands[1]) == REG
- && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
- || (reload_in_progress && GET_CODE (operands[1]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[1])) == REG
- && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER))
- {
- if (aligned_memory_operand (operands[1], QImode))
- {
- if (reload_in_progress)
- {
- emit_insn (gen_reload_inqi_help
- (operands[0], operands[1],
- gen_rtx_REG (SImode, REGNO (operands[0]))));
- }
- else
- {
- rtx aligned_mem, bitnum;
- rtx scratch = gen_reg_rtx (SImode);
-
- get_aligned_mem (operands[1], &aligned_mem, &bitnum);
-
- emit_insn (gen_aligned_loadqi (operands[0], aligned_mem, bitnum,
- scratch));
- }
- }
- else
- {
- /* Don't pass these as parameters since that makes the generated
- code depend on parameter evaluation order which will cause
- bootstrap failures. */
-
- rtx temp1 = gen_reg_rtx (DImode);
- rtx temp2 = gen_reg_rtx (DImode);
- rtx seq
- = gen_unaligned_loadqi (operands[0],
- get_unaligned_address (operands[1], 0),
- temp1, temp2);
-
- alpha_set_memflags (seq, operands[1]);
- emit_insn (seq);
- }
-
- DONE;
- }
-
- else if (GET_CODE (operands[0]) == MEM
- || (GET_CODE (operands[0]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[0])) == MEM)
- || (reload_in_progress && GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
- || (reload_in_progress && GET_CODE (operands[0]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER))
- {
- if (aligned_memory_operand (operands[0], QImode))
- {
- rtx aligned_mem, bitnum;
- rtx temp1 = gen_reg_rtx (SImode);
- rtx temp2 = gen_reg_rtx (SImode);
-
- get_aligned_mem (operands[0], &aligned_mem, &bitnum);
-
- emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
- temp1, temp2));
- }
- else
- {
- rtx temp1 = gen_reg_rtx (DImode);
- rtx temp2 = gen_reg_rtx (DImode);
- rtx temp3 = gen_reg_rtx (DImode);
- rtx seq
- = gen_unaligned_storeqi (get_unaligned_address (operands[0], 0),
- operands[1], temp1, temp2, temp3);
-
- alpha_set_memflags (seq, operands[0]);
- emit_insn (seq);
- }
- DONE;
- }
- def:;
+ if (TARGET_BWX
+ ? alpha_expand_mov (QImode, operands)
+ : alpha_expand_mov_nobwx (QImode, operands))
+ DONE;
})
(define_expand "movhi"
@@ -5240,117 +5063,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:HI 1 "general_operand" ""))]
""
{
- if (TARGET_BWX)
- {
- if (GET_CODE (operands[0]) == MEM
- && ! reg_or_0_operand (operands[1], HImode))
- operands[1] = force_reg (HImode, operands[1]);
-
- if (GET_CODE (operands[1]) == CONST_INT
- && ! input_operand (operands[1], HImode))
- {
- operands[1] = alpha_emit_set_const (operands[0], HImode,
- INTVAL (operands[1]), 3);
-
- if (rtx_equal_p (operands[0], operands[1]))
- DONE;
- }
-
- goto def;
- }
-
- /* If the output is not a register, the input must be. */
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (HImode, operands[1]);
-
- /* Handle four memory cases, unaligned and aligned for either the input
- or the output. The only case where we can be called during reload is
- for aligned loads; all other cases require temporaries. */
-
- if (GET_CODE (operands[1]) == MEM
- || (GET_CODE (operands[1]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[1])) == MEM)
- || (reload_in_progress && GET_CODE (operands[1]) == REG
- && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
- || (reload_in_progress && GET_CODE (operands[1]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[1])) == REG
- && REGNO (SUBREG_REG (operands[1])) >= FIRST_PSEUDO_REGISTER))
- {
- if (aligned_memory_operand (operands[1], HImode))
- {
- if (reload_in_progress)
- {
- emit_insn (gen_reload_inhi_help
- (operands[0], operands[1],
- gen_rtx_REG (SImode, REGNO (operands[0]))));
- }
- else
- {
- rtx aligned_mem, bitnum;
- rtx scratch = gen_reg_rtx (SImode);
-
- get_aligned_mem (operands[1], &aligned_mem, &bitnum);
-
- emit_insn (gen_aligned_loadhi (operands[0], aligned_mem, bitnum,
- scratch));
- }
- }
- else
- {
- /* Don't pass these as parameters since that makes the generated
- code depend on parameter evaluation order which will cause
- bootstrap failures. */
-
- rtx temp1 = gen_reg_rtx (DImode);
- rtx temp2 = gen_reg_rtx (DImode);
- rtx seq
- = gen_unaligned_loadhi (operands[0],
- get_unaligned_address (operands[1], 0),
- temp1, temp2);
-
- alpha_set_memflags (seq, operands[1]);
- emit_insn (seq);
- }
-
- DONE;
- }
-
- else if (GET_CODE (operands[0]) == MEM
- || (GET_CODE (operands[0]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[0])) == MEM)
- || (reload_in_progress && GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
- || (reload_in_progress && GET_CODE (operands[0]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER))
- {
- if (aligned_memory_operand (operands[0], HImode))
- {
- rtx aligned_mem, bitnum;
- rtx temp1 = gen_reg_rtx (SImode);
- rtx temp2 = gen_reg_rtx (SImode);
-
- get_aligned_mem (operands[0], &aligned_mem, &bitnum);
-
- emit_insn (gen_aligned_store (aligned_mem, operands[1], bitnum,
- temp1, temp2));
- }
- else
- {
- rtx temp1 = gen_reg_rtx (DImode);
- rtx temp2 = gen_reg_rtx (DImode);
- rtx temp3 = gen_reg_rtx (DImode);
- rtx seq
- = gen_unaligned_storehi (get_unaligned_address (operands[0], 0),
- operands[1], temp1, temp2, temp3);
-
- alpha_set_memflags (seq, operands[0]);
- emit_insn (seq);
- }
-
- DONE;
- }
- def:;
+ if (TARGET_BWX
+ ? alpha_expand_mov (HImode, operands)
+ : alpha_expand_mov_nobwx (HImode, operands))
+ DONE;
})
;; Here are the versions for reload. Note that in the unaligned cases