[llvm-commits] CVS: gcc-3.4/gcc/llvm-expand.c
Chris Lattner
lattner at cs.uiuc.edu
Tue Mar 9 21:06:02 PST 2004
Changes in directory gcc-3.4/gcc:
llvm-expand.c updated: 1.23 -> 1.24
---
Log message:
Expand large initializers of zeros into memset calls, and large constant
initializers into memcpy calls from a global. This addresses PR275.
---
Diffs of the changes: (+63 -60)
Index: gcc-3.4/gcc/llvm-expand.c
diff -u gcc-3.4/gcc/llvm-expand.c:1.23 gcc-3.4/gcc/llvm-expand.c:1.24
--- gcc-3.4/gcc/llvm-expand.c:1.23 Tue Mar 9 16:50:42 2004
+++ gcc-3.4/gcc/llvm-expand.c Tue Mar 9 21:05:22 2004
@@ -3866,6 +3866,26 @@
}
+/* llvm_count_constructor_init_elements - Given a constructor initializer, count
+ * how many elements are zero values and, of the remaining values, how many are
+ * non-zero constants.
+ */
+static void
+llvm_count_constructor_init_elements(llvm_value **Elements, unsigned Size,
+ unsigned *NumConstant, unsigned *NumZero) {
+ unsigned Constants = 0, Zeros = 0, i;
+ for (i = 0; i != Size; ++i)
+ if (llvm_value_is_constant(Elements[i])) {
+ if (llvm_is_null_constant(Elements[i]))
+ ++Zeros;
+ else
+ ++Constants;
+ }
+ *NumConstant = Constants;
+ *NumZero = Zeros;
+}
+
+
/* llvm_expand_constructor - Store the value of a CONSTRUCTOR (exp) into the
* LLVM value (Dest). Dest is guaranteed to be a pointer to the appropriate
* memory location.
@@ -3901,74 +3921,57 @@
/* Composite elements handled already */
if (!llvm_type_is_composite(Ty->Elements[0])) {
- /* 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.
+ /* It is very common for constructors to be fully constant, and not
+ * infrequent for them to be large. In this case, emit an internal global
+ * variable with the constructor value as its initializer, and memcpy it
+ * over.
*/
- unsigned TailStart = Size;
- if (TailStart) {
- do --TailStart;
- while (TailStart && Elements[TailStart] == Elements[TailStart-1]);
- }
+ if (Size > 16) {
+ unsigned Alignment = TYPE_ALIGN_UNIT(TREE_TYPE(exp));
+ unsigned NumBytes = Size*llvm_type_get_size(Ty->Elements[0]);
+ unsigned NumConstants = 0, NumZeros = 0;
+ llvm_count_constructor_init_elements(Elements, Size,
+ &NumConstants, &NumZeros);
+
+ /* If all of the elements are zeros, memset the constructor to zero. */
+ if (NumZeros == Size) {
+ EmitMemset(Fn, target, llvm_constant_ubyte_0,
+ llvm_constant_new_integral(LongTy, NumBytes), Alignment);
+ free(Elements);
+ return;
+ } else if (NumZeros+NumConstants == Size) {
+ /* Otherwise, if all of the elements are constants, initialize a
+ * global variable with the constant value, and memcpy it into the
+ * current location.
+ */
+ llvm_constant *C = G2C(llvm_constant_aggregate_new(Ty, Elements));
+ llvm_global *G;
+ static int CtorCounter = 0;
+ char Name[20];
+ sprintf(Name, ".ctor_%d", ++CtorCounter);
+ G = llvm_global_new(D2V(C)->Ty, Name);
+ G->Init = C;
+ llvm_ilist_push_back(llvm_global, TheProgram.Globals, G);
+ EmitMemCpyMove(Fn, target, G2V(G),
+ llvm_constant_new_integral(LongTy, NumBytes),
+ Alignment, 0);
+ return;
+ }
- /* Only do this for substantial tails. */
- if (Size-TailStart < 16)
- TailStart = Size;
+ /* FIXME: MORE CASES WE COULD HANDLE EFFICIENTLY:
+ * - When the init is mostly zeros but not all constant, memset, then
+ * fill in elements.
+ * - When the constant is mostly zeros, we could use memset to set
+ * it to zero, then memcpy the smaller non-zero portion.
+ */
+ }
- /* FIXME: If tailstart is obscenely large, we are better off starting with
- * an initialized global and memcpy'ing it over.
- */
- for (i = 0; i != TailStart; ++i) {
+ for (i = 0; i != Size; ++i) {
/* Make a getelementptr instruction that addresses the field */
OffsetInst = create_gep3(target, llvm_constant_long_0,
llvm_constant_new_integral(LongTy, i));
Offset = append_inst(Fn, OffsetInst); /* Add it to the program */
append_inst(Fn, create_store_inst(Elements[i], Offset, isVolatile));
- }
-
- /* If there is tail padding to emit, add the loop or memset call now. */
- if (TailStart != Size) {
- llvm_value *Val = Elements[i];
- if (llvm_type_get_size(Val->Ty) == 1) {
- llvm_value *DestPtr =
- append_inst(Fn, create_gep3(target, llvm_constant_long_0,
- llvm_constant_new_integral(LongTy, TailStart)));
- EmitMemset(Fn, DestPtr, Val,
- llvm_constant_new_integral(LongTy, Size-TailStart), 1);
- } else {
- 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);
- }
}
}
}
More information about the llvm-commits
mailing list