This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]