This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Code getting optimized away after instrumenation for memory analysis
- From: Prateek Saxena <prateeksaxena at gmail dot com>
- To: gcc at gcc dot gnu dot org
- Date: Fri, 18 Nov 2005 04:13:13 -0500
- Subject: Code getting optimized away after instrumenation for memory analysis
Hello,
I am doing some code instrumentation for program memory access
validation using gcc-4.1 head.
For every assignment, p=q
I pass the address of the operands, "&p" and "&q" to an external
library function.
This works fine at O0, but at O1, some legitimate code gets optimized
away. In the dumps generated by my pass( runs immediately after
t08.useless), there is a statement
*D.2383 = __taint_addr10;
The "__taint_addr10" is an artificial variable created by my pass,
which replaces the original operand, since the address of the original
operand is taken. If this variable is used later in any expression
with a binary operator or a COND_EXPR, then it must be replaced by a
copy that doesnot have its address taken. So, in this prototype
currently I replace its occurance in every rhs expression.
This statement gets optimized away in the dead code elemination(t26.dce1)
pass, because in the "is_global_hidden_store" function , there is a
check :
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
which fails, and the function returns false. Thus, this statement is
not marked as necessary and gets removed.
The program which I am instrumenting is as follows:
int
main()
{
int i, k=1, n, *x;
printf( "Enter n: ");
scanf( "%d", &n );
x = malloc( (n+1) * sizeof(int));
x[1] = 1;
while (k)
{
if ( x[k]== n)
{
k--;
x[k]++;
}
else
{
k++;
x[k] = x[k-1] + 1;
}
}
return 0;
}
The dump after my instrumentation for "x[k]++" in the first if block
in while looks like -
L1:
...
...
/* Computes in __taint_addr.121 = k*4 */
__taint_addr.115 = k;
D.2381 = __taint_addr.115 * 4;
__taint_addr.125 = D.2381;
__taint_addr.128 = x;
D.2383 = __taint_addr.125 + __taint_addr.128;
library_call (D.2383);
/* Computes the incremented value in D.2385 */
D.2384 = *D.2383;
__taint_addr.135 = D.2384;
D.2385 = __taint_addr.135 + 1;
__taint_addr.11 = D.2385
*D.2383 = __taint_addr.11; /* ==> gets optimized away */
I would be thankful if someone could give me pointers to what could be
going wrong here. Clearly, The reference to *D.2383, is a valid heap
address, and hence must not be removed as a dead store. There is
something which my instrumentation is messing up.
I looked at the alias analysis dumps t20.alias1 . What I noticed is
that in function update_alias_info (),
there is a place where gcc processes each operand use is seen ,and for
pointers, it determines whether they are dereferenced by a given
statement or not. So, I added some printfs there, as follows:
FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
{
tree op, var;
var_ann_t v_ann;
struct ptr_info_def *pi;
bool is_store, is_potential_deref;
unsigned num_uses, num_derefs;
op = USE_FROM_PTR (use_p);
/* Debug statemets added */
==> fprintf (stderr, "Stament and uses\n");
==> debug_generic_stmt (stmt);
==> debug_generic_stmt (op);
At this point, the stmt:
# VUSE <D.2383_307>;
*D.2383 = __taint_addr.11D.3119_323;
_doesnot_ show any used op like,
D.2383.
why is this happening?
Thanks in advance,
Prateek.