diff options
| author | David Bolvansky <david.bolvansky@gmail.com> | 2019-08-13 09:11:49 +0000 | 
|---|---|---|
| committer | David Bolvansky <david.bolvansky@gmail.com> | 2019-08-13 09:11:49 +0000 | 
| commit | 39130314feeda2d3e0f8966c3809e9cd73ff6b22 (patch) | |
| tree | acb2b831e8a280cc449b00d930e6fec49f4a1144 | |
| parent | 09eb71ced3b80211f3997bd7bc2844c61cd265c7 (diff) | |
| download | bcm5719-llvm-39130314feeda2d3e0f8966c3809e9cd73ff6b22.tar.gz bcm5719-llvm-39130314feeda2d3e0f8966c3809e9cd73ff6b22.zip  | |
[SimplifyLibCalls] Add dereferenceable bytes from known callsites
Summary:
int mm(char *a, char *b) {
    return memcmp(a,b,16);
}
Currently:
define dso_local i32 @mm(i8* nocapture readonly %a, i8* nocapture readonly %b) local_unnamed_addr #1 {
entry:
  %call = tail call i32 @memcmp(i8* %a, i8* %b, i64 16)
  ret i32 %call
}
After patch:
define dso_local i32 @mm(i8* nocapture readonly %a, i8* nocapture readonly %b) local_unnamed_addr #1 {
entry:
  %call = tail call i32 @memcmp(i8* dereferenceable(16)  %a, i8* dereferenceable(16)  %b, i64 16)
  ret i32 %call
}
Reviewers: jdoerfert, efriedma
Reviewed By: jdoerfert
Subscribers: javed.absar, spatel, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D66079
llvm-svn: 368657
22 files changed, 870 insertions, 361 deletions
diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h index 2572094ddac..b7e6224f855 100644 --- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -167,9 +167,9 @@ private:    Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B);    Value *optimizeBCmp(CallInst *CI, IRBuilder<> &B);    Value *optimizeMemCmpBCmpCommon(CallInst *CI, IRBuilder<> &B); -  Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B); -  Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B); -  Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B); +  Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B, bool isIntrinsic = false); +  Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B, bool isIntrinsic = false); +  Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B, bool isIntrinsic = false);    Value *optimizeRealloc(CallInst *CI, IRBuilder<> &B);    Value *optimizeWcslen(CallInst *CI, IRBuilder<> &B);    // Wrapper for all String/Memory Library Call Optimizations diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 32b845cb16b..396690e1860 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -186,6 +186,20 @@ static bool canTransformToMemCmp(CallInst *CI, Value *Str, uint64_t Len,    return true;  } +static void annotateDereferenceableBytes(CallInst *CI, +                                         ArrayRef<unsigned> ArgNos, +                                         uint64_t DerefBytes) { +  for (unsigned ArgNo : ArgNos) { +    if (CI->getDereferenceableBytes(ArgNo + AttributeList::FirstArgIndex) < +        DerefBytes) { +      CI->removeParamAttr(ArgNo, Attribute::Dereferenceable); +      CI->removeParamAttr(ArgNo, Attribute::DereferenceableOrNull); +      CI->addParamAttr(ArgNo, Attribute::getWithDereferenceableBytes( +                                  CI->getContext(), DerefBytes)); +    } +  } +} +  //===----------------------------------------------------------------------===//  // String and Memory Library Call Optimizations  //===----------------------------------------------------------------------===// @@ -765,9 +779,11 @@ Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilder<> &B) {    ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getArgOperand(2));    // memchr(x, y, 0) -> null -  if (LenC && LenC->isZero()) -    return Constant::getNullValue(CI->getType()); - +  if (LenC) { +    if (LenC->isZero()) +      return Constant::getNullValue(CI->getType()); +    annotateDereferenceableBytes(CI, {0}, LenC->getZExtValue()); +  }    // From now on we need at least constant length and string.    StringRef Str;    if (!LenC || !getConstantStringInfo(SrcStr, Str, 0, /*TrimAtNul=*/false)) @@ -926,10 +942,12 @@ Value *LibCallSimplifier::optimizeMemCmpBCmpCommon(CallInst *CI,      return Constant::getNullValue(CI->getType());    // Handle constant lengths. -  if (ConstantInt *LenC = dyn_cast<ConstantInt>(Size)) +  if (ConstantInt *LenC = dyn_cast<ConstantInt>(Size)) {      if (Value *Res = optimizeMemCmpConstantSize(CI, LHS, RHS,                                                  LenC->getZExtValue(), B, DL))        return Res; +    annotateDereferenceableBytes(CI, {0, 1}, LenC->getZExtValue()); +  }    return nullptr;  } @@ -955,18 +973,31 @@ Value *LibCallSimplifier::optimizeBCmp(CallInst *CI, IRBuilder<> &B) {    return optimizeMemCmpBCmpCommon(CI, B);  } -Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B) { +Value *LibCallSimplifier::optimizeMemCpy(CallInst *CI, IRBuilder<> &B, +                                         bool isIntrinsic) { +  Value *Size = CI->getArgOperand(2); +  if (ConstantInt *LenC = dyn_cast<ConstantInt>(Size)) +    annotateDereferenceableBytes(CI, {0, 1}, LenC->getZExtValue()); + +  if (isIntrinsic) +    return nullptr; +    // memcpy(x, y, n) -> llvm.memcpy(align 1 x, align 1 y, n) -  B.CreateMemCpy(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, -                 CI->getArgOperand(2)); +  B.CreateMemCpy(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, Size);    return CI->getArgOperand(0);  } -Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B) { +Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B, bool isIntrinsic) { +  Value *Size = CI->getArgOperand(2); +  if (ConstantInt *LenC = dyn_cast<ConstantInt>(Size)) +    annotateDereferenceableBytes(CI, {0, 1}, LenC->getZExtValue()); + +  if (isIntrinsic) +    return nullptr; +    // memmove(x, y, n) -> llvm.memmove(align 1 x, align 1 y, n) -  B.CreateMemMove(CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, -                  CI->getArgOperand(2)); -  return CI->getArgOperand(0); +  B.CreateMemMove( CI->getArgOperand(0), 1, CI->getArgOperand(1), 1, Size); +  return  CI->getArgOperand(0);  }  /// Fold memset[_chk](malloc(n), 0, n) --> calloc(1, n). @@ -1015,13 +1046,21 @@ Value *LibCallSimplifier::foldMallocMemset(CallInst *Memset, IRBuilder<> &B) {    return Calloc;  } -Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B) { +Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B, +                                         bool isIntrinsic) { +  Value *Size = CI->getArgOperand(2); +  if (ConstantInt *LenC = dyn_cast<ConstantInt>(Size)) +    annotateDereferenceableBytes(CI, {0}, LenC->getZExtValue()); + +  if (isIntrinsic) +    return nullptr; +    if (auto *Calloc = foldMallocMemset(CI, B))      return Calloc;    // 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); +  B.CreateMemSet(CI->getArgOperand(0), Val, Size, 1);    return CI->getArgOperand(0);  } @@ -2710,6 +2749,12 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI) {      case Intrinsic::sqrt:        return optimizeSqrt(CI, Builder);      // TODO: Use foldMallocMemset() with memset intrinsic. +    case Intrinsic::memset: +      return optimizeMemSet(CI, Builder, true); +    case Intrinsic::memcpy: +      return optimizeMemCpy(CI, Builder, true); +    case Intrinsic::memmove: +      return optimizeMemMove(CI, Builder, true);      default:        return nullptr;      } diff --git a/llvm/test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll b/llvm/test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll index ecc737c77e4..2af23629d1c 100644 --- a/llvm/test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll +++ b/llvm/test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll @@ -6,7 +6,7 @@ target datalayout = "e-p:64:64:64"  ; it has a TBAA tag which declares that it is unrelated.  ; CHECK: @foo -; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %p, i8* align 1 %q, i64 16, i1 false), !tbaa !0 +; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(16) %p, i8* align 1 dereferenceable(16) %q, i64 16, i1 false), !tbaa !0  ; CHECK-NEXT: store i8 2, i8* %s, align 1, !tbaa [[TAGA:!.*]]  ; CHECK-NEXT: ret void  define void @foo(i8* nocapture %p, i8* nocapture %q, i8* nocapture %s) nounwind { diff --git a/llvm/test/Transforms/InstCombine/ARM/strcmp.ll b/llvm/test/Transforms/InstCombine/ARM/strcmp.ll index 571a0f950e0..0a07d0a8ac8 100644 --- a/llvm/test/Transforms/InstCombine/ARM/strcmp.ll +++ b/llvm/test/Transforms/InstCombine/ARM/strcmp.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; Test that the strcmp library call simplifier works correctly.  ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -13,10 +14,11 @@ declare i32 @strcmp(i8*, i8*)  ; strcmp("", x) -> -*x  define arm_aapcscc i32 @test1(i8* %str2) {  ; CHECK-LABEL: @test1( -; CHECK: %strcmpload = load i8, i8* %str -; CHECK: %1 = zext i8 %strcmpload to i32 -; CHECK: %2 = sub nsw i32 0, %1 -; CHECK: ret i32 %2 +; CHECK-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR2:%.*]], align 1 +; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 +; CHECK-NEXT:    [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]] +; CHECK-NEXT:    ret i32 [[TMP2]] +;    %str1 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0    %temp1 = call arm_apcscc i32 @strcmp(i8* %str1, i8* %str2) @@ -27,9 +29,10 @@ define arm_aapcscc i32 @test1(i8* %str2) {  ; strcmp(x, "") -> *x  define arm_aapcscc i32 @test2(i8* %str1) {  ; CHECK-LABEL: @test2( -; CHECK: %strcmpload = load i8, i8* %str -; CHECK: %1 = zext i8 %strcmpload to i32 -; CHECK: ret i32 %1 +; CHECK-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR1:%.*]], align 1 +; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 +; CHECK-NEXT:    ret i32 [[TMP1]] +;    %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0    %temp1 = call arm_aapcscc i32 @strcmp(i8* %str1, i8* %str2) @@ -39,7 +42,8 @@ define arm_aapcscc i32 @test2(i8* %str1) {  ; strcmp(x, y)  -> cnst  define arm_aapcscc i32 @test3() {  ; CHECK-LABEL: @test3( -; CHECK: ret i32 -1 +; CHECK-NEXT:    ret i32 -1 +;    %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0    %str2 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0 @@ -49,7 +53,8 @@ define arm_aapcscc i32 @test3() {  define arm_aapcscc i32 @test4() {  ; CHECK-LABEL: @test4( -; CHECK: ret i32 1 +; CHECK-NEXT:    ret i32 1 +;    %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0    %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0 @@ -61,8 +66,10 @@ define arm_aapcscc i32 @test4() {  ; (This transform is rather difficult to trigger in a useful manner)  define arm_aapcscc i32 @test5(i1 %b) {  ; CHECK-LABEL: @test5( -; CHECK: %memcmp = call i32 @memcmp(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* %str2, i32 5) -; CHECK: ret i32 %memcmp +; CHECK-NEXT:    [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; CHECK-NEXT:    ret i32 [[MEMCMP]] +;    %str1 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0    %temp1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0 @@ -75,7 +82,8 @@ define arm_aapcscc i32 @test5(i1 %b) {  ; strcmp(x,x)  -> 0  define arm_aapcscc i32 @test6(i8* %str) {  ; CHECK-LABEL: @test6( -; CHECK: ret i32 0 +; CHECK-NEXT:    ret i32 0 +;    %temp1 = call arm_aapcscc i32 @strcmp(i8* %str, i8* %str)    ret i32 %temp1 @@ -84,10 +92,11 @@ define arm_aapcscc i32 @test6(i8* %str) {  ; strcmp("", x) -> -*x  define arm_aapcs_vfpcc i32 @test1_vfp(i8* %str2) {  ; CHECK-LABEL: @test1_vfp( -; CHECK: %strcmpload = load i8, i8* %str -; CHECK: %1 = zext i8 %strcmpload to i32 -; CHECK: %2 = sub nsw i32 0, %1 -; CHECK: ret i32 %2 +; CHECK-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR2:%.*]], align 1 +; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 +; CHECK-NEXT:    [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]] +; CHECK-NEXT:    ret i32 [[TMP2]] +;    %str1 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0    %temp1 = call arm_aapcs_vfpcc i32 @strcmp(i8* %str1, i8* %str2) @@ -98,9 +107,10 @@ define arm_aapcs_vfpcc i32 @test1_vfp(i8* %str2) {  ; strcmp(x, "") -> *x  define arm_aapcs_vfpcc i32 @test2_vfp(i8* %str1) {  ; CHECK-LABEL: @test2_vfp( -; CHECK: %strcmpload = load i8, i8* %str -; CHECK: %1 = zext i8 %strcmpload to i32 -; CHECK: ret i32 %1 +; CHECK-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR1:%.*]], align 1 +; CHECK-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 +; CHECK-NEXT:    ret i32 [[TMP1]] +;    %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0    %temp1 = call arm_aapcs_vfpcc i32 @strcmp(i8* %str1, i8* %str2) @@ -110,7 +120,8 @@ define arm_aapcs_vfpcc i32 @test2_vfp(i8* %str1) {  ; strcmp(x, y)  -> cnst  define arm_aapcs_vfpcc i32 @test3_vfp() {  ; CHECK-LABEL: @test3_vfp( -; CHECK: ret i32 -1 +; CHECK-NEXT:    ret i32 -1 +;    %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0    %str2 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0 @@ -120,7 +131,8 @@ define arm_aapcs_vfpcc i32 @test3_vfp() {  define arm_aapcs_vfpcc i32 @test4_vfp() {  ; CHECK-LABEL: @test4_vfp( -; CHECK: ret i32 1 +; CHECK-NEXT:    ret i32 1 +;    %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0    %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0 @@ -132,8 +144,10 @@ define arm_aapcs_vfpcc i32 @test4_vfp() {  ; (This transform is rather difficult to trigger in a useful manner)  define arm_aapcs_vfpcc i32 @test5_vfp(i1 %b) {  ; CHECK-LABEL: @test5_vfp( -; CHECK: %memcmp = call i32 @memcmp(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* %str2, i32 5) -; CHECK: ret i32 %memcmp +; CHECK-NEXT:    [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; CHECK-NEXT:    ret i32 [[MEMCMP]] +;    %str1 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0    %temp1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0 @@ -146,7 +160,8 @@ define arm_aapcs_vfpcc i32 @test5_vfp(i1 %b) {  ; strcmp(x,x)  -> 0  define arm_aapcs_vfpcc i32 @test6_vfp(i8* %str) {  ; CHECK-LABEL: @test6_vfp( -; CHECK: ret i32 0 +; CHECK-NEXT:    ret i32 0 +;    %temp1 = call arm_aapcs_vfpcc i32 @strcmp(i8* %str, i8* %str)    ret i32 %temp1 diff --git a/llvm/test/Transforms/InstCombine/align-addr.ll b/llvm/test/Transforms/InstCombine/align-addr.ll index d92daddd761..80449918b95 100644 --- a/llvm/test/Transforms/InstCombine/align-addr.ll +++ b/llvm/test/Transforms/InstCombine/align-addr.ll @@ -1,13 +1,33 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; RUN: opt < %s -instcombine -S | FileCheck %s  target datalayout = "E-p:64:64:64-p1:32:32:32-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"  ; Instcombine should be able to prove vector alignment in the  ; presence of a few mild address computation tricks. -; CHECK-LABEL: @test0( -; CHECK: align 16 -  define void @test0(i8* %b, i64 %n, i64 %u, i64 %y) nounwind  { +; CHECK-LABEL: @test0( +; CHECK-NEXT:  entry: +; CHECK-NEXT:    [[C:%.*]] = ptrtoint i8* [[B:%.*]] to i64 +; CHECK-NEXT:    [[D:%.*]] = and i64 [[C]], -16 +; CHECK-NEXT:    [[E:%.*]] = inttoptr i64 [[D]] to double* +; CHECK-NEXT:    [[V:%.*]] = shl i64 [[U:%.*]], 1 +; CHECK-NEXT:    [[Z:%.*]] = and i64 [[Y:%.*]], -2 +; CHECK-NEXT:    [[T1421:%.*]] = icmp eq i64 [[N:%.*]], 0 +; CHECK-NEXT:    br i1 [[T1421]], label [[RETURN:%.*]], label [[BB:%.*]] +; CHECK:       bb: +; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], [[BB]] ], [ 20, [[ENTRY:%.*]] ] +; CHECK-NEXT:    [[J:%.*]] = mul i64 [[I]], [[V]] +; CHECK-NEXT:    [[H:%.*]] = add i64 [[J]], [[Z]] +; CHECK-NEXT:    [[T8:%.*]] = getelementptr double, double* [[E]], i64 [[H]] +; CHECK-NEXT:    [[P:%.*]] = bitcast double* [[T8]] to <2 x double>* +; CHECK-NEXT:    store <2 x double> zeroinitializer, <2 x double>* [[P]], align 16 +; CHECK-NEXT:    [[INDVAR_NEXT]] = add i64 [[I]], 1 +; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], [[N]] +; CHECK-NEXT:    br i1 [[EXITCOND]], label [[RETURN]], label [[BB]] +; CHECK:       return: +; CHECK-NEXT:    ret void +;  entry:    %c = ptrtoint i8* %b to i64    %d = and i64 %c, -16 @@ -35,24 +55,26 @@ return:  ; When we see a unaligned load from an insufficiently aligned global or  ; alloca, increase the alignment of the load, turning it into an aligned load. -; CHECK-LABEL: @test1( -; CHECK: tmp = load -; CHECK: GLOBAL{{.*}}align 16 -  @GLOBAL = internal global [4 x i32] zeroinitializer  define <16 x i8> @test1(<2 x i64> %x) { +; CHECK-LABEL: @test1( +; CHECK-NEXT:  entry: +; CHECK-NEXT:    [[TMP:%.*]] = load <16 x i8>, <16 x i8>* bitcast ([4 x i32]* @GLOBAL to <16 x i8>*), align 16 +; CHECK-NEXT:    ret <16 x i8> [[TMP]] +;  entry: -	%tmp = load <16 x i8>, <16 x i8>* bitcast ([4 x i32]* @GLOBAL to <16 x i8>*), align 1 -	ret <16 x i8> %tmp +  %tmp = load <16 x i8>, <16 x i8>* bitcast ([4 x i32]* @GLOBAL to <16 x i8>*), align 1 +  ret <16 x i8> %tmp  }  @GLOBAL_as1 = internal addrspace(1) global [4 x i32] zeroinitializer  define <16 x i8> @test1_as1(<2 x i64> %x) {  ; CHECK-LABEL: @test1_as1( -; CHECK: tmp = load -; CHECK: GLOBAL_as1{{.*}}align 16 +; CHECK-NEXT:    [[TMP:%.*]] = load <16 x i8>, <16 x i8> addrspace(1)* bitcast ([4 x i32] addrspace(1)* @GLOBAL_as1 to <16 x i8> addrspace(1)*), align 16 +; CHECK-NEXT:    ret <16 x i8> [[TMP]] +;    %tmp = load <16 x i8>, <16 x i8> addrspace(1)* bitcast ([4 x i32] addrspace(1)* @GLOBAL_as1 to <16 x i8> addrspace(1)*), align 1    ret <16 x i8> %tmp  } @@ -61,8 +83,9 @@ define <16 x i8> @test1_as1(<2 x i64> %x) {  define <16 x i8> @test1_as1_gep(<2 x i64> %x) {  ; CHECK-LABEL: @test1_as1_gep( -; CHECK: tmp = load -; CHECK: GLOBAL_as1_gep{{.*}}align 16 +; CHECK-NEXT:    [[TMP:%.*]] = load <16 x i8>, <16 x i8> addrspace(1)* bitcast (i32 addrspace(1)* getelementptr inbounds ([8 x i32], [8 x i32] addrspace(1)* @GLOBAL_as1_gep, i32 0, i32 4) to <16 x i8> addrspace(1)*), align 16 +; CHECK-NEXT:    ret <16 x i8> [[TMP]] +;    %tmp = load <16 x i8>, <16 x i8> addrspace(1)* bitcast (i32 addrspace(1)* getelementptr ([8 x i32], [8 x i32] addrspace(1)* @GLOBAL_as1_gep, i16 0, i16 4) to <16 x i8> addrspace(1)*), align 1    ret <16 x i8> %tmp  } @@ -70,11 +93,12 @@ define <16 x i8> @test1_as1_gep(<2 x i64> %x) {  ; When a load or store lacks an explicit alignment, add one. -; CHECK-LABEL: @test2( -; CHECK: load double, double* %p, align 8 -; CHECK: store double %n, double* %p, align 8 -  define double @test2(double* %p, double %n) nounwind { +; CHECK-LABEL: @test2( +; CHECK-NEXT:    [[T:%.*]] = load double, double* [[P:%.*]], align 8 +; CHECK-NEXT:    store double [[N:%.*]], double* [[P]], align 8 +; CHECK-NEXT:    ret double [[T]] +;    %t = load double, double* %p    store double %n, double* %p    ret double %t @@ -89,9 +113,13 @@ declare void @use(i8*)  define void @test3(%struct.s* sret %a4) {  ; Check that the alignment is bumped up the alignment of the sret type.  ; CHECK-LABEL: @test3( +; CHECK-NEXT:    [[A4_CAST:%.*]] = bitcast %struct.s* [[A4:%.*]] to i8* +; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 dereferenceable(16) [[A4_CAST]], i8 0, i64 16, i1 false) +; CHECK-NEXT:    call void @use(i8* [[A4_CAST]]) +; CHECK-NEXT:    ret void +;    %a4.cast = bitcast %struct.s* %a4 to i8*    call void @llvm.memset.p0i8.i64(i8* %a4.cast, i8 0, i64 16, i1 false) -; CHECK: call void @llvm.memset.p0i8.i64(i8* align 4 %a4.cast, i8 0, i64 16, i1 false)    call void @use(i8* %a4.cast)    ret void  } diff --git a/llvm/test/Transforms/InstCombine/mem-deref-bytes.ll b/llvm/test/Transforms/InstCombine/mem-deref-bytes.ll new file mode 100644 index 00000000000..a329f9dcdaa --- /dev/null +++ b/llvm/test/Transforms/InstCombine/mem-deref-bytes.ll @@ -0,0 +1,127 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -instcombine  -S < %s | FileCheck %s + +declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) +declare i8* @memcpy(i8* nocapture, i8* nocapture, i64) +declare i8* @memmove(i8* nocapture, i8* nocapture, i64) +declare i8* @memset(i8* nocapture, i8, i64) +declare i8* @memchr(i8* nocapture, i32, i64) +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) +declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) + +define i32 @memcmp_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { +; CHECK-LABEL: @memcmp_const_size_set_deref( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(16) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT:    ret i32 [[CALL]] +; +  %call = tail call i32 @memcmp(i8* %d, i8* %s, i64 16) +  ret i32 %call +} + +define i32 @memcmp_const_size_update_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { +; CHECK-LABEL: @memcmp_const_size_update_deref( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(16) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT:    ret i32 [[CALL]] +; +  %call = tail call i32 @memcmp(i8* dereferenceable(4) %d, i8* dereferenceable(8) %s, i64 16) +  ret i32 %call +} + +define i32 @memcmp_const_size_update_deref2(i8* nocapture readonly %d, i8* nocapture readonly %s) { +; CHECK-LABEL: @memcmp_const_size_update_deref2( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(16) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT:    ret i32 [[CALL]] +; +  %call = tail call i32 @memcmp(i8* %d, i8* dereferenceable_or_null(8) %s, i64 16) +  ret i32 %call +} + +define i32 @memcmp_const_size_no_update_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { +; CHECK-LABEL: @memcmp_const_size_no_update_deref( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(40) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT:    ret i32 [[CALL]] +; +  %call = tail call i32 @memcmp(i8* dereferenceable(40) %d, i8* %s, i64 16) +  ret i32 %call +} + +define i32 @memcmp_const_size_no_update_deref2(i8* nocapture readonly %d, i8* nocapture readonly %s) { +; CHECK-LABEL: @memcmp_const_size_no_update_deref2( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(16) [[D:%.*]], i8* dereferenceable(16) [[S:%.*]], i64 16) +; CHECK-NEXT:    ret i32 [[CALL]] +; +  %call = tail call i32 @memcmp(i8* dereferenceable_or_null(40) %d, i8* %s, i64 16) +  ret i32 %call +} + +define i32 @memcmp_nonconst_size(i8* nocapture readonly %d, i8* nocapture readonly %s, i64 %n) { +; CHECK-LABEL: @memcmp_nonconst_size( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* [[D:%.*]], i8* [[S:%.*]], i64 [[N:%.*]]) +; CHECK-NEXT:    ret i32 [[CALL]] +; +  %call = tail call i32 @memcmp(i8* %d, i8* %s, i64 %n) +  ret i32 %call +} + +define i8* @memcpy_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { +; CHECK-LABEL: @memcpy_const_size_set_deref( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(64) [[D:%.*]], i8* align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false) +; CHECK-NEXT:    ret i8* [[D]] +; +  %call = tail call i8* @memcpy(i8* %d, i8* %s, i64 64) +  ret i8* %call +} + +define i8* @memmove_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { +; CHECK-LABEL: @memmove_const_size_set_deref( +; CHECK-NEXT:    call void @llvm.memmove.p0i8.p0i8.i64(i8* align 1 dereferenceable(64) [[D:%.*]], i8* align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false) +; CHECK-NEXT:    ret i8* [[D]] +; +  %call = tail call i8* @memmove(i8* %d, i8* %s, i64 64) +  ret i8* %call +} + +define i8* @memset_const_size_set_deref(i8* nocapture readonly %s, i8 %c) { +; CHECK-LABEL: @memset_const_size_set_deref( +; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 1 dereferenceable(64) [[S:%.*]], i8 [[C:%.*]], i64 64, i1 false) +; CHECK-NEXT:    ret i8* [[S]] +; +  %call = tail call i8* @memset(i8* %s, i8 %c, i64 64) +  ret i8* %call +} + +define i8* @memchr_const_size_set_deref(i8* nocapture readonly %s, i32 %c) { +; CHECK-LABEL: @memchr_const_size_set_deref( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @memchr(i8* dereferenceable(64) [[S:%.*]], i32 [[C:%.*]], i64 64) +; CHECK-NEXT:    ret i8* [[CALL]] +; +  %call = tail call i8* @memchr(i8* %s, i32 %c, i64 64) +  ret i8* %call +} + +define i8* @llvm_memcpy_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { +; CHECK-LABEL: @llvm_memcpy_const_size_set_deref( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(16) [[D:%.*]], i8* align 1 dereferenceable(16) [[S:%.*]], i64 16, i1 false) +; CHECK-NEXT:    ret i8* [[D]] +; +  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %d, i8* align 1 %s, i64 16, i1 false) +  ret i8* %d +} + +define i8* @llvm_memmove_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) { +; CHECK-LABEL: @llvm_memmove_const_size_set_deref( +; CHECK-NEXT:    call void @llvm.memmove.p0i8.p0i8.i64(i8* align 1 dereferenceable(16) [[D:%.*]], i8* align 1 dereferenceable(16) [[S:%.*]], i64 16, i1 false) +; CHECK-NEXT:    ret i8* [[D]] +; +  call void @llvm.memmove.p0i8.p0i8.i64(i8* align 1 %d, i8* align 1 %s, i64 16, i1 false) +  ret i8* %d +} +define i8* @llvm_memset_const_size_set_deref(i8* nocapture readonly %s, i8 %c) { +; CHECK-LABEL: @llvm_memset_const_size_set_deref( +; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 1 dereferenceable(16) [[S:%.*]], i8 [[C:%.*]], i64 16, i1 false) +; CHECK-NEXT:    ret i8* [[S]] +; +  call void @llvm.memset.p0i8.i64(i8* align 1 %s, i8 %c, i64 16, i1 false) +  ret i8* %s +} diff --git a/llvm/test/Transforms/InstCombine/memchr.ll b/llvm/test/Transforms/InstCombine/memchr.ll index 83073e20676..808467955bc 100644 --- a/llvm/test/Transforms/InstCombine/memchr.ll +++ b/llvm/test/Transforms/InstCombine/memchr.ll @@ -50,7 +50,7 @@ define void @test3() {  define void @test4(i32 %chr) {  ; CHECK-LABEL: @test4( -; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 0), i32 [[CHR:%.*]], i32 14) +; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* dereferenceable(14) getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 0), i32 [[CHR:%.*]], i32 14)  ; CHECK-NEXT:    store i8* [[DST]], i8** @chp, align 4  ; CHECK-NEXT:    ret void  ; @@ -148,7 +148,7 @@ define i1 @test11(i32 %C) {  ; No 64 bits here  define i1 @test12(i32 %C) {  ; CHECK-LABEL: @test12( -; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @spaces, i32 0, i32 0), i32 [[C:%.*]], i32 3) +; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* dereferenceable(3) getelementptr inbounds ([4 x i8], [4 x i8]* @spaces, i32 0, i32 0), i32 [[C:%.*]], i32 3)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8* [[DST]], null  ; CHECK-NEXT:    ret i1 [[CMP]]  ; @@ -185,7 +185,7 @@ define i1 @test14(i32 %C) {  define i1 @test15(i32 %C) {  ; CHECK-LABEL: @test15( -; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @negative, i32 0, i32 0), i32 [[C:%.*]], i32 3) +; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @negative, i32 0, i32 0), i32 [[C:%.*]], i32 3)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8* [[DST]], null  ; CHECK-NEXT:    ret i1 [[CMP]]  ; diff --git a/llvm/test/Transforms/InstCombine/memcmp-constant-fold.ll b/llvm/test/Transforms/InstCombine/memcmp-constant-fold.ll index 211b3b5ab2c..62a17ea3a0e 100644 --- a/llvm/test/Transforms/InstCombine/memcmp-constant-fold.ll +++ b/llvm/test/Transforms/InstCombine/memcmp-constant-fold.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; RUN: opt < %s -instcombine -S -data-layout=e-n32 | FileCheck %s --check-prefix=ALL --check-prefix=LE  ; RUN: opt < %s -instcombine -S -data-layout=E-n32 | FileCheck %s --check-prefix=ALL --check-prefix=BE @@ -9,13 +10,13 @@ declare i32 @memcmp(i8*, i8*, i64)  define i1 @memcmp_4bytes_unaligned_constant_i8(i8* align 4 %x) {  ; LE-LABEL: @memcmp_4bytes_unaligned_constant_i8( -; LE-NEXT:    [[TMP1:%.*]] = bitcast i8* %x to i32* +; LE-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*  ; LE-NEXT:    [[LHSV:%.*]] = load i32, i32* [[TMP1]], align 4  ; LE-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[LHSV]], 16777216  ; LE-NEXT:    ret i1 [[TMP2]]  ;  ; BE-LABEL: @memcmp_4bytes_unaligned_constant_i8( -; BE-NEXT:    [[TMP1:%.*]] = bitcast i8* %x to i32* +; BE-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*  ; BE-NEXT:    [[LHSV:%.*]] = load i32, i32* [[TMP1]], align 4  ; BE-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[LHSV]], 1  ; BE-NEXT:    ret i1 [[TMP2]] @@ -32,13 +33,13 @@ define i1 @memcmp_4bytes_unaligned_constant_i8(i8* align 4 %x) {  define i1 @memcmp_4bytes_unaligned_constant_i16(i8* align 4 %x) {  ; LE-LABEL: @memcmp_4bytes_unaligned_constant_i16( -; LE-NEXT:    [[TMP1:%.*]] = bitcast i8* %x to i32* +; LE-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*  ; LE-NEXT:    [[RHSV:%.*]] = load i32, i32* [[TMP1]], align 4  ; LE-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[RHSV]], 131073  ; LE-NEXT:    ret i1 [[TMP2]]  ;  ; BE-LABEL: @memcmp_4bytes_unaligned_constant_i16( -; BE-NEXT:    [[TMP1:%.*]] = bitcast i8* %x to i32* +; BE-NEXT:    [[TMP1:%.*]] = bitcast i8* [[X:%.*]] to i32*  ; BE-NEXT:    [[RHSV:%.*]] = load i32, i32* [[TMP1]], align 4  ; BE-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[RHSV]], 65538  ; BE-NEXT:    ret i1 [[TMP2]] @@ -54,7 +55,7 @@ define i1 @memcmp_4bytes_unaligned_constant_i16(i8* align 4 %x) {  define i1 @memcmp_3bytes_aligned_constant_i32(i8* align 4 %x) {  ; ALL-LABEL: @memcmp_3bytes_aligned_constant_i32( -; ALL-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* bitcast (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @intbuf, i64 0, i64 1) to i8*), i8* bitcast ([2 x i32]* @intbuf to i8*), i64 3) +; ALL-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(3) bitcast (i32* getelementptr inbounds ([2 x i32], [2 x i32]* @intbuf, i64 0, i64 1) to i8*), i8* dereferenceable(3) bitcast ([2 x i32]* @intbuf to i8*), i64 3)  ; ALL-NEXT:    [[CMPEQ0:%.*]] = icmp eq i32 [[CALL]], 0  ; ALL-NEXT:    ret i1 [[CMPEQ0]]  ; @@ -67,7 +68,7 @@ define i1 @memcmp_3bytes_aligned_constant_i32(i8* align 4 %x) {  define i1 @memcmp_4bytes_one_unaligned_i8(i8* align 4 %x, i8* align 1 %y) {  ; ALL-LABEL: @memcmp_4bytes_one_unaligned_i8( -; ALL-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* %x, i8* %y, i64 4) +; ALL-NEXT:    [[CALL:%.*]] = tail call i32 @memcmp(i8* dereferenceable(4) [[X:%.*]], i8* dereferenceable(4) [[Y:%.*]], i64 4)  ; ALL-NEXT:    [[CMPEQ0:%.*]] = icmp eq i32 [[CALL]], 0  ; ALL-NEXT:    ret i1 [[CMPEQ0]]  ; diff --git a/llvm/test/Transforms/InstCombine/memcpy-from-global.ll b/llvm/test/Transforms/InstCombine/memcpy-from-global.ll index c14b1a70fd0..2e5b83c91e1 100644 --- a/llvm/test/Transforms/InstCombine/memcpy-from-global.ll +++ b/llvm/test/Transforms/InstCombine/memcpy-from-global.ll @@ -1,39 +1,66 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; RUN: opt < %s -instcombine -S | FileCheck %s  target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64"  @C.0.1248 = internal constant [128 x float] [ float -1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float -1.000000e+00, float 1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float -1.000000e+00, float 0.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00 ], align 32		; <[128 x float]*> [#uses=1]  define float @test1(i32 %hash, float %x, float %y, float %z, float %w) { -entry: -	%lookupTable = alloca [128 x float], align 16		; <[128 x float]*> [#uses=5] -	%lookupTable1 = bitcast [128 x float]* %lookupTable to i8*		; <i8*> [#uses=1] -	call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %lookupTable1, i8* align 16 bitcast ([128 x float]* @C.0.1248 to i8*), i64 512, i1 false) -  ; CHECK-LABEL: @test1( -; CHECK-NOT: alloca -; CHECK-NOT: call{{.*}}@llvm.memcpy - -	%tmp3 = shl i32 %hash, 2		; <i32> [#uses=1] -	%tmp5 = and i32 %tmp3, 124		; <i32> [#uses=4] -	%tmp753 = getelementptr [128 x float], [128 x float]* %lookupTable, i32 0, i32 %tmp5		; <float*> [#uses=1] -	%tmp9 = load float, float* %tmp753		; <float> [#uses=1] -	%tmp11 = fmul float %tmp9, %x		; <float> [#uses=1] -	%tmp13 = fadd float %tmp11, 0.000000e+00		; <float> [#uses=1] -	%tmp17.sum52 = or i32 %tmp5, 1		; <i32> [#uses=1] -	%tmp1851 = getelementptr [128 x float], [128 x float]* %lookupTable, i32 0, i32 %tmp17.sum52		; <float*> [#uses=1] -	%tmp19 = load float, float* %tmp1851		; <float> [#uses=1] -	%tmp21 = fmul float %tmp19, %y		; <float> [#uses=1] -	%tmp23 = fadd float %tmp21, %tmp13		; <float> [#uses=1] -	%tmp27.sum50 = or i32 %tmp5, 2		; <i32> [#uses=1] -	%tmp2849 = getelementptr [128 x float], [128 x float]* %lookupTable, i32 0, i32 %tmp27.sum50		; <float*> [#uses=1] -	%tmp29 = load float, float* %tmp2849		; <float> [#uses=1] -	%tmp31 = fmul float %tmp29, %z		; <float> [#uses=1] -	%tmp33 = fadd float %tmp31, %tmp23		; <float> [#uses=1] -	%tmp37.sum48 = or i32 %tmp5, 3		; <i32> [#uses=1] -	%tmp3847 = getelementptr [128 x float], [128 x float]* %lookupTable, i32 0, i32 %tmp37.sum48		; <float*> [#uses=1] -	%tmp39 = load float, float* %tmp3847		; <float> [#uses=1] -	%tmp41 = fmul float %tmp39, %w		; <float> [#uses=1] -	%tmp43 = fadd float %tmp41, %tmp33		; <float> [#uses=1] -	ret float %tmp43 +; CHECK-NEXT:  entry: +; CHECK-NEXT:    [[TMP3:%.*]] = shl i32 [[HASH:%.*]], 2 +; CHECK-NEXT:    [[TMP5:%.*]] = and i32 [[TMP3]], 124 +; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[TMP5]] to i64 +; CHECK-NEXT:    [[TMP753:%.*]] = getelementptr [128 x float], [128 x float]* @C.0.1248, i64 0, i64 [[TMP0]] +; CHECK-NEXT:    [[TMP9:%.*]] = load float, float* [[TMP753]], align 16 +; CHECK-NEXT:    [[TMP11:%.*]] = fmul float [[TMP9]], [[X:%.*]] +; CHECK-NEXT:    [[TMP13:%.*]] = fadd float [[TMP11]], 0.000000e+00 +; CHECK-NEXT:    [[TMP17_SUM52:%.*]] = or i32 [[TMP5]], 1 +; CHECK-NEXT:    [[TMP1:%.*]] = zext i32 [[TMP17_SUM52]] to i64 +; CHECK-NEXT:    [[TMP1851:%.*]] = getelementptr [128 x float], [128 x float]* @C.0.1248, i64 0, i64 [[TMP1]] +; CHECK-NEXT:    [[TMP19:%.*]] = load float, float* [[TMP1851]], align 4 +; CHECK-NEXT:    [[TMP21:%.*]] = fmul float [[TMP19]], [[Y:%.*]] +; CHECK-NEXT:    [[TMP23:%.*]] = fadd float [[TMP21]], [[TMP13]] +; CHECK-NEXT:    [[TMP27_SUM50:%.*]] = or i32 [[TMP5]], 2 +; CHECK-NEXT:    [[TMP2:%.*]] = zext i32 [[TMP27_SUM50]] to i64 +; CHECK-NEXT:    [[TMP2849:%.*]] = getelementptr [128 x float], [128 x float]* @C.0.1248, i64 0, i64 [[TMP2]] +; CHECK-NEXT:    [[TMP29:%.*]] = load float, float* [[TMP2849]], align 8 +; CHECK-NEXT:    [[TMP31:%.*]] = fmul float [[TMP29]], [[Z:%.*]] +; CHECK-NEXT:    [[TMP33:%.*]] = fadd float [[TMP31]], [[TMP23]] +; CHECK-NEXT:    [[TMP37_SUM48:%.*]] = or i32 [[TMP5]], 3 +; CHECK-NEXT:    [[TMP3:%.*]] = zext i32 [[TMP37_SUM48]] to i64 +; CHECK-NEXT:    [[TMP3847:%.*]] = getelementptr [128 x float], [128 x float]* @C.0.1248, i64 0, i64 [[TMP3]] +; CHECK-NEXT:    [[TMP39:%.*]] = load float, float* [[TMP3847]], align 4 +; CHECK-NEXT:    [[TMP41:%.*]] = fmul float [[TMP39]], [[W:%.*]] +; CHECK-NEXT:    [[TMP43:%.*]] = fadd float [[TMP41]], [[TMP33]] +; CHECK-NEXT:    ret float [[TMP43]] +; +entry: +  %lookupTable = alloca [128 x float], align 16		; <[128 x float]*> [#uses=5] +  %lookupTable1 = bitcast [128 x float]* %lookupTable to i8*		; <i8*> [#uses=1] +  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %lookupTable1, i8* align 16 bitcast ([128 x float]* @C.0.1248 to i8*), i64 512, i1 false) + + +  %tmp3 = shl i32 %hash, 2		; <i32> [#uses=1] +  %tmp5 = and i32 %tmp3, 124		; <i32> [#uses=4] +  %tmp753 = getelementptr [128 x float], [128 x float]* %lookupTable, i32 0, i32 %tmp5		; <float*> [#uses=1] +  %tmp9 = load float, float* %tmp753		; <float> [#uses=1] +  %tmp11 = fmul float %tmp9, %x		; <float> [#uses=1] +  %tmp13 = fadd float %tmp11, 0.000000e+00		; <float> [#uses=1] +  %tmp17.sum52 = or i32 %tmp5, 1		; <i32> [#uses=1] +  %tmp1851 = getelementptr [128 x float], [128 x float]* %lookupTable, i32 0, i32 %tmp17.sum52		; <float*> [#uses=1] +  %tmp19 = load float, float* %tmp1851		; <float> [#uses=1] +  %tmp21 = fmul float %tmp19, %y		; <float> [#uses=1] +  %tmp23 = fadd float %tmp21, %tmp13		; <float> [#uses=1] +  %tmp27.sum50 = or i32 %tmp5, 2		; <i32> [#uses=1] +  %tmp2849 = getelementptr [128 x float], [128 x float]* %lookupTable, i32 0, i32 %tmp27.sum50		; <float*> [#uses=1] +  %tmp29 = load float, float* %tmp2849		; <float> [#uses=1] +  %tmp31 = fmul float %tmp29, %z		; <float> [#uses=1] +  %tmp33 = fadd float %tmp31, %tmp23		; <float> [#uses=1] +  %tmp37.sum48 = or i32 %tmp5, 3		; <i32> [#uses=1] +  %tmp3847 = getelementptr [128 x float], [128 x float]* %lookupTable, i32 0, i32 %tmp37.sum48		; <float*> [#uses=1] +  %tmp39 = load float, float* %tmp3847		; <float> [#uses=1] +  %tmp41 = fmul float %tmp39, %w		; <float> [#uses=1] +  %tmp43 = fadd float %tmp41, %tmp33		; <float> [#uses=1] +  ret float %tmp43  }  declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) nounwind @@ -48,19 +75,22 @@ declare void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* nocapture, i8 addrspace  @H = constant [2 x %U] zeroinitializer, align 16  define void @test2() { +; CHECK-LABEL: @test2( +; CHECK-NEXT:    [[B1:%.*]] = alloca [124 x i8], align 8 +; CHECK-NEXT:    [[B1_SUB:%.*]] = getelementptr inbounds [124 x i8], [124 x i8]* [[B1]], i64 0, i64 0 +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 dereferenceable(124) [[B1_SUB]], i8* align 16 dereferenceable(124) getelementptr inbounds (%T, %T* @G, i64 0, i32 0), i64 124, i1 false) +; CHECK-NEXT:    call void @bar(i8* nonnull [[B1_SUB]]) +; CHECK-NEXT:    ret void +;    %A = alloca %T    %B = alloca %T    %a = bitcast %T* %A to i8*    %b = bitcast %T* %B to i8* -; CHECK-LABEL: @test2(  ; %A alloca is deleted -; CHECK-NEXT: alloca [124 x i8] -; CHECK-NEXT: getelementptr inbounds [124 x i8], [124 x i8]*  ; use @G instead of %A -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 %{{.*}}, i8* align 16 getelementptr inbounds (%T, %T* @G, i64 0, i32 0)    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a, i8* align 4 bitcast (%T* @G to i8*), i64 124, i1 false)    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %b, i8* align 4 %a, i64 124, i1 false)    call void @bar(i8* %b) @@ -68,19 +98,22 @@ define void @test2() {  }  define void @test2_no_null_opt() #0 { +; CHECK-LABEL: @test2_no_null_opt( +; CHECK-NEXT:    [[B1:%.*]] = alloca [124 x i8], align 8 +; CHECK-NEXT:    [[B1_SUB:%.*]] = getelementptr inbounds [124 x i8], [124 x i8]* [[B1]], i64 0, i64 0 +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 dereferenceable(124) [[B1_SUB]], i8* align 16 dereferenceable(124) getelementptr inbounds (%T, %T* @G, i64 0, i32 0), i64 124, i1 false) +; CHECK-NEXT:    call void @bar(i8* [[B1_SUB]]) +; CHECK-NEXT:    ret void +;    %A = alloca %T    %B = alloca %T    %a = bitcast %T* %A to i8*    %b = bitcast %T* %B to i8* -; CHECK-LABEL: @test2_no_null_opt(  ; %A alloca is deleted -; CHECK-NEXT: alloca [124 x i8] -; CHECK-NEXT: getelementptr inbounds [124 x i8], [124 x i8]*  ; use @G instead of %A -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %{{.*}}, i8* align 16 getelementptr inbounds (%T, %T* @G, i64 0, i32 0)    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a, i8* align 4 bitcast (%T* @G to i8*), i64 124, i1 false)    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %b, i8* align 4 %a, i64 124, i1 false)    call void @bar(i8* %b) @@ -88,22 +121,25 @@ define void @test2_no_null_opt() #0 {  }  define void @test2_addrspacecast() { +; CHECK-LABEL: @test2_addrspacecast( +; CHECK-NEXT:    [[B1:%.*]] = alloca [124 x i8], align 8 +; CHECK-NEXT:    [[B1_SUB:%.*]] = getelementptr inbounds [124 x i8], [124 x i8]* [[B1]], i64 0, i64 0 +; CHECK-NEXT:    [[B:%.*]] = addrspacecast i8* [[B1_SUB]] to i8 addrspace(1)* +; CHECK-NEXT:    call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* align 4 dereferenceable(124) [[B]], i8 addrspace(1)* align 4 dereferenceable(124) addrspacecast (i8* getelementptr inbounds (%T, %T* @G, i64 0, i32 0) to i8 addrspace(1)*), i64 124, i1 false) +; CHECK-NEXT:    call void @bar_as1(i8 addrspace(1)* [[B]]) +; CHECK-NEXT:    ret void +;    %A = alloca %T    %B = alloca %T    %a = addrspacecast %T* %A to i8 addrspace(1)*    %b = addrspacecast %T* %B to i8 addrspace(1)* -; CHECK-LABEL: @test2_addrspacecast(  ; %A alloca is deleted  ; This doesn't exactly match what test2 does, because folding the type  ; cast into the alloca doesn't work for the addrspacecast yet. -; CHECK-NEXT: alloca [124 x i8] -; CHECK-NEXT: getelementptr -; CHECK-NEXT: addrspacecast  ; use @G instead of %A -; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* align 4 %{{.*}},    call void @llvm.memcpy.p1i8.p0i8.i64(i8 addrspace(1)* align 4 %a, i8* align 4 bitcast (%T* @G to i8*), i64 124, i1 false)    call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* align 4 %b, i8 addrspace(1)* align 4 %a, i64 124, i1 false)    call void @bar_as1(i8 addrspace(1)* %b) @@ -116,45 +152,53 @@ declare void @bar_as1(i8 addrspace(1)*)  ;; Should be able to eliminate the alloca.  define void @test3() { +; CHECK-LABEL: @test3( +; CHECK-NEXT:    call void @bar(i8* getelementptr inbounds (%T, %T* @G, i64 0, i32 0)) #2 +; CHECK-NEXT:    ret void +;    %A = alloca %T    %a = bitcast %T* %A to i8*    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a, i8* align 4 bitcast (%T* @G to i8*), i64 124, i1 false)    call void @bar(i8* %a) readonly -; CHECK-LABEL: @test3( -; CHECK-NEXT: call void @bar(i8* getelementptr inbounds (%T, %T* @G, i64 0, i32 0))    ret void  }  define void @test3_addrspacecast() { +; CHECK-LABEL: @test3_addrspacecast( +; CHECK-NEXT:    call void @bar(i8* getelementptr inbounds (%T, %T* @G, i64 0, i32 0)) #2 +; CHECK-NEXT:    ret void +;    %A = alloca %T    %a = bitcast %T* %A to i8*    call void @llvm.memcpy.p0i8.p1i8.i64(i8* align 4 %a, i8 addrspace(1)* align 4 addrspacecast (%T* @G to i8 addrspace(1)*), i64 124, i1 false)    call void @bar(i8* %a) readonly -; CHECK-LABEL: @test3_addrspacecast( -; CHECK-NEXT: call void @bar(i8* getelementptr inbounds (%T, %T* @G, i64 0, i32 0))    ret void  }  define void @test4() { +; CHECK-LABEL: @test4( +; CHECK-NEXT:    call void @baz(i8* byval getelementptr inbounds (%T, %T* @G, i64 0, i32 0)) +; CHECK-NEXT:    ret void +;    %A = alloca %T    %a = bitcast %T* %A to i8*    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a, i8* align 4 bitcast (%T* @G to i8*), i64 124, i1 false)    call void @baz(i8* byval %a) -; CHECK-LABEL: @test4( -; CHECK-NEXT: call void @baz(i8* byval getelementptr inbounds (%T, %T* @G, i64 0, i32 0))    ret void  }  declare void @llvm.lifetime.start.p0i8(i64, i8*)  define void @test5() { +; CHECK-LABEL: @test5( +; CHECK-NEXT:    call void @baz(i8* byval getelementptr inbounds (%T, %T* @G, i64 0, i32 0)) +; CHECK-NEXT:    ret void +;    %A = alloca %T    %a = bitcast %T* %A to i8*    call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a)    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a, i8* align 4 bitcast (%T* @G to i8*), i64 124, i1 false)    call void @baz(i8* byval %a) -; CHECK-LABEL: @test5( -; CHECK-NEXT: call void @baz(i8* byval getelementptr inbounds (%T, %T* @G, i64 0, i32 0))    ret void  } @@ -163,65 +207,81 @@ declare void @baz(i8* byval)  define void @test6() { +; CHECK-LABEL: @test6( +; CHECK-NEXT:    call void @bar(i8* bitcast ([2 x %U]* @H to i8*)) #2 +; CHECK-NEXT:    ret void +;    %A = alloca %U, align 16    %a = bitcast %U* %A to i8*    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 %a, i8* align 16 bitcast ([2 x %U]* @H to i8*), i64 20, i1 false)    call void @bar(i8* %a) readonly -; CHECK-LABEL: @test6( -; CHECK-NEXT: call void @bar(i8* bitcast ([2 x %U]* @H to i8*))    ret void  }  define void @test7() { +; CHECK-LABEL: @test7( +; CHECK-NEXT:    call void @bar(i8* bitcast ([2 x %U]* @H to i8*)) #2 +; CHECK-NEXT:    ret void +;    %A = alloca %U, align 16    %a = bitcast %U* %A to i8*    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a, i8* align 4 bitcast (%U* getelementptr ([2 x %U], [2 x %U]* @H, i64 0, i32 0) to i8*), i64 20, i1 false)    call void @bar(i8* %a) readonly -; CHECK-LABEL: @test7( -; CHECK-NEXT: call void @bar(i8* bitcast ([2 x %U]* @H to i8*))    ret void  }  define void @test8() { -  %A = alloca %U, align 16 -  %a = bitcast %U* %A to i8* +; CHECK-LABEL: @test8( +; CHECK-NEXT:    [[AL:%.*]] = alloca [[U:%.*]], align 16 +; CHECK-NEXT:    [[A:%.*]] = bitcast %U* [[AL]] to i8* +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 16 dereferenceable(20) [[A]], i8* align 4 dereferenceable(20) bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*), i64 20, i1 false) +; CHECK-NEXT:    call void @bar(i8* nonnull [[A]]) #2 +; CHECK-NEXT:    ret void +; +  %al = alloca %U, align 16 +  %a = bitcast %U* %al to i8*    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a, i8* align 4 bitcast (%U* getelementptr ([2 x %U], [2 x %U]* @H, i64 0, i32 1) to i8*), i64 20, i1 false)    call void @bar(i8* %a) readonly -; CHECK-LABEL: @test8( -; CHECK: llvm.memcpy -; CHECK: bar    ret void  }  define void @test8_addrspacecast() { -  %A = alloca %U, align 16 -  %a = bitcast %U* %A to i8* +; CHECK-LABEL: @test8_addrspacecast( +; CHECK-NEXT:    [[AL:%.*]] = alloca [[U:%.*]], align 16 +; CHECK-NEXT:    [[A:%.*]] = bitcast %U* [[AL]] to i8* +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p1i8.i64(i8* nonnull align 16 dereferenceable(20) [[A]], i8 addrspace(1)* align 4 dereferenceable(20) addrspacecast (i8* bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*) to i8 addrspace(1)*), i64 20, i1 false) +; CHECK-NEXT:    call void @bar(i8* nonnull [[A]]) #2 +; CHECK-NEXT:    ret void +; +  %Al = alloca %U, align 16 +  %a = bitcast %U* %Al to i8*    call void @llvm.memcpy.p0i8.p1i8.i64(i8* align 4 %a, i8 addrspace(1)* align 4 addrspacecast (%U* getelementptr ([2 x %U], [2 x %U]* @H, i64 0, i32 1) to i8 addrspace(1)*), i64 20, i1 false)    call void @bar(i8* %a) readonly -; CHECK-LABEL: @test8_addrspacecast( -; CHECK: llvm.memcpy -; CHECK: bar    ret void  }  define void @test9() { +; CHECK-LABEL: @test9( +; CHECK-NEXT:    call void @bar(i8* bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*)) #2 +; CHECK-NEXT:    ret void +;    %A = alloca %U, align 4    %a = bitcast %U* %A to i8*    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %a, i8* align 4 bitcast (%U* getelementptr ([2 x %U], [2 x %U]* @H, i64 0, i32 1) to i8*), i64 20, i1 false)    call void @bar(i8* %a) readonly -; CHECK-LABEL: @test9( -; CHECK-NEXT: call void @bar(i8* bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*))    ret void  }  define void @test9_addrspacecast() { +; CHECK-LABEL: @test9_addrspacecast( +; CHECK-NEXT:    call void @bar(i8* bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*)) #2 +; CHECK-NEXT:    ret void +;    %A = alloca %U, align 4    %a = bitcast %U* %A to i8*    call void @llvm.memcpy.p0i8.p1i8.i64(i8* align 4 %a, i8 addrspace(1)* align 4 addrspacecast (%U* getelementptr ([2 x %U], [2 x %U]* @H, i64 0, i32 1) to i8 addrspace(1)*), i64 20, i1 false)    call void @bar(i8* %a) readonly -; CHECK-LABEL: @test9_addrspacecast( -; CHECK-NEXT: call void @bar(i8* bitcast (%U* getelementptr inbounds ([2 x %U], [2 x %U]* @H, i64 0, i64 1) to i8*))    ret void  } @@ -231,8 +291,13 @@ define void @test9_addrspacecast() {  ; Should not replace alloca with global because of size mismatch.  define void @test9_small_global() {  ; CHECK-LABEL: @test9_small_global( -; CHECK-NOT: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}@bbb,{{.*}}@_ZL3KKK,  -; CHECK: alloca [1000000 x i8] +; CHECK-NEXT:  entry: +; CHECK-NEXT:    [[CC:%.*]] = alloca [1000000 x i8], align 16 +; CHECK-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [1000000 x i8], [1000000 x i8]* [[CC]], i64 0, i64 0 +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 16 dereferenceable(3) [[ARRAYDECAY]], i8* align 16 dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @_ZL3KKK, i64 0, i64 0), i64 3, i1 false) +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 dereferenceable(1000000) getelementptr inbounds ([1000000 x i8], [1000000 x i8]* @bbb, i64 0, i64 0), i8* nonnull align 16 dereferenceable(1000000) [[ARRAYDECAY]], i64 1000000, i1 false) +; CHECK-NEXT:    ret void +;  entry:    %cc = alloca [1000000 x i8], align 16    %cc.0..sroa_idx = getelementptr inbounds [1000000 x i8], [1000000 x i8]* %cc, i64 0, i64 0 @@ -245,8 +310,10 @@ entry:  ; Should replace alloca with global as they have exactly the same size.  define void @test10_same_global() {  ; CHECK-LABEL: @test10_same_global( -; CHECK-NOT: alloca -; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}@bbb,{{.*}}@_ZL3KKK,{{.*}}, i64 3, +; CHECK-NEXT:  entry: +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 16 dereferenceable(3) getelementptr inbounds ([1000000 x i8], [1000000 x i8]* @bbb, i64 0, i64 0), i8* align 16 dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @_ZL3KKK, i64 0, i64 0), i64 3, i1 false) +; CHECK-NEXT:    ret void +;  entry:    %cc = alloca [3 x i8], align 1    %cc.0..sroa_idx = getelementptr inbounds [3 x i8], [3 x i8]* %cc, i64 0, i64 0 diff --git a/llvm/test/Transforms/InstCombine/memcpy-to-load.ll b/llvm/test/Transforms/InstCombine/memcpy-to-load.ll index 614ae186406..172c83d8a25 100644 --- a/llvm/test/Transforms/InstCombine/memcpy-to-load.ll +++ b/llvm/test/Transforms/InstCombine/memcpy-to-load.ll @@ -34,7 +34,7 @@ define void @copy_2_bytes(i8* %d, i8* %s) {  define void @copy_3_bytes(i8* %d, i8* %s) {  ; ALL-LABEL: @copy_3_bytes( -; ALL-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[D:%.*]], i8* align 1 [[S:%.*]], i32 3, i1 false) +; ALL-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(3) [[D:%.*]], i8* align 1 dereferenceable(3) [[S:%.*]], i32 3, i1 false)  ; ALL-NEXT:    ret void  ;    call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 3, i1 false) @@ -57,7 +57,7 @@ define void @copy_4_bytes(i8* %d, i8* %s) {  define void @copy_5_bytes(i8* %d, i8* %s) {  ; ALL-LABEL: @copy_5_bytes( -; ALL-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[D:%.*]], i8* align 1 [[S:%.*]], i32 5, i1 false) +; ALL-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(5) [[D:%.*]], i8* align 1 dereferenceable(5) [[S:%.*]], i32 5, i1 false)  ; ALL-NEXT:    ret void  ;    call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 5, i1 false) @@ -78,7 +78,7 @@ define void @copy_8_bytes(i8* %d, i8* %s) {  define void @copy_16_bytes(i8* %d, i8* %s) {  ; ALL-LABEL: @copy_16_bytes( -; ALL-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[D:%.*]], i8* align 1 [[S:%.*]], i32 16, i1 false) +; ALL-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(16) [[D:%.*]], i8* align 1 dereferenceable(16) [[S:%.*]], i32 16, i1 false)  ; ALL-NEXT:    ret void  ;    call void @llvm.memcpy.p0i8.p0i8.i32(i8* %d, i8* %s, i32 16, i1 false) diff --git a/llvm/test/Transforms/InstCombine/memcpy.ll b/llvm/test/Transforms/InstCombine/memcpy.ll index ae8f96c9078..18e08535b5f 100644 --- a/llvm/test/Transforms/InstCombine/memcpy.ll +++ b/llvm/test/Transforms/InstCombine/memcpy.ll @@ -29,7 +29,7 @@ define void @test2(i8* %a) {  define void @test3(i8* %d, i8* %s) {  ; CHECK-LABEL: @test3( -; CHECK-NEXT:    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 [[D:%.*]], i8* align 4 [[S:%.*]], i64 17179869184, i1 false) +; CHECK-NEXT:    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 dereferenceable(17179869184) [[D:%.*]], i8* align 4 dereferenceable(17179869184) [[S:%.*]], i64 17179869184, i1 false)  ; CHECK-NEXT:    ret void  ;    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %d, i8* align 4 %s, i64 17179869184, i1 false) diff --git a/llvm/test/Transforms/InstCombine/memcpy_chk-1.ll b/llvm/test/Transforms/InstCombine/memcpy_chk-1.ll index a372ef2feca..155bcb19ba8 100644 --- a/llvm/test/Transforms/InstCombine/memcpy_chk-1.ll +++ b/llvm/test/Transforms/InstCombine/memcpy_chk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; Test lib call simplification of __memcpy_chk calls with various values  ; for dstlen and len.  ; @@ -17,22 +18,22 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3  define i8* @test_simplify1() {  ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) +; CHECK-NEXT:    ret i8* bitcast (%struct.T1* @t1 to i8*) +;    %dst = bitcast %struct.T1* @t1 to i8*    %src = bitcast %struct.T2* @t2 to i8* - -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 bitcast (%struct.T1* @t1 to i8*), i8* align 4 bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*)    %ret = call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1824, i64 1824)    ret i8* %ret  }  define i8* @test_simplify2() {  ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* align 4 dereferenceable(1824) bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false) +; CHECK-NEXT:    ret i8* bitcast (%struct.T1* @t1 to i8*) +;    %dst = bitcast %struct.T1* @t1 to i8*    %src = bitcast %struct.T3* @t3 to i8* - -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 bitcast (%struct.T1* @t1 to i8*), i8* align 4 bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*)    %ret = call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1824, i64 2848)    ret i8* %ret  } @@ -41,36 +42,35 @@ define i8* @test_simplify2() {  define i8* @test_no_simplify1() {  ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT:    [[RET:%.*]] = call i8* @__memcpy_chk(i8* bitcast (%struct.T3* @t3 to i8*), i8* bitcast (%struct.T1* @t1 to i8*), i64 2848, i64 1824) +; CHECK-NEXT:    ret i8* [[RET]] +;    %dst = bitcast %struct.T3* @t3 to i8*    %src = bitcast %struct.T1* @t1 to i8* - -; CHECK-NEXT: %ret = call i8* @__memcpy_chk(i8* bitcast (%struct.T3* @t3 to i8*), i8* bitcast (%struct.T1* @t1 to i8*), i64 2848, i64 1824) -; CHECK-NEXT: ret i8* %ret    %ret = call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 2848, i64 1824)    ret i8* %ret  }  define i8* @test_no_simplify2() {  ; CHECK-LABEL: @test_no_simplify2( +; CHECK-NEXT:    [[RET:%.*]] = call i8* @__memcpy_chk(i8* bitcast (%struct.T1* @t1 to i8*), i8* bitcast (%struct.T2* @t2 to i8*), i64 1024, i64 0) +; CHECK-NEXT:    ret i8* [[RET]] +;    %dst = bitcast %struct.T1* @t1 to i8*    %src = bitcast %struct.T2* @t2 to i8* - -; CHECK-NEXT: %ret = call i8* @__memcpy_chk(i8* bitcast (%struct.T1* @t1 to i8*), i8* bitcast (%struct.T2* @t2 to i8*), i64 1024, i64 0) -; CHECK-NEXT: ret i8* %ret    %ret = call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1024, i64 0)    ret i8* %ret  }  define i8* @test_simplify_return_indcall(i8* ()* %alloc) {  ; CHECK-LABEL: @test_simplify_return_indcall( +; CHECK-NEXT:    [[DST:%.*]] = call i8* [[ALLOC:%.*]]() +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 dereferenceable(1824) [[DST]], i8* align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) +; CHECK-NEXT:    ret i8* [[DST]] +;    %src = bitcast %struct.T2* @t2 to i8* - -; CHECK-NEXT: %dst = call i8* %alloc()    %dst = call i8* %alloc() - -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64    %ret = call i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1824, i64 1824) -; CHECK-NEXT: ret i8* %dst    ret i8* %ret  } diff --git a/llvm/test/Transforms/InstCombine/memmove_chk-1.ll b/llvm/test/Transforms/InstCombine/memmove_chk-1.ll index f006985305b..79f10fd5f73 100644 --- a/llvm/test/Transforms/InstCombine/memmove_chk-1.ll +++ b/llvm/test/Transforms/InstCombine/memmove_chk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; Test lib call simplification of __memmove_chk calls with various values  ; for dstlen and len.  ; @@ -17,22 +18,24 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3  define i8* @test_simplify1() {  ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT:    call void @llvm.memmove.p0i8.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) +; CHECK-NEXT:    ret i8* bitcast (%struct.T1* @t1 to i8*) +;    %dst = bitcast %struct.T1* @t1 to i8*    %src = bitcast %struct.T2* @t2 to i8* -; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 4 bitcast (%struct.T1* @t1 to i8*), i8* align 4 bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*)    %ret = call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1824, i64 1824)    ret i8* %ret  }  define i8* @test_simplify2() {  ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT:    call void @llvm.memmove.p0i8.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* align 4 dereferenceable(1824) bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false) +; CHECK-NEXT:    ret i8* bitcast (%struct.T1* @t1 to i8*) +;    %dst = bitcast %struct.T1* @t1 to i8*    %src = bitcast %struct.T3* @t3 to i8* -; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* align 4 bitcast (%struct.T1* @t1 to i8*), i8* align 4 bitcast (%struct.T3* @t3 to i8*), i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*)    %ret = call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1824, i64 2848)    ret i8* %ret  } @@ -41,22 +44,24 @@ define i8* @test_simplify2() {  define i8* @test_no_simplify1() {  ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT:    [[RET:%.*]] = call i8* @__memmove_chk(i8* bitcast (%struct.T3* @t3 to i8*), i8* bitcast (%struct.T1* @t1 to i8*), i64 2848, i64 1824) +; CHECK-NEXT:    ret i8* [[RET]] +;    %dst = bitcast %struct.T3* @t3 to i8*    %src = bitcast %struct.T1* @t1 to i8* -; CHECK-NEXT: %ret = call i8* @__memmove_chk(i8* bitcast (%struct.T3* @t3 to i8*), i8* bitcast (%struct.T1* @t1 to i8*), i64 2848, i64 1824) -; CHECK-NEXT: ret i8* %ret    %ret = call i8* @__memmove_chk(i8* %dst, i8* %src, i64 2848, i64 1824)    ret i8* %ret  }  define i8* @test_no_simplify2() {  ; CHECK-LABEL: @test_no_simplify2( +; CHECK-NEXT:    [[RET:%.*]] = call i8* @__memmove_chk(i8* bitcast (%struct.T1* @t1 to i8*), i8* bitcast (%struct.T2* @t2 to i8*), i64 1024, i64 0) +; CHECK-NEXT:    ret i8* [[RET]] +;    %dst = bitcast %struct.T1* @t1 to i8*    %src = bitcast %struct.T2* @t2 to i8* -; CHECK-NEXT: %ret = call i8* @__memmove_chk(i8* bitcast (%struct.T1* @t1 to i8*), i8* bitcast (%struct.T2* @t2 to i8*), i64 1024, i64 0) -; CHECK-NEXT: ret i8* %ret    %ret = call i8* @__memmove_chk(i8* %dst, i8* %src, i64 1024, i64 0)    ret i8* %ret  } diff --git a/llvm/test/Transforms/InstCombine/memset_chk-1.ll b/llvm/test/Transforms/InstCombine/memset_chk-1.ll index 71f95b02457..e6e9427bc1c 100644 --- a/llvm/test/Transforms/InstCombine/memset_chk-1.ll +++ b/llvm/test/Transforms/InstCombine/memset_chk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; Test lib call simplification of __memset_chk calls with various values  ; for dstlen and len.  ; @@ -13,30 +14,33 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3  define i8* @test_simplify1() {  ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) +; CHECK-NEXT:    ret i8* bitcast (%struct.T* @t to i8*) +;    %dst = bitcast %struct.T* @t to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*)    %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 1824)    ret i8* %ret  }  define i8* @test_simplify2() {  ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) +; CHECK-NEXT:    ret i8* bitcast (%struct.T* @t to i8*) +;    %dst = bitcast %struct.T* @t to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*)    %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 3648)    ret i8* %ret  }  define i8* @test_simplify3() {  ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 dereferenceable(1824) bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) +; CHECK-NEXT:    ret i8* bitcast (%struct.T* @t to i8*) +;    %dst = bitcast %struct.T* @t to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) -; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*)    %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 -1)    ret i8* %ret  } @@ -45,41 +49,55 @@ define i8* @test_simplify3() {  define i8* @test_no_simplify1() {  ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT:    [[RET:%.*]] = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 400) +; CHECK-NEXT:    ret i8* [[RET]] +;    %dst = bitcast %struct.T* @t to i8* -; CHECK-NEXT: %ret = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 400) -; CHECK-NEXT: ret i8* %ret    %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 400)    ret i8* %ret  }  define i8* @test_no_simplify2() {  ; CHECK-LABEL: @test_no_simplify2( +; CHECK-NEXT:    [[RET:%.*]] = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 0) +; CHECK-NEXT:    ret i8* [[RET]] +;    %dst = bitcast %struct.T* @t to i8* -; CHECK-NEXT: %ret = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 0) -; CHECK-NEXT: ret i8* %ret    %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 0)    ret i8* %ret  }  ; Test that RAUW in SimplifyLibCalls for __memset_chk generates valid IR  define i32 @test_rauw(i8* %a, i8* %b, i8** %c) { -; CHECK-LABEL: test_rauw +; CHECK-LABEL: @test_rauw( +; CHECK-NEXT:  entry: +; CHECK-NEXT:    [[CALL49:%.*]] = call i64 @strlen(i8* [[A:%.*]]) +; CHECK-NEXT:    [[ADD180:%.*]] = add i64 [[CALL49]], 1 +; CHECK-NEXT:    [[YO107:%.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* [[B:%.*]], i1 false, i1 false, i1 false) +; CHECK-NEXT:    [[CALL50:%.*]] = call i8* @__memmove_chk(i8* [[B]], i8* [[A]], i64 [[ADD180]], i64 [[YO107]]) +; CHECK-NEXT:    [[STRLEN:%.*]] = call i64 @strlen(i8* [[B]]) +; CHECK-NEXT:    [[STRCHR2:%.*]] = getelementptr i8, i8* [[B]], i64 [[STRLEN]] +; CHECK-NEXT:    [[TMP0:%.*]] = bitcast i8** [[C:%.*]] to i64* +; CHECK-NEXT:    [[D1:%.*]] = load i64, i64* [[TMP0]], align 8 +; CHECK-NEXT:    [[SUB183:%.*]] = ptrtoint i8* [[B]] to i64 +; CHECK-NEXT:    [[SUB184:%.*]] = sub i64 [[D1]], [[SUB183]] +; CHECK-NEXT:    [[ADD52_I_I:%.*]] = add nsw i64 [[SUB184]], 1 +; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 1 [[STRCHR2]], i8 0, i64 [[ADD52_I_I]], i1 false) +; CHECK-NEXT:    ret i32 4 +;  entry:    %call49 = call i64 @strlen(i8* %a)    %add180 = add i64 %call49, 1    %yo107 = call i64 @llvm.objectsize.i64.p0i8(i8* %b, i1 false, i1 false, i1 false)    %call50 = call i8* @__memmove_chk(i8* %b, i8* %a, i64 %add180, i64 %yo107) -; CHECK: %strlen = call i64 @strlen(i8* %b) -; CHECK-NEXT: %strchr2 = getelementptr i8, i8* %b, i64 %strlen    %call51i = call i8* @strrchr(i8* %b, i32 0)    %d = load i8*, i8** %c, align 8    %sub182 = ptrtoint i8* %d to i64    %sub183 = ptrtoint i8* %b to i64    %sub184 = sub i64 %sub182, %sub183    %add52.i.i = add nsw i64 %sub184, 1 -; CHECK: call void @llvm.memset.p0i8.i64(i8* align 1 %strchr2    %call185 = call i8* @__memset_chk(i8* %call51i, i32 0, i64 %add52.i.i, i64 -1)    ret i32 4  } @@ -94,6 +112,20 @@ declare i8* @__memset_chk(i8*, i32, i64, i64)  ; FIXME: memset(malloc(x), 0, x) -> calloc(1, x)  define float* @pr25892(i64 %size) #0 { +; CHECK-LABEL: @pr25892( +; CHECK-NEXT:  entry: +; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @malloc(i64 [[SIZE:%.*]]) #3 +; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8* [[CALL]], null +; CHECK-NEXT:    br i1 [[CMP]], label [[CLEANUP:%.*]], label [[IF_END:%.*]] +; CHECK:       if.end: +; CHECK-NEXT:    [[BC:%.*]] = bitcast i8* [[CALL]] to float* +; CHECK-NEXT:    [[CALL2:%.*]] = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull [[CALL]], i1 false, i1 false, i1 false) +; CHECK-NEXT:    [[CALL3:%.*]] = tail call i8* @__memset_chk(i8* nonnull [[CALL]], i32 0, i64 [[SIZE]], i64 [[CALL2]]) #3 +; CHECK-NEXT:    br label [[CLEANUP]] +; CHECK:       cleanup: +; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi float* [ [[BC]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ] +; CHECK-NEXT:    ret float* [[RETVAL_0]] +;  entry:    %call = tail call i8* @malloc(i64 %size) #1    %cmp = icmp eq i8* %call, null @@ -107,19 +139,6 @@ cleanup:    %retval.0 = phi float* [ %bc, %if.end ], [ null, %entry ]    ret float* %retval.0 -; CHECK-LABEL: @pr25892( -; CHECK:       entry: -; CHECK-NEXT:    %call = tail call i8* @malloc(i64 %size) -; CHECK-NEXT:    %cmp = icmp eq i8* %call, null -; CHECK-NEXT:    br i1 %cmp, label %cleanup, label %if.end -; CHECK:       if.end: -; CHECK-NEXT:    %bc = bitcast i8* %call to float* -; CHECK-NEXT:    %call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false, i1 false, i1 false) -; CHECK-NEXT:    %call3 = tail call i8* @__memset_chk(i8* nonnull %call, i32 0, i64 %size, i64 %call2) -; CHECK-NEXT:    br label %cleanup -; CHECK:       cleanup: -; CHECK-NEXT:    %retval.0 = phi float* [ %bc, %if.end ], [ null, %entry ] -; CHECK-NEXT:    ret float* %retval.0  }  declare noalias i8* @malloc(i64) #1 diff --git a/llvm/test/Transforms/InstCombine/objsize.ll b/llvm/test/Transforms/InstCombine/objsize.ll index 97c708fb6bf..327b31a1fdc 100644 --- a/llvm/test/Transforms/InstCombine/objsize.ll +++ b/llvm/test/Transforms/InstCombine/objsize.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; Test a pile of objectsize bounds checking.  ; RUN: opt < %s -instcombine -S | FileCheck %s  ; We need target data to get the sizes of the arrays and structures. @@ -7,18 +8,27 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3  @.str = private constant [8 x i8] c"abcdefg\00"   ; <[8 x i8]*>  define i32 @foo() nounwind {  ; CHECK-LABEL: @foo( -; CHECK-NEXT: ret i32 60 +; CHECK-NEXT:    ret i32 60 +;    %1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)    ret i32 %1  }  define i8* @bar() nounwind {  ; CHECK-LABEL: @bar( +; CHECK-NEXT:  entry: +; CHECK-NEXT:    [[RETVAL:%.*]] = alloca i8*, align 4 +; CHECK-NEXT:    br i1 true, label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +; CHECK:       cond.true: +; CHECK-NEXT:    [[TMP0:%.*]] = load i8*, i8** [[RETVAL]], align 4 +; CHECK-NEXT:    ret i8* [[TMP0]] +; CHECK:       cond.false: +; CHECK-NEXT:    ret i8* undef +;  entry:    %retval = alloca i8*    %0 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false)    %cmp = icmp ne i32 %0, -1 -; CHECK: br i1 true    br i1 %cmp, label %cond.true, label %cond.false  cond.true: @@ -32,7 +42,8 @@ cond.false:  define i32 @f() nounwind {  ; CHECK-LABEL: @f( -; CHECK-NEXT: ret i32 0 +; CHECK-NEXT:    ret i32 0 +;    %1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr ([60 x i8], [60 x i8]* @a, i32 1, i32 0), i1 false, i1 false, i1 false)    ret i32 %1  } @@ -41,7 +52,10 @@ define i32 @f() nounwind {  define i1 @baz() nounwind {  ; CHECK-LABEL: @baz( -; CHECK-NEXT: objectsize +; CHECK-NEXT:    [[TMP1:%.*]] = tail call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 0), i1 false, i1 false, i1 false) +; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[TMP1]], -1 +; CHECK-NEXT:    ret i1 [[TMP2]] +;    %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 0), i1 false, i1 false, i1 false)    %2 = icmp eq i32 %1, -1    ret i1 %2 @@ -49,7 +63,15 @@ define i1 @baz() nounwind {  define void @test1(i8* %q, i32 %x) nounwind noinline {  ; CHECK-LABEL: @test1( -; CHECK: objectsize.i32.p0i8 +; CHECK-NEXT:  entry: +; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 10), i1 false, i1 false, i1 false) +; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[TMP0]], -1 +; CHECK-NEXT:    br i1 [[TMP1]], label %"47", label %"46" +; CHECK:       "46": +; CHECK-NEXT:    unreachable +; CHECK:       "47": +; CHECK-NEXT:    unreachable +;  entry:    %0 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([0 x i8], [0 x i8]* @window, i32 0, i32 10), i1 false, i1 false, i1 false) ; <i64> [#uses=1]    %1 = icmp eq i32 %0, -1                         ; <i1> [#uses=1] @@ -66,7 +88,8 @@ entry:   101, i32 102, i32 103, i32 0], align 4  define i32 @test2() nounwind {  ; CHECK-LABEL: @test2( -; CHECK-NEXT: ret i32 34 +; CHECK-NEXT:    ret i32 34 +;    %1 = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr (i8, i8* bitcast ([9 x i32]* @.str5 to i8*), i32 2), i1 false, i1 false, i1 false)    ret i32 %1  } @@ -84,6 +107,14 @@ declare i8* @__inline_memcpy_chk(i8*, i8*, i32) nounwind inlinehint  define void @test3() nounwind {  ; CHECK-LABEL: @test3( +; CHECK-NEXT:  entry: +; CHECK-NEXT:    br i1 undef, label [[BB11:%.*]], label [[BB12:%.*]] +; CHECK:       bb11: +; CHECK-NEXT:    unreachable +; CHECK:       bb12: +; CHECK-NEXT:    [[TMP0:%.*]] = call i8* @__inline_memcpy_chk(i8* bitcast (float* getelementptr inbounds ([480 x float], [480 x float]* @array, i32 0, i32 1) to i8*), i8* undef, i32 512) #3 +; CHECK-NEXT:    unreachable +;  entry:    br i1 undef, label %bb11, label %bb12 @@ -92,14 +123,12 @@ bb11:    %1 = bitcast float* %0 to i8*                   ; <i8*> [#uses=1]    %2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false, i1 false, i1 false) ; <i32> [#uses=1]    %3 = call i8* @__memcpy_chk(i8* undef, i8* undef, i32 512, i32 %2) nounwind ; <i8*> [#uses=0] -; CHECK: unreachable    unreachable  bb12:    %4 = getelementptr inbounds float, float* getelementptr inbounds ([480 x float], [480 x float]* @array, i32 0, i32 128), i32 -127 ; <float*> [#uses=1]    %5 = bitcast float* %4 to i8*                   ; <i8*> [#uses=1]    %6 = call i8* @__inline_memcpy_chk(i8* %5, i8* undef, i32 512) nounwind inlinehint ; <i8*> [#uses=0] -; CHECK: @__inline_memcpy_chk    unreachable  } @@ -109,12 +138,18 @@ bb12:  define i32 @test4(i8** %esc) nounwind ssp {  ; CHECK-LABEL: @test4( +; CHECK-NEXT:  entry: +; CHECK-NEXT:    [[TMP0:%.*]] = alloca [[STRUCT_DATA:%.*]], align 8 +; CHECK-NEXT:    [[TMP1:%.*]] = bitcast %struct.data* [[TMP0]] to i8* +; CHECK-NEXT:    call void @llvm.memset.p0i8.i32(i8* nonnull align 8 dereferenceable(1824) [[TMP1]], i8 0, i32 1824, i1 false) +; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8** [[ESC:%.*]] to %struct.data** +; CHECK-NEXT:    store %struct.data* [[TMP0]], %struct.data** [[TMP2]], align 4 +; CHECK-NEXT:    ret i32 0 +;  entry:    %0 = alloca %struct.data, align 8    %1 = bitcast %struct.data* %0 to i8*    %2 = call i32 @llvm.objectsize.i32.p0i8(i8* %1, i1 false, i1 false, i1 false) nounwind -; CHECK-NOT: @llvm.objectsize -; CHECK: @llvm.memset.p0i8.i32(i8* nonnull align 8 %1, i8 0, i32 1824, i1 false)    %3 = call i8* @__memset_chk(i8* %1, i32 0, i32 1824, i32 %2) nounwind    store i8* %1, i8** %esc    ret i32 0 @@ -125,24 +160,32 @@ entry:  define i8* @test5(i32 %n) nounwind ssp {  ; CHECK-LABEL: @test5( +; CHECK-NEXT:  entry: +; CHECK-NEXT:    [[TMP0:%.*]] = tail call noalias i8* @malloc(i32 20) #0 +; CHECK-NEXT:    [[TMP1:%.*]] = load i8*, i8** @s, align 8 +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(10) [[TMP0]], i8* align 1 dereferenceable(10) [[TMP1]], i32 10, i1 false) +; CHECK-NEXT:    ret i8* [[TMP0]] +;  entry:    %0 = tail call noalias i8* @malloc(i32 20) nounwind    %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false, i1 false, i1 false)    %2 = load i8*, i8** @s, align 8 -; CHECK-NOT: @llvm.objectsize -; CHECK: @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %0, i8* align 1 %1, i32 10, i1 false)    %3 = tail call i8* @__memcpy_chk(i8* %0, i8* %2, i32 10, i32 %1) nounwind    ret i8* %0  }  define void @test6(i32 %n) nounwind ssp {  ; CHECK-LABEL: @test6( +; CHECK-NEXT:  entry: +; CHECK-NEXT:    [[TMP0:%.*]] = tail call noalias i8* @malloc(i32 20) #0 +; CHECK-NEXT:    [[TMP1:%.*]] = load i8*, i8** @s, align 8 +; CHECK-NEXT:    [[TMP2:%.*]] = tail call i8* @__memcpy_chk(i8* [[TMP0]], i8* [[TMP1]], i32 30, i32 20) #0 +; CHECK-NEXT:    ret void +;  entry:    %0 = tail call noalias i8* @malloc(i32 20) nounwind    %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %0, i1 false, i1 false, i1 false)    %2 = load i8*, i8** @s, align 8 -; CHECK-NOT: @llvm.objectsize -; CHECK: @__memcpy_chk(i8* %0, i8* %1, i32 30, i32 20)    %3 = tail call i8* @__memcpy_chk(i8* %0, i8* %2, i32 30, i32 %1) nounwind    ret void  } @@ -153,11 +196,14 @@ declare noalias i8* @malloc(i32) nounwind  define i32 @test7(i8** %esc) {  ; CHECK-LABEL: @test7( +; CHECK-NEXT:    [[ALLOC:%.*]] = call noalias i8* @malloc(i32 48) #0 +; CHECK-NEXT:    store i8* [[ALLOC]], i8** [[ESC:%.*]], align 4 +; CHECK-NEXT:    ret i32 32 +;    %alloc = call noalias i8* @malloc(i32 48) nounwind    store i8* %alloc, i8** %esc    %gep = getelementptr inbounds i8, i8* %alloc, i32 16    %objsize = call i32 @llvm.objectsize.i32.p0i8(i8* %gep, i1 false, i1 false, i1 false) nounwind readonly -; CHECK: ret i32 32    ret i32 %objsize  } @@ -165,67 +211,86 @@ declare noalias i8* @calloc(i32, i32) nounwind  define i32 @test8(i8** %esc) {  ; CHECK-LABEL: @test8( +; CHECK-NEXT:    [[ALLOC:%.*]] = call noalias i8* @calloc(i32 5, i32 7) #0 +; CHECK-NEXT:    store i8* [[ALLOC]], i8** [[ESC:%.*]], align 4 +; CHECK-NEXT:    ret i32 30 +;    %alloc = call noalias i8* @calloc(i32 5, i32 7) nounwind    store i8* %alloc, i8** %esc    %gep = getelementptr inbounds i8, i8* %alloc, i32 5    %objsize = call i32 @llvm.objectsize.i32.p0i8(i8* %gep, i1 false, i1 false, i1 false) nounwind readonly -; CHECK: ret i32 30    ret i32 %objsize  }  declare noalias i8* @strdup(i8* nocapture) nounwind  declare noalias i8* @strndup(i8* nocapture, i32) nounwind -; CHECK-LABEL: @test9(  define i32 @test9(i8** %esc) { +; CHECK-LABEL: @test9( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strdup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0)) #0 +; CHECK-NEXT:    store i8* [[CALL]], i8** [[ESC:%.*]], align 8 +; CHECK-NEXT:    ret i32 8 +;    %call = tail call i8* @strdup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0)) nounwind    store i8* %call, i8** %esc, align 8    %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false, i1 false) -; CHECK: ret i32 8    ret i32 %1  } -; CHECK-LABEL: @test10(  define i32 @test10(i8** %esc) { +; CHECK-LABEL: @test10( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 3) #0 +; CHECK-NEXT:    store i8* [[CALL]], i8** [[ESC:%.*]], align 8 +; CHECK-NEXT:    ret i32 4 +;    %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 3) nounwind    store i8* %call, i8** %esc, align 8    %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false, i1 false) -; CHECK: ret i32 4    ret i32 %1  } -; CHECK-LABEL: @test11(  define i32 @test11(i8** %esc) { +; CHECK-LABEL: @test11( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 7) #0 +; CHECK-NEXT:    store i8* [[CALL]], i8** [[ESC:%.*]], align 8 +; CHECK-NEXT:    ret i32 8 +;    %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 7) nounwind    store i8* %call, i8** %esc, align 8    %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false, i1 false) -; CHECK: ret i32 8    ret i32 %1  } -; CHECK-LABEL: @test12(  define i32 @test12(i8** %esc) { +; CHECK-LABEL: @test12( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 8) #0 +; CHECK-NEXT:    store i8* [[CALL]], i8** [[ESC:%.*]], align 8 +; CHECK-NEXT:    ret i32 8 +;    %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 8) nounwind    store i8* %call, i8** %esc, align 8    %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false, i1 false) -; CHECK: ret i32 8    ret i32 %1  } -; CHECK-LABEL: @test13(  define i32 @test13(i8** %esc) { +; CHECK-LABEL: @test13( +; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i32 57) #0 +; CHECK-NEXT:    store i8* [[CALL]], i8** [[ESC:%.*]], align 8 +; CHECK-NEXT:    ret i32 8 +;    %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i64 0, i64 0), i32 57) nounwind    store i8* %call, i8** %esc, align 8    %1 = tail call i32 @llvm.objectsize.i32.p0i8(i8* %call, i1 true, i1 false, i1 false) -; CHECK: ret i32 8    ret i32 %1  }  @globalalias = internal alias [60 x i8], [60 x i8]* @a -; CHECK-LABEL: @test18( -; CHECK-NEXT: ret i32 60  define i32 @test18() { +; CHECK-LABEL: @test18( +; CHECK-NEXT:    ret i32 60 +;    %bc = bitcast [60 x i8]* @globalalias to i8*    %1 = call i32 @llvm.objectsize.i32.p0i8(i8* %bc, i1 false, i1 false, i1 false)    ret i32 %1 @@ -233,71 +298,87 @@ define i32 @test18() {  @globalalias2 = weak alias [60 x i8], [60 x i8]* @a -; CHECK-LABEL: @test19( -; CHECK: llvm.objectsize  define i32 @test19() { +; CHECK-LABEL: @test19( +; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @globalalias2, i32 0, i32 0), i1 false, i1 false, i1 false) +; CHECK-NEXT:    ret i32 [[TMP1]] +;    %bc = bitcast [60 x i8]* @globalalias2 to i8*    %1 = call i32 @llvm.objectsize.i32.p0i8(i8* %bc, i1 false, i1 false, i1 false)    ret i32 %1  } -; CHECK-LABEL: @test20( -; CHECK: ret i32 0  define i32 @test20() { +; CHECK-LABEL: @test20( +; CHECK-NEXT:    ret i32 0 +;    %1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 false, i1 false, i1 false)    ret i32 %1  } -; CHECK-LABEL: @test21( -; CHECK: ret i32 0  define i32 @test21() { +; CHECK-LABEL: @test21( +; CHECK-NEXT:    ret i32 0 +;    %1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 true, i1 false, i1 false)    ret i32 %1  } -; CHECK-LABEL: @test22( -; CHECK: llvm.objectsize  define i32 @test22() { +; CHECK-LABEL: @test22( +; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 false, i1 true, i1 false) +; CHECK-NEXT:    ret i32 [[TMP1]] +;    %1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 false, i1 true, i1 false)    ret i32 %1  } -; CHECK-LABEL: @test23( -; CHECK: llvm.objectsize  define i32 @test23() { +; CHECK-LABEL: @test23( +; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 true, i1 true, i1 false) +; CHECK-NEXT:    ret i32 [[TMP1]] +;    %1 = call i32 @llvm.objectsize.i32.p0i8(i8* null, i1 true, i1 true, i1 false)    ret i32 %1  }  ; 1 is an arbitrary non-zero address space. -; CHECK-LABEL: @test24( -; CHECK: llvm.objectsize  define i32 @test24() { +; CHECK-LABEL: @test24( +; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 false, i1 false, i1 false) +; CHECK-NEXT:    ret i32 [[TMP1]] +;    %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 false, -                                          i1 false, i1 false) +  i1 false, i1 false)    ret i32 %1  } -; CHECK-LABEL: @test25( -; CHECK: llvm.objectsize  define i32 @test25() { +; CHECK-LABEL: @test25( +; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 true, i1 false, i1 false) +; CHECK-NEXT:    ret i32 [[TMP1]] +;    %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 true, -                                          i1 false, i1 false) +  i1 false, i1 false)    ret i32 %1  } -; CHECK-LABEL: @test26( -; CHECK: llvm.objectsize  define i32 @test26() { +; CHECK-LABEL: @test26( +; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 false, i1 true, i1 false) +; CHECK-NEXT:    ret i32 [[TMP1]] +;    %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 false, -                                          i1 true, i1 false) +  i1 true, i1 false)    ret i32 %1  } -; CHECK-LABEL: @test27( -; CHECK: llvm.objectsize  define i32 @test27() { +; CHECK-LABEL: @test27( +; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 true, i1 true, i1 false) +; CHECK-NEXT:    ret i32 [[TMP1]] +;    %1 = call i32 @llvm.objectsize.i32.p1i8(i8 addrspace(1)* null, i1 true, -                                          i1 true, i1 false) +  i1 true, i1 false)    ret i32 %1  } diff --git a/llvm/test/Transforms/InstCombine/sprintf-1.ll b/llvm/test/Transforms/InstCombine/sprintf-1.ll index 1fbdc43bd56..12957b3404e 100644 --- a/llvm/test/Transforms/InstCombine/sprintf-1.ll +++ b/llvm/test/Transforms/InstCombine/sprintf-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; Test that the sprintf library call simplifier works correctly.  ;  ; RUN: opt < %s -instcombine -S | FileCheck %s @@ -20,81 +21,125 @@ declare i32 @sprintf(i8*, i8*, ...)  define void @test_simplify1(i8* %dst) {  ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(13) [[DST:%.*]], i8* align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false) +; CHECK-NEXT:    ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify1( +; CHECK-IPRINTF-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(13) [[DST:%.*]], i8* align 1 dereferenceable(13) getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false) +; CHECK-IPRINTF-NEXT:    ret void +;    %fmt = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0    call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt) -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %dst, i8* align 1 getelementptr inbounds ([13 x i8], [13 x i8]* @hello_world, i32 0, i32 0), i32 13, i1 false)    ret void -; CHECK-NEXT: ret void  }  define void @test_simplify2(i8* %dst) {  ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT:    store i8 0, i8* [[DST:%.*]], align 1 +; CHECK-NEXT:    ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify2( +; CHECK-IPRINTF-NEXT:    store i8 0, i8* [[DST:%.*]], align 1 +; CHECK-IPRINTF-NEXT:    ret void +;    %fmt = getelementptr [1 x i8], [1 x i8]* @null, i32 0, i32 0    call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt) -; CHECK-NEXT: store i8 0, i8* %dst, align 1    ret void -; CHECK-NEXT: ret void  }  define void @test_simplify3(i8* %dst) {  ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT:    store i8 0, i8* [[DST:%.*]], align 1 +; CHECK-NEXT:    ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify3( +; CHECK-IPRINTF-NEXT:    store i8 0, i8* [[DST:%.*]], align 1 +; CHECK-IPRINTF-NEXT:    ret void +;    %fmt = getelementptr [7 x i8], [7 x i8]* @null_hello, i32 0, i32 0    call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt) -; CHECK-NEXT: store i8 0, i8* %dst, align 1    ret void -; CHECK-NEXT: ret void  }  ; Check sprintf(dst, "%c", chr) -> *(i8*)dst = chr; *((i8*)dst + 1) = 0.  define void @test_simplify4(i8* %dst) {  ; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT:    store i8 104, i8* [[DST:%.*]], align 1 +; CHECK-NEXT:    [[NUL:%.*]] = getelementptr i8, i8* [[DST]], i32 1 +; CHECK-NEXT:    store i8 0, i8* [[NUL]], align 1 +; CHECK-NEXT:    ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify4( +; CHECK-IPRINTF-NEXT:    store i8 104, i8* [[DST:%.*]], align 1 +; CHECK-IPRINTF-NEXT:    [[NUL:%.*]] = getelementptr i8, i8* [[DST]], i32 1 +; CHECK-IPRINTF-NEXT:    store i8 0, i8* [[NUL]], align 1 +; CHECK-IPRINTF-NEXT:    ret void +;    %fmt = getelementptr [3 x i8], [3 x i8]* @percent_c, i32 0, i32 0    call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i8 104) -; CHECK-NEXT: store i8 104, i8* %dst, align 1 -; CHECK-NEXT: [[NUL:%[a-z0-9]+]] = getelementptr i8, i8* %dst, i32 1 -; CHECK-NEXT: store i8 0, i8* [[NUL]], align 1    ret void -; CHECK-NEXT: ret void  }  ; Check sprintf(dst, "%s", str) -> llvm.memcpy(dest, str, strlen(str) + 1, 1).  define void @test_simplify5(i8* %dst, i8* %str) {  ; CHECK-LABEL: @test_simplify5( +; CHECK-NEXT:    [[STRLEN:%.*]] = call i32 @strlen(i8* [[STR:%.*]]) +; CHECK-NEXT:    [[LENINC:%.*]] = add i32 [[STRLEN]], 1 +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[DST:%.*]], i8* align 1 [[STR]], i32 [[LENINC]], i1 false) +; CHECK-NEXT:    ret void +; +; CHECK-IPRINTF-LABEL: @test_simplify5( +; CHECK-IPRINTF-NEXT:    [[STRLEN:%.*]] = call i32 @strlen(i8* [[STR:%.*]]) +; CHECK-IPRINTF-NEXT:    [[LENINC:%.*]] = add i32 [[STRLEN]], 1 +; CHECK-IPRINTF-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[DST:%.*]], i8* align 1 [[STR]], i32 [[LENINC]], i1 false) +; CHECK-IPRINTF-NEXT:    ret void +;    %fmt = getelementptr [3 x i8], [3 x i8]* @percent_s, i32 0, i32 0    call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i8* %str) -; CHECK-NEXT: [[STRLEN:%[a-z0-9]+]] = call i32 @strlen(i8* %str) -; CHECK-NEXT: [[LENINC:%[a-z0-9]+]] = add i32 [[STRLEN]], 1 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 %dst, i8* align 1 %str, i32 [[LENINC]], i1 false)    ret void -; CHECK-NEXT: ret void  }  ; Check sprintf(dst, format, ...) -> siprintf(str, format, ...) if no floating.  define void @test_simplify6(i8* %dst) { +; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT:    [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* [[DST:%.*]], i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187) +; CHECK-NEXT:    ret void +;  ; CHECK-IPRINTF-LABEL: @test_simplify6( +; CHECK-IPRINTF-NEXT:    [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @siprintf(i8* [[DST:%.*]], i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187) +; CHECK-IPRINTF-NEXT:    ret void +;    %fmt = getelementptr [3 x i8], [3 x i8]* @percent_d, i32 0, i32 0    call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, i32 187) -; CHECK-IPRINTF-NEXT: call i32 (i8*, i8*, ...) @siprintf(i8* %dst, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_d, i32 0, i32 0), i32 187)    ret void -; CHECK-IPRINTF-NEXT: ret void  }  define void @test_no_simplify1(i8* %dst) { +; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT:    [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* [[DST:%.*]], i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00) +; CHECK-NEXT:    ret void +;  ; CHECK-IPRINTF-LABEL: @test_no_simplify1( +; CHECK-IPRINTF-NEXT:    [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* [[DST:%.*]], i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00) +; CHECK-IPRINTF-NEXT:    ret void +;    %fmt = getelementptr [3 x i8], [3 x i8]* @percent_f, i32 0, i32 0    call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, double 1.87) -; CHECK-IPRINTF-NEXT: call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @percent_f, i32 0, i32 0), double 1.870000e+00)    ret void -; CHECK-IPRINTF-NEXT: ret void  }  define void @test_no_simplify2(i8* %dst, i8* %fmt, double %d) {  ; CHECK-LABEL: @test_no_simplify2( +; CHECK-NEXT:    [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* [[DST:%.*]], i8* [[FMT:%.*]], double [[D:%.*]]) +; CHECK-NEXT:    ret void +; +; CHECK-IPRINTF-LABEL: @test_no_simplify2( +; CHECK-IPRINTF-NEXT:    [[TMP1:%.*]] = call i32 (i8*, i8*, ...) @sprintf(i8* [[DST:%.*]], i8* [[FMT:%.*]], double [[D:%.*]]) +; CHECK-IPRINTF-NEXT:    ret void +;    call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, double %d) -; CHECK-NEXT: call i32 (i8*, i8*, ...) @sprintf(i8* %dst, i8* %fmt, double %d)    ret void -; CHECK-NEXT: ret void  } diff --git a/llvm/test/Transforms/InstCombine/stpcpy_chk-1.ll b/llvm/test/Transforms/InstCombine/stpcpy_chk-1.ll index b2e0416ae3d..b2f1f6a94f3 100644 --- a/llvm/test/Transforms/InstCombine/stpcpy_chk-1.ll +++ b/llvm/test/Transforms/InstCombine/stpcpy_chk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; Test lib call simplification of __stpcpy_chk calls with various values  ; for src, dst, and slen.  ; @@ -13,33 +14,36 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3  define i8* @test_simplify1() {  ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT:    ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11) +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) -; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11)    %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 60)    ret i8* %ret  }  define i8* @test_simplify2() {  ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT:    ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11) +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) -; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11)    %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 12)    ret i8* %ret  }  define i8* @test_simplify3() {  ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT:    ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11) +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) -; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11)    %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 -1)    ret i8* %ret  } @@ -48,11 +52,12 @@ define i8* @test_simplify3() {  define i8* @test_simplify4() {  ; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT:    [[STPCPY:%.*]] = call i8* @stpcpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0)) +; CHECK-NEXT:    ret i8* [[STPCPY]] +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 -; CHECK-NEXT: %stpcpy = call i8* @stpcpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0)) -; CHECK-NEXT: ret i8* %stpcpy    %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 -1)    ret i8* %ret  } @@ -61,12 +66,13 @@ define i8* @test_simplify4() {  define i8* @test_simplify5() {  ; CHECK-LABEL: @test_simplify5( +; CHECK-NEXT:    [[LEN:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false) +; CHECK-NEXT:    [[TMP1:%.*]] = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 [[LEN]]) +; CHECK-NEXT:    ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11) +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false) -; CHECK-NEXT: %1 = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 %len) -; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 11)    %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false, i1 false)    %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 %len)    ret i8* %ret @@ -76,11 +82,12 @@ define i8* @test_simplify5() {  define i8* @test_simplify6() {  ; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT:    [[STRLEN:%.*]] = call i32 @strlen(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)) +; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 [[STRLEN]] +; CHECK-NEXT:    ret i8* [[TMP1]] +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 -; CHECK-NEXT: %strlen = call i32 @strlen(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)) -; CHECK-NEXT: %1 = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 %strlen -; CHECK-NEXT: ret i8* %1    %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false, i1 false)    %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %dst, i32 %len)    ret i8* %ret @@ -90,11 +97,12 @@ define i8* @test_simplify6() {  define i8* @test_no_simplify1() {  ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT:    [[RET:%.*]] = call i8* @__stpcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 8) +; CHECK-NEXT:    ret i8* [[RET]] +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 -; CHECK-NEXT: %ret = call i8* @__stpcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 8) -; CHECK-NEXT: ret i8* %ret    %ret = call i8* @__stpcpy_chk(i8* %dst, i8* %src, i32 8)    ret i8* %ret  } diff --git a/llvm/test/Transforms/InstCombine/strcmp-1.ll b/llvm/test/Transforms/InstCombine/strcmp-1.ll index 4dfda047280..7d86ec51f7f 100644 --- a/llvm/test/Transforms/InstCombine/strcmp-1.ll +++ b/llvm/test/Transforms/InstCombine/strcmp-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; Test that the strcmp library call simplifier works correctly.  ; RUN: opt < %s -instcombine -S | FileCheck %s --check-prefix=NOBCMP  ; RUN: opt < %s -instcombine -mtriple=unknown-unknown-linux-gnu -S | FileCheck %s --check-prefix=BCMP @@ -18,7 +19,18 @@ define i32 @test1(i8* %str2) {  ; CHECK: %1 = zext i8 %strcmpload to i32  ; CHECK: %2 = sub nsw i32 0, %1  ; CHECK: ret i32 %2 - +; NOBCMP-LABEL: @test1( +; NOBCMP-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR2:%.*]], align 1 +; NOBCMP-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 +; NOBCMP-NEXT:    [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]] +; NOBCMP-NEXT:    ret i32 [[TMP2]] +; +; BCMP-LABEL: @test1( +; BCMP-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR2:%.*]], align 1 +; BCMP-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 +; BCMP-NEXT:    [[TMP2:%.*]] = sub nsw i32 0, [[TMP1]] +; BCMP-NEXT:    ret i32 [[TMP2]] +;    %str1 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0    %temp1 = call i32 @strcmp(i8* %str1, i8* %str2)    ret i32 %temp1 @@ -31,7 +43,16 @@ define i32 @test2(i8* %str1) {  ; CHECK: %strcmpload = load i8, i8* %str  ; CHECK: %1 = zext i8 %strcmpload to i32  ; CHECK: ret i32 %1 - +; NOBCMP-LABEL: @test2( +; NOBCMP-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR1:%.*]], align 1 +; NOBCMP-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 +; NOBCMP-NEXT:    ret i32 [[TMP1]] +; +; BCMP-LABEL: @test2( +; BCMP-NEXT:    [[STRCMPLOAD:%.*]] = load i8, i8* [[STR1:%.*]], align 1 +; BCMP-NEXT:    [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 +; BCMP-NEXT:    ret i32 [[TMP1]] +;    %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0    %temp1 = call i32 @strcmp(i8* %str1, i8* %str2)    ret i32 %temp1 @@ -41,7 +62,12 @@ define i32 @test2(i8* %str1) {  define i32 @test3() {  ; CHECK-LABEL: @test3(  ; CHECK: ret i32 -1 - +; NOBCMP-LABEL: @test3( +; NOBCMP-NEXT:    ret i32 -1 +; +; BCMP-LABEL: @test3( +; BCMP-NEXT:    ret i32 -1 +;    %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0    %str2 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0    %temp1 = call i32 @strcmp(i8* %str1, i8* %str2) @@ -51,7 +77,12 @@ define i32 @test3() {  define i32 @test4() {  ; CHECK-LABEL: @test4(  ; CHECK: ret i32 1 - +; NOBCMP-LABEL: @test4( +; NOBCMP-NEXT:    ret i32 1 +; +; BCMP-LABEL: @test4( +; BCMP-NEXT:    ret i32 1 +;    %str1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0    %str2 = getelementptr inbounds [1 x i8], [1 x i8]* @null, i32 0, i32 0    %temp1 = call i32 @strcmp(i8* %str1, i8* %str2) @@ -64,7 +95,16 @@ define i32 @test5(i1 %b) {  ; CHECK-LABEL: @test5(  ; CHECK: %memcmp = call i32 @memcmp(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* %str2, i32 5)  ; CHECK: ret i32 %memcmp - +; NOBCMP-LABEL: @test5( +; NOBCMP-NEXT:    [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) +; NOBCMP-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; NOBCMP-NEXT:    ret i32 [[MEMCMP]] +; +; BCMP-LABEL: @test5( +; BCMP-NEXT:    [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) +; BCMP-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; BCMP-NEXT:    ret i32 [[MEMCMP]] +;    %str1 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0    %temp1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0    %temp2 = getelementptr inbounds [5 x i8], [5 x i8]* @bell, i32 0, i32 0 @@ -77,22 +117,31 @@ define i32 @test5(i1 %b) {  define i32 @test6(i8* %str) {  ; CHECK-LABEL: @test6(  ; CHECK: ret i32 0 - +; NOBCMP-LABEL: @test6( +; NOBCMP-NEXT:    ret i32 0 +; +; BCMP-LABEL: @test6( +; BCMP-NEXT:    ret i32 0 +;    %temp1 = call i32 @strcmp(i8* %str, i8* %str)    ret i32 %temp1  }  ; strcmp(x, y) == 0  -> bcmp(x, y, <known length>)  define i1 @test7(i1 %b) { +; NOBCMP-LABEL: @test7( +; NOBCMP-NEXT:    [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) +; NOBCMP-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; NOBCMP-NEXT:    [[RES:%.*]] = icmp eq i32 [[MEMCMP]], 0 +; NOBCMP-NEXT:    ret i1 [[RES]] +;  ; BCMP-LABEL: @test7( -; BCMP: %bcmp = call i32 @bcmp(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* %str2, i32 5) -; BCMP: %res = icmp eq i32 %bcmp, 0 -; BCMP: ret i1 %res +; BCMP-NEXT:    [[STR2:%.*]] = select i1 [[B:%.*]], i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hell, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @bell, i32 0, i32 0) +; BCMP-NEXT:    [[BCMP:%.*]] = call i32 @bcmp(i8* dereferenceable(5) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* dereferenceable(5) [[STR2]], i32 5) +; BCMP-NEXT:    [[RES:%.*]] = icmp eq i32 [[BCMP]], 0 +; BCMP-NEXT:    ret i1 [[RES]] +; -; NOBCMP-LABEL: @test7( -; NOBCMP: %memcmp = call i32 @memcmp(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i8* %str2, i32 5) -; NOBCMP: %res = icmp eq i32 %memcmp, 0 -; NOBCMP: ret i1 %res    %str1 = getelementptr inbounds [6 x i8], [6 x i8]* @hello, i32 0, i32 0    %temp1 = getelementptr inbounds [5 x i8], [5 x i8]* @hell, i32 0, i32 0 diff --git a/llvm/test/Transforms/InstCombine/strcmp-memcmp.ll b/llvm/test/Transforms/InstCombine/strcmp-memcmp.ll index 092a47fe1db..14490339d1c 100644 --- a/llvm/test/Transforms/InstCombine/strcmp-memcmp.ll +++ b/llvm/test/Transforms/InstCombine/strcmp-memcmp.ll @@ -11,7 +11,7 @@ declare void @use(i32)  define i32 @strcmp_memcmp([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strcmp_memcmp(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -28,7 +28,7 @@ declare i32 @strcmp(i8* nocapture, i8* nocapture)  define i32 @strcmp_memcmp2([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strcmp_memcmp2(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -43,7 +43,7 @@ define i32 @strcmp_memcmp2([12 x i8]* dereferenceable (12) %buf) {  define i32 @strcmp_memcmp3([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strcmp_memcmp3(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -58,7 +58,7 @@ define i32 @strcmp_memcmp3([12 x i8]* dereferenceable (12) %buf) {  define i32 @strcmp_memcmp4([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strcmp_memcmp4(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -73,7 +73,7 @@ define i32 @strcmp_memcmp4([12 x i8]* dereferenceable (12) %buf) {  define i32 @strcmp_memcmp5([5 x i8]* dereferenceable (5) %buf) {  ; CHECK-LABEL: @strcmp_memcmp5(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [5 x i8], [5 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -88,7 +88,7 @@ define i32 @strcmp_memcmp5([5 x i8]* dereferenceable (5) %buf) {  define i32 @strcmp_memcmp6([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strcmp_memcmp6(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -103,7 +103,7 @@ define i32 @strcmp_memcmp6([12 x i8]* dereferenceable (12) %buf) {  define i32 @strcmp_memcmp7([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strcmp_memcmp7(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4)  ; CHECK-NEXT:    [[MEMCMP_LOBIT:%.*]] = lshr i32 [[MEMCMP]], 31  ; CHECK-NEXT:    ret i32 [[MEMCMP_LOBIT]]  ; @@ -117,7 +117,7 @@ define i32 @strcmp_memcmp7([12 x i8]* dereferenceable (12) %buf) {  define i32 @strcmp_memcmp8([4 x i8]* dereferenceable (4) %buf) {  ; CHECK-LABEL: @strcmp_memcmp8(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -132,7 +132,7 @@ define i32 @strcmp_memcmp8([4 x i8]* dereferenceable (4) %buf) {  define i32 @strcmp_memcmp9([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strcmp_memcmp9(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -148,7 +148,7 @@ define i32 @strcmp_memcmp9([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 2) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(2) [[STRING]], i8* dereferenceable(2) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 2)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -165,7 +165,7 @@ declare i32 @strncmp(i8* nocapture, i8* nocapture, i64)  define i32 @strncmp_memcmp2([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp2(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -180,7 +180,7 @@ define i32 @strncmp_memcmp2([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp3([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp3(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -195,7 +195,7 @@ define i32 @strncmp_memcmp3([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp4([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp4(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -210,7 +210,7 @@ define i32 @strncmp_memcmp4([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp5([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp5(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -226,7 +226,7 @@ define i32 @strncmp_memcmp5([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp6([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp6(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -241,7 +241,7 @@ define i32 @strncmp_memcmp6([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp7([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp7(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -256,7 +256,7 @@ define i32 @strncmp_memcmp7([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp8([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp8(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 3) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(3) [[STRING]], i8* dereferenceable(3) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i64 3)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -271,7 +271,7 @@ define i32 @strncmp_memcmp8([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp9([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp9(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -286,7 +286,7 @@ define i32 @strncmp_memcmp9([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp10([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp10(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4)  ; CHECK-NEXT:    [[MEMCMP_LOBIT:%.*]] = lshr i32 [[MEMCMP]], 31  ; CHECK-NEXT:    ret i32 [[MEMCMP_LOBIT]]  ; @@ -300,7 +300,7 @@ define i32 @strncmp_memcmp10([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp11([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp11(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -315,7 +315,7 @@ define i32 @strncmp_memcmp11([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp12([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp12(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull [[STRING]], i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* dereferenceable(4) getelementptr inbounds ([4 x i8], [4 x i8]* @key, i64 0, i64 0), i8* nonnull dereferenceable(4) [[STRING]], i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -330,7 +330,7 @@ define i32 @strncmp_memcmp12([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp13([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp13(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 2) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(2) [[STRING]], i8* dereferenceable(2) getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 2)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] @@ -345,7 +345,7 @@ define i32 @strncmp_memcmp13([12 x i8]* dereferenceable (12) %buf) {  define i32 @strncmp_memcmp14([12 x i8]* dereferenceable (12) %buf) {  ; CHECK-LABEL: @strncmp_memcmp14(  ; CHECK-NEXT:    [[STRING:%.*]] = getelementptr inbounds [12 x i8], [12 x i8]* [[BUF:%.*]], i64 0, i64 0 -; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull [[STRING]], i8* getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 4) +; CHECK-NEXT:    [[MEMCMP:%.*]] = call i32 @memcmp(i8* nonnull dereferenceable(4) [[STRING]], i8* dereferenceable(4) getelementptr inbounds ([8 x i8], [8 x i8]* @abc, i64 0, i64 0), i64 4)  ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[MEMCMP]], 0  ; CHECK-NEXT:    [[CONV:%.*]] = zext i1 [[CMP]] to i32  ; CHECK-NEXT:    ret i32 [[CONV]] diff --git a/llvm/test/Transforms/InstCombine/strcpy_chk-1.ll b/llvm/test/Transforms/InstCombine/strcpy_chk-1.ll index 859d810d3c4..292591f7281 100644 --- a/llvm/test/Transforms/InstCombine/strcpy_chk-1.ll +++ b/llvm/test/Transforms/InstCombine/strcpy_chk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; Test lib call simplification of __strcpy_chk calls with various values  ; for src, dst, and slen.  ; @@ -13,33 +14,36 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3  define i8* @test_simplify1() {  ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT:    ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0) +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) -; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)    %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 60)    ret i8* %ret  }  define i8* @test_simplify2() {  ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT:    ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0) +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) -; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)    %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 12)    ret i8* %ret  }  define i8* @test_simplify3() {  ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT:    ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0) +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) -; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)    %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 -1)    ret i8* %ret  } @@ -48,11 +52,12 @@ define i8* @test_simplify3() {  define i8* @test_simplify4() {  ; CHECK-LABEL: @test_simplify4( +; CHECK-NEXT:    [[STRCPY:%.*]] = call i8* @strcpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0)) +; CHECK-NEXT:    ret i8* [[STRCPY]] +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 -; CHECK-NEXT: %strcpy = call i8* @strcpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0)) -; CHECK-NEXT: ret i8* %strcpy    %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 -1)    ret i8* %ret  } @@ -61,12 +66,13 @@ define i8* @test_simplify4() {  define i8* @test_simplify5() {  ; CHECK-LABEL: @test_simplify5( +; CHECK-NEXT:    [[LEN:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false) +; CHECK-NEXT:    [[TMP1:%.*]] = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 [[LEN]]) +; CHECK-NEXT:    ret i8* [[TMP1]] +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false) -; CHECK-NEXT: %1 = call i8* @__memcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i32 %len) -; CHECK-NEXT: ret i8* %1    %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false, i1 false)    %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 %len)    ret i8* %ret @@ -76,11 +82,12 @@ define i8* @test_simplify5() {  define i8* @test_simplify6() {  ; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT:    [[LEN:%.*]] = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false) +; CHECK-NEXT:    [[RET:%.*]] = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i32 [[LEN]]) +; CHECK-NEXT:    ret i8* [[RET]] +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0 -; CHECK-NEXT: %len = call i32 @llvm.objectsize.i32.p0i8(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i1 false, i1 false, i1 false) -; CHECK-NEXT: %ret = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i32 %len) -; CHECK-NEXT: ret i8* %ret    %len = call i32 @llvm.objectsize.i32.p0i8(i8* %dst, i1 false, i1 false, i1 false)    %ret = call i8* @__strcpy_chk(i8* %dst, i8* %dst, i32 %len)    ret i8* %ret @@ -90,11 +97,12 @@ define i8* @test_simplify6() {  define i8* @test_no_simplify1() {  ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT:    [[RET:%.*]] = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 8) +; CHECK-NEXT:    ret i8* [[RET]] +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 -; CHECK-NEXT: %ret = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 8) -; CHECK-NEXT: ret i8* %ret    %ret = call i8* @__strcpy_chk(i8* %dst, i8* %src, i32 8)    ret i8* %ret  } diff --git a/llvm/test/Transforms/InstCombine/strncpy_chk-1.ll b/llvm/test/Transforms/InstCombine/strncpy_chk-1.ll index bc3ff35ef05..6f7b0415b1f 100644 --- a/llvm/test/Transforms/InstCombine/strncpy_chk-1.ll +++ b/llvm/test/Transforms/InstCombine/strncpy_chk-1.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; Test lib call simplification of __strncpy_chk calls with various values  ; for len and dstlen.  ; @@ -13,33 +14,36 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3  define i8* @test_simplify1() {  ; CHECK-LABEL: @test_simplify1( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT:    ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0) +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) -; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)    %ret = call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 12, i32 60)    ret i8* %ret  }  define i8* @test_simplify2() {  ; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 dereferenceable(12) getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 dereferenceable(12) getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) +; CHECK-NEXT:    ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0) +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* align 1 getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 12, i1 false) -; CHECK-NEXT: ret i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0)    %ret = call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 12, i32 12)    ret i8* %ret  }  define i8* @test_simplify3() {  ; CHECK-LABEL: @test_simplify3( +; CHECK-NEXT:    [[STRNCPY:%.*]] = call i8* @strncpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 12) +; CHECK-NEXT:    ret i8* [[STRNCPY]] +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 -; CHECK-NEXT: %strncpy = call i8* @strncpy(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 12) -; CHECK-NEXT: ret i8* %strncpy    %ret = call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 12, i32 60)    ret i8* %ret  } @@ -48,22 +52,24 @@ define i8* @test_simplify3() {  define i8* @test_no_simplify1() {  ; CHECK-LABEL: @test_no_simplify1( +; CHECK-NEXT:    [[RET:%.*]] = call i8* @__strncpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 8, i32 4) +; CHECK-NEXT:    ret i8* [[RET]] +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [12 x i8], [12 x i8]* @.str, i32 0, i32 0 -; CHECK-NEXT: %ret = call i8* @__strncpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i32 0, i32 0), i32 8, i32 4) -; CHECK-NEXT: ret i8* %ret    %ret = call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 8, i32 4)    ret i8* %ret  }  define i8* @test_no_simplify2() {  ; CHECK-LABEL: @test_no_simplify2( +; CHECK-NEXT:    [[RET:%.*]] = call i8* @__strncpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 8, i32 0) +; CHECK-NEXT:    ret i8* [[RET]] +;    %dst = getelementptr inbounds [60 x i8], [60 x i8]* @a, i32 0, i32 0    %src = getelementptr inbounds [60 x i8], [60 x i8]* @b, i32 0, i32 0 -; CHECK-NEXT: %ret = call i8* @__strncpy_chk(i8* getelementptr inbounds ([60 x i8], [60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([60 x i8], [60 x i8]* @b, i32 0, i32 0), i32 8, i32 0) -; CHECK-NEXT: ret i8* %ret    %ret = call i8* @__strncpy_chk(i8* %dst, i8* %src, i32 8, i32 0)    ret i8* %ret  } diff --git a/llvm/test/Transforms/MemCpyOpt/memcpy-to-memset-with-lifetimes.ll b/llvm/test/Transforms/MemCpyOpt/memcpy-to-memset-with-lifetimes.ll index 73d567a00ae..ee2f6adb431 100644 --- a/llvm/test/Transforms/MemCpyOpt/memcpy-to-memset-with-lifetimes.ll +++ b/llvm/test/Transforms/MemCpyOpt/memcpy-to-memset-with-lifetimes.ll @@ -1,9 +1,16 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py  ; RUN: opt -basicaa -memcpyopt -instcombine -S < %s | FileCheck %s  target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"  target triple = "x86_64-unknown-linux-gnu"  define void @foo([8 x i64]* noalias nocapture sret dereferenceable(64) %sret) { +; CHECK-LABEL: @foo( +; CHECK-NEXT:  entry-block: +; CHECK-NEXT:    [[SRET1:%.*]] = bitcast [8 x i64]* [[SRET:%.*]] to i8* +; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(64) [[SRET1]], i8 0, i64 64, i1 false) +; CHECK-NEXT:    ret void +;  entry-block:    %a = alloca [8 x i64], align 8    %a.cast = bitcast [8 x i64]* %a to i8* @@ -14,14 +21,23 @@ entry-block:    call void @llvm.lifetime.end.p0i8(i64 64, i8* %a.cast)    ret void -; CHECK-LABEL: @foo( -; CHECK:         %[[sret_cast:[^=]+]] = bitcast [8 x i64]* %sret to i8* -; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* nonnull align 8 %[[sret_cast]], i8 0, i64 64 -; CHECK-NOT: call void @llvm.memcpy -; CHECK: ret void  }  define void @bar([8 x i64]* noalias nocapture sret dereferenceable(64) %sret, [8 x i64]* noalias nocapture dereferenceable(64) %out) { +; CHECK-LABEL: @bar( +; CHECK-NEXT:  entry-block: +; CHECK-NEXT:    [[A:%.*]] = alloca [8 x i64], align 8 +; CHECK-NEXT:    [[A_CAST:%.*]] = bitcast [8 x i64]* [[A]] to i8* +; CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 64, i8* nonnull [[A_CAST]]) +; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(64) [[A_CAST]], i8 0, i64 64, i1 false) +; CHECK-NEXT:    [[SRET_CAST:%.*]] = bitcast [8 x i64]* [[SRET:%.*]] to i8* +; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(64) [[SRET_CAST]], i8 0, i64 64, i1 false) +; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(32) [[A_CAST]], i8 42, i64 32, i1 false) +; CHECK-NEXT:    [[OUT_CAST:%.*]] = bitcast [8 x i64]* [[OUT:%.*]] to i8* +; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 dereferenceable(64) [[OUT_CAST]], i8* nonnull align 8 dereferenceable(64) [[A_CAST]], i64 64, i1 false) +; CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 64, i8* nonnull [[A_CAST]]) +; CHECK-NEXT:    ret void +;  entry-block:    %a = alloca [8 x i64], align 8    %a.cast = bitcast [8 x i64]* %a to i8* @@ -35,17 +51,6 @@ entry-block:    call void @llvm.lifetime.end.p0i8(i64 64, i8* %a.cast)    ret void -; CHECK-LABEL: @bar( -; CHECK:         %[[a:[^=]+]] = alloca [8 x i64] -; CHECK:         %[[a_cast:[^=]+]] = bitcast [8 x i64]* %[[a]] to i8* -; CHECK:         call void @llvm.memset.p0i8.i64(i8* nonnull align 8 %[[a_cast]], i8 0, i64 64 -; CHECK:         %[[sret_cast:[^=]+]] = bitcast [8 x i64]* %sret to i8* -; CHECK:         call void @llvm.memset.p0i8.i64(i8* nonnull align 8 %[[sret_cast]], i8 0, i64 64 -; CHECK:         call void @llvm.memset.p0i8.i64(i8* nonnull align 8 %[[a_cast]], i8 42, i64 32 -; CHECK:         %[[out_cast:[^=]+]] = bitcast [8 x i64]* %out to i8* -; CHECK:         call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 8 %[[out_cast]], i8* nonnull align 8 %[[a_cast]], i64 64 -; CHECK-NOT: call void @llvm.memcpy -; CHECK: ret void  }  declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind  | 

