[SLC] Optimize strncpy(a, a, C) to memcpy(a, a000, C)
authorDávid Bolvanský <david.bolvansky@gmail.com>
Thu, 13 Aug 2020 20:22:33 +0000 (22:22 +0200)
committerDávid Bolvanský <david.bolvansky@gmail.com>
Thu, 13 Aug 2020 20:22:51 +0000 (22:22 +0200)
Solves PR47154

llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
llvm/test/Transforms/InstCombine/strncpy-3.ll [new file with mode: 0644]

index b03389a..2f6e60f 100644 (file)
@@ -608,9 +608,15 @@ Value *LibCallSimplifier::optimizeStrNCpy(CallInst *CI, IRBuilderBase &B) {
     return Dst;
   }
 
-  // Let strncpy handle the zero padding
-  if (Len > SrcLen + 1)
-    return nullptr;
+  // strncpy(a, "a", 4) - > memcpy(a, "a\0\0\0", 4)
+  if (Len > SrcLen + 1) {
+    StringRef Str;
+    if (!getConstantStringInfo(Src, Str))
+      return nullptr;
+    std::string SrcStr = Str.str();
+    SrcStr.resize(Len, '\0');
+    Src = B.CreateGlobalString(SrcStr, "str");
+  }
 
   Type *PT = Callee->getFunctionType()->getParamType(0);
   // strncpy(x, s, c) -> memcpy(align 1 x, align 1 s, c) [s and c are constant]
diff --git a/llvm/test/Transforms/InstCombine/strncpy-3.ll b/llvm/test/Transforms/InstCombine/strncpy-3.ll
new file mode 100644 (file)
index 0000000..744f1e4
--- /dev/null
@@ -0,0 +1,40 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+
+@str = constant [2 x i8] c"a\00"
+@str2 = constant [3 x i8] c"abc"
+@str3 = constant [4 x i8] c"abcd"
+
+declare i8* @strncpy(i8*, i8*, i64)
+
+
+define void @fill_with_zeros(i8* %dst) {
+; CHECK-LABEL: @fill_with_zeros(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i8* [[DST:%.*]] to i32*
+; CHECK-NEXT:    store i32 97, i32* [[TMP1]], align 1
+; CHECK-NEXT:    ret void
+;
+  tail call i8* @strncpy(i8* %dst, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @str, i64 0, i64 0), i64 4)
+  ret void
+}
+
+define void @fill_with_zeros2(i8* %dst) {
+; CHECK-LABEL: @fill_with_zeros2(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i8* [[DST:%.*]] to i32*
+; CHECK-NEXT:    store i32 6513249, i32* [[TMP1]], align 1
+; CHECK-NEXT:    ret void
+;
+  tail call i8* @strncpy(i8* %dst, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @str2, i64 0, i64 0), i64 4)
+  ret void
+}
+
+define void @fill_with_zeros3(i8* %dst) {
+; CHECK-LABEL: @fill_with_zeros3(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast i8* [[DST:%.*]] to i32*
+; CHECK-NEXT:    store i32 1684234849, i32* [[TMP1]], align 1
+; CHECK-NEXT:    ret void
+;
+  tail call i8* @strncpy(i8* %dst, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @str3, i64 0, i64 0), i64 4)
+  ret void
+}