1; Test a pile of objectsize bounds checking. 2; RUN: opt < %s -instcombine -S | FileCheck %s 3; We need target data to get the sizes of the arrays and structures. 4target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" 5 6@a = private global [60 x i8] zeroinitializer, align 1 ; <[60 x i8]*> 7@.str = private constant [8 x i8] c"abcdefg\00" ; <[8 x i8]*> 8 9define i32 @foo() nounwind { 10; CHECK: @foo 11; CHECK-NEXT: ret i32 60 12 %1 = call i32 @llvm.objectsize.i32(i8* getelementptr inbounds ([60 x i8]* @a, i32 0, i32 0), i1 false) 13 ret i32 %1 14} 15 16define i8* @bar() nounwind { 17; CHECK: @bar 18entry: 19 %retval = alloca i8* 20 %0 = call i32 @llvm.objectsize.i32(i8* getelementptr inbounds ([60 x i8]* @a, i32 0, i32 0), i1 false) 21 %cmp = icmp ne i32 %0, -1 22; CHECK: br i1 true 23 br i1 %cmp, label %cond.true, label %cond.false 24 25cond.true: 26 %1 = load i8** %retval 27 ret i8* %1 28 29cond.false: 30 %2 = load i8** %retval 31 ret i8* %2 32} 33 34define i32 @f() nounwind { 35; CHECK: @f 36; CHECK-NEXT: ret i32 0 37 %1 = call i32 @llvm.objectsize.i32(i8* getelementptr ([60 x i8]* @a, i32 1, i32 0), i1 false) 38 ret i32 %1 39} 40 41@window = external global [0 x i8] 42 43define i1 @baz() nounwind { 44; CHECK: @baz 45; CHECK-NEXT: objectsize 46 %1 = tail call i32 @llvm.objectsize.i32(i8* getelementptr inbounds ([0 x i8]* @window, i32 0, i32 0), i1 false) 47 %2 = icmp eq i32 %1, -1 48 ret i1 %2 49} 50 51define void @test1(i8* %q, i32 %x) nounwind noinline { 52; CHECK: @test1 53; CHECK: objectsize.i32 54entry: 55 %0 = call i32 @llvm.objectsize.i32(i8* getelementptr inbounds ([0 x i8]* @window, i32 0, i32 10), i1 false) ; <i64> [#uses=1] 56 %1 = icmp eq i32 %0, -1 ; <i1> [#uses=1] 57 br i1 %1, label %"47", label %"46" 58 59"46": ; preds = %entry 60 unreachable 61 62"47": ; preds = %entry 63 unreachable 64} 65 66@.str5 = private constant [9 x i32] [i32 97, i32 98, i32 99, i32 100, i32 0, i32 67 101, i32 102, i32 103, i32 0], align 4 68define i32 @test2() nounwind { 69; CHECK: @test2 70; CHECK-NEXT: ret i32 34 71 %1 = call i32 @llvm.objectsize.i32(i8* getelementptr (i8* bitcast ([9 x i32]* @.str5 to i8*), i32 2), i1 false) 72 ret i32 %1 73} 74 75; rdar://7674946 76@array = internal global [480 x float] zeroinitializer ; <[480 x float]*> [#uses=1] 77 78declare i8* @__memcpy_chk(i8*, i8*, i32, i32) nounwind 79 80declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readonly 81 82declare i8* @__inline_memcpy_chk(i8*, i8*, i32) nounwind inlinehint 83 84define void @test3() nounwind { 85; CHECK: @test3 86entry: 87 br i1 undef, label %bb11, label %bb12 88 89bb11: 90 %0 = getelementptr inbounds float* getelementptr inbounds ([480 x float]* @array, i32 0, i32 128), i32 -127 ; <float*> [#uses=1] 91 %1 = bitcast float* %0 to i8* ; <i8*> [#uses=1] 92 %2 = call i32 @llvm.objectsize.i32(i8* %1, i1 false) ; <i32> [#uses=1] 93 %3 = call i8* @__memcpy_chk(i8* undef, i8* undef, i32 512, i32 %2) nounwind ; <i8*> [#uses=0] 94; CHECK: unreachable 95 unreachable 96 97bb12: 98 %4 = getelementptr inbounds float* getelementptr inbounds ([480 x float]* @array, i32 0, i32 128), i32 -127 ; <float*> [#uses=1] 99 %5 = bitcast float* %4 to i8* ; <i8*> [#uses=1] 100 %6 = call i8* @__inline_memcpy_chk(i8* %5, i8* undef, i32 512) nounwind inlinehint ; <i8*> [#uses=0] 101; CHECK: @__inline_memcpy_chk 102 unreachable 103} 104 105; rdar://7718857 106 107%struct.data = type { [100 x i32], [100 x i32], [1024 x i8] } 108 109define i32 @test4(i8** %esc) nounwind ssp { 110; CHECK: @test4 111entry: 112 %0 = alloca %struct.data, align 8 113 %1 = bitcast %struct.data* %0 to i8* 114 %2 = call i32 @llvm.objectsize.i32(i8* %1, i1 false) nounwind 115; CHECK-NOT: @llvm.objectsize 116; CHECK: @llvm.memset.p0i8.i32(i8* %1, i8 0, i32 1824, i32 8, i1 false) 117 %3 = call i8* @__memset_chk(i8* %1, i32 0, i32 1824, i32 %2) nounwind 118 store i8* %1, i8** %esc 119 ret i32 0 120} 121 122; rdar://7782496 123@s = external global i8* 124 125define i8* @test5(i32 %n) nounwind ssp { 126; CHECK: @test5 127entry: 128 %0 = tail call noalias i8* @malloc(i32 20) nounwind 129 %1 = tail call i32 @llvm.objectsize.i32(i8* %0, i1 false) 130 %2 = load i8** @s, align 8 131; CHECK-NOT: @llvm.objectsize 132; CHECK: @llvm.memcpy.p0i8.p0i8.i32(i8* %0, i8* %1, i32 10, i32 1, i1 false) 133 %3 = tail call i8* @__memcpy_chk(i8* %0, i8* %2, i32 10, i32 %1) nounwind 134 ret i8* %0 135} 136 137define void @test6(i32 %n) nounwind ssp { 138; CHECK: @test6 139entry: 140 %0 = tail call noalias i8* @malloc(i32 20) nounwind 141 %1 = tail call i32 @llvm.objectsize.i32(i8* %0, i1 false) 142 %2 = load i8** @s, align 8 143; CHECK-NOT: @llvm.objectsize 144; CHECK: @__memcpy_chk(i8* %0, i8* %1, i32 30, i32 20) 145 %3 = tail call i8* @__memcpy_chk(i8* %0, i8* %2, i32 30, i32 %1) nounwind 146 ret void 147} 148 149declare i8* @__memset_chk(i8*, i32, i32, i32) nounwind 150 151declare noalias i8* @malloc(i32) nounwind 152 153define i32 @test7(i8** %esc) { 154; CHECK: @test7 155 %alloc = call noalias i8* @malloc(i32 48) nounwind 156 store i8* %alloc, i8** %esc 157 %gep = getelementptr inbounds i8* %alloc, i32 16 158 %objsize = call i32 @llvm.objectsize.i32(i8* %gep, i1 false) nounwind readonly 159; CHECK: ret i32 32 160 ret i32 %objsize 161} 162 163declare noalias i8* @calloc(i32, i32) nounwind 164 165define i32 @test8(i8** %esc) { 166; CHECK: @test8 167 %alloc = call noalias i8* @calloc(i32 5, i32 7) nounwind 168 store i8* %alloc, i8** %esc 169 %gep = getelementptr inbounds i8* %alloc, i32 5 170 %objsize = call i32 @llvm.objectsize.i32(i8* %gep, i1 false) nounwind readonly 171; CHECK: ret i32 30 172 ret i32 %objsize 173} 174 175declare noalias i8* @strdup(i8* nocapture) nounwind 176declare noalias i8* @strndup(i8* nocapture, i32) nounwind 177 178; CHECK: @test9 179define i32 @test9(i8** %esc) { 180 %call = tail call i8* @strdup(i8* getelementptr inbounds ([8 x i8]* @.str, i64 0, i64 0)) nounwind 181 store i8* %call, i8** %esc, align 8 182 %1 = tail call i32 @llvm.objectsize.i32(i8* %call, i1 true) 183; CHECK: ret i32 8 184 ret i32 %1 185} 186 187; CHECK: @test10 188define i32 @test10(i8** %esc) { 189 %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8]* @.str, i64 0, i64 0), i32 3) nounwind 190 store i8* %call, i8** %esc, align 8 191 %1 = tail call i32 @llvm.objectsize.i32(i8* %call, i1 true) 192; CHECK: ret i32 4 193 ret i32 %1 194} 195 196; CHECK: @test11 197define i32 @test11(i8** %esc) { 198 %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8]* @.str, i64 0, i64 0), i32 7) nounwind 199 store i8* %call, i8** %esc, align 8 200 %1 = tail call i32 @llvm.objectsize.i32(i8* %call, i1 true) 201; CHECK: ret i32 8 202 ret i32 %1 203} 204 205; CHECK: @test12 206define i32 @test12(i8** %esc) { 207 %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8]* @.str, i64 0, i64 0), i32 8) nounwind 208 store i8* %call, i8** %esc, align 8 209 %1 = tail call i32 @llvm.objectsize.i32(i8* %call, i1 true) 210; CHECK: ret i32 8 211 ret i32 %1 212} 213 214; CHECK: @test13 215define i32 @test13(i8** %esc) { 216 %call = tail call i8* @strndup(i8* getelementptr inbounds ([8 x i8]* @.str, i64 0, i64 0), i32 57) nounwind 217 store i8* %call, i8** %esc, align 8 218 %1 = tail call i32 @llvm.objectsize.i32(i8* %call, i1 true) 219; CHECK: ret i32 8 220 ret i32 %1 221} 222 223; CHECK: @PR13390 224define i32 @PR13390(i1 %bool, i8* %a) { 225entry: 226 %cond = or i1 %bool, true 227 br i1 %cond, label %return, label %xpto 228 229xpto: 230 %select = select i1 %bool, i8* %select, i8* %a 231 %select2 = select i1 %bool, i8* %a, i8* %select2 232 %0 = tail call i32 @llvm.objectsize.i32(i8* %select, i1 true) 233 %1 = tail call i32 @llvm.objectsize.i32(i8* %select2, i1 true) 234 %2 = add i32 %0, %1 235; CHECK: ret i32 undef 236 ret i32 %2 237 238return: 239 ret i32 42 240} 241 242; CHECK: @PR13621 243define i32 @PR13621(i1 %bool) nounwind { 244entry: 245 %cond = or i1 %bool, true 246 br i1 %cond, label %return, label %xpto 247 248; technically reachable, but this malformed IR may appear as a result of constant propagation 249xpto: 250 %gep2 = getelementptr i8* %gep, i32 1 251 %gep = getelementptr i8* %gep2, i32 1 252 %o = call i32 @llvm.objectsize.i32(i8* %gep, i1 true) 253; CHECK: ret i32 undef 254 ret i32 %o 255 256return: 257 ret i32 7 258} 259