aboutsummaryrefslogtreecommitdiff
path: root/gcc/regrename.c
diff options
context:
space:
mode:
authorBernd Schmidt <bernd.schmidt@analog.com>2010-03-07 15:20:12 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2010-03-07 15:20:12 +0000
commitc41379182bcafb29fe64ccf8e2fe78d362ccc388 (patch)
treeae26214452e5ac1cf2db92de594dd9a347be2161 /gcc/regrename.c
parentf7cf1ce042f8a3f1f069a3e25c2ea3417c2be861 (diff)
downloadgcc-c41379182bcafb29fe64ccf8e2fe78d362ccc388.zip
gcc-c41379182bcafb29fe64ccf8e2fe78d362ccc388.tar.gz
gcc-c41379182bcafb29fe64ccf8e2fe78d362ccc388.tar.bz2
re PR middle-end/42220 (FAIL: gfortran.dg/complex_intrinsic_5.f90 -m64 -O -frename-registers)
PR rtl-optimization/42220 * regrename.c (scan_rtx) <case STRICT_LOW_PART, ZERO_EXTRACT>: Use verify_reg_tracked to determine if we should use OP_OUT rather than OP_INOUT. (build_def_use): If we see an in-out operand for a register that we know nothing about, treat is an output if possible, fail the block if not. From-SVN: r157263
Diffstat (limited to 'gcc/regrename.c')
-rw-r--r--gcc/regrename.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/gcc/regrename.c b/gcc/regrename.c
index e003fd4..f7891d1 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -889,13 +889,15 @@ scan_rtx (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
return;
case STRICT_LOW_PART:
- scan_rtx (insn, &XEXP (x, 0), cl, action, OP_INOUT);
+ scan_rtx (insn, &XEXP (x, 0), cl, action,
+ verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT);
return;
case ZERO_EXTRACT:
case SIGN_EXTRACT:
scan_rtx (insn, &XEXP (x, 0), cl, action,
- type == OP_IN ? OP_IN : OP_INOUT);
+ (type == OP_IN ? OP_IN :
+ verify_reg_tracked (XEXP (x, 0)) ? OP_INOUT : OP_OUT));
scan_rtx (insn, &XEXP (x, 1), cl, action, OP_IN);
scan_rtx (insn, &XEXP (x, 2), cl, action, OP_IN);
return;
@@ -1067,6 +1069,7 @@ build_def_use (basic_block bb)
int n_ops;
rtx note;
rtx old_operands[MAX_RECOG_OPERANDS];
+ bool has_dup[MAX_RECOG_OPERANDS];
rtx old_dups[MAX_DUP_OPERANDS];
int i;
int alt;
@@ -1105,6 +1108,10 @@ build_def_use (basic_block bb)
n_ops = recog_data.n_operands;
untracked_operands = 0;
+ memset (has_dup, 0, sizeof has_dup);
+ for (i = 0; i < recog_data.n_dups; i++)
+ has_dup[(int)recog_data.dup_num[i]] = true;
+
/* Simplify the code below by rewriting things to reflect
matching constraints. Also promote OP_OUT to OP_INOUT in
predicated instructions, but only for register operands
@@ -1137,6 +1144,20 @@ build_def_use (basic_block bb)
untracked_operands |= 1 << matches;
}
}
+ /* If there's an in-out operand with a register that is not
+ being tracked at all yet, convert it to an earlyclobber
+ output operand.
+ This only works if the operand isn't duplicated, i.e. for
+ a ZERO_EXTRACT in a SET_DEST. */
+ if (recog_data.operand_type[i] == OP_INOUT
+ && !(untracked_operands & (1 << i))
+ && !verify_reg_tracked (recog_data.operand[i]))
+ {
+ if (has_dup[i])
+ fail_current_block = true;
+ recog_data.operand_type[i] = OP_OUT;
+ recog_op_alt[i][alt].earlyclobber = 1;
+ }
}
if (fail_current_block)