[llvm-commits] CVS: gcc-3.4/gcc/llvm-expand.c
Chris Lattner
lattner at cs.uiuc.edu
Thu Feb 12 15:05:01 PST 2004
Changes in directory gcc-3.4/gcc:
llvm-expand.c updated: 1.8 -> 1.9
---
Log message:
Make llvm_copy_aggregate emit a call to llvm.memcpy if the copied aggregate
is large. Also implement the __builtin_memcpy intrinsic in GCC in terms of
llvm.memcpy. Also fix an apparent bug in the llvm_expand_call code which
used a value that was never defined.
---
Diffs of the changes: (+64 -18)
Index: gcc-3.4/gcc/llvm-expand.c
diff -u gcc-3.4/gcc/llvm-expand.c:1.8 gcc-3.4/gcc/llvm-expand.c:1.9
--- gcc-3.4/gcc/llvm-expand.c:1.8 Thu Feb 5 10:05:45 2004
+++ gcc-3.4/gcc/llvm-expand.c Thu Feb 12 15:04:48 2004
@@ -307,21 +307,45 @@
}
}
+static void EmitMemcpy(llvm_function *Fn, llvm_value *DestPtr,
+ llvm_value *SrcPtr, llvm_value *Size,
+ unsigned Alignment) {
+ static llvm_function *llvm_memcpy_fn = 0;
+ static llvm_type *size_tTy = 0;
+
+ llvm_instruction *I;
+ if (!llvm_memcpy_fn) {
+ llvm_type *FnTy = llvm_type_create_function(4, VoidTy);
+ FnTy->Elements[1] = FnTy->Elements[2] = VoidPtrTy;
+ FnTy->Elements[3] = size_tTy = llvm_type_get_from_tree(size_type_node);
+ FnTy->Elements[4] = UIntTy;
+ FnTy = llvm_type_get_cannonical_function(FnTy);
+ llvm_memcpy_fn = CreateIntrinsicFnWithType("llvm.memcpy", FnTy);
+ }
+
+ I = llvm_instruction_new(VoidTy, "", O_Call, 5);
+ I->Operands[0] = G2V(llvm_memcpy_fn);
+ I->Operands[1] = cast_if_type_not_equal(Fn, DestPtr, VoidPtrTy);
+ I->Operands[2] = cast_if_type_not_equal(Fn, SrcPtr, VoidPtrTy);
+ I->Operands[3] = cast_if_type_not_equal(Fn, Size, size_tTy);
+ I->Operands[4] = llvm_constant_new_integral(UIntTy, Alignment);
+ append_inst(Fn, I);
+}
+
+
/* llvm_copy_aggregate - Given two pointers to structures, copy *SrcPtr into
* *DestPtr, element by element.
*
- * FIXME: for objects of non-trivial complexity, we could instead call a
- * "assignment" function to perform the copy. This could save a lot of code
- * space. We would have to mark the generated function as linkonce.
*/
static void llvm_copy_aggregate(llvm_function *Fn, llvm_value *DestPtr,
llvm_value *SrcPtr, int isSourceVolatile,
- int isDestVolatile) {
+ int isDestVolatile, unsigned Alignment) {
llvm_type *ObjTy;
unsigned i;
assert(DestPtr && SrcPtr && "Cannot copy from null ptr!");
assert(DestPtr->Ty == SrcPtr->Ty && "Cannot copy incompatible structs!");
- if (DestPtr == SrcPtr) return; /* X = X; --> Noop */
+ if (DestPtr == SrcPtr && !isSourceVolatile && !isDestVolatile)
+ return; /* X = X; --> Noop */
/* Get the type of the object being copied... */
ObjTy = GET_POINTER_TYPE_ELEMENT(DestPtr->Ty);
@@ -334,6 +358,15 @@
return;
}
+ /* If this is a large object copy, emit a call to the llvm.memcpy intrinsic.
+ */
+ if (llvm_type_get_size(ObjTy) > 128) {
+ EmitMemcpy(Fn, DestPtr, SrcPtr,
+ llvm_constant_new_integral(LongTy, llvm_type_get_size(ObjTy)),
+ Alignment);
+ return;
+ }
+
/* Copy aggregate values recursively... */
switch (ObjTy->ID) {
case StructTyID:
@@ -345,7 +378,7 @@
llvm_constant_long_0, FieldNo));
llvm_copy_aggregate(Fn, DestElPtr, SrcElPtr,
- isSourceVolatile, isDestVolatile);
+ isSourceVolatile, isDestVolatile, 1);
}
break;
@@ -357,7 +390,7 @@
llvm_value *SrcElPtr = append_inst(Fn, create_gep3(SrcPtr,
llvm_constant_long_0, FieldNo));
llvm_copy_aggregate(Fn, DestElPtr, SrcElPtr,
- isSourceVolatile, isDestVolatile);
+ isSourceVolatile, isDestVolatile, 1);
}
break;
}
@@ -2764,7 +2797,7 @@
/* If this argument is passed by invisible reference... */
if (isPassedByInvisibleReference(TREE_TYPE(TREE_VALUE(arg)))) {
/* Get the address of the parameters passed in. */
- llvm_value *ArgAddr = llvm_expand_lvalue_expr(Fn, TREE_VALUE(arg), 0, 0);
+ ArgVal = llvm_expand_lvalue_expr(Fn, TREE_VALUE(arg), 0, 0);
if (ArgTy) ArgVal = cast_if_type_not_equal(Fn, ArgVal, ArgTy);
Call->Operands[NumArgs+ArgOffset] = ArgVal;
CalledFuncType->Elements[1+NumArgs] = ArgVal->Ty;
@@ -3934,6 +3967,20 @@
return CreateIntrinsicFnWithType(Name, FnTy);
}
+static llvm_value *llvm_expand_builtin_memcpy(llvm_function *Fn, tree arglist) {
+ llvm_value *Op0, *Op1, *Op2;
+
+ Op0 = llvm_expand_expr(Fn, TREE_VALUE(arglist), 0);
+ arglist = TREE_CHAIN(arglist);
+ Op1 = llvm_expand_expr(Fn, TREE_VALUE(arglist), 0);
+ arglist = TREE_CHAIN(arglist);
+ Op2 = llvm_expand_expr(Fn, TREE_VALUE(arglist), 0);
+
+ EmitMemcpy(Fn, Op0, Op1, Op2, 1);
+ return Op0;
+}
+
+
static void llvm_expand_builtin_va_start(llvm_function *Fn, tree exp) {
tree arglist = TREE_OPERAND (exp, 1);
@@ -4094,7 +4141,6 @@
case BUILT_IN_ATAN2F:
case BUILT_IN_ATAN2L:
case BUILT_IN_MEMSET:
- case BUILT_IN_MEMCPY:
case BUILT_IN_MEMCMP:
case BUILT_IN_BCMP:
case BUILT_IN_BZERO:
@@ -4142,6 +4188,10 @@
case BUILT_IN_NEARBYINTF:
case BUILT_IN_NEARBYINTL:
return llvm_expand_call (Fn, exp, DestLoc);
+
+ case BUILT_IN_MEMCPY:
+ assert(DestLoc == 0 && "memcpy doesn't return aggregate!");
+ return llvm_expand_builtin_memcpy(Fn, arglist);
default:
break;
}
@@ -4395,12 +4445,6 @@
return target;
break;
- case BUILT_IN_MEMCPY:
- target = expand_builtin_memcpy (arglist, target, mode);
- if (target)
- return target;
- break;
-
case BUILT_IN_MEMSET:
target = expand_builtin_memset (exp, target, mode);
if (target)
@@ -5459,8 +5503,9 @@
Result = ReadBitField(Fn, Result, BitStart, BitSize);
} else if (DestLoc) { /* Generating structure, using value */
+ unsigned Align = TYPE_ALIGN(TREE_TYPE(exp))/8;
assert(BitSize == 0 && "Invalid bitfield read of composite value!");
- llvm_copy_aggregate(Fn, DestLoc, op0, expVolatile, 0);
+ llvm_copy_aggregate(Fn, DestLoc, op0, expVolatile, 0, Align);
}
}
break; /* Generating structure, ignoring value */
@@ -5487,7 +5532,8 @@
if (!isDestTyComposite) { /* Return a normal scalar by loading it */
Result = append_inst(Fn, create_load_inst("tmp", op0, expVolatile));
} else {
- llvm_copy_aggregate(Fn, DestLoc, op0, expVolatile, 0);
+ unsigned Align = TYPE_ALIGN(TREE_TYPE(exp))/8;
+ llvm_copy_aggregate(Fn, DestLoc, op0, expVolatile, 0, Align);
}
break;
}
@@ -5948,7 +5994,7 @@
*/
if (DestLoc)
llvm_copy_aggregate(Fn, DestLoc, op0,
- TYPE_VOLATILE(TREE_TYPE(TREE_OPERAND (exp, 0))), 0);
+ TYPE_VOLATILE(TREE_TYPE(TREE_OPERAND (exp, 0))), 0,1);
break;
More information about the llvm-commits
mailing list