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

            Bug ID: 66348
           Summary: Simple loop with 64-bit index has only lower half
                    initialized correctly
           Product: gcc
           Version: 4.9.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: sebastiano.vigna at unimi dot it
  Target Milestone: ---

Created attachment 35657
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=35657&action=edit
Source (buffer.c) and a bunch of header files

This is a fragment of ne, the nice editor:

line_desc *nth_line_desc(const buffer *b, const int64_t n) {
   if (n < 0 || n >= b->num_lines) return NULL;

   line_desc *ld;
   const int64_t best_absolute_cost = min(n, b->num_lines - 1 - n);
   const int64_t relative_cost = b->cur_line < n ? n - b->cur_line :
b->cur_line - n;

   if (best_absolute_cost < relative_cost) {
      if (n < b->num_lines / 2) {
         ld = (line_desc *)b->line_desc_list.head;
         for(int64_t i = 0; i < n; i++) ld = (line_desc *)ld->ld_node.next;
      }
      else {
         ld = (line_desc *)b->line_desc_list.tail_pred;
         // Problematic loop
         for(int64_t i = 0; i < b->num_lines - 1 - n; i++) ld = (line_desc
*)ld->ld_node.prev;;
      }
   }
   else {
      ld = (line_desc *)b->cur_line_desc;
      if (n < b->cur_line) for(int64_t i = 0; i < b->cur_line - n; i++) ld =
(line_desc *)ld->ld_node.prev;
      else for(int64_t i = 0; i < n - b->cur_line; i++) ld = (line_desc
*)ld->ld_node.next;
   }

   return ld;
}

The loop commented as "problematic loop" is compiled (with -O3) as

        xorl    %eax, %eax      # i
        .p2align 4,,10
        .p2align 3
.L527:
        addq    $1, %rax        #, i
        movq    8(%rbx), %rbx   # ld_64->ld_node.prev, ld
        cmpq    %rdx, %rax      # D.11490, i
        jne     .L527   #,


That is, the loop index i is in %rax, but only the lower half is zeroed at the
start of the loop. When we enter the loop with a large (>32-bit) value, the
loop never ends. This happens already with -O1. We had to #pragma the function
to -O0 to make it work.

I have attached a bunch of header files and the source of the file containing
the function. Compile with 

gcc -std=c99 -D_GNU_SOURCE -D__USE_GNU -DSTDC_HEADERS -Dinline=__inline__ -O3
-DNDEBUG -c -S -fverbose-asm buffer.c

to get the code above.

Reply via email to