https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127447

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED
           Assignee|unassigned at gcc dot gnu.org      |rguenth at gcc dot 
gnu.org

--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> ---
✦ Root Cause Analysis

  The miscompilation of obj/gcc/t.c at -O2 is caused by a bug in the
  GIMPLE-level ifcombine optimization pass, specifically during the decoding of
  field references in decode_field_reference (gcc/gcc/gimple-fold.cc).

   1. Comparison Structure:
     The code inside b() contains a conditional block equivalent to:

   1    _6 = (unsigned char) _2; // where _2 = a.1_1 ^ -8
   2    _3 = (short int) _2;
   3    if (_6 != 0) goto return_block;
   4    if (_3 != 0) goto return_block;
   5    else marker_32();
     To reach the marker_32() block, both _6 == 0 and _3 == 0 must hold,
forming
  an OR/AND combination pattern that ifcombine attempts to optimize into a
  single 16-bit comparison.

   2. Constant Decoding Mismatch:
     During fold_truth_andor_for_ifcombine (and through
decode_field_reference),
  the XOR binary operation a.1_1 ^ -8 != 0 is rewritten to compare a.1_1
against
  -8.
      - The left comparison's target constant is -8 (an INTEGER_CST of type
int,
        32-bit), but the outer cast is unsigned char (8-bit).
      - In decode_field_reference, when the outer cast is stripped, the outer
        type (unsigned char, 8-bit) is saved in outer_type. However, the
        constant operand -8 is returned with its original 32-bit precision
        without being truncated/cast to outer_type.
      - Consequently, ll_bitsize is determined to be 8, and the right-hand
        constant bitsize lr_bitsize is also 8. Because ll_bitsize < lr_bitsize
        (8 < 8) evaluates to false, the constant -8 (which has set bits outside
        the lowest 8 bits) is never truncated to 8 bits (248).

   3. Tautological Check Failure:
     During comparison combination, thePass checks if the constant (-8
  represented as 0xfff8 in 16-bit) has set bits outside the mask for the
  compared field (ll_mask = 0x00ff). Since 0xfff8 & ~0x00ff != 0, ifcombine
  incorrectly concludes that the comparison is tautological (always false),
  causing the entire conditional check to fold into constant 0 (false), which
  optimizes away the call to marker_32().

Reply via email to