From 9e2446b38c94db61b2416c28fee415c03663c11c Mon Sep 17 00:00:00 2001
From: rdivacky <rdivacky@FreeBSD.org>
Date: Wed, 10 Mar 2010 17:45:15 +0000
Subject: Update LLVM to r98164.

---
 lib/Transforms/InstCombine/InstCombineCalls.cpp | 141 +++++++++++++++++++++++-
 1 file changed, 139 insertions(+), 2 deletions(-)

(limited to 'lib/Transforms/InstCombine/InstCombineCalls.cpp')

diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index a241f169..0582210 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -16,6 +16,7 @@
 #include "llvm/Support/CallSite.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Analysis/MemoryBuiltins.h"
+#include "llvm/Transforms/Utils/BuildLibCalls.h"
 using namespace llvm;
 
 /// getPromotedType - Return the specified type promoted as it would be to pass
@@ -336,6 +337,16 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
         }
         return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, AllocaSize));
       }
+    } else if (CallInst *MI = extractMallocCall(Op1)) {
+      const Type* MallocType = getMallocAllocatedType(MI);
+      // Get alloca size.
+      if (MallocType && MallocType->isSized()) {
+        if (Value *NElems = getMallocArraySize(MI, TD, true)) {
+          if (ConstantInt *NElements = dyn_cast<ConstantInt>(NElems))
+        return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy,
+               (NElements->getZExtValue() * TD->getTypeAllocSize(MallocType))));
+        }
+      }
     } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Op1)) {      
       // Only handle constant GEPs here.
       if (CE->getOpcode() != Instruction::GetElementPtr) break;
@@ -347,7 +358,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
       Operand = Operand->stripPointerCasts();
       if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Operand))
         if (!GV->hasDefinitiveInitializer()) break;
-      
+        
       // Get what we're pointing to and its size. 
       const PointerType *BaseType = 
         cast<PointerType>(Operand->getType());
@@ -370,7 +381,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
       Constant *RetVal = ConstantInt::get(ReturnTy, Size-Offset);
       return ReplaceInstUsesWith(CI, RetVal);
       
-    }
+    } 
 
     // Do not return "I don't know" here. Later optimization passes could
     // make it possible to evaluate objectsize to a constant.
@@ -740,6 +751,122 @@ static bool isSafeToEliminateVarargsCast(const CallSite CS,
   return true;
 }
 
+// Try to fold some different type of calls here.
+// Currently we're only working with the checking functions, memcpy_chk, 
+// mempcpy_chk, memmove_chk, memset_chk, strcpy_chk, stpcpy_chk, strncpy_chk,
+// strcat_chk and strncat_chk.
+Instruction *InstCombiner::tryOptimizeCall(CallInst *CI, const TargetData *TD) {
+  if (CI->getCalledFunction() == 0) return 0;
+  
+  StringRef Name = CI->getCalledFunction()->getName();
+  BasicBlock *BB = CI->getParent();
+  IRBuilder<> B(CI->getParent()->getContext());
+  
+  // Set the builder to the instruction after the call.
+  B.SetInsertPoint(BB, CI);
+
+  if (Name == "__memcpy_chk") {
+    ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4));
+    if (!SizeCI)
+      return 0;
+    ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3));
+    if (!SizeArg)
+      return 0;
+    if (SizeCI->isAllOnesValue() ||
+        SizeCI->getZExtValue() <= SizeArg->getZExtValue()) {
+      EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3),
+                 1, B, TD);
+      return ReplaceInstUsesWith(*CI, CI->getOperand(1));
+    }
+    return 0;
+  }
+
+  // Should be similar to memcpy.
+  if (Name == "__mempcpy_chk") {
+    return 0;
+  }
+
+  if (Name == "__memmove_chk") {
+    ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4));
+    if (!SizeCI)
+      return 0;
+    ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3));
+    if (!SizeArg)
+      return 0;
+    if (SizeCI->isAllOnesValue() ||
+        SizeCI->getZExtValue() <= SizeArg->getZExtValue()) {
+      EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3),
+                  1, B, TD);
+      return ReplaceInstUsesWith(*CI, CI->getOperand(1));
+    }
+    return 0;
+  }
+
+  if (Name == "__memset_chk") {
+    ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4));
+    if (!SizeCI)
+      return 0;
+    ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3));
+    if (!SizeArg)
+      return 0;
+    if (SizeCI->isAllOnesValue() ||
+        SizeCI->getZExtValue() <= SizeArg->getZExtValue()) {
+      Value *Val = B.CreateIntCast(CI->getOperand(2), B.getInt8Ty(),
+                                   false);
+      EmitMemSet(CI->getOperand(1), Val,  CI->getOperand(3), B, TD);
+      return ReplaceInstUsesWith(*CI, CI->getOperand(1));
+    }
+    return 0;
+  }
+
+  if (Name == "__strcpy_chk") {
+    ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3));
+    if (!SizeCI)
+      return 0;
+    // If a) we don't have any length information, or b) we know this will
+    // fit then just lower to a plain strcpy. Otherwise we'll keep our
+    // strcpy_chk call which may fail at runtime if the size is too long.
+    // TODO: It might be nice to get a maximum length out of the possible
+    // string lengths for varying.
+    if (SizeCI->isAllOnesValue() ||
+      SizeCI->getZExtValue() >= GetStringLength(CI->getOperand(2))) {
+      Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD);
+      return ReplaceInstUsesWith(*CI, Ret);
+    }
+    return 0;
+  }
+
+  // Should be similar to strcpy.
+  if (Name == "__stpcpy_chk") {
+    return 0;
+  }
+
+  if (Name == "__strncpy_chk") {
+    ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(4));
+    if (!SizeCI)
+      return 0;
+    ConstantInt *SizeArg = dyn_cast<ConstantInt>(CI->getOperand(3));
+    if (!SizeArg)
+      return 0;
+    if (SizeCI->isAllOnesValue() ||
+        SizeCI->getZExtValue() <= SizeArg->getZExtValue()) {
+      Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD);
+      return ReplaceInstUsesWith(*CI, Ret);
+    }
+    return 0; 
+  }
+
+  if (Name == "__strcat_chk") {
+    return 0;
+  }
+
+  if (Name == "__strncat_chk") {
+    return 0;
+  }
+
+  return 0;
+}
+
 // visitCallSite - Improvements for call and invoke instructions.
 //
 Instruction *InstCombiner::visitCallSite(CallSite CS) {
@@ -826,6 +953,16 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) {
     Changed = true;
   }
 
+  // Try to optimize the call if possible, we require TargetData for most of
+  // this.  None of these calls are seen as possibly dead so go ahead and
+  // delete the instruction now.
+  if (CallInst *CI = dyn_cast<CallInst>(CS.getInstruction())) {
+    Instruction *I = tryOptimizeCall(CI, TD);
+    // If we changed something return the result, etc. Otherwise let
+    // the fallthrough check.
+    if (I) return EraseInstFromFunction(*I);
+  }
+
   return Changed ? CS.getInstruction() : 0;
 }
 
-- 
cgit v1.1