1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instsimplify -S | FileCheck %s 3 4define i32 @fold(i32 %x) { 5; CHECK-LABEL: @fold( 6; CHECK-NEXT: [[Y:%.*]] = freeze i32 [[X:%.*]] 7; CHECK-NEXT: ret i32 [[Y]] 8; 9 %y = freeze i32 %x 10 %z = freeze i32 %y 11 ret i32 %z 12} 13 14define i32 @make_const() { 15; CHECK-LABEL: @make_const( 16; CHECK-NEXT: ret i32 10 17; 18 %x = freeze i32 10 19 ret i32 %x 20} 21 22define float @make_const2() { 23; CHECK-LABEL: @make_const2( 24; CHECK-NEXT: ret float 1.000000e+01 25; 26 %x = freeze float 10.0 27 ret float %x 28} 29 30@glb = constant i32 0 31 32define i32* @make_const_glb() { 33; CHECK-LABEL: @make_const_glb( 34; CHECK-NEXT: ret i32* @glb 35; 36 %k = freeze i32* @glb 37 ret i32* %k 38} 39 40define i32()* @make_const_fn() { 41; CHECK-LABEL: @make_const_fn( 42; CHECK-NEXT: ret i32 ()* @make_const 43; 44 %k = freeze i32()* @make_const 45 ret i32()* %k 46} 47 48define i32* @make_const_null() { 49; CHECK-LABEL: @make_const_null( 50; CHECK-NEXT: ret i32* null 51; 52 %k = freeze i32* null 53 ret i32* %k 54} 55 56define <2 x i32> @constvector() { 57; CHECK-LABEL: @constvector( 58; CHECK-NEXT: ret <2 x i32> <i32 0, i32 1> 59; 60 %x = freeze <2 x i32> <i32 0, i32 1> 61 ret <2 x i32> %x 62} 63 64define <3 x i5> @constvector_weird() { 65; CHECK-LABEL: @constvector_weird( 66; CHECK-NEXT: ret <3 x i5> <i5 0, i5 1, i5 10> 67; 68 %x = freeze <3 x i5> <i5 0, i5 1, i5 42> 69 ret <3 x i5> %x 70} 71 72define <2 x float> @constvector_FP() { 73; CHECK-LABEL: @constvector_FP( 74; CHECK-NEXT: ret <2 x float> <float 0.000000e+00, float 1.000000e+00> 75; 76 %x = freeze <2 x float> <float 0.0, float 1.0> 77 ret <2 x float> %x 78} 79 80; Negative test 81 82define <2 x i32> @constvector_noopt() { 83; CHECK-LABEL: @constvector_noopt( 84; CHECK-NEXT: [[X:%.*]] = freeze <2 x i32> <i32 0, i32 undef> 85; CHECK-NEXT: ret <2 x i32> [[X]] 86; 87 %x = freeze <2 x i32> <i32 0, i32 undef> 88 ret <2 x i32> %x 89} 90 91; Negative test 92 93define <3 x i5> @constvector_weird_noopt() { 94; CHECK-LABEL: @constvector_weird_noopt( 95; CHECK-NEXT: [[X:%.*]] = freeze <3 x i5> <i5 0, i5 undef, i5 10> 96; CHECK-NEXT: ret <3 x i5> [[X]] 97; 98 %x = freeze <3 x i5> <i5 0, i5 undef, i5 42> 99 ret <3 x i5> %x 100} 101 102; Negative test 103 104define <2 x float> @constvector_FP_noopt() { 105; CHECK-LABEL: @constvector_FP_noopt( 106; CHECK-NEXT: [[X:%.*]] = freeze <2 x float> <float 0.000000e+00, float undef> 107; CHECK-NEXT: ret <2 x float> [[X]] 108; 109 %x = freeze <2 x float> <float 0.0, float undef> 110 ret <2 x float> %x 111} 112 113@g = external global i16, align 1 114@g2 = external global i16, align 1 115 116define float @constant_expr() { 117; CHECK-LABEL: @constant_expr( 118; CHECK-NEXT: ret float bitcast (i32 ptrtoint (i16* @g to i32) to float) 119; 120 %r = freeze float bitcast (i32 ptrtoint (i16* @g to i32) to float) 121 ret float %r 122} 123 124define i8* @constant_expr2() { 125; CHECK-LABEL: @constant_expr2( 126; CHECK-NEXT: ret i8* bitcast (i16* @g to i8*) 127; 128 %r = freeze i8* bitcast (i16* @g to i8*) 129 ret i8* %r 130} 131 132define i32* @constant_expr3() { 133; CHECK-LABEL: @constant_expr3( 134; CHECK-NEXT: ret i32* getelementptr (i32, i32* @glb, i64 3) 135; 136 %r = freeze i32* getelementptr (i32, i32* @glb, i64 3) 137 ret i32* %r 138} 139 140define i64 @ptrdiff() { 141; CHECK-LABEL: @ptrdiff( 142; CHECK-NEXT: ret i64 sub (i64 ptrtoint (i16* @g to i64), i64 ptrtoint (i16* @g2 to i64)) 143; 144 %i = ptrtoint i16* @g to i64 145 %i2 = ptrtoint i16* @g2 to i64 146 %diff = sub i64 %i, %i2 147 %r = freeze i64 %diff 148 ret i64 %r 149} 150 151; Negative test 152 153define <2 x i31> @vector_element_constant_expr() { 154; CHECK-LABEL: @vector_element_constant_expr( 155; CHECK-NEXT: [[R:%.*]] = freeze <2 x i31> <i31 34, i31 ptrtoint (i16* @g to i31)> 156; CHECK-NEXT: ret <2 x i31> [[R]] 157; 158 %r = freeze <2 x i31> <i31 34, i31 ptrtoint (i16* @g to i31)> 159 ret <2 x i31> %r 160} 161 162define void @alloca() { 163; CHECK-LABEL: @alloca( 164; CHECK-NEXT: [[P:%.*]] = alloca i8, align 1 165; CHECK-NEXT: call void @f3(i8* [[P]]) 166; CHECK-NEXT: ret void 167; 168 %p = alloca i8 169 %y = freeze i8* %p 170 call void @f3(i8* %y) 171 ret void 172} 173 174define i8* @gep() { 175; CHECK-LABEL: @gep( 176; CHECK-NEXT: [[P:%.*]] = alloca [4 x i8], align 1 177; CHECK-NEXT: [[Q:%.*]] = getelementptr [4 x i8], [4 x i8]* [[P]], i32 0, i32 6 178; CHECK-NEXT: ret i8* [[Q]] 179; 180 %p = alloca [4 x i8] 181 %q = getelementptr [4 x i8], [4 x i8]* %p, i32 0, i32 6 182 %q2 = freeze i8* %q 183 ret i8* %q2 184} 185 186define i8* @gep_noopt(i32 %arg) { 187; CHECK-LABEL: @gep_noopt( 188; CHECK-NEXT: [[Q:%.*]] = getelementptr [4 x i8], [4 x i8]* null, i32 0, i32 [[ARG:%.*]] 189; CHECK-NEXT: [[Q2:%.*]] = freeze i8* [[Q]] 190; CHECK-NEXT: ret i8* [[Q2]] 191; 192 %q = getelementptr [4 x i8], [4 x i8]* null, i32 0, i32 %arg 193 %q2 = freeze i8* %q 194 ret i8* %q2 195} 196 197define i8* @gep_inbounds() { 198; CHECK-LABEL: @gep_inbounds( 199; CHECK-NEXT: [[P:%.*]] = alloca [4 x i8], align 1 200; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[P]], i32 0, i32 0 201; CHECK-NEXT: ret i8* [[Q]] 202; 203 %p = alloca [4 x i8] 204 %q = getelementptr inbounds [4 x i8], [4 x i8]* %p, i32 0, i32 0 205 %q2 = freeze i8* %q 206 ret i8* %q2 207} 208 209define i8* @gep_inbounds_noopt(i32 %arg) { 210; CHECK-LABEL: @gep_inbounds_noopt( 211; CHECK-NEXT: [[P:%.*]] = alloca [4 x i8], align 1 212; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds [4 x i8], [4 x i8]* [[P]], i32 0, i32 [[ARG:%.*]] 213; CHECK-NEXT: [[Q2:%.*]] = freeze i8* [[Q]] 214; CHECK-NEXT: ret i8* [[Q2]] 215; 216 %p = alloca [4 x i8] 217 %q = getelementptr inbounds [4 x i8], [4 x i8]* %p, i32 0, i32 %arg 218 %q2 = freeze i8* %q 219 ret i8* %q2 220} 221 222define i32* @gep_inbounds_null() { 223; CHECK-LABEL: @gep_inbounds_null( 224; CHECK-NEXT: ret i32* null 225; 226 %p = getelementptr inbounds i32, i32* null, i32 0 227 %k = freeze i32* %p 228 ret i32* %k 229} 230 231define i32* @gep_inbounds_null_noopt(i32* %p) { 232; CHECK-LABEL: @gep_inbounds_null_noopt( 233; CHECK-NEXT: [[K:%.*]] = freeze i32* [[P:%.*]] 234; CHECK-NEXT: ret i32* [[K]] 235; 236 %q = getelementptr inbounds i32, i32* %p, i32 0 237 %k = freeze i32* %q 238 ret i32* %k 239} 240 241define i8* @load_ptr(i8* %ptr) { 242; CHECK-LABEL: @load_ptr( 243; CHECK-NEXT: [[V:%.*]] = load i8, i8* [[PTR:%.*]], align 1 244; CHECK-NEXT: call void @f4(i8 [[V]]) 245; CHECK-NEXT: ret i8* [[PTR]] 246; 247 %v = load i8, i8* %ptr 248 %q = freeze i8* %ptr 249 call void @f4(i8 %v) ; prevents %v from being DCEd 250 ret i8* %q 251} 252 253define i8* @store_ptr(i8* %ptr) { 254; CHECK-LABEL: @store_ptr( 255; CHECK-NEXT: store i8 0, i8* [[PTR:%.*]], align 1 256; CHECK-NEXT: ret i8* [[PTR]] 257; 258 store i8 0, i8* %ptr 259 %q = freeze i8* %ptr 260 ret i8* %q 261} 262 263define i8* @call_noundef_ptr(i8* %ptr) { 264; CHECK-LABEL: @call_noundef_ptr( 265; CHECK-NEXT: call void @f3(i8* noundef [[PTR:%.*]]) 266; CHECK-NEXT: ret i8* [[PTR]] 267; 268 call void @f3(i8* noundef %ptr) 269 %q = freeze i8* %ptr 270 ret i8* %q 271} 272 273define i8* @invoke_noundef_ptr(i8* %ptr) personality i8 1 { 274; CHECK-LABEL: @invoke_noundef_ptr( 275; CHECK-NEXT: invoke void @f3(i8* noundef [[PTR:%.*]]) 276; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[UNWIND:%.*]] 277; CHECK: normal: 278; CHECK-NEXT: ret i8* [[PTR]] 279; CHECK: unwind: 280; CHECK-NEXT: [[TMP1:%.*]] = landingpad i8* 281; CHECK-NEXT: cleanup 282; CHECK-NEXT: resume i8* [[PTR]] 283; 284 %q = freeze i8* %ptr 285 invoke void @f3(i8* noundef %ptr) to label %normal unwind label %unwind 286normal: 287 ret i8* %q 288unwind: 289 landingpad i8* cleanup 290 resume i8* %q 291} 292 293define i8* @cmpxchg_ptr(i8* %ptr) { 294; CHECK-LABEL: @cmpxchg_ptr( 295; CHECK-NEXT: [[TMP1:%.*]] = cmpxchg i8* [[PTR:%.*]], i8 1, i8 2 acq_rel monotonic, align 1 296; CHECK-NEXT: ret i8* [[PTR]] 297; 298 cmpxchg i8* %ptr, i8 1, i8 2 acq_rel monotonic 299 %q = freeze i8* %ptr 300 ret i8* %q 301} 302 303define i8* @atomicrmw_ptr(i8* %ptr) { 304; CHECK-LABEL: @atomicrmw_ptr( 305; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add i8* [[PTR:%.*]], i8 1 acquire, align 1 306; CHECK-NEXT: ret i8* [[PTR]] 307; 308 atomicrmw add i8* %ptr, i8 1 acquire 309 %q = freeze i8* %ptr 310 ret i8* %q 311} 312 313define i1 @icmp(i32 %a, i32 %b) { 314; CHECK-LABEL: @icmp( 315; CHECK-NEXT: [[A_FR:%.*]] = freeze i32 [[A:%.*]] 316; CHECK-NEXT: [[B_FR:%.*]] = freeze i32 [[B:%.*]] 317; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A_FR]], [[B_FR]] 318; CHECK-NEXT: ret i1 [[C]] 319; 320 %a.fr = freeze i32 %a 321 %b.fr = freeze i32 %b 322 %c = icmp eq i32 %a.fr, %b.fr 323 %c.fr = freeze i1 %c 324 ret i1 %c.fr 325} 326 327define i1 @icmp_noopt(i32 %a, i32 %b) { 328; CHECK-LABEL: @icmp_noopt( 329; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 330; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]] 331; CHECK-NEXT: ret i1 [[C_FR]] 332; 333 %c = icmp eq i32 %a, %b 334 %c.fr = freeze i1 %c 335 ret i1 %c.fr 336} 337 338define i1 @fcmp(float %x, float %y) { 339; CHECK-LABEL: @fcmp( 340; CHECK-NEXT: [[FX:%.*]] = freeze float [[X:%.*]] 341; CHECK-NEXT: [[FY:%.*]] = freeze float [[Y:%.*]] 342; CHECK-NEXT: [[C:%.*]] = fcmp oeq float [[FX]], [[FY]] 343; CHECK-NEXT: ret i1 [[C]] 344; 345 %fx = freeze float %x 346 %fy = freeze float %y 347 %c = fcmp oeq float %fx, %fy 348 %fc = freeze i1 %c 349 ret i1 %fc 350} 351 352define i1 @fcmp_noopt(float %x, float %y) { 353; CHECK-LABEL: @fcmp_noopt( 354; CHECK-NEXT: [[FX:%.*]] = freeze float [[X:%.*]] 355; CHECK-NEXT: [[FY:%.*]] = freeze float [[Y:%.*]] 356; CHECK-NEXT: [[C:%.*]] = fcmp nnan oeq float [[FX]], [[FY]] 357; CHECK-NEXT: [[FC:%.*]] = freeze i1 [[C]] 358; CHECK-NEXT: ret i1 [[FC]] 359; 360 %fx = freeze float %x 361 %fy = freeze float %y 362 %c = fcmp nnan oeq float %fx, %fy 363 %fc = freeze i1 %c 364 ret i1 %fc 365} 366 367define i1 @brcond(i1 %c, i1 %c2) { 368; CHECK-LABEL: @brcond( 369; CHECK-NEXT: br i1 [[C:%.*]], label [[A:%.*]], label [[B:%.*]] 370; CHECK: A: 371; CHECK-NEXT: br i1 [[C2:%.*]], label [[A2:%.*]], label [[B]] 372; CHECK: A2: 373; CHECK-NEXT: ret i1 [[C]] 374; CHECK: B: 375; CHECK-NEXT: ret i1 [[C]] 376; 377 br i1 %c, label %A, label %B 378A: 379 br i1 %c2, label %A2, label %B 380A2: 381 %f1 = freeze i1 %c 382 ret i1 %f1 383B: 384 %f2 = freeze i1 %c 385 ret i1 %f2 386} 387 388define i32 @phi(i1 %cond, i1 %cond2, i32 %a0, i32 %a1) { 389; CHECK-LABEL: @phi( 390; CHECK-NEXT: ENTRY: 391; CHECK-NEXT: [[A0_FR:%.*]] = freeze i32 [[A0:%.*]] 392; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 393; CHECK: BB1: 394; CHECK-NEXT: [[A1_FR:%.*]] = freeze i32 [[A1:%.*]] 395; CHECK-NEXT: br i1 [[COND2:%.*]], label [[BB2]], label [[EXIT:%.*]] 396; CHECK: BB2: 397; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[A0_FR]], [[ENTRY:%.*]] ], [ [[A1_FR]], [[BB1]] ] 398; CHECK-NEXT: br label [[EXIT]] 399; CHECK: EXIT: 400; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[A0_FR]], [[BB1]] ], [ [[PHI1]], [[BB2]] ] 401; CHECK-NEXT: ret i32 [[PHI2]] 402; 403ENTRY: 404 %a0.fr = freeze i32 %a0 405 br i1 %cond, label %BB1, label %BB2 406BB1: 407 %a1.fr = freeze i32 %a1 408 br i1 %cond2, label %BB2, label %EXIT 409BB2: 410 %phi1 = phi i32 [%a0.fr, %ENTRY], [%a1.fr, %BB1] 411 br label %EXIT 412EXIT: 413 %phi2 = phi i32 [%a0.fr, %BB1], [%phi1, %BB2] 414 %phi2.fr = freeze i32 %phi2 415 ret i32 %phi2.fr 416} 417 418define i32 @phi_noopt(i1 %cond, i1 %cond2, i32 %a0, i32 %a1) { 419; CHECK-LABEL: @phi_noopt( 420; CHECK-NEXT: ENTRY: 421; CHECK-NEXT: [[A0_FR:%.*]] = freeze i32 [[A0:%.*]] 422; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 423; CHECK: BB1: 424; CHECK-NEXT: br i1 [[COND2:%.*]], label [[BB2]], label [[EXIT:%.*]] 425; CHECK: BB2: 426; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[A0_FR]], [[ENTRY:%.*]] ], [ [[A1:%.*]], [[BB1]] ] 427; CHECK-NEXT: br label [[EXIT]] 428; CHECK: EXIT: 429; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[A0_FR]], [[BB1]] ], [ [[PHI1]], [[BB2]] ] 430; CHECK-NEXT: [[PHI2_FR:%.*]] = freeze i32 [[PHI2]] 431; CHECK-NEXT: ret i32 [[PHI2_FR]] 432; 433ENTRY: 434 %a0.fr = freeze i32 %a0 435 br i1 %cond, label %BB1, label %BB2 436BB1: 437 br i1 %cond2, label %BB2, label %EXIT 438BB2: 439 %phi1 = phi i32 [%a0.fr, %ENTRY], [%a1, %BB1] 440 br label %EXIT 441EXIT: 442 %phi2 = phi i32 [%a0.fr, %BB1], [%phi1, %BB2] 443 %phi2.fr = freeze i32 %phi2 444 ret i32 %phi2.fr 445} 446 447define i32 @brcond_switch(i32 %x) { 448; CHECK-LABEL: @brcond_switch( 449; CHECK-NEXT: switch i32 [[X:%.*]], label [[EXIT:%.*]] [ 450; CHECK-NEXT: i32 0, label [[A:%.*]] 451; CHECK-NEXT: ] 452; CHECK: A: 453; CHECK-NEXT: ret i32 [[X]] 454; CHECK: EXIT: 455; CHECK-NEXT: ret i32 [[X]] 456; 457 switch i32 %x, label %EXIT [ i32 0, label %A ] 458A: 459 %fr1 = freeze i32 %x 460 ret i32 %fr1 461EXIT: 462 %fr2 = freeze i32 %x 463 ret i32 %fr2 464} 465 466declare i32 @any_num() 467 468define i32 @brcond_call() { 469; CHECK-LABEL: @brcond_call( 470; CHECK-NEXT: [[X:%.*]] = call i32 @any_num() 471; CHECK-NEXT: switch i32 [[X]], label [[EXIT:%.*]] [ 472; CHECK-NEXT: ] 473; CHECK: EXIT: 474; CHECK-NEXT: ret i32 [[X]] 475; 476 %x = call i32 @any_num() 477 switch i32 %x, label %EXIT [] 478EXIT: 479 %y = freeze i32 %x 480 ret i32 %y 481} 482 483define i1 @brcond_noopt(i1 %c, i1 %c2) { 484; CHECK-LABEL: @brcond_noopt( 485; CHECK-NEXT: [[F:%.*]] = freeze i1 [[C:%.*]] 486; CHECK-NEXT: call void @f1(i1 [[F]]) 487; CHECK-NEXT: call void @f2() 488; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] 489; CHECK: A: 490; CHECK-NEXT: ret i1 false 491; CHECK: B: 492; CHECK-NEXT: ret i1 true 493; 494 %f = freeze i1 %c 495 call void @f1(i1 %f) ; cannot optimize i1 %f to %c 496 call void @f2() ; .. because if f2() exits, `br %c` cannot be reached 497 br i1 %c, label %A, label %B 498A: 499 ret i1 0 500B: 501 ret i1 1 502} 503declare void @f1(i1) 504declare void @f2() 505declare void @f3(i8*) 506declare void @f4(i8) 507