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]

IA-64 fixup_var_refs_1 fix for kernel miscompilation


This fixes an ia64-linux kernel miscompilation.  The miscompiled function
is fn_hash().  Here is a simple testcase

static unsigned int
fn_hash (unsigned int key)
{
	unsigned int h = key >> 10;
	h ^= (h>>20);
	return *(unsigned int *) &h;
}

The problem occurs when we have a paradoxical subreg of a local variable
used inside a bitfield extract, and we later take the address of the local
variable.  The RTL we get is

(insn 25 22 28 (set (reg:DI 349)
        (subreg:DI (reg:SI 348) 0)) -1 (nil)
    (nil))

(insn 28 25 14 (set (reg:SI 348)
        (mem/f:SI (addressof:DI (reg/v:SI 346) 341 0x4018b280) 5)) -1 (nil)
    (nil))

(insn 14 28 16 (set (reg:DI 344)
        (zero_extract:DI (reg:DI 349)
            (const_int 12 [0xc])
            (const_int 20 [0x14]))) -1 (nil)
    (nil))

This uses reg 348 before it is set, and also uses one more pseudo than is
necessary.  The bug is in fixup_var_refs_1, in the ZERO_EXTRACT case, in
the code that handles paradoxical subregs.  There is an obvious problem here
in that we generate a subreg, and then fall through to code that can only
handle a MEM.  If we handle the subreg where we generated it, then all of
the problems go away.

The testcase does not fail with current gcc sources, presumably because the
C front-end rewrite for function-at-a-time means that this code doesn't
get executed anymore.  The problem is still there though, and hence still
needs to be fixed.

2000-09-18  Jim Wilson  <wilson@cygnus.com>

	* function.c (fixup_var_refs_1, case ZERO_EXTRACT): If we have a
	paradoxical subreg, then directly substitute the replacement and
	return.

Index: function.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/function.c,v
retrieving revision 1.219
diff -p -r1.219 function.c
*** function.c	2000/09/18 19:27:36	1.219
--- function.c	2000/09/18 21:28:48
*************** fixup_var_refs_1 (var, promoted_mode, lo
*** 2015,2020 ****
--- 2015,2028 ----
  		  if (replacement->new == 0)
  		    replacement->new = gen_reg_rtx (GET_MODE (var));
  		  SUBREG_REG (tem) = replacement->new;
+ 
+ 		  /* The following code works only if we have a MEM, so we
+ 		     need to handle the subreg here.  We directly substitute
+ 		     it assuming that a subreg must be OK here.  We already
+ 		     scheduled a replacement to copy the mem into the
+ 		     subreg.  */
+ 		  XEXP (x, 0) = tem;
+ 		  return;
  		}
  	      else
  		tem = fixup_memory_subreg (tem, insn, 0);

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