[PATCH] D45344: [SimplifyLibcalls] Fold malloc + memset to calloc even for llvm.memset

Dávid Bolvanský via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 7 11:22:28 PDT 2018


xbolva00 updated this revision to Diff 141499.

https://reviews.llvm.org/D45344

Files:
  lib/Transforms/Utils/SimplifyLibCalls.cpp
  test/Transforms/InstCombine/memset-1.ll


Index: test/Transforms/InstCombine/memset-1.ll
===================================================================
--- test/Transforms/InstCombine/memset-1.ll
+++ test/Transforms/InstCombine/memset-1.ll
@@ -31,17 +31,14 @@
   ret i8* %call2
 }
 
-; FIXME: A memset intrinsic should be handled similarly to a memset() libcall.
-
-define i8* @malloc_and_memset_intrinsic(i32 %n) #0 {
-; CHECK-LABEL: @malloc_and_memset_intrinsic(
-; CHECK-NEXT:    [[CALL:%.*]] = call i8* @malloc(i32 [[N:%.*]])
-; CHECK-NEXT:    call void @llvm.memset.p0i8.i32(i8* align 1 [[CALL]], i8 0, i32 [[N]], i1 false)
-; CHECK-NEXT:    ret i8* [[CALL]]
+define i8* @memset_intristic_malloc(i32 %n) #0 {
+; CHECK-LABEL: @memset_intristic_malloc(
+; CHECK-NEXT:    [[CALLOC:%.*]] = call i8* @calloc(i32 1, i32 [[N:%.*]])
+; CHECK-NEXT:    ret i8* [[CALLOC]]
 ;
   %call = call i8* @malloc(i32 %n)
   call void @llvm.memset.p0i8.i32(i8* %call, i8 0, i32 %n, i32 1, i1 false)
-  ret i8* %call
+  ret i8*%call
 }
 
 ; This should not create a calloc and should not crash the compiler.
Index: lib/Transforms/Utils/SimplifyLibCalls.cpp
===================================================================
--- lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -835,19 +835,39 @@
 /// Fold memset[_chk](malloc(n), 0, n) --> calloc(1, n).
 static Value *foldMallocMemset(CallInst *Memset, IRBuilder<> &B,
                                const TargetLibraryInfo &TLI) {
+  auto Src = Memset->getArgOperand(0);
   // This has to be a memset of zeros (bzero).
   auto *FillValue = dyn_cast<ConstantInt>(Memset->getArgOperand(1));
   if (!FillValue || FillValue->getZExtValue() != 0)
     return nullptr;
 
-  // TODO: We should handle the case where the malloc has more than one use.
-  // This is necessary to optimize common patterns such as when the result of
-  // the malloc is checked against null or when a memset intrinsic is used in
-  // place of a memset library call.
+  auto *Malloc = dyn_cast<CallInst>(Src);
+  if (!FillValue || FillValue->getZExtValue() != 0)
+    return nullptr;
+
   auto *Malloc = dyn_cast<CallInst>(Memset->getArgOperand(0));
-  if (!Malloc || !Malloc->hasOneUse())
+  if (!Malloc)
     return nullptr;
 
+  if (!Malloc->hasOneUse()) {
+    Instruction *I = Malloc->getNextNode();
+    while (I) {
+      auto *Call = dyn_cast<CallInst>(I);
+      if (Call && Call == Memset)
+        break;
+
+      for (unsigned i = 0; i < I->getNumOperands(); ++i) {
+        if (Src == I->getOperand(i)) {
+          return nullptr;
+        }
+      }
+
+      I = I->getNextNode();
+      if (!I)
+        return nullptr;
+    }
+  }
+
   // Is the inner call really malloc()?
   Function *InnerCallee = Malloc->getCalledFunction();
   if (!InnerCallee)
@@ -883,6 +903,10 @@
   if (auto *Calloc = foldMallocMemset(CI, B, *TLI))
     return Calloc;
 
+  if (CI->getCalledFunction()->isIntrinsic()) {
+    return nullptr;
+  }
+
   // memset(p, v, n) -> llvm.memset(align 1 p, v, n)
   Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false);
   B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), 1);
@@ -2219,7 +2243,8 @@
       return optimizeLog(CI, Builder);
     case Intrinsic::sqrt:
       return optimizeSqrt(CI, Builder);
-    // TODO: Use foldMallocMemset() with memset intrinsic.
+    case Intrinsic::memset:
+      return optimizeMemSet(CI, Builder);
     default:
       return nullptr;
     }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D45344.141499.patch
Type: text/x-patch
Size: 3463 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180407/545118f9/attachment.bin>


More information about the llvm-commits mailing list