This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR middle-end/13400: Unsafe writes in ifcvt.c
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 15 Dec 2003 17:41:27 -0700 (MST)
- Subject: [PATCH] PR middle-end/13400: Unsafe writes in ifcvt.c
The following patch is my proposed solution to PR middle-end/13400
which is an incorrect code generation problem caused by GCC's
if-conversion, i.e. the recent "Compiled code crashes storing to
read-only location" thread on the gcc list.
The problem is that its possible for GCC's if-conversion to optimize
"if (...) x = a;" into an unconditional write to x, by assuming an
implicit "else x = x;". Unfortunately, this is unsafe if writing to
x may generate a trap, such as being a read-only memory location.
This not only affects my recent noce_try_move optimization, but most
of the existing if-conversion optimizations (store_flag, abs, minmax,
etc...)
The solution is to explicitly check, when there is no explicit else
clause, whether the target is a memory that could trap (i.e. isn't
a static variable or stack slot). In these cases, we only allow
if-conversion optimizations that generate condition move sequences.
The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all languages except treelang, and regression tested
with a top-level "make -k check" with no new failures. It looks like
this bug is also present on the gcc-3_3-branch, but it isn't triggered
by the attached testcase.
Ok for mainline? and for 3.3?
Many thanks in advance,
2003-12-15 Roger Sayle <roger@eyesopen.com>
PR middle-end/13400
* ifcvt.c (noce_process_if_block): Disable unconditional write
optimizations if we could introduce a store to trapping memory
that wasn't present previously.
* gcc.c-torture/execute/20031215-1.c: New test case.
Index: ifcvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ifcvt.c,v
retrieving revision 1.132
diff -c -3 -p -r1.132 ifcvt.c
*** ifcvt.c 11 Dec 2003 00:20:44 -0000 1.132
--- ifcvt.c 15 Dec 2003 14:08:04 -0000
*************** noce_process_if_block (struct ce_if_bloc
*** 1965,1970 ****
--- 1965,1989 ----
goto success;
}
+ /* Disallow the "if (...) x = a;" form (with an implicit "else x = x;")
+ for most optimizations if writing to x may trap, i.e. its a memory
+ other than a static var or a stack slot. */
+ if (! set_b
+ && GET_CODE (orig_x) == MEM
+ && ! MEM_NOTRAP_P (orig_x)
+ && rtx_addr_can_trap_p (XEXP (orig_x, 0)))
+ {
+ if (HAVE_conditional_move)
+ {
+ if (noce_try_cmove (&if_info))
+ goto success;
+ if (! HAVE_conditional_execution
+ && noce_try_cmove_arith (&if_info))
+ goto success;
+ }
+ return FALSE;
+ }
+
if (noce_try_move (&if_info))
goto success;
if (noce_try_store_flag (&if_info))
/* PR middle-end/13400 */
/* The following test used to fail at run-time with a write to read-only
memory, caused by if-conversion converting a conditional write into an
unconditional write. */
typedef struct {int c, l; char ch[3];} pstr;
const pstr ao = {2, 2, "OK"};
const pstr * const a = &ao;
void test1(void)
{
if (a->ch[a->l]) {
((char *)a->ch)[a->l] = 0;
}
}
void test2(void)
{
if (a->ch[a->l]) {
((char *)a->ch)[a->l] = -1;
}
}
void test3(void)
{
if (a->ch[a->l]) {
((char *)a->ch)[a->l] = 1;
}
}
int main(void)
{
test1();
test2();
test3();
return 0;
}
Roger
--
Roger Sayle, E-mail: roger@eyesopen.com
OpenEye Scientific Software, WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507. Fax: (+1) 505-473-0833