Bugzilla – Bug 75
[llvmgcc] Constant initializer of automatic arrays generate huge straight-line code
Last modified: 2003-11-26 02:14:52
You need to log in before you can comment on or make changes to this bug.
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.
Wow, this is bad. I probably won't have a chance to fix this until after the 15th though. -Chris
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.
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
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); + } } }