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 i1 @icmp(i32 %a, i32 %b) { 242; CHECK-LABEL: @icmp( 243; CHECK-NEXT: [[A_FR:%.*]] = freeze i32 [[A:%.*]] 244; CHECK-NEXT: [[B_FR:%.*]] = freeze i32 [[B:%.*]] 245; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A_FR]], [[B_FR]] 246; CHECK-NEXT: ret i1 [[C]] 247; 248 %a.fr = freeze i32 %a 249 %b.fr = freeze i32 %b 250 %c = icmp eq i32 %a.fr, %b.fr 251 %c.fr = freeze i1 %c 252 ret i1 %c.fr 253} 254 255define i1 @icmp_noopt(i32 %a, i32 %b) { 256; CHECK-LABEL: @icmp_noopt( 257; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 258; CHECK-NEXT: [[C_FR:%.*]] = freeze i1 [[C]] 259; CHECK-NEXT: ret i1 [[C_FR]] 260; 261 %c = icmp eq i32 %a, %b 262 %c.fr = freeze i1 %c 263 ret i1 %c.fr 264} 265 266define i1 @fcmp(float %x, float %y) { 267; CHECK-LABEL: @fcmp( 268; CHECK-NEXT: [[FX:%.*]] = freeze float [[X:%.*]] 269; CHECK-NEXT: [[FY:%.*]] = freeze float [[Y:%.*]] 270; CHECK-NEXT: [[C:%.*]] = fcmp oeq float [[FX]], [[FY]] 271; CHECK-NEXT: ret i1 [[C]] 272; 273 %fx = freeze float %x 274 %fy = freeze float %y 275 %c = fcmp oeq float %fx, %fy 276 %fc = freeze i1 %c 277 ret i1 %fc 278} 279 280define i1 @fcmp_noopt(float %x, float %y) { 281; CHECK-LABEL: @fcmp_noopt( 282; CHECK-NEXT: [[FX:%.*]] = freeze float [[X:%.*]] 283; CHECK-NEXT: [[FY:%.*]] = freeze float [[Y:%.*]] 284; CHECK-NEXT: [[C:%.*]] = fcmp nnan oeq float [[FX]], [[FY]] 285; CHECK-NEXT: [[FC:%.*]] = freeze i1 [[C]] 286; CHECK-NEXT: ret i1 [[FC]] 287; 288 %fx = freeze float %x 289 %fy = freeze float %y 290 %c = fcmp nnan oeq float %fx, %fy 291 %fc = freeze i1 %c 292 ret i1 %fc 293} 294 295define i1 @brcond(i1 %c, i1 %c2) { 296; CHECK-LABEL: @brcond( 297; CHECK-NEXT: br i1 [[C:%.*]], label [[A:%.*]], label [[B:%.*]] 298; CHECK: A: 299; CHECK-NEXT: br i1 [[C2:%.*]], label [[A2:%.*]], label [[B]] 300; CHECK: A2: 301; CHECK-NEXT: ret i1 [[C]] 302; CHECK: B: 303; CHECK-NEXT: ret i1 [[C]] 304; 305 br i1 %c, label %A, label %B 306A: 307 br i1 %c2, label %A2, label %B 308A2: 309 %f1 = freeze i1 %c 310 ret i1 %f1 311B: 312 %f2 = freeze i1 %c 313 ret i1 %f2 314} 315 316define i32 @phi(i1 %cond, i1 %cond2, i32 %a0, i32 %a1) { 317; CHECK-LABEL: @phi( 318; CHECK-NEXT: ENTRY: 319; CHECK-NEXT: [[A0_FR:%.*]] = freeze i32 [[A0:%.*]] 320; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 321; CHECK: BB1: 322; CHECK-NEXT: [[A1_FR:%.*]] = freeze i32 [[A1:%.*]] 323; CHECK-NEXT: br i1 [[COND2:%.*]], label [[BB2]], label [[EXIT:%.*]] 324; CHECK: BB2: 325; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[A0_FR]], [[ENTRY:%.*]] ], [ [[A1_FR]], [[BB1]] ] 326; CHECK-NEXT: br label [[EXIT]] 327; CHECK: EXIT: 328; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[A0_FR]], [[BB1]] ], [ [[PHI1]], [[BB2]] ] 329; CHECK-NEXT: ret i32 [[PHI2]] 330; 331ENTRY: 332 %a0.fr = freeze i32 %a0 333 br i1 %cond, label %BB1, label %BB2 334BB1: 335 %a1.fr = freeze i32 %a1 336 br i1 %cond2, label %BB2, label %EXIT 337BB2: 338 %phi1 = phi i32 [%a0.fr, %ENTRY], [%a1.fr, %BB1] 339 br label %EXIT 340EXIT: 341 %phi2 = phi i32 [%a0.fr, %BB1], [%phi1, %BB2] 342 %phi2.fr = freeze i32 %phi2 343 ret i32 %phi2.fr 344} 345 346define i32 @phi_noopt(i1 %cond, i1 %cond2, i32 %a0, i32 %a1) { 347; CHECK-LABEL: @phi_noopt( 348; CHECK-NEXT: ENTRY: 349; CHECK-NEXT: [[A0_FR:%.*]] = freeze i32 [[A0:%.*]] 350; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 351; CHECK: BB1: 352; CHECK-NEXT: br i1 [[COND2:%.*]], label [[BB2]], label [[EXIT:%.*]] 353; CHECK: BB2: 354; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[A0_FR]], [[ENTRY:%.*]] ], [ [[A1:%.*]], [[BB1]] ] 355; CHECK-NEXT: br label [[EXIT]] 356; CHECK: EXIT: 357; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ [[A0_FR]], [[BB1]] ], [ [[PHI1]], [[BB2]] ] 358; CHECK-NEXT: [[PHI2_FR:%.*]] = freeze i32 [[PHI2]] 359; CHECK-NEXT: ret i32 [[PHI2_FR]] 360; 361ENTRY: 362 %a0.fr = freeze i32 %a0 363 br i1 %cond, label %BB1, label %BB2 364BB1: 365 br i1 %cond2, label %BB2, label %EXIT 366BB2: 367 %phi1 = phi i32 [%a0.fr, %ENTRY], [%a1, %BB1] 368 br label %EXIT 369EXIT: 370 %phi2 = phi i32 [%a0.fr, %BB1], [%phi1, %BB2] 371 %phi2.fr = freeze i32 %phi2 372 ret i32 %phi2.fr 373} 374 375define i32 @brcond_switch(i32 %x) { 376; CHECK-LABEL: @brcond_switch( 377; CHECK-NEXT: switch i32 [[X:%.*]], label [[EXIT:%.*]] [ 378; CHECK-NEXT: i32 0, label [[A:%.*]] 379; CHECK-NEXT: ] 380; CHECK: A: 381; CHECK-NEXT: ret i32 [[X]] 382; CHECK: EXIT: 383; CHECK-NEXT: ret i32 [[X]] 384; 385 switch i32 %x, label %EXIT [ i32 0, label %A ] 386A: 387 %fr1 = freeze i32 %x 388 ret i32 %fr1 389EXIT: 390 %fr2 = freeze i32 %x 391 ret i32 %fr2 392} 393 394declare i32 @any_num() 395 396define i32 @brcond_call() { 397; CHECK-LABEL: @brcond_call( 398; CHECK-NEXT: [[X:%.*]] = call i32 @any_num() 399; CHECK-NEXT: switch i32 [[X]], label [[EXIT:%.*]] [ 400; CHECK-NEXT: ] 401; CHECK: EXIT: 402; CHECK-NEXT: ret i32 [[X]] 403; 404 %x = call i32 @any_num() 405 switch i32 %x, label %EXIT [] 406EXIT: 407 %y = freeze i32 %x 408 ret i32 %y 409} 410 411define i1 @brcond_noopt(i1 %c, i1 %c2) { 412; CHECK-LABEL: @brcond_noopt( 413; CHECK-NEXT: [[F:%.*]] = freeze i1 [[C:%.*]] 414; CHECK-NEXT: call void @f1(i1 [[F]]) 415; CHECK-NEXT: call void @f2() 416; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] 417; CHECK: A: 418; CHECK-NEXT: ret i1 false 419; CHECK: B: 420; CHECK-NEXT: ret i1 true 421; 422 %f = freeze i1 %c 423 call void @f1(i1 %f) ; cannot optimize i1 %f to %c 424 call void @f2() ; .. because if f2() exits, `br %c` cannot be reached 425 br i1 %c, label %A, label %B 426A: 427 ret i1 0 428B: 429 ret i1 1 430} 431declare void @f1(i1) 432declare void @f2() 433declare void @f3(i8*) 434