fold memcpy/set/move_chk to llvm.memcpy/set/move when the sizes
are trivial.  This exposes opportunities earlier, and allows fastisel
to do good things with these at -O0.

This addresses rdar://9289468 - clang doesn't fold memset_chk at -O0


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129651 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 97b93d5..51d9eeb 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -543,6 +543,22 @@
     return RValue::get(Address);
   }
       
+  case Builtin::BI__builtin___memcpy_chk: {
+    // fold __builtin_memcpy_chk(x, y, cst1, cst2) to memset iff cst1<=cst2.
+    if (!E->getArg(2)->isEvaluatable(CGM.getContext()) ||
+        !E->getArg(3)->isEvaluatable(CGM.getContext()))
+      break;
+    llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext());
+    llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext());
+    if (Size.ugt(DstSize))
+      break;
+    Value *Dest = EmitScalarExpr(E->getArg(0));
+    Value *Src = EmitScalarExpr(E->getArg(1));
+    Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size);
+    Builder.CreateMemCpy(Dest, Src, SizeVal, 1, false);
+    return RValue::get(0);
+  }
+      
   case Builtin::BI__builtin_objc_memmove_collectable: {
     Value *Address = EmitScalarExpr(E->getArg(0));
     Value *SrcAddr = EmitScalarExpr(E->getArg(1));
@@ -551,7 +567,23 @@
                                                   Address, SrcAddr, SizeVal);
     return RValue::get(Address);
   }
-      
+
+  case Builtin::BI__builtin___memmove_chk: {
+    // fold __builtin_memmove_chk(x, y, cst1, cst2) to memset iff cst1<=cst2.
+    if (!E->getArg(2)->isEvaluatable(CGM.getContext()) ||
+        !E->getArg(3)->isEvaluatable(CGM.getContext()))
+      break;
+    llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext());
+    llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext());
+    if (Size.ugt(DstSize))
+      break;
+    Value *Dest = EmitScalarExpr(E->getArg(0));
+    Value *Src = EmitScalarExpr(E->getArg(1));
+    Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size);
+    Builder.CreateMemMove(Dest, Src, SizeVal, 1, false);
+    return RValue::get(0);
+  }
+
   case Builtin::BImemmove:
   case Builtin::BI__builtin_memmove: {
     Value *Address = EmitScalarExpr(E->getArg(0));
@@ -569,6 +601,23 @@
     Builder.CreateMemSet(Address, ByteVal, SizeVal, 1, false);
     return RValue::get(Address);
   }
+  case Builtin::BI__builtin___memset_chk: {
+    // fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2.
+    if (!E->getArg(2)->isEvaluatable(CGM.getContext()) ||
+        !E->getArg(3)->isEvaluatable(CGM.getContext()))
+      break;
+    llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext());
+    llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext());
+    if (Size.ugt(DstSize))
+      break;
+    Value *Address = EmitScalarExpr(E->getArg(0));
+    Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)),
+                                         Builder.getInt8Ty());
+    Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size);
+    Builder.CreateMemSet(Address, ByteVal, SizeVal, 1, false);
+    
+    return RValue::get(0);
+  }
   case Builtin::BI__builtin_dwarf_cfa: {
     // The offset in bytes from the first argument to the CFA.
     //