First Last Prev Next    No search results available
Details
: [llvmgcc] Constant initializer of automatic arrays genera...
Bug#: 75
: tools
: llvm-gcc
Status: RESOLVED
Resolution: FIXED
: All
: All
: 1.0
: P2
: normal
: 1.1

:
: quality-of-implementation
:
:
  Show dependency tree - Show dependency graph
People
Reporter: Brian R. Gaeke <gaeke+bugs@uiuc.edu>
Assigned To: Chris Lattner <sabre@nondot.org>

Attachments


Note

You need to log in before you can comment on or make changes to this bug.

Related actions


Description:   Opened: 2003-10-30 13:00
barf.c:
 void
 preformatted_filter(void)
 {
  char head[20000]="";
 }

% llvm-gcc -S barf.c

The above tries to explicitly initialize every single one of the 20000 bytes of
head[] using a gep/store pair. I think it should just zero the first byte. At
the very least, it should call memset(), or generate a loop, or anything other
than what it does now.

Why did I notice, you might ask? A program in xf86 4.3.0 uses a couple of huge
arrays like this, and llvm-gcc turns 345 lines of preprocessed C into a 622
kilobyte bytecode file, on which gccas proceeds to run for an extremely long
time. The slow pass in question is gcse. I let it run on the full version of the
above function for 10 minutes before giving up on it.
------- Comment #1 From Chris Lattner 2003-10-30 14:00:55 -------
Wow, this is bad.  I probably won't have a chance to fix this until after the
15th though.

-Chris
------- Comment #2 From Brian R. Gaeke 2003-10-31 10:31:01 -------
For the record, Chris believes that programs do depend on the zeroing-out of
string constant initializers like this. Emitting a libcall is probably not a
good idea, so we'll probably fix this by emitting a loop.
------- Comment #3 From Chris Lattner 2003-11-08 16:56:05 -------
This is another REALLY wierd case.  I have no idea why LLVMG++ is wanting to
initialize this array:

struct foo {
  int array[100];
  void bar();
};

void test() {
  foo().bar();
}

test with:

$ llvmg++ -c test.cc -o - | llvm-dis
------- Comment #4 From Chris Lattner 2003-11-26 02:14:52 -------
Fixed.  Long live huge identifiers.

Here's the patch:

$ diff -u llvm-expand.c~ llvm-expand.c
--- llvm-expand.c~      2003-11-26 01:48:41.000000000 -0600
+++ llvm-expand.c       2003-11-26 02:12:01.000000000 -0600
@@ -3587,7 +3587,21 @@
 
     /* Composite elements handled already */
     if (!llvm_type_is_composite(Ty->Elements[0])) {
-      for (i = 0; i != Size; ++i) {
+      /* Lots of initializers have LARGE tails of zeros at the end of them.  To
+       * handle this efficiently, we actually check to see if there is a large
+       * tail pad, and if so, emit a loop to initialize it.
+       */
+      unsigned TailStart = Size;
+      if (TailStart) {
+        do --TailStart;
+        while (TailStart && Elements[TailStart] == Elements[TailStart-1]);
+      }
+
+      /* Only do this for substantial tails. */
+      if (Size-TailStart < 16)
+        TailStart = Size;
+
+      for (i = 0; i != TailStart; ++i) {
         /* Make a getelementptr instruction that addresses the field */
         OffsetInst = create_gep3(target, llvm_constant_long_0,
                                  llvm_constant_new_integral(LongTy, i));
@@ -3595,6 +3609,42 @@
         append_inst(Fn, create_store_inst(Elements[i], Offset, isVolatile));
       }
 
+      /* If there is tail padding to emit, add the loop now. */
+      if (TailStart != Size) {
+        llvm_value *Val = Elements[i];
+        llvm_basicblock *FromBlock =
+          llvm_ilist_back(llvm_basicblock, Fn->BasicBlocks);
+        llvm_basicblock *Loop = llvm_basicblock_new("initializeloop");
+        llvm_basicblock *After = llvm_basicblock_new("continue");
+        llvm_instruction *PHI;
+        llvm_value *SetNE;
+        
+        /* Output the branch to the loop block, and the loop block itself. */
+        append_inst(Fn, create_uncond_branch(Loop));
+        llvm_emit_label(Fn, Loop);
+
+        /* Create the PHI node now */
+        PHI = llvm_instruction_new(LongTy, "idx", O_PHINode, 4);
+        PHI->Operands[0] = llvm_constant_new_integral(LongTy, TailStart);
+        PHI->Operands[1] = D2V(FromBlock);
+        PHI->Operands[3] = D2V(Loop);
+        append_inst(Fn, PHI);
+
+        /* Make a getelementptr & store to the fields */
+        OffsetInst = create_gep3(target, llvm_constant_long_0, D2V(PHI));
+        Offset = append_inst(Fn, OffsetInst);   /* Add it to the program */
+        append_inst(Fn, create_store_inst(Val, Offset, isVolatile));
+
+        /* Add one to the counter, add it to the PHI operand */
+        PHI->Operands[2] = 
+          append_inst(Fn, create_binary_inst("tmp", O_Add, D2V(PHI), 
+                                     llvm_constant_new_integral(LongTy, 1)));
+        /* Add a setne instruction to test for loop termination */
+        SetNE = append_inst(Fn, create_binary_inst("hasmore", O_SetNE, D2V(PHI),
+                                   llvm_constant_new_integral(LongTy, Size-1)));
+        append_inst(Fn, create_cond_branch(SetNE, Loop, After));
+        llvm_emit_label(Fn, After);
+      }
     }
   }
 

First Last Prev Next    No search results available