1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine -S < %s | FileCheck %s 3 4target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 5 6declare ptr @getptr() 7declare void @use(ptr) 8declare void @use.i1(i1) 9 10define i1 @eq_base(ptr %x, i64 %y) { 11; CHECK-LABEL: @eq_base( 12; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[Y:%.*]], 0 13; CHECK-NEXT: ret i1 [[R]] 14; 15 %g = getelementptr i8, ptr %x, i64 %y 16 %r = icmp eq ptr %g, %x 17 ret i1 %r 18} 19 20define i1 @ne_base_commute(i64 %y) { 21; CHECK-LABEL: @ne_base_commute( 22; CHECK-NEXT: [[X:%.*]] = call ptr @getptr() 23; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0 24; CHECK-NEXT: ret i1 [[R]] 25; 26 %x = call ptr @getptr() ; thwart complexity-based canonicalization 27 %g = getelementptr i8, ptr %x, i64 %y 28 %r = icmp ne ptr %x, %g 29 ret i1 %r 30} 31 32define i1 @ne_base_inbounds(ptr %x, i64 %y) { 33; CHECK-LABEL: @ne_base_inbounds( 34; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0 35; CHECK-NEXT: ret i1 [[R]] 36; 37 %g = getelementptr inbounds i8, ptr %x, i64 %y 38 %r = icmp ne ptr %g, %x 39 ret i1 %r 40} 41 42define i1 @eq_base_inbounds_commute(i64 %y) { 43; CHECK-LABEL: @eq_base_inbounds_commute( 44; CHECK-NEXT: [[X:%.*]] = call ptr @getptr() 45; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[Y:%.*]], 0 46; CHECK-NEXT: ret i1 [[R]] 47; 48 %x = call ptr @getptr() ; thwart complexity-based canonicalization 49 %g = getelementptr inbounds i8, ptr %x, i64 %y 50 %r = icmp eq ptr %x, %g 51 ret i1 %r 52} 53 54define i1 @slt_base(ptr %x, i64 %y) { 55; CHECK-LABEL: @slt_base( 56; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[Y:%.*]] 57; CHECK-NEXT: [[R:%.*]] = icmp slt ptr [[G]], [[X]] 58; CHECK-NEXT: ret i1 [[R]] 59; 60 %g = getelementptr i8, ptr %x, i64 %y 61 %r = icmp slt ptr %g, %x 62 ret i1 %r 63} 64 65define i1 @sgt_base_commute(i64 %y) { 66; CHECK-LABEL: @sgt_base_commute( 67; CHECK-NEXT: [[X:%.*]] = call ptr @getptr() 68; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[X]], i64 [[Y:%.*]] 69; CHECK-NEXT: [[R:%.*]] = icmp sgt ptr [[X]], [[G]] 70; CHECK-NEXT: ret i1 [[R]] 71; 72 %x = call ptr @getptr() ; thwart complexity-based canonicalization 73 %g = getelementptr i8, ptr %x, i64 %y 74 %r = icmp sgt ptr %x, %g 75 ret i1 %r 76} 77 78define i1 @slt_base_inbounds(ptr %x, i64 %y) { 79; CHECK-LABEL: @slt_base_inbounds( 80; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[X:%.*]], i64 [[Y:%.*]] 81; CHECK-NEXT: [[R:%.*]] = icmp slt ptr [[G]], [[X]] 82; CHECK-NEXT: ret i1 [[R]] 83; 84 %g = getelementptr inbounds i8, ptr %x, i64 %y 85 %r = icmp slt ptr %g, %x 86 ret i1 %r 87} 88 89define i1 @sgt_base_inbounds_commute(i64 %y) { 90; CHECK-LABEL: @sgt_base_inbounds_commute( 91; CHECK-NEXT: [[X:%.*]] = call ptr @getptr() 92; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[Y:%.*]] 93; CHECK-NEXT: [[R:%.*]] = icmp sgt ptr [[X]], [[G]] 94; CHECK-NEXT: ret i1 [[R]] 95; 96 %x = call ptr @getptr() ; thwart complexity-based canonicalization 97 %g = getelementptr inbounds i8, ptr %x, i64 %y 98 %r = icmp sgt ptr %x, %g 99 ret i1 %r 100} 101 102define i1 @ult_base(ptr %x, i64 %y) { 103; CHECK-LABEL: @ult_base( 104; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[Y:%.*]] 105; CHECK-NEXT: [[R:%.*]] = icmp ult ptr [[G]], [[X]] 106; CHECK-NEXT: ret i1 [[R]] 107; 108 %g = getelementptr i8, ptr %x, i64 %y 109 %r = icmp ult ptr %g, %x 110 ret i1 %r 111} 112 113define i1 @ugt_base_commute(i64 %y) { 114; CHECK-LABEL: @ugt_base_commute( 115; CHECK-NEXT: [[X:%.*]] = call ptr @getptr() 116; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[X]], i64 [[Y:%.*]] 117; CHECK-NEXT: [[R:%.*]] = icmp ugt ptr [[X]], [[G]] 118; CHECK-NEXT: ret i1 [[R]] 119; 120 %x = call ptr @getptr() ; thwart complexity-based canonicalization 121 %g = getelementptr i8, ptr %x, i64 %y 122 %r = icmp ugt ptr %x, %g 123 ret i1 %r 124} 125 126define i1 @ult_base_inbounds(ptr %x, i64 %y) { 127; CHECK-LABEL: @ult_base_inbounds( 128; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0 129; CHECK-NEXT: ret i1 [[R]] 130; 131 %g = getelementptr inbounds i8, ptr %x, i64 %y 132 %r = icmp ult ptr %g, %x 133 ret i1 %r 134} 135 136define i1 @ult_base_nusw(ptr %x, i64 %y) { 137; CHECK-LABEL: @ult_base_nusw( 138; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0 139; CHECK-NEXT: ret i1 [[R]] 140; 141 %g = getelementptr nusw i8, ptr %x, i64 %y 142 %r = icmp ult ptr %g, %x 143 ret i1 %r 144} 145 146define i1 @ugt_base_nuw(ptr %x, i64 %y) { 147; CHECK-LABEL: @ugt_base_nuw( 148; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0 149; CHECK-NEXT: ret i1 [[R]] 150; 151 %g = getelementptr nuw i8, ptr %x, i64 %y 152 %r = icmp ugt ptr %g, %x 153 ret i1 %r 154} 155 156define i1 @ugt_base_nusw_nuw(ptr %x, i64 %y) { 157; CHECK-LABEL: @ugt_base_nusw_nuw( 158; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y:%.*]], 0 159; CHECK-NEXT: ret i1 [[R]] 160; 161 %g = getelementptr nusw nuw i8, ptr %x, i64 %y 162 %r = icmp ugt ptr %g, %x 163 ret i1 %r 164} 165 166define i1 @uge_base_nuw(ptr %x, i64 %y) { 167; CHECK-LABEL: @uge_base_nuw( 168; CHECK-NEXT: ret i1 true 169; 170 %g = getelementptr nuw i8, ptr %x, i64 %y 171 %r = icmp uge ptr %g, %x 172 ret i1 %r 173} 174 175define i1 @uge_base_nusw_nuw(ptr %x, i64 %y) { 176; CHECK-LABEL: @uge_base_nusw_nuw( 177; CHECK-NEXT: ret i1 true 178; 179 %g = getelementptr nusw nuw i8, ptr %x, i64 %y 180 %r = icmp uge ptr %g, %x 181 ret i1 %r 182} 183 184define i1 @ugt_base_inbounds_commute(i64 %y) { 185; CHECK-LABEL: @ugt_base_inbounds_commute( 186; CHECK-NEXT: [[X:%.*]] = call ptr @getptr() 187; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[Y:%.*]], 0 188; CHECK-NEXT: ret i1 [[R]] 189; 190 %x = call ptr @getptr() ; thwart complexity-based canonicalization 191 %g = getelementptr inbounds i8, ptr %x, i64 %y 192 %r = icmp ugt ptr %x, %g 193 ret i1 %r 194} 195 196define i1 @ne_base_inbounds_use(ptr %x, i64 %y) { 197; CHECK-LABEL: @ne_base_inbounds_use( 198; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[X:%.*]], i64 [[Y:%.*]] 199; CHECK-NEXT: call void @use(ptr [[G]]) 200; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y]], 0 201; CHECK-NEXT: ret i1 [[R]] 202; 203 %g = getelementptr inbounds i8, ptr %x, i64 %y 204 call void @use(ptr %g) 205 %r = icmp ne ptr %g, %x 206 ret i1 %r 207} 208 209define i1 @eq_base_inbounds_commute_use(i64 %y) { 210; CHECK-LABEL: @eq_base_inbounds_commute_use( 211; CHECK-NEXT: [[X:%.*]] = call ptr @getptr() 212; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[Y:%.*]] 213; CHECK-NEXT: call void @use(ptr [[G]]) 214; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[Y]], 0 215; CHECK-NEXT: ret i1 [[R]] 216; 217 %x = call ptr @getptr() ; thwart complexity-based canonicalization 218 %g = getelementptr inbounds i8, ptr %x, i64 %y 219 call void @use(ptr %g) 220 %r = icmp eq ptr %x, %g 221 ret i1 %r 222} 223 224define i1 @eq_bitcast_base(ptr %p, i64 %x) { 225; CHECK-LABEL: @eq_bitcast_base( 226; CHECK-NEXT: [[GEP_IDX_MASK:%.*]] = and i64 [[X:%.*]], 9223372036854775807 227; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[GEP_IDX_MASK]], 0 228; CHECK-NEXT: ret i1 [[R]] 229; 230 %gep = getelementptr [2 x i8], ptr %p, i64 %x, i64 0 231 %r = icmp eq ptr %gep, %p 232 ret i1 %r 233} 234 235define i1 @eq_bitcast_base_inbounds(ptr %p, i64 %x) { 236; CHECK-LABEL: @eq_bitcast_base_inbounds( 237; CHECK-NEXT: [[R:%.*]] = icmp eq i64 [[X:%.*]], 0 238; CHECK-NEXT: ret i1 [[R]] 239; 240 %gep = getelementptr inbounds [2 x i8], ptr %p, i64 %x, i64 0 241 %r = icmp eq ptr %gep, %p 242 ret i1 %r 243} 244 245@X = global [1000 x i32] zeroinitializer 246 247define i1 @PR8882(i64 %i) { 248; CHECK-LABEL: @PR8882( 249; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[I:%.*]], 1000 250; CHECK-NEXT: ret i1 [[CMP]] 251; 252 %p1 = getelementptr inbounds i32, ptr @X, i64 %i 253 %cmp = icmp eq ptr %p1, getelementptr inbounds ([1000 x i32], ptr @X, i64 1, i64 0) 254 ret i1 %cmp 255} 256 257@X_as1 = addrspace(1) global [1000 x i32] zeroinitializer 258 259define i1 @test24_as1(i64 %i) { 260; CHECK-LABEL: @test24_as1( 261; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[I:%.*]], 65535 262; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], 1000 263; CHECK-NEXT: ret i1 [[CMP]] 264; 265 %p1 = getelementptr inbounds i32, ptr addrspace(1) @X_as1, i64 %i 266 %cmp = icmp eq ptr addrspace(1) %p1, getelementptr inbounds ([1000 x i32], ptr addrspace(1) @X_as1, i64 1, i64 0) 267 ret i1 %cmp 268} 269 270; PR16244 271define i1 @test71(ptr %x) { 272; CHECK-LABEL: @test71( 273; CHECK-NEXT: ret i1 false 274; 275 %a = getelementptr i8, ptr %x, i64 8 276 %b = getelementptr inbounds i8, ptr %x, i64 8 277 %c = icmp ugt ptr %a, %b 278 ret i1 %c 279} 280 281define i1 @test71_as1(ptr addrspace(1) %x) { 282; CHECK-LABEL: @test71_as1( 283; CHECK-NEXT: ret i1 false 284; 285 %a = getelementptr i8, ptr addrspace(1) %x, i64 8 286 %b = getelementptr inbounds i8, ptr addrspace(1) %x, i64 8 287 %c = icmp ugt ptr addrspace(1) %a, %b 288 ret i1 %c 289} 290 291declare i32 @test58_d(i64) 292 293define i1 @test59(ptr %foo) { 294; CHECK-LABEL: @test59( 295; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO:%.*]], i64 8 296; CHECK-NEXT: [[USE:%.*]] = ptrtoint ptr [[GEP1]] to i64 297; CHECK-NEXT: [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]]) 298; CHECK-NEXT: ret i1 true 299; 300 %gep1 = getelementptr inbounds i32, ptr %foo, i64 2 301 %gep2 = getelementptr inbounds i8, ptr %foo, i64 10 302 %cmp = icmp ult ptr %gep1, %gep2 303 %use = ptrtoint ptr %gep1 to i64 304 %call = call i32 @test58_d(i64 %use) 305 ret i1 %cmp 306} 307 308define i1 @test59_as1(ptr addrspace(1) %foo) { 309; CHECK-LABEL: @test59_as1( 310; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(1) [[FOO:%.*]], i16 8 311; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr addrspace(1) [[GEP1]] to i16 312; CHECK-NEXT: [[USE:%.*]] = zext i16 [[TMP1]] to i64 313; CHECK-NEXT: [[CALL:%.*]] = call i32 @test58_d(i64 [[USE]]) 314; CHECK-NEXT: ret i1 true 315; 316 %gep1 = getelementptr inbounds i32, ptr addrspace(1) %foo, i64 2 317 %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i64 10 318 %cmp = icmp ult ptr addrspace(1) %gep1, %gep2 319 %use = ptrtoint ptr addrspace(1) %gep1 to i64 320 %call = call i32 @test58_d(i64 %use) 321 ret i1 %cmp 322} 323 324define i1 @test60(ptr %foo, i64 %i, i64 %j) { 325; CHECK-LABEL: @test60( 326; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2 327; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]] 328; CHECK-NEXT: ret i1 [[CMP]] 329; 330 %gep1 = getelementptr inbounds i32, ptr %foo, i64 %i 331 %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j 332 %cmp = icmp ult ptr %gep1, %gep2 333 ret i1 %cmp 334} 335 336define i1 @test60_nusw(ptr %foo, i64 %i, i64 %j) { 337; CHECK-LABEL: @test60_nusw( 338; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2 339; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]] 340; CHECK-NEXT: ret i1 [[CMP]] 341; 342 %gep1 = getelementptr nusw i32, ptr %foo, i64 %i 343 %gep2 = getelementptr nusw i8, ptr %foo, i64 %j 344 %cmp = icmp ult ptr %gep1, %gep2 345 ret i1 %cmp 346} 347 348define i1 @test60_nusw_inbounds(ptr %foo, i64 %i, i64 %j) { 349; CHECK-LABEL: @test60_nusw_inbounds( 350; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2 351; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]] 352; CHECK-NEXT: ret i1 [[CMP]] 353; 354 %gep1 = getelementptr nusw i32, ptr %foo, i64 %i 355 %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j 356 %cmp = icmp ult ptr %gep1, %gep2 357 ret i1 %cmp 358} 359 360define i1 @test60_nuw(ptr %foo, i64 %i, i64 %j) { 361; CHECK-LABEL: @test60_nuw( 362; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[I:%.*]], 2 363; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[GEP1_IDX]], [[J:%.*]] 364; CHECK-NEXT: ret i1 [[CMP]] 365; 366 %gep1 = getelementptr nuw i32, ptr %foo, i64 %i 367 %gep2 = getelementptr nuw i8, ptr %foo, i64 %j 368 %cmp = icmp ult ptr %gep1, %gep2 369 ret i1 %cmp 370} 371 372define i1 @test60_nusw_nuw(ptr %foo, i64 %i, i64 %j) { 373; CHECK-LABEL: @test60_nusw_nuw( 374; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw nsw i64 [[I:%.*]], 2 375; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i64 [[GEP1_IDX]], [[J:%.*]] 376; CHECK-NEXT: ret i1 [[CMP]] 377; 378 %gep1 = getelementptr nusw nuw i32, ptr %foo, i64 %i 379 %gep2 = getelementptr nusw nuw i8, ptr %foo, i64 %j 380 %cmp = icmp ult ptr %gep1, %gep2 381 ret i1 %cmp 382} 383 384define i1 @test60_nusw_nuw_mix(ptr %foo, i64 %i, i64 %j) { 385; CHECK-LABEL: @test60_nusw_nuw_mix( 386; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i32, ptr [[FOO:%.*]], i64 [[I:%.*]] 387; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nusw i8, ptr [[FOO]], i64 [[J:%.*]] 388; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]] 389; CHECK-NEXT: ret i1 [[CMP]] 390; 391 %gep1 = getelementptr nuw i32, ptr %foo, i64 %i 392 %gep2 = getelementptr nusw i8, ptr %foo, i64 %j 393 %cmp = icmp ult ptr %gep1, %gep2 394 ret i1 %cmp 395} 396 397define i1 @test_gep_ult_no_inbounds(ptr %foo, i64 %i, i64 %j) { 398; CHECK-LABEL: @test_gep_ult_no_inbounds( 399; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[FOO:%.*]], i64 [[I:%.*]] 400; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[FOO]], i64 [[J:%.*]] 401; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]] 402; CHECK-NEXT: ret i1 [[CMP]] 403; 404 %gep1 = getelementptr i32, ptr %foo, i64 %i 405 %gep2 = getelementptr i8, ptr %foo, i64 %j 406 %cmp = icmp ult ptr %gep1, %gep2 407 ret i1 %cmp 408} 409 410define i1 @test_gep_eq_no_inbounds(ptr %foo, i64 %i, i64 %j) { 411; CHECK-LABEL: @test_gep_eq_no_inbounds( 412; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i64 [[I:%.*]], 2 413; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[GEP1_IDX]], [[J:%.*]] 414; CHECK-NEXT: ret i1 [[CMP]] 415; 416 %gep1 = getelementptr i32, ptr %foo, i64 %i 417 %gep2 = getelementptr i8, ptr %foo, i64 %j 418 %cmp = icmp eq ptr %gep1, %gep2 419 ret i1 %cmp 420} 421 422define i1 @test60_as1(ptr addrspace(1) %foo, i64 %i, i64 %j) { 423; CHECK-LABEL: @test60_as1( 424; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[I:%.*]] to i16 425; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i16 [[TMP1]], 2 426; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[J:%.*]] to i16 427; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP2]] 428; CHECK-NEXT: ret i1 [[CMP]] 429; 430 %gep1 = getelementptr inbounds i32, ptr addrspace(1) %foo, i64 %i 431 %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i64 %j 432 %cmp = icmp ult ptr addrspace(1) %gep1, %gep2 433 ret i1 %cmp 434} 435 436; Same as test60, but look through an addrspacecast instead of a 437; bitcast. This uses the same sized addrspace. 438define i1 @test60_addrspacecast(ptr %foo, i64 %i, i64 %j) { 439; CHECK-LABEL: @test60_addrspacecast( 440; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2 441; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[J:%.*]], [[GEP1_IDX]] 442; CHECK-NEXT: ret i1 [[CMP]] 443; 444 %bit = addrspacecast ptr %foo to ptr addrspace(3) 445 %gep1 = getelementptr inbounds i32, ptr addrspace(3) %bit, i64 %i 446 %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j 447 %cast1 = addrspacecast ptr addrspace(3) %gep1 to ptr 448 %cmp = icmp ult ptr %cast1, %gep2 449 ret i1 %cmp 450} 451 452define i1 @test60_addrspacecast_smaller(ptr %foo, i16 %i, i64 %j) { 453; CHECK-LABEL: @test60_addrspacecast_smaller( 454; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2 455; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[J:%.*]] to i16 456; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP1]] 457; CHECK-NEXT: ret i1 [[CMP]] 458; 459 %bit = addrspacecast ptr %foo to ptr addrspace(1) 460 %gep1 = getelementptr inbounds i32, ptr addrspace(1) %bit, i16 %i 461 %gep2 = getelementptr inbounds i8, ptr %foo, i64 %j 462 %cast1 = addrspacecast ptr addrspace(1) %gep1 to ptr 463 %cmp = icmp ult ptr %cast1, %gep2 464 ret i1 %cmp 465} 466 467define i1 @test60_addrspacecast_larger(ptr addrspace(1) %foo, i32 %i, i16 %j) { 468; CHECK-LABEL: @test60_addrspacecast_larger( 469; CHECK-NEXT: [[I_TR:%.*]] = trunc i32 [[I:%.*]] to i16 470; CHECK-NEXT: [[TMP1:%.*]] = shl i16 [[I_TR]], 2 471; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i16 [[J:%.*]], [[TMP1]] 472; CHECK-NEXT: ret i1 [[CMP]] 473; 474 %bit = addrspacecast ptr addrspace(1) %foo to ptr addrspace(2) 475 %gep1 = getelementptr inbounds i32, ptr addrspace(2) %bit, i32 %i 476 %gep2 = getelementptr inbounds i8, ptr addrspace(1) %foo, i16 %j 477 %cast1 = addrspacecast ptr addrspace(2) %gep1 to ptr addrspace(1) 478 %cmp = icmp ult ptr addrspace(1) %cast1, %gep2 479 ret i1 %cmp 480} 481 482define i1 @test61(ptr %foo, i64 %i, i64 %j) { 483; CHECK-LABEL: @test61( 484; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[FOO:%.*]], i64 [[I:%.*]] 485; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[FOO]], i64 [[J:%.*]] 486; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[GEP1]], [[GEP2]] 487; CHECK-NEXT: ret i1 [[CMP]] 488; 489 %gep1 = getelementptr i32, ptr %foo, i64 %i 490 %gep2 = getelementptr i8, ptr %foo, i64 %j 491 %cmp = icmp ult ptr %gep1, %gep2 492 ret i1 %cmp 493; Don't transform non-inbounds GEPs. 494} 495 496define i1 @test61_as1(ptr addrspace(1) %foo, i16 %i, i16 %j) { 497; CHECK-LABEL: @test61_as1( 498; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr addrspace(1) [[FOO:%.*]], i16 [[I:%.*]] 499; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr addrspace(1) [[FOO]], i16 [[J:%.*]] 500; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr addrspace(1) [[GEP1]], [[GEP2]] 501; CHECK-NEXT: ret i1 [[CMP]] 502; 503 %gep1 = getelementptr i32, ptr addrspace(1) %foo, i16 %i 504 %gep2 = getelementptr i8, ptr addrspace(1) %foo, i16 %j 505 %cmp = icmp ult ptr addrspace(1) %gep1, %gep2 506 ret i1 %cmp 507; Don't transform non-inbounds GEPs. 508} 509 510define i1 @test60_extra_use(ptr %foo, i64 %i, i64 %j) { 511; CHECK-LABEL: @test60_extra_use( 512; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2 513; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 [[GEP1_IDX]] 514; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nsw i64 [[J:%.*]], 1 515; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 [[GEP2_IDX]] 516; CHECK-NEXT: call void @use(ptr [[GEP1]]) 517; CHECK-NEXT: call void @use(ptr [[GEP2]]) 518; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[GEP2_IDX]] 519; CHECK-NEXT: ret i1 [[CMP]] 520; 521 %gep1 = getelementptr inbounds i32, ptr %foo, i64 %i 522 %gep2 = getelementptr inbounds i16, ptr %foo, i64 %j 523 call void @use(ptr %gep1) 524 call void @use(ptr %gep2) 525 %cmp = icmp ult ptr %gep1, %gep2 526 ret i1 %cmp 527} 528 529define i1 @test60_extra_use_const_operands_inbounds(ptr %foo, i64 %i, i64 %j) { 530; CHECK-LABEL: @test60_extra_use_const_operands_inbounds( 531; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO:%.*]], i64 4 532; CHECK-NEXT: call void @use(ptr nonnull [[GEP1]]) 533; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[J:%.*]], 2 534; CHECK-NEXT: ret i1 [[CMP]] 535; 536 %gep1 = getelementptr inbounds i32, ptr %foo, i64 1 537 %gep2 = getelementptr inbounds i16, ptr %foo, i64 %j 538 call void @use(ptr %gep1) 539 %cmp = icmp eq ptr %gep1, %gep2 540 ret i1 %cmp 541} 542 543define i1 @test60_extra_use_const_operands_no_inbounds(ptr %foo, i64 %i, i64 %j) { 544; CHECK-LABEL: @test60_extra_use_const_operands_no_inbounds( 545; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[FOO:%.*]], i64 4 546; CHECK-NEXT: call void @use(ptr [[GEP1]]) 547; CHECK-NEXT: [[GEP2_IDX_MASK:%.*]] = and i64 [[J:%.*]], 9223372036854775807 548; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[GEP2_IDX_MASK]], 2 549; CHECK-NEXT: ret i1 [[CMP]] 550; 551 %gep1 = getelementptr i32, ptr %foo, i64 1 552 %gep2 = getelementptr i16, ptr %foo, i64 %j 553 call void @use(ptr %gep1) 554 %cmp = icmp eq ptr %gep1, %gep2 555 ret i1 %cmp 556} 557 558define void @test60_extra_use_fold(ptr %foo, i64 %start.idx, i64 %end.offset) { 559; CHECK-LABEL: @test60_extra_use_fold( 560; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[START_IDX:%.*]], 2 561; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 [[GEP1_IDX]] 562; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 [[END_OFFSET:%.*]] 563; CHECK-NEXT: call void @use(ptr [[GEP1]]) 564; CHECK-NEXT: call void @use(ptr [[GEP2]]) 565; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i64 [[GEP1_IDX]], [[END_OFFSET]] 566; CHECK-NEXT: call void @use.i1(i1 [[CMP1]]) 567; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i64 [[GEP1_IDX]], [[END_OFFSET]] 568; CHECK-NEXT: call void @use.i1(i1 [[CMP2]]) 569; CHECK-NEXT: ret void 570; 571 %gep1 = getelementptr inbounds i32, ptr %foo, i64 %start.idx 572 %gep2 = getelementptr inbounds i8, ptr %foo, i64 %end.offset 573 call void @use(ptr %gep1) 574 call void @use(ptr %gep2) 575 %cmp1 = icmp eq ptr %gep1, %gep2 576 call void @use.i1(i1 %cmp1) 577 %cmp2 = icmp ult ptr %gep1, %gep2 578 call void @use.i1(i1 %cmp2) 579 ret void 580} 581 582define i1 @test_scalable_same(ptr %x) { 583; CHECK-LABEL: @test_scalable_same( 584; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 585; CHECK-NEXT: [[A_IDX:%.*]] = shl i64 [[TMP1]], 5 586; CHECK-NEXT: [[A:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[A_IDX]] 587; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vscale.i64() 588; CHECK-NEXT: [[B_IDX:%.*]] = shl i64 [[TMP2]], 5 589; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[X]], i64 [[B_IDX]] 590; CHECK-NEXT: [[C:%.*]] = icmp ugt ptr [[A]], [[B]] 591; CHECK-NEXT: ret i1 [[C]] 592; 593 %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8 594 %b = getelementptr inbounds <vscale x 4 x i8>, ptr %x, i64 8 595 %c = icmp ugt ptr %a, %b 596 ret i1 %c 597} 598 599define i1 @test_scalable_x(ptr %x) { 600; CHECK-LABEL: @test_scalable_x( 601; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 602; CHECK-NEXT: [[A_IDX_MASK:%.*]] = and i64 [[TMP1]], 576460752303423487 603; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[A_IDX_MASK]], 0 604; CHECK-NEXT: ret i1 [[C]] 605; 606 %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8 607 %c = icmp eq ptr %a, %x 608 ret i1 %c 609} 610 611define i1 @test_scalable_xc(ptr %x) { 612; CHECK-LABEL: @test_scalable_xc( 613; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 614; CHECK-NEXT: [[A_IDX_MASK:%.*]] = and i64 [[TMP1]], 576460752303423487 615; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[A_IDX_MASK]], 0 616; CHECK-NEXT: ret i1 [[C]] 617; 618 %a = getelementptr <vscale x 4 x i8>, ptr %x, i64 8 619 %c = icmp eq ptr %x, %a 620 ret i1 %c 621} 622 623define i1 @test_scalable_xy(ptr %foo, i64 %i, i64 %j) { 624; CHECK-LABEL: @test_scalable_xy( 625; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 626; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[TMP1]], 4 627; CHECK-NEXT: [[GEP1_IDX:%.*]] = mul nsw i64 [[I:%.*]], [[TMP2]] 628; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.vscale.i64() 629; CHECK-NEXT: [[TMP4:%.*]] = shl i64 [[TMP3]], 2 630; CHECK-NEXT: [[GEP2_IDX:%.*]] = mul nsw i64 [[J:%.*]], [[TMP4]] 631; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i64 [[GEP2_IDX]], [[GEP1_IDX]] 632; CHECK-NEXT: ret i1 [[CMP]] 633; 634 %bit = addrspacecast ptr %foo to ptr addrspace(3) 635 %gep1 = getelementptr inbounds <vscale x 4 x i32>, ptr addrspace(3) %bit, i64 %i 636 %gep2 = getelementptr inbounds <vscale x 4 x i8>, ptr %foo, i64 %j 637 %cast1 = addrspacecast ptr addrspace(3) %gep1 to ptr 638 %cmp = icmp ult ptr %cast1, %gep2 639 ret i1 %cmp 640} 641 642define i1 @test_scalable_ij(ptr %foo, i64 %i, i64 %j) { 643; CHECK-LABEL: @test_scalable_ij( 644; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64() 645; CHECK-NEXT: [[TMP2:%.*]] = shl i64 [[TMP1]], 4 646; CHECK-NEXT: [[GEP1_IDX:%.*]] = mul nsw i64 [[I:%.*]], [[TMP2]] 647; CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.vscale.i64() 648; CHECK-NEXT: [[TMP4:%.*]] = shl i64 [[TMP3]], 2 649; CHECK-NEXT: [[GEP2_IDX:%.*]] = mul nsw i64 [[J:%.*]], [[TMP4]] 650; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[GEP1_IDX]], [[GEP2_IDX]] 651; CHECK-NEXT: ret i1 [[CMP]] 652; 653 %gep1 = getelementptr inbounds <vscale x 4 x i32>, ptr %foo, i64 %i 654 %gep2 = getelementptr inbounds <vscale x 4 x i8>, ptr %foo, i64 %j 655 %cmp = icmp ult ptr %gep1, %gep2 656 ret i1 %cmp 657} 658 659define i1 @gep_nuw(ptr %p, i64 %a, i64 %b, i64 %c, i64 %d) { 660; CHECK-LABEL: @gep_nuw( 661; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[A:%.*]], 2 662; CHECK-NEXT: [[GEP1_IDX1:%.*]] = shl nuw i64 [[B:%.*]], 1 663; CHECK-NEXT: [[GEP1_OFFS:%.*]] = add nuw i64 [[GEP1_IDX]], [[GEP1_IDX1]] 664; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nuw i64 [[C:%.*]], 3 665; CHECK-NEXT: [[GEP2_IDX2:%.*]] = shl nuw i64 [[D:%.*]], 2 666; CHECK-NEXT: [[GEP2_OFFS:%.*]] = add nuw i64 [[GEP2_IDX]], [[GEP2_IDX2]] 667; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[GEP1_OFFS]], [[GEP2_OFFS]] 668; CHECK-NEXT: ret i1 [[CMP]] 669; 670 %gep1 = getelementptr nuw [2 x i16], ptr %p, i64 %a, i64 %b 671 %gep2 = getelementptr nuw [2 x i32], ptr %p, i64 %c, i64 %d 672 %cmp = icmp eq ptr %gep1, %gep2 673 ret i1 %cmp 674} 675 676define i1 @gep_nusw(ptr %p, i64 %a, i64 %b, i64 %c, i64 %d) { 677; CHECK-LABEL: @gep_nusw( 678; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[A:%.*]], 2 679; CHECK-NEXT: [[GEP1_IDX1:%.*]] = shl nsw i64 [[B:%.*]], 1 680; CHECK-NEXT: [[GEP1_OFFS:%.*]] = add nsw i64 [[GEP1_IDX]], [[GEP1_IDX1]] 681; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nsw i64 [[C:%.*]], 3 682; CHECK-NEXT: [[GEP2_IDX2:%.*]] = shl nsw i64 [[D:%.*]], 2 683; CHECK-NEXT: [[GEP2_OFFS:%.*]] = add nsw i64 [[GEP2_IDX]], [[GEP2_IDX2]] 684; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[GEP1_OFFS]], [[GEP2_OFFS]] 685; CHECK-NEXT: ret i1 [[CMP]] 686; 687 %gep1 = getelementptr nusw [2 x i16], ptr %p, i64 %a, i64 %b 688 %gep2 = getelementptr nusw [2 x i32], ptr %p, i64 %c, i64 %d 689 %cmp = icmp eq ptr %gep1, %gep2 690 ret i1 %cmp 691} 692 693define i1 @pointer_icmp_aligned_with_offset(ptr align 8 %a, ptr align 8 %a2) { 694; CHECK-LABEL: @pointer_icmp_aligned_with_offset( 695; CHECK-NEXT: ret i1 false 696; 697 %gep = getelementptr i8, ptr %a, i64 4 698 %cmp = icmp eq ptr %gep, %a2 699 ret i1 %cmp 700} 701 702define i1 @pointer_icmp_aligned_with_offset_negative(ptr align 8 %a, ptr align 8 %a2) { 703; CHECK-LABEL: @pointer_icmp_aligned_with_offset_negative( 704; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[A:%.*]], i64 8 705; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP]], [[A2:%.*]] 706; CHECK-NEXT: ret i1 [[CMP]] 707; 708 %gep = getelementptr i8, ptr %a, i64 8 709 %cmp = icmp eq ptr %gep, %a2 710 ret i1 %cmp 711} 712 713define i1 @gep_diff_base_same_indices(ptr %x, ptr %y, i64 %z) { 714; CHECK-LABEL: @gep_diff_base_same_indices( 715; CHECK-NEXT: [[X:%.*]] = getelementptr i8, ptr [[X1:%.*]], i64 [[Z:%.*]] 716; CHECK-NEXT: [[Y:%.*]] = getelementptr i8, ptr [[Y1:%.*]], i64 [[Z]] 717; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[X]], [[Y]] 718; CHECK-NEXT: ret i1 [[CMP]] 719; 720 %gep1 = getelementptr i8, ptr %x, i64 %z 721 %gep2 = getelementptr i8, ptr %y, i64 %z 722 %cmp = icmp ult ptr %gep1, %gep2 723 ret i1 %cmp 724} 725 726define i1 @gep_diff_base_same_indices_nuw(ptr %x, ptr %y, i64 %z) { 727; CHECK-LABEL: @gep_diff_base_same_indices_nuw( 728; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[X:%.*]], [[Y:%.*]] 729; CHECK-NEXT: ret i1 [[CMP]] 730; 731 %gep1 = getelementptr nuw i8, ptr %x, i64 %z 732 %gep2 = getelementptr nuw i8, ptr %y, i64 %z 733 %cmp = icmp ult ptr %gep1, %gep2 734 ret i1 %cmp 735} 736 737define i1 @gep_diff_base_same_indices_nusw(ptr %x, ptr %y, i64 %z) { 738; CHECK-LABEL: @gep_diff_base_same_indices_nusw( 739; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[X:%.*]], [[Y:%.*]] 740; CHECK-NEXT: ret i1 [[CMP]] 741; 742 %gep1 = getelementptr nusw i8, ptr %x, i64 %z 743 %gep2 = getelementptr nusw i8, ptr %y, i64 %z 744 %cmp = icmp ult ptr %gep1, %gep2 745 ret i1 %cmp 746} 747 748define i1 @gep_diff_base_same_indices_nuw_nusw(ptr %x, ptr %y, i64 %z) { 749; CHECK-LABEL: @gep_diff_base_same_indices_nuw_nusw( 750; CHECK-NEXT: [[X:%.*]] = getelementptr nuw i8, ptr [[X1:%.*]], i64 [[Z:%.*]] 751; CHECK-NEXT: [[Y:%.*]] = getelementptr nusw i8, ptr [[Y1:%.*]], i64 [[Z]] 752; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[X]], [[Y]] 753; CHECK-NEXT: ret i1 [[CMP]] 754; 755 %gep1 = getelementptr nuw i8, ptr %x, i64 %z 756 %gep2 = getelementptr nusw i8, ptr %y, i64 %z 757 %cmp = icmp ult ptr %gep1, %gep2 758 ret i1 %cmp 759} 760