1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3; PR1201 4 5target datalayout = "p:32:32:32" 6 7define i32 @main(i32 %argc, ptr %argv) { 8; CHECK-LABEL: @main( 9; CHECK-NEXT: ret i32 0 10; 11 %c_19 = alloca ptr 12 %malloc_206 = tail call ptr @malloc(i32 mul (i32 ptrtoint (ptr getelementptr (i8, ptr null, i32 1) to i32), i32 10)) 13 store ptr %malloc_206, ptr %c_19 14 %tmp_207 = load ptr, ptr %c_19 15 tail call void @free(ptr %tmp_207) 16 ret i32 0 17} 18 19define i32 @dead_aligned_alloc(i32 %size, i32 %alignment, i8 %value) { 20; CHECK-LABEL: @dead_aligned_alloc( 21; CHECK-NEXT: ret i32 0 22; 23 %aligned_allocation = tail call ptr @aligned_alloc(i32 %alignment, i32 %size) 24 store i8 %value, ptr %aligned_allocation 25 tail call void @free(ptr %aligned_allocation) 26 ret i32 0 27} 28 29define i1 @aligned_alloc_only_pointe(i32 %size, i32 %alignment, i8 %value) { 30; CHECK-LABEL: @aligned_alloc_only_pointe( 31; CHECK-NEXT: [[ALIGNED_ALLOCATION:%.*]] = tail call ptr @aligned_alloc(i32 [[ALIGNMENT:%.*]], i32 [[SIZE:%.*]]) 32; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[ALIGNED_ALLOCATION]], null 33; CHECK-NEXT: ret i1 [[CMP]] 34; 35 %aligned_allocation = tail call ptr @aligned_alloc(i32 %alignment, i32 %size) 36 %cmp = icmp ne ptr %aligned_allocation, null 37 ret i1 %cmp 38} 39 40define i1 @aligned_alloc_pointer_only_used_by_cmp_alignment_and_value_known_ok(i32 %size, i32 %alignment, i8 %value) { 41; CHECK-LABEL: @aligned_alloc_pointer_only_used_by_cmp_alignment_and_value_known_ok( 42; CHECK-NEXT: ret i1 true 43; 44 %aligned_allocation = tail call ptr @aligned_alloc(i32 8, i32 32) 45 %cmp = icmp ne ptr %aligned_allocation, null 46 ret i1 %cmp 47} 48 49define i1 @aligned_alloc_pointer_only_used_by_cmp_alignment_no_power_of_2(i32 %size, i32 %alignment, i8 %value) { 50; CHECK-LABEL: @aligned_alloc_pointer_only_used_by_cmp_alignment_no_power_of_2( 51; CHECK-NEXT: [[ALIGNED_ALLOCATION:%.*]] = tail call dereferenceable_or_null(32) ptr @aligned_alloc(i32 3, i32 32) 52; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[ALIGNED_ALLOCATION]], null 53; CHECK-NEXT: ret i1 [[CMP]] 54; 55 %aligned_allocation = tail call ptr @aligned_alloc(i32 3, i32 32) 56 %cmp = icmp ne ptr %aligned_allocation, null 57 ret i1 %cmp 58} 59 60define i1 @aligned_alloc_pointer_only_used_by_cmp_size_not_multiple_of_alignment(i32 %size, i32 %alignment, i8 %value) { 61; CHECK-LABEL: @aligned_alloc_pointer_only_used_by_cmp_size_not_multiple_of_alignment( 62; CHECK-NEXT: [[ALIGNED_ALLOCATION:%.*]] = tail call dereferenceable_or_null(31) ptr @aligned_alloc(i32 8, i32 31) 63; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[ALIGNED_ALLOCATION]], null 64; CHECK-NEXT: ret i1 [[CMP]] 65; 66 %aligned_allocation = tail call ptr @aligned_alloc(i32 8, i32 31) 67 %cmp = icmp ne ptr %aligned_allocation, null 68 ret i1 %cmp 69} 70 71; This test uses a aligned allocation function different to @aligned_alloc, 72; and should be treated as having @aligned_alloc's constraints on alignment 73; and size operands. 74define i1 @other_aligned_allocation_function(i32 %size, i32 %alignment, i8 %value) { 75; CHECK-LABEL: @other_aligned_allocation_function( 76; CHECK-NEXT: ret i1 true 77; 78 %aligned_allocation = tail call ptr @other_aligned_alloc(i32 %alignment, i32 %size) 79 %cmp = icmp ne ptr %aligned_allocation, null 80 ret i1 %cmp 81} 82 83declare noalias ptr @calloc(i32, i32) nounwind allockind("alloc,zeroed") allocsize(0,1) "alloc-family"="malloc" 84declare noalias ptr @malloc(i32) allockind("alloc,uninitialized") allocsize(0) "alloc-family"="malloc" 85declare noalias ptr @aligned_alloc(i32, i32) allockind("alloc,uninitialized,aligned") allocsize(1) "alloc-family"="malloc" 86declare noalias ptr @other_aligned_alloc(i32, i32) allockind("alloc,uninitialized,aligned") allocsize(1) "alloc-family"="malloc" 87declare void @free(ptr) allockind("free") "alloc-family"="malloc" 88 89define i1 @foo() { 90; CHECK-LABEL: @foo( 91; CHECK-NEXT: ret i1 false 92; 93 %m = call ptr @malloc(i32 1) 94 %z = icmp eq ptr %m, null 95 call void @free(ptr %m) 96 ret i1 %z 97} 98 99declare void @llvm.lifetime.start.p0(i64, ptr) 100declare void @llvm.lifetime.end.p0(i64, ptr) 101declare i64 @llvm.objectsize.i64(ptr, i1) 102declare void @llvm.memcpy.p0.p0.i32(ptr nocapture, ptr nocapture, i32, i1) nounwind 103declare void @llvm.memmove.p0.p0.i32(ptr nocapture, ptr nocapture, i32, i1) nounwind 104declare void @llvm.memset.p0.i32(ptr, i8, i32, i1) nounwind 105 106define void @test3(ptr %src) { 107; CHECK-LABEL: @test3( 108; CHECK-NEXT: ret void 109; 110 %a = call noalias ptr @malloc(i32 10) 111 call void @llvm.lifetime.start.p0(i64 10, ptr %a) 112 call void @llvm.lifetime.end.p0(i64 10, ptr %a) 113 %size = call i64 @llvm.objectsize.i64(ptr %a, i1 true) 114 store i8 42, ptr %a 115 call void @llvm.memcpy.p0.p0.i32(ptr %a, ptr %src, i32 32, i1 false) 116 call void @llvm.memmove.p0.p0.i32(ptr %a, ptr %src, i32 32, i1 false) 117 call void @llvm.memset.p0.i32(ptr %a, i8 5, i32 32, i1 false) 118 %alloc2 = call noalias ptr @calloc(i32 5, i32 7) nounwind 119 %z = icmp ne ptr %alloc2, null 120 ret void 121} 122 123;; This used to crash. 124define void @test4() { 125; CHECK-LABEL: @test4( 126; CHECK-NEXT: ret void 127; 128 %A = call ptr @malloc(i32 16000) 129 call void @free(ptr %A) 130 ret void 131} 132 133define void @test5(ptr %ptr, ptr %esc) { 134; CHECK-LABEL: @test5( 135; CHECK-NEXT: [[A:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) 136; CHECK-NEXT: [[B:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) 137; CHECK-NEXT: [[C:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) 138; CHECK-NEXT: [[D:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) 139; CHECK-NEXT: [[E:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) 140; CHECK-NEXT: [[F:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) 141; CHECK-NEXT: [[G:%.*]] = call dereferenceable_or_null(700) ptr @malloc(i32 700) 142; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(32) [[PTR:%.*]], ptr noundef nonnull align 1 dereferenceable(32) [[A]], i32 32, i1 false) 143; CHECK-NEXT: call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(32) [[PTR]], ptr noundef nonnull align 1 dereferenceable(32) [[B]], i32 32, i1 false) 144; CHECK-NEXT: store ptr [[C]], ptr [[ESC:%.*]], align 4 145; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[D]], ptr [[PTR]], i32 32, i1 true) 146; CHECK-NEXT: call void @llvm.memmove.p0.p0.i32(ptr [[E]], ptr [[PTR]], i32 32, i1 true) 147; CHECK-NEXT: call void @llvm.memset.p0.i32(ptr [[F]], i8 5, i32 32, i1 true) 148; CHECK-NEXT: store volatile i8 4, ptr [[G]], align 1 149; CHECK-NEXT: ret void 150; 151 %a = call ptr @malloc(i32 700) 152 %b = call ptr @malloc(i32 700) 153 %c = call ptr @malloc(i32 700) 154 %d = call ptr @malloc(i32 700) 155 %e = call ptr @malloc(i32 700) 156 %f = call ptr @malloc(i32 700) 157 %g = call ptr @malloc(i32 700) 158 call void @llvm.memcpy.p0.p0.i32(ptr %ptr, ptr %a, i32 32, i1 false) 159 call void @llvm.memmove.p0.p0.i32(ptr %ptr, ptr %b, i32 32, i1 false) 160 store ptr %c, ptr %esc 161 call void @llvm.memcpy.p0.p0.i32(ptr %d, ptr %ptr, i32 32, i1 true) 162 call void @llvm.memmove.p0.p0.i32(ptr %e, ptr %ptr, i32 32, i1 true) 163 call void @llvm.memset.p0.i32(ptr %f, i8 5, i32 32, i1 true) 164 store volatile i8 4, ptr %g 165 ret void 166} 167 168;; When a basic block contains only a call to free and this block is accessed 169;; through a test of the argument of free against null, move the call in the 170;; predecessor block. 171;; Using simplifycfg will remove the empty basic block and the branch operation 172;; Then, performing a dead elimination will remove the comparison. 173;; This is what happens with -O1 and upper. 174define void @test6(ptr %foo) minsize { 175; CHECK-LABEL: @test6( 176; CHECK-NEXT: entry: 177; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq ptr [[FOO:%.*]], null 178; CHECK-NEXT: tail call void @free(ptr [[FOO]]) 179; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] 180; CHECK: if.then: 181; CHECK-NEXT: br label [[IF_END]] 182; CHECK: if.end: 183; CHECK-NEXT: ret void 184; 185;; Call to free moved 186;; Block is now empty and may be simplified by simplifycfg 187entry: 188 %tobool = icmp eq ptr %foo, null 189 br i1 %tobool, label %if.end, label %if.then 190 191if.then: ; preds = %entry 192 tail call void @free(ptr %foo) 193 br label %if.end 194 195if.end: ; preds = %entry, %if.then 196 ret void 197} 198 199;; Check that the optimization that moves a call to free in its predecessor 200;; block (see test6) also happens when noop casts are involved. 201define void @test12(ptr %foo) minsize { 202; CHECK-LABEL: @test12( 203; CHECK-NEXT: entry: 204; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq ptr [[FOO:%.*]], null 205; CHECK-NEXT: tail call void @free(ptr [[FOO]]) 206; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] 207; CHECK: if.then: 208; CHECK-NEXT: br label [[IF_END]] 209; CHECK: if.end: 210; CHECK-NEXT: ret void 211; 212;; Everything before the call to free should have been moved as well. 213;; Call to free moved 214;; Block is now empty and may be simplified by simplifycfg 215entry: 216 %tobool = icmp eq ptr %foo, null 217 br i1 %tobool, label %if.end, label %if.then 218 219if.then: ; preds = %entry 220 tail call void @free(ptr %foo) 221 br label %if.end 222 223if.end: ; preds = %entry, %if.then 224 ret void 225} 226 227;; Test that nonnull-implying attributes on the parameter are adjusted when the 228;; call is moved, since they may no longer be valid and result in miscompiles if 229;; kept unchanged. 230define void @test_nonnull_free_move(ptr %foo) minsize { 231; CHECK-LABEL: @test_nonnull_free_move( 232; CHECK-NEXT: entry: 233; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq ptr [[FOO:%.*]], null 234; CHECK-NEXT: tail call void @free(ptr [[FOO]]) 235; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] 236; CHECK: if.then: 237; CHECK-NEXT: br label [[IF_END]] 238; CHECK: if.end: 239; CHECK-NEXT: ret void 240; 241entry: 242 %tobool = icmp eq ptr %foo, null 243 br i1 %tobool, label %if.end, label %if.then 244 245if.then: ; preds = %entry 246 tail call void @free(ptr nonnull %foo) 247 br label %if.end 248 249if.end: ; preds = %entry, %if.then 250 ret void 251} 252 253define void @test_dereferenceable_free_move(ptr %foo) minsize { 254; CHECK-LABEL: @test_dereferenceable_free_move( 255; CHECK-NEXT: entry: 256; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq ptr [[FOO:%.*]], null 257; CHECK-NEXT: tail call void @free(ptr dereferenceable_or_null(4) [[FOO]]) 258; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] 259; CHECK: if.then: 260; CHECK-NEXT: br label [[IF_END]] 261; CHECK: if.end: 262; CHECK-NEXT: ret void 263; 264entry: 265 %tobool = icmp eq ptr %foo, null 266 br i1 %tobool, label %if.end, label %if.then 267 268if.then: ; preds = %entry 269 tail call void @free(ptr dereferenceable(4) %foo) 270 br label %if.end 271 272if.end: ; preds = %entry, %if.then 273 ret void 274} 275 276define void @test_nonnull_dereferenceable_free_move(ptr %foo) minsize { 277; CHECK-LABEL: @test_nonnull_dereferenceable_free_move( 278; CHECK-NEXT: entry: 279; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq ptr [[FOO:%.*]], null 280; CHECK-NEXT: tail call void @free(ptr dereferenceable_or_null(16) [[FOO]]) 281; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] 282; CHECK: if.then: 283; CHECK-NEXT: br label [[IF_END]] 284; CHECK: if.end: 285; CHECK-NEXT: ret void 286; 287entry: 288 %tobool = icmp eq ptr %foo, null 289 br i1 %tobool, label %if.end, label %if.then 290 291if.then: ; preds = %entry 292 tail call void @free(ptr nonnull dereferenceable(16) %foo) 293 br label %if.end 294 295if.end: ; preds = %entry, %if.then 296 ret void 297} 298 299; The next four tests cover the semantics of the nofree attributes. These 300; are thought to be legal transforms, but an implementation thereof has 301; been reverted once due to difficult to isolate fallout. 302 303; TODO: Freeing a no-free pointer -> %foo must be null 304define void @test13(ptr nofree %foo) { 305; CHECK-LABEL: @test13( 306; CHECK-NEXT: call void @free(ptr [[FOO:%.*]]) 307; CHECK-NEXT: ret void 308; 309 call void @free(ptr %foo) 310 ret void 311} 312 313; TODO: Freeing a no-free pointer -> %foo must be null 314define void @test14(ptr %foo) nofree { 315; CHECK-LABEL: @test14( 316; CHECK-NEXT: call void @free(ptr [[FOO:%.*]]) 317; CHECK-NEXT: ret void 318; 319 call void @free(ptr %foo) 320 ret void 321} 322 323; TODO: free call marked no-free -> %foo must be null 324define void @test15(ptr %foo) { 325; CHECK-LABEL: @test15( 326; CHECK-NEXT: call void @free(ptr [[FOO:%.*]]) #[[ATTR8:[0-9]+]] 327; CHECK-NEXT: ret void 328; 329 call void @free(ptr %foo) nofree 330 ret void 331} 332 333; TODO: freeing a nonnull nofree pointer -> full UB 334define void @test16(ptr nonnull nofree %foo) { 335; CHECK-LABEL: @test16( 336; CHECK-NEXT: call void @free(ptr [[FOO:%.*]]) 337; CHECK-NEXT: ret void 338; 339 call void @free(ptr %foo) 340 ret void 341} 342