[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