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 7target 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 14define 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 24define 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 34define 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 46define 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 56define 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 67define i32 @test_rauw(i8* %a, i8* %b, i8** %c) { 68; CHECK-LABEL: test_rauw 69entry: 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 87declare i8* @__memmove_chk(i8*, i8*, i64, i64) 88declare i8* @strrchr(i8*, i32) 89declare i64 @strlen(i8* nocapture) 90declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) 91 92declare i8* @__memset_chk(i8*, i32, i64, i64) 93 94; FIXME: memset(malloc(x), 0, x) -> calloc(1, x) 95 96define float* @pr25892(i64 %size) #0 { 97entry: 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 101if.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 106cleanup: 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 125declare noalias i8* @malloc(i64) #1 126 127attributes #0 = { nounwind ssp uwtable } 128attributes #1 = { nounwind } 129attributes #2 = { nounwind readnone } 130 131