1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=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 ptr @make_const_glb() { 33; CHECK-LABEL: @make_const_glb( 34; CHECK-NEXT: ret ptr @glb 35; 36 %k = freeze ptr @glb 37 ret ptr %k 38} 39 40define ptr @make_const_fn() { 41; CHECK-LABEL: @make_const_fn( 42; CHECK-NEXT: ret ptr @make_const 43; 44 %k = freeze ptr @make_const 45 ret ptr %k 46} 47 48define ptr @make_const_null() { 49; CHECK-LABEL: @make_const_null( 50; CHECK-NEXT: ret ptr null 51; 52 %k = freeze ptr null 53 ret ptr %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 (ptr @g to i32) to float) 119; 120 %r = freeze float bitcast (i32 ptrtoint (ptr @g to i32) to float) 121 ret float %r 122} 123 124define ptr @constant_expr2() { 125; CHECK-LABEL: @constant_expr2( 126; CHECK-NEXT: ret ptr @g 127; 128 %r = freeze ptr @g 129 ret ptr %r 130} 131 132define ptr @constant_expr3() { 133; CHECK-LABEL: @constant_expr3( 134; CHECK-NEXT: ret ptr getelementptr (i32, ptr @glb, i64 3) 135; 136 %r = freeze ptr getelementptr (i32, ptr @glb, i64 3) 137 ret ptr %r 138} 139 140define i64 @ptrdiff() { 141; CHECK-LABEL: @ptrdiff( 142; CHECK-NEXT: ret i64 sub (i64 ptrtoint (ptr @g to i64), i64 ptrtoint (ptr @g2 to i64)) 143; 144 %i = ptrtoint ptr @g to i64 145 %i2 = ptrtoint ptr @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 (ptr @g to i31)> 156; CHECK-NEXT: ret <2 x i31> [[R]] 157; 158 %r = freeze <2 x i31> <i31 34, i31 ptrtoint (ptr @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(ptr [[P]]) 166; CHECK-NEXT: ret void 167; 168 %p = alloca i8 169 %y = freeze ptr %p 170 call void @f3(ptr %y) 171 ret void 172} 173 174define ptr @gep() { 175; CHECK-LABEL: @gep( 176; CHECK-NEXT: [[P:%.*]] = alloca [4 x i8], align 1 177; CHECK-NEXT: [[Q:%.*]] = getelementptr [4 x i8], ptr [[P]], i32 0, i32 6 178; CHECK-NEXT: ret ptr [[Q]] 179; 180 %p = alloca [4 x i8] 181 %q = getelementptr [4 x i8], ptr %p, i32 0, i32 6 182 %q2 = freeze ptr %q 183 ret ptr %q2 184} 185 186define ptr @gep_noopt(i32 %arg) { 187; CHECK-LABEL: @gep_noopt( 188; CHECK-NEXT: [[Q:%.*]] = getelementptr [4 x i8], ptr null, i32 0, i32 [[ARG:%.*]] 189; CHECK-NEXT: [[Q2:%.*]] = freeze ptr [[Q]] 190; CHECK-NEXT: ret ptr [[Q2]] 191; 192 %q = getelementptr [4 x i8], ptr null, i32 0, i32 %arg 193 %q2 = freeze ptr %q 194 ret ptr %q2 195} 196 197define ptr @gep_inbounds() { 198; CHECK-LABEL: @gep_inbounds( 199; CHECK-NEXT: [[P:%.*]] = alloca [4 x i8], align 1 200; CHECK-NEXT: ret ptr [[P]] 201; 202 %p = alloca [4 x i8] 203 %q2 = freeze ptr %p 204 ret ptr %q2 205} 206 207define ptr @gep_inbounds_noopt(i32 %arg) { 208; CHECK-LABEL: @gep_inbounds_noopt( 209; CHECK-NEXT: [[P:%.*]] = alloca [4 x i8], align 1 210; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds [4 x i8], ptr [[P]], i32 0, i32 [[ARG:%.*]] 211; CHECK-NEXT: [[Q2:%.*]] = freeze ptr [[Q]] 212; CHECK-NEXT: ret ptr [[Q2]] 213; 214 %p = alloca [4 x i8] 215 %q = getelementptr inbounds [4 x i8], ptr %p, i32 0, i32 %arg 216 %q2 = freeze ptr %q 217 ret ptr %q2 218} 219 220define ptr @gep_inbounds_null() { 221; CHECK-LABEL: @gep_inbounds_null( 222; CHECK-NEXT: ret ptr null 223; 224 %k = freeze ptr null 225 ret ptr %k 226} 227 228define ptr @gep_inbounds_null_noopt(ptr %p) { 229; CHECK-LABEL: @gep_inbounds_null_noopt( 230; CHECK-NEXT: [[K:%.*]] = freeze ptr [[P:%.*]] 231; CHECK-NEXT: ret ptr [[K]] 232; 233 %k = freeze ptr %p 234 ret ptr %k 235} 236 237define ptr @load_ptr(ptr %ptr) { 238; CHECK-LABEL: @load_ptr( 239; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[PTR:%.*]], align 1 240; CHECK-NEXT: call void @f4(i8 [[V]]) 241; CHECK-NEXT: ret ptr [[PTR]] 242; 243 %v = load i8, ptr %ptr 244 %q = freeze ptr %ptr 245 call void @f4(i8 %v) ; prevents %v from being DCEd 246 ret ptr %q 247} 248 249define ptr @store_ptr(ptr %ptr) { 250; CHECK-LABEL: @store_ptr( 251; CHECK-NEXT: store i8 0, ptr [[PTR:%.*]], align 1 252; CHECK-NEXT: ret ptr [[PTR]] 253; 254 store i8 0, ptr %ptr 255 %q = freeze ptr %ptr 256 ret ptr %q 257} 258 259define ptr @call_noundef_ptr(ptr %ptr) { 260; CHECK-LABEL: @call_noundef_ptr( 261; CHECK-NEXT: call void @f3(ptr noundef [[PTR:%.*]]) 262; CHECK-NEXT: ret ptr [[PTR]] 263; 264 call void @f3(ptr noundef %ptr) 265 %q = freeze ptr %ptr 266 ret ptr %q 267} 268 269define ptr @invoke_noundef_ptr(ptr %ptr) personality i8 1 { 270; CHECK-LABEL: @invoke_noundef_ptr( 271; CHECK-NEXT: invoke void @f3(ptr noundef [[PTR:%.*]]) 272; CHECK-NEXT: to label [[NORMAL:%.*]] unwind label [[UNWIND:%.*]] 273; CHECK: normal: 274; CHECK-NEXT: ret ptr [[PTR]] 275; CHECK: unwind: 276; CHECK-NEXT: [[TMP1:%.*]] = landingpad ptr 277; CHECK-NEXT: cleanup 278; CHECK-NEXT: resume ptr [[PTR]] 279; 280 %q = freeze ptr %ptr 281 invoke void @f3(ptr noundef %ptr) to label %normal unwind label %unwind 282normal: 283 ret ptr %q 284unwind: 285 landingpad ptr cleanup 286 resume ptr %q 287} 288 289define ptr @cmpxchg_ptr(ptr %ptr) { 290; CHECK-LABEL: @cmpxchg_ptr( 291; CHECK-NEXT: [[TMP1:%.*]] = cmpxchg ptr [[PTR:%.*]], i8 1, i8 2 acq_rel monotonic, align 1 292; CHECK-NEXT: ret ptr [[PTR]] 293; 294 cmpxchg ptr %ptr, i8 1, i8 2 acq_rel monotonic 295 %q = freeze ptr %ptr 296 ret ptr %q 297} 298 299define ptr @atomicrmw_ptr(ptr %ptr) { 300; CHECK-LABEL: @atomicrmw_ptr( 301; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add ptr [[PTR:%.*]], i8 1 acquire, align 1 302; CHECK-NEXT: ret ptr [[PTR]] 303; 304 atomicrmw add ptr %ptr, i8 1 acquire 305 %q = freeze ptr %ptr 306 ret ptr %q 307} 308 309define i1 @icmp(i32 %a, i32 %b) { 310; CHECK-LABEL: @icmp( 311; CHECK-NEXT: [[A_FR:%.*]] = freeze i32 [[A:%.*]] 312; CHECK-NEXT: [[B_FR:%.*]] = freeze i32 [[B:%.*]] 313; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A_FR]], [[B_FR]] 314; CHECK-NEXT: ret i1 [[C]] 315; 316 %a.fr = freeze i32 %a 317 %b.fr = freeze i32 %b 318 %c = icmp eq i32 %a.fr, %b.fr 319 %c.fr = freeze i1 %c 320 ret i1 %c.fr 321} 322 323define i1 @icmp_noopt(i32 %a, i32 %b) { 324; CHECK-LABEL: @icmp_noopt( 325; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 326; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]] 327; CHECK-NEXT: ret i1 [[C_FR]] 328; 329 %c = icmp eq i32 %a, %b 330 %c.fr = freeze i1 %c 331 ret i1 %c.fr 332} 333 334define i1 @fcmp(float %x, float %y) { 335; CHECK-LABEL: @fcmp( 336; CHECK-NEXT: [[FX:%.*]] = freeze float [[X:%.*]] 337; CHECK-NEXT: [[FY:%.*]] = freeze float [[Y:%.*]] 338; CHECK-NEXT: [[C:%.*]] = fcmp oeq float [[FX]], [[FY]] 339; CHECK-NEXT: ret i1 [[C]] 340; 341 %fx = freeze float %x 342 %fy = freeze float %y 343 %c = fcmp oeq float %fx, %fy 344 %fc = freeze i1 %c 345 ret i1 %fc 346} 347 348define i1 @fcmp_noopt(float %x, float %y) { 349; CHECK-LABEL: @fcmp_noopt( 350; CHECK-NEXT: [[FX:%.*]] = freeze float [[X:%.*]] 351; CHECK-NEXT: [[FY:%.*]] = freeze float [[Y:%.*]] 352; CHECK-NEXT: [[C:%.*]] = fcmp nnan oeq float [[FX]], [[FY]] 353; CHECK-NEXT: [[FC:%.*]] = freeze i1 [[C]] 354; CHECK-NEXT: ret i1 [[FC]] 355; 356 %fx = freeze float %x 357 %fy = freeze float %y 358 %c = fcmp nnan oeq float %fx, %fy 359 %fc = freeze i1 %c 360 ret i1 %fc 361} 362 363define i1 @brcond(i1 %c, i1 %c2) { 364; CHECK-LABEL: @brcond( 365; CHECK-NEXT: br i1 [[C:%.*]], label [[A:%.*]], label [[B:%.*]] 366; CHECK: A: 367; CHECK-NEXT: br i1 [[C2:%.*]], label [[A2:%.*]], label [[B]] 368; CHECK: A2: 369; CHECK-NEXT: ret i1 [[C]] 370; CHECK: B: 371; CHECK-NEXT: ret i1 [[C]] 372; 373 br i1 %c, label %A, label %B 374A: 375 br i1 %c2, label %A2, label %B 376A2: 377 %f1 = freeze i1 %c 378 ret i1 %f1 379B: 380 %f2 = freeze i1 %c 381 ret i1 %f2 382} 383 384define i32 @phi(i1 %cond, i1 %cond2, i32 %a0, i32 %a1) { 385; CHECK-LABEL: @phi( 386; CHECK-NEXT: ENTRY: 387; CHECK-NEXT: [[A0_FR:%.*]] = freeze i32 [[A0:%.*]] 388; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 389; CHECK: BB1: 390; CHECK-NEXT: [[A1_FR:%.*]] = freeze i32 [[A1:%.*]] 391; CHECK-NEXT: br i1 [[COND2:%.*]], label [[BB2]], label [[EXIT:%.*]] 392; CHECK: BB2: 393; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[A0_FR]], [[ENTRY:%.*]] ], [ [[A1_FR]], [[BB1]] ] 394; CHECK-NEXT: br label [[EXIT]] 395; CHECK: EXIT: 396; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[A0_FR]], [[BB1]] ], [ [[PHI1]], [[BB2]] ] 397; CHECK-NEXT: ret i32 [[PHI2]] 398; 399ENTRY: 400 %a0.fr = freeze i32 %a0 401 br i1 %cond, label %BB1, label %BB2 402BB1: 403 %a1.fr = freeze i32 %a1 404 br i1 %cond2, label %BB2, label %EXIT 405BB2: 406 %phi1 = phi i32 [%a0.fr, %ENTRY], [%a1.fr, %BB1] 407 br label %EXIT 408EXIT: 409 %phi2 = phi i32 [%a0.fr, %BB1], [%phi1, %BB2] 410 %phi2.fr = freeze i32 %phi2 411 ret i32 %phi2.fr 412} 413 414define i32 @phi_noopt(i1 %cond, i1 %cond2, i32 %a0, i32 %a1) { 415; CHECK-LABEL: @phi_noopt( 416; CHECK-NEXT: ENTRY: 417; CHECK-NEXT: [[A0_FR:%.*]] = freeze i32 [[A0:%.*]] 418; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 419; CHECK: BB1: 420; CHECK-NEXT: br i1 [[COND2:%.*]], label [[BB2]], label [[EXIT:%.*]] 421; CHECK: BB2: 422; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[A0_FR]], [[ENTRY:%.*]] ], [ [[A1:%.*]], [[BB1]] ] 423; CHECK-NEXT: br label [[EXIT]] 424; CHECK: EXIT: 425; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[A0_FR]], [[BB1]] ], [ [[PHI1]], [[BB2]] ] 426; CHECK-NEXT: [[PHI2_FR:%.*]] = freeze i32 [[PHI2]] 427; CHECK-NEXT: ret i32 [[PHI2_FR]] 428; 429ENTRY: 430 %a0.fr = freeze i32 %a0 431 br i1 %cond, label %BB1, label %BB2 432BB1: 433 br i1 %cond2, label %BB2, label %EXIT 434BB2: 435 %phi1 = phi i32 [%a0.fr, %ENTRY], [%a1, %BB1] 436 br label %EXIT 437EXIT: 438 %phi2 = phi i32 [%a0.fr, %BB1], [%phi1, %BB2] 439 %phi2.fr = freeze i32 %phi2 440 ret i32 %phi2.fr 441} 442 443define i32 @brcond_switch(i32 %x) { 444; CHECK-LABEL: @brcond_switch( 445; CHECK-NEXT: switch i32 [[X:%.*]], label [[EXIT:%.*]] [ 446; CHECK-NEXT: i32 0, label [[A:%.*]] 447; CHECK-NEXT: ] 448; CHECK: A: 449; CHECK-NEXT: ret i32 [[X]] 450; CHECK: EXIT: 451; CHECK-NEXT: ret i32 [[X]] 452; 453 switch i32 %x, label %EXIT [ i32 0, label %A ] 454A: 455 %fr1 = freeze i32 %x 456 ret i32 %fr1 457EXIT: 458 %fr2 = freeze i32 %x 459 ret i32 %fr2 460} 461 462declare i32 @any_num() 463 464define i32 @brcond_call() { 465; CHECK-LABEL: @brcond_call( 466; CHECK-NEXT: [[X:%.*]] = call i32 @any_num() 467; CHECK-NEXT: switch i32 [[X]], label [[EXIT:%.*]] [ 468; CHECK-NEXT: ] 469; CHECK: EXIT: 470; CHECK-NEXT: ret i32 [[X]] 471; 472 %x = call i32 @any_num() 473 switch i32 %x, label %EXIT [] 474EXIT: 475 %y = freeze i32 %x 476 ret i32 %y 477} 478 479define i1 @brcond_noopt(i1 %c, i1 %c2) { 480; CHECK-LABEL: @brcond_noopt( 481; CHECK-NEXT: [[F:%.*]] = freeze i1 [[C:%.*]] 482; CHECK-NEXT: call void @f1(i1 [[F]]) 483; CHECK-NEXT: call void @f2() 484; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] 485; CHECK: A: 486; CHECK-NEXT: ret i1 false 487; CHECK: B: 488; CHECK-NEXT: ret i1 true 489; 490 %f = freeze i1 %c 491 call void @f1(i1 %f) ; cannot optimize i1 %f to %c 492 call void @f2() ; .. because if f2() exits, `br %c` cannot be reached 493 br i1 %c, label %A, label %B 494A: 495 ret i1 0 496B: 497 ret i1 1 498} 499declare void @f1(i1) 500declare void @f2() 501declare void @f3(ptr) 502declare void @f4(i8) 503