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. 4 target 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 9 define i32 @foo() nounwind { 10 ; CHECK-LABEL: @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 16 define i8* @bar() nounwind { 17 ; CHECK-LABEL: @bar( 18 entry: 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 25 cond.true: 26 %1 = load i8** %retval 27 ret i8* %1 28 29 cond.false: 30 %2 = load i8** %retval 31 ret i8* %2 32 } 33 34 define i32 @f() nounwind { 35 ; CHECK-LABEL: @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 43 define i1 @baz() nounwind { 44 ; CHECK-LABEL: @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 51 define void @test1(i8* %q, i32 %x) nounwind noinline { 52 ; CHECK-LABEL: @test1( 53 ; CHECK: objectsize.i32 54 entry: 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 68 define i32 @test2() nounwind { 69 ; CHECK-LABEL: @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 78 declare i8* @__memcpy_chk(i8*, i8*, i32, i32) nounwind 79 80 declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readonly 81 82 declare i8* @__inline_memcpy_chk(i8*, i8*, i32) nounwind inlinehint 83 84 define void @test3() nounwind { 85 ; CHECK-LABEL: @test3( 86 entry: 87 br i1 undef, label %bb11, label %bb12 88 89 bb11: 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 97 bb12: 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 109 define i32 @test4(i8** %esc) nounwind ssp { 110 ; CHECK-LABEL: @test4( 111 entry: 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 125 define i8* @test5(i32 %n) nounwind ssp { 126 ; CHECK-LABEL: @test5( 127 entry: 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 137 define void @test6(i32 %n) nounwind ssp { 138 ; CHECK-LABEL: @test6( 139 entry: 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 149 declare i8* @__memset_chk(i8*, i32, i32, i32) nounwind 150 151 declare noalias i8* @malloc(i32) nounwind 152 153 define i32 @test7(i8** %esc) { 154 ; CHECK-LABEL: @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 163 declare noalias i8* @calloc(i32, i32) nounwind 164 165 define i32 @test8(i8** %esc) { 166 ; CHECK-LABEL: @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 175 declare noalias i8* @strdup(i8* nocapture) nounwind 176 declare noalias i8* @strndup(i8* nocapture, i32) nounwind 177 178 ; CHECK-LABEL: @test9( 179 define 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-LABEL: @test10( 188 define 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-LABEL: @test11( 197 define 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-LABEL: @test12( 206 define 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-LABEL: @test13( 215 define 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-LABEL: @PR13390( 224 define i32 @PR13390(i1 %bool, i8* %a) { 225 entry: 226 %cond = or i1 %bool, true 227 br i1 %cond, label %return, label %xpto 228 229 xpto: 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 238 return: 239 ret i32 42 240 } 241 242 ; CHECK-LABEL: @PR13621( 243 define i32 @PR13621(i1 %bool) nounwind { 244 entry: 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 249 xpto: 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 256 return: 257 ret i32 7 258 } 259 260 @globalalias = alias internal [60 x i8]* @a 261 262 ; CHECK-LABEL: @test18( 263 ; CHECK-NEXT: ret i32 60 264 define i32 @test18() { 265 %bc = bitcast [60 x i8]* @globalalias to i8* 266 %1 = call i32 @llvm.objectsize.i32(i8* %bc, i1 false) 267 ret i32 %1 268 } 269 270 @globalalias2 = alias weak [60 x i8]* @a 271 272 ; CHECK-LABEL: @test19( 273 ; CHECK: llvm.objectsize 274 define i32 @test19() { 275 %bc = bitcast [60 x i8]* @globalalias2 to i8* 276 %1 = call i32 @llvm.objectsize.i32(i8* %bc, i1 false) 277 ret i32 %1 278 } 279