1 ; Test lib call simplification of __memset_chk calls with various values 2 ; for dstlen and len. 3 ; 4 ; RUN: opt < %s -instcombine -S | FileCheck %s 5 ; rdar://7719085 6 7 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 8 9 %struct.T = type { [100 x i32], [100 x i32], [1024 x i8] } 10 @t = common global %struct.T zeroinitializer 11 12 ; Check cases where dstlen >= len. 13 14 define i8* @test_simplify1() { 15 ; CHECK-LABEL: @test_simplify1( 16 %dst = bitcast %struct.T* @t to i8* 17 18 ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i32 4, i1 false) 19 ; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*) 20 %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 1824) 21 ret i8* %ret 22 } 23 24 define i8* @test_simplify2() { 25 ; CHECK-LABEL: @test_simplify2( 26 %dst = bitcast %struct.T* @t to i8* 27 28 ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i32 4, i1 false) 29 ; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*) 30 %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 3648) 31 ret i8* %ret 32 } 33 34 define i8* @test_simplify3() { 35 ; CHECK-LABEL: @test_simplify3( 36 %dst = bitcast %struct.T* @t to i8* 37 38 ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i32 4, i1 false) 39 ; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*) 40 %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 -1) 41 ret i8* %ret 42 } 43 44 ; Check cases where dstlen < len. 45 46 define i8* @test_no_simplify1() { 47 ; CHECK-LABEL: @test_no_simplify1( 48 %dst = bitcast %struct.T* @t to i8* 49 50 ; CHECK-NEXT: %ret = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 400) 51 ; CHECK-NEXT: ret i8* %ret 52 %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 400) 53 ret i8* %ret 54 } 55 56 define i8* @test_no_simplify2() { 57 ; CHECK-LABEL: @test_no_simplify2( 58 %dst = bitcast %struct.T* @t to i8* 59 60 ; CHECK-NEXT: %ret = call i8* @__memset_chk(i8* bitcast (%struct.T* @t to i8*), i32 0, i64 1824, i64 0) 61 ; CHECK-NEXT: ret i8* %ret 62 %ret = call i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 0) 63 ret i8* %ret 64 } 65 66 ; Test that RAUW in SimplifyLibCalls for __memset_chk generates valid IR 67 define i32 @test_rauw(i8* %a, i8* %b, i8** %c) { 68 ; CHECK-LABEL: test_rauw 69 entry: 70 %call49 = call i64 @strlen(i8* %a) 71 %add180 = add i64 %call49, 1 72 %yo107 = call i64 @llvm.objectsize.i64.p0i8(i8* %b, i1 false) 73 %call50 = call i8* @__memmove_chk(i8* %b, i8* %a, i64 %add180, i64 %yo107) 74 ; CHECK: %strlen = call i64 @strlen(i8* %b) 75 ; CHECK-NEXT: %strchr2 = getelementptr i8, i8* %b, i64 %strlen 76 %call51i = call i8* @strrchr(i8* %b, i32 0) 77 %d = load i8*, i8** %c, align 8 78 %sub182 = ptrtoint i8* %d to i64 79 %sub183 = ptrtoint i8* %b to i64 80 %sub184 = sub i64 %sub182, %sub183 81 %add52.i.i = add nsw i64 %sub184, 1 82 ; CHECK: call void @llvm.memset.p0i8.i64(i8* %strchr2 83 %call185 = call i8* @__memset_chk(i8* %call51i, i32 0, i64 %add52.i.i, i64 -1) 84 ret i32 4 85 } 86 87 declare i8* @__memmove_chk(i8*, i8*, i64, i64) 88 declare i8* @strrchr(i8*, i32) 89 declare i64 @strlen(i8* nocapture) 90 declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) 91 92 declare i8* @__memset_chk(i8*, i32, i64, i64) 93 94 ; FIXME: memset(malloc(x), 0, x) -> calloc(1, x) 95 96 define float* @pr25892(i64 %size) #0 { 97 entry: 98 %call = tail call i8* @malloc(i64 %size) #1 99 %cmp = icmp eq i8* %call, null 100 br i1 %cmp, label %cleanup, label %if.end 101 if.end: 102 %bc = bitcast i8* %call to float* 103 %call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false) 104 %call3 = tail call i8* @__memset_chk(i8* nonnull %call, i32 0, i64 %size, i64 %call2) #1 105 br label %cleanup 106 cleanup: 107 %retval.0 = phi float* [ %bc, %if.end ], [ null, %entry ] 108 ret float* %retval.0 109 110 ; CHECK-LABEL: @pr25892( 111 ; CHECK: entry: 112 ; CHECK-NEXT: %call = tail call i8* @malloc(i64 %size) 113 ; CHECK-NEXT: %cmp = icmp eq i8* %call, null 114 ; CHECK-NEXT: br i1 %cmp, label %cleanup, label %if.end 115 ; CHECK: if.end: 116 ; CHECK-NEXT: %bc = bitcast i8* %call to float* 117 ; CHECK-NEXT: %call2 = tail call i64 @llvm.objectsize.i64.p0i8(i8* nonnull %call, i1 false) 118 ; CHECK-NEXT: %call3 = tail call i8* @__memset_chk(i8* nonnull %call, i32 0, i64 %size, i64 %call2) 119 ; CHECK-NEXT: br label %cleanup 120 ; CHECK: cleanup: 121 ; CHECK-NEXT: %retval.0 = phi float* [ %bc, %if.end ], [ null, %entry ] 122 ; CHECK-NEXT: ret float* %retval.0 123 } 124 125 declare noalias i8* @malloc(i64) #1 126 127 attributes #0 = { nounwind ssp uwtable } 128 attributes #1 = { nounwind } 129 attributes #2 = { nounwind readnone } 130 131