Hi all, I've encountered another wrong-code bug with the store merging pass. This time it's in RTL. The test gcc.target/aarch64/aapcs64/test_27.c on aarch64 merges a few __fp16 values at GIMPLE level but during RTL dse1 one of the constants generated gets wrongly misinterpreted from HImode to HFmode by simplify_immed_subreg. The HFmode value it ends up producing is completely bogus.
By stepping through the code with GDB the problem is in the hunk touched by this patch when it fills in an array of longs with the value bytes before passing it down to real_from_target. It fills in the array by orring in each byte. However, the array it declared to use for this doesn not get properly zero-initialised for modes less that 32 bits wide (HFmode in this case). The fix in this patch is to just use an array initialiser to zero it out. This makes the failure go away. Bootstrapped and tested on aarch64, x86_64. Ok for trunk? Thanks, Kyrill 2016-10-06 Kyrylo Tkachov <kyrylo.tkac...@arm.com> * simplify-rtx.c (simplify_immed_subreg): Zero-initialize tmp array before merging in bytes to pass down to real_from_target.
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 4bb16f896f89b06612e923a0b8db8e074b8a734c..9e7376c9f2b967d96b3195a6d9de57a543644d10 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -5906,14 +5906,12 @@ simplify_immed_subreg (machine_mode outermode, rtx op, case MODE_DECIMAL_FLOAT: { REAL_VALUE_TYPE r; - long tmp[MAX_BITSIZE_MODE_ANY_MODE / 32]; + long tmp[MAX_BITSIZE_MODE_ANY_MODE / 32] = { 0 }; /* real_from_target wants its input in words affected by FLOAT_WORDS_BIG_ENDIAN. However, we ignore this, and use WORDS_BIG_ENDIAN instead; see the documentation of SUBREG in rtl.texi. */ - for (i = 0; i < max_bitsize / 32; i++) - tmp[i] = 0; for (i = 0; i < elem_bitsize; i += value_bit) { int ibase;