From c41379182bcafb29fe64ccf8e2fe78d362ccc388 Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Sun, 7 Mar 2010 15:20:12 +0000 Subject: re PR middle-end/42220 (FAIL: gfortran.dg/complex_intrinsic_5.f90 -m64 -O -frename-registers) PR rtl-optimization/42220 * regrename.c (scan_rtx) : 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 --- gcc/regrename.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'gcc/regrename.c') 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) -- cgit v1.1