543 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1200 -passes=separate-const-offset-from-gep -S | FileCheck %s3 4; gfx1200 is particularly interesting since it allows negative immediate offsets5; in flat instructions, so the transformation is applied in more cases.6 7; The inbounds flags cannot be preserved here: If the pointers point to the8; beginning of an object and %i is 1, the intermediate GEPs are out of bounds.9define ptr @maybe_oob(ptr %p, i64 %i) {10; CHECK-LABEL: @maybe_oob(11; CHECK-NEXT: entry:12; CHECK-NEXT: [[IDX1:%.*]] = sub i64 0, [[I:%.*]]13; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IDX1]]14; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 415; CHECK-NEXT: ret ptr [[ARRAYIDX2]]16;17entry:18 %idx = sub nsw i64 1, %i19 %arrayidx = getelementptr inbounds i32, ptr %p, i64 %idx20 ret ptr %arrayidx21}22 23; All indices must be non-negative, so inbounds can be preserved.24define ptr @must_be_inbounds(ptr %p, i32 %i) {25; CHECK-LABEL: @must_be_inbounds(26; CHECK-NEXT: entry:27; CHECK-NEXT: [[I_PROM:%.*]] = zext i32 [[I:%.*]] to i6428; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[I_PROM]]29; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 430; CHECK-NEXT: ret ptr [[ARRAYIDX2]]31;32entry:33 %i.prom = zext i32 %i to i6434 %idx = add nsw i64 %i.prom, 135 %arrayidx = getelementptr inbounds i32, ptr %p, i64 %idx36 ret ptr %arrayidx37}38 39; idx must be non-negative -> preserve inbounds40define ptr @sign_bit_clear(ptr %p, i64 %i) {41; CHECK-LABEL: @sign_bit_clear(42; CHECK-NEXT: entry:43; CHECK-NEXT: [[IDX:%.*]] = and i64 [[I:%.*]], 922337203685477580744; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 [[IDX]]45; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 446; CHECK-NEXT: ret ptr [[ARRAYIDX]]47;48entry:49 %idx = and i64 %i, u0x7fffffffffffffff50 %idx.add = add i64 %idx, 151 %arrayidx = getelementptr inbounds i32, ptr %p, i64 %idx.add52 ret ptr %arrayidx53}54 55; idx may be negative -> don't preserve inbounds56define ptr @sign_bit_not_clear(ptr %p, i64 %i) {57; CHECK-LABEL: @sign_bit_not_clear(58; CHECK-NEXT: entry:59; CHECK-NEXT: [[IDX:%.*]] = and i64 [[I:%.*]], -25660; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IDX]]61; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 462; CHECK-NEXT: ret ptr [[ARRAYIDX2]]63;64entry:65 %idx = and i64 %i, u0xffffffffffffff0066 %idx.add = add i64 %idx, 167 %arrayidx = getelementptr inbounds i32, ptr %p, i64 %idx.add68 ret ptr %arrayidx69}70 71; idx may be 0 or very negative -> don't preserve inbounds72define ptr @only_sign_bit_not_clear(ptr %p, i64 %i) {73; CHECK-LABEL: @only_sign_bit_not_clear(74; CHECK-NEXT: entry:75; CHECK-NEXT: [[IDX:%.*]] = and i64 [[I:%.*]], -922337203685477580876; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IDX]]77; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 478; CHECK-NEXT: ret ptr [[ARRAYIDX2]]79;80entry:81 %idx = and i64 %i, u0x800000000000000082 %idx.add = add i64 %idx, 183 %arrayidx = getelementptr inbounds i32, ptr %p, i64 %idx.add84 ret ptr %arrayidx85}86 87; all indices non-negative -> preserve inbounds88define ptr @multi_level_nonnegative(ptr %p, i64 %idx1, i64 %idx2) {89; CHECK-LABEL: @multi_level_nonnegative(90; CHECK-NEXT: entry:91; CHECK-NEXT: [[MASKED_IDX1:%.*]] = and i64 [[IDX1:%.*]], 25592; CHECK-NEXT: [[MASKED_IDX2:%.*]] = and i64 [[IDX2:%.*]], 6553593; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [10 x [20 x i32]], ptr [[P:%.*]], i64 0, i64 [[MASKED_IDX1]], i64 [[MASKED_IDX2]]94; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 18095; CHECK-NEXT: ret ptr [[ARRAYIDX3]]96;97entry:98 %masked.idx1 = and i64 %idx1, u0xff99 %masked.idx2 = and i64 %idx2, u0xffff100 %idx1.add = add i64 %masked.idx1, 2101 %idx2.add = add i64 %masked.idx2, 5102 %arrayidx = getelementptr inbounds [10 x [20 x i32]], ptr %p, i64 0, i64 %idx1.add, i64 %idx2.add103 ret ptr %arrayidx104}105 106; It doesn't matter that %idx2.add might be negative, the indices in the resulting GEPs are all non-negative -> preserve inbounds107define ptr @multi_level_mixed_okay(ptr %p, i64 %idx1, i64 %idx2) {108; CHECK-LABEL: @multi_level_mixed_okay(109; CHECK-NEXT: entry:110; CHECK-NEXT: [[MASKED_IDX1:%.*]] = and i64 [[IDX1:%.*]], 255111; CHECK-NEXT: [[MASKED_IDX2:%.*]] = and i64 [[IDX2:%.*]], 65535112; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [10 x [20 x i32]], ptr [[P:%.*]], i64 0, i64 [[MASKED_IDX1]], i64 [[MASKED_IDX2]]113; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 156114; CHECK-NEXT: ret ptr [[ARRAYIDX3]]115;116entry:117 %masked.idx1 = and i64 %idx1, u0xff118 %masked.idx2 = and i64 %idx2, u0xffff119 %idx1.add = add i64 %masked.idx1, 2120 %idx2.add = add i64 %masked.idx2, -1121 %arrayidx = getelementptr inbounds [10 x [20 x i32]], ptr %p, i64 0, i64 %idx1.add, i64 %idx2.add122 ret ptr %arrayidx123}124 125; One index may be negative -> don't preserve inbounds126define ptr @multi_level_mixed_not_okay(ptr %p, i64 %idx1, i64 %idx2) {127; CHECK-LABEL: @multi_level_mixed_not_okay(128; CHECK-NEXT: entry:129; CHECK-NEXT: [[MASKED_IDX1:%.*]] = and i64 [[IDX1:%.*]], -256130; CHECK-NEXT: [[MASKED_IDX2:%.*]] = and i64 [[IDX2:%.*]], 65535131; CHECK-NEXT: [[TMP0:%.*]] = getelementptr [10 x [20 x i32]], ptr [[P:%.*]], i64 0, i64 [[MASKED_IDX1]], i64 [[MASKED_IDX2]]132; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr i8, ptr [[TMP0]], i64 156133; CHECK-NEXT: ret ptr [[ARRAYIDX3]]134;135entry:136 %masked.idx1 = and i64 %idx1, u0xffffffffffffff00137 %masked.idx2 = and i64 %idx2, u0xffff138 %idx1.add = add i64 %masked.idx1, 2139 %idx2.add = add i64 %masked.idx2, -1140 %arrayidx = getelementptr inbounds [10 x [20 x i32]], ptr %p, i64 0, i64 %idx1.add, i64 %idx2.add141 ret ptr %arrayidx142}143 144 145define ptr @nuw_implies_nuw(ptr %p, i64 %i) {146; CHECK-LABEL: @nuw_implies_nuw(147; CHECK-NEXT: entry:148; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nuw i32, ptr [[P:%.*]], i64 [[I:%.*]]149; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr nuw i8, ptr [[TMP0]], i64 4150; CHECK-NEXT: ret ptr [[ARRAYIDX2]]151;152entry:153 %idx = add nuw i64 %i, 1154 %arrayidx = getelementptr nuw i32, ptr %p, i64 %idx155 ret ptr %arrayidx156}157 158define ptr @nuw_implies_nuw_negative(ptr %p, i64 %i) {159; CHECK-LABEL: @nuw_implies_nuw_negative(160; CHECK-NEXT: entry:161; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nuw i32, ptr [[P:%.*]], i64 [[I:%.*]]162; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr nuw i8, ptr [[TMP0]], i64 -64163; CHECK-NEXT: ret ptr [[ARRAYIDX2]]164;165entry:166 %idx = add nuw i64 %i, -16167 %arrayidx = getelementptr nuw i32, ptr %p, i64 %idx168 ret ptr %arrayidx169}170 171define ptr @nuw_inbounds_implies_nuw_inbounds(ptr %p, i64 %i) {172; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds(173; CHECK-NEXT: entry:174; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i32, ptr [[P:%.*]], i64 [[I:%.*]]175; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 4176; CHECK-NEXT: ret ptr [[ARRAYIDX2]]177;178entry:179 %idx = add nuw i64 %i, 1180 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx181 ret ptr %arrayidx182}183 184; This is poison anyway, so we can preserve the flags.185define ptr @nuw_inbounds_implies_nuw_inbounds_negative(ptr %p, i64 %i) {186; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_negative(187; CHECK-NEXT: entry:188; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i32, ptr [[P:%.*]], i64 [[I:%.*]]189; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 -64190; CHECK-NEXT: ret ptr [[ARRAYIDX2]]191;192entry:193 %idx = add nuw i64 %i, -16194 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx195 ret ptr %arrayidx196}197 198define ptr @nuw_nusw_implies_nuw_nusw(ptr %p, i64 %i) {199; CHECK-LABEL: @nuw_nusw_implies_nuw_nusw(200; CHECK-NEXT: entry:201; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nusw nuw i32, ptr [[P:%.*]], i64 [[I:%.*]]202; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr nusw nuw i8, ptr [[TMP0]], i64 4203; CHECK-NEXT: ret ptr [[ARRAYIDX2]]204;205entry:206 %idx = add nuw i64 %i, 1207 %arrayidx = getelementptr nusw nuw i32, ptr %p, i64 %idx208 ret ptr %arrayidx209}210 211; Also poison.212define ptr @nuw_implies_nuw_nusw_negative(ptr %p, i64 %i) {213; CHECK-LABEL: @nuw_implies_nuw_nusw_negative(214; CHECK-NEXT: entry:215; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nusw nuw i32, ptr [[P:%.*]], i64 [[I:%.*]]216; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr nusw nuw i8, ptr [[TMP0]], i64 -64217; CHECK-NEXT: ret ptr [[ARRAYIDX2]]218;219entry:220 %idx = add nuw i64 %i, -16221 %arrayidx = getelementptr nusw nuw i32, ptr %p, i64 %idx222 ret ptr %arrayidx223}224 225 226define ptr @nuw_inbounds_implies_nuw_inbounds_ordisjoint(ptr %p, i64 %i) {227; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_ordisjoint(228; CHECK-NEXT: entry:229; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i32, ptr [[P:%.*]], i64 [[I:%.*]]230; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 4231; CHECK-NEXT: ret ptr [[ARRAYIDX2]]232;233entry:234 %idx = or disjoint i64 %i, 1235 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx236 ret ptr %arrayidx237}238 239; This is poison anyway, so we can do the transformation.240define ptr @nuw_inbounds_implies_nuw_inbounds_ordisjoint_negative(ptr %p, i64 %i) {241; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_ordisjoint_negative(242; CHECK-NEXT: entry:243; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i32, ptr [[P:%.*]], i64 [[I:%.*]]244; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 -64245; CHECK-NEXT: ret ptr [[ARRAYIDX2]]246;247entry:248 %idx = or disjoint i64 %i, -16249 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx250 ret ptr %arrayidx251}252 253; Check that nothing happens for non-disjoint ors254define ptr @or_no_disjoint(ptr %p, i64 %i) {255; CHECK-LABEL: @or_no_disjoint(256; CHECK-NEXT: entry:257; CHECK-NEXT: [[IDX:%.*]] = or i64 [[I:%.*]], 1258; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[P:%.*]], i64 [[IDX]]259; CHECK-NEXT: ret ptr [[ARRAYIDX]]260;261entry:262 %idx = or i64 %i, 1263 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx264 ret ptr %arrayidx265}266 267define ptr @no_nuw_inbounds_for_sub(ptr %p, i64 %i) {268; CHECK-LABEL: @no_nuw_inbounds_for_sub(269; CHECK-NEXT: entry:270; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[I:%.*]]271; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 -4272; CHECK-NEXT: ret ptr [[ARRAYIDX2]]273;274entry:275 %idx = sub nuw i64 %i, 1276 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx277 ret ptr %arrayidx278}279 280define ptr @no_nuw_inbounds_for_sub_negative(ptr %p, i64 %i) {281; CHECK-LABEL: @no_nuw_inbounds_for_sub_negative(282; CHECK-NEXT: entry:283; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[I:%.*]]284; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 64285; CHECK-NEXT: ret ptr [[ARRAYIDX2]]286;287entry:288 %idx = sub nuw i64 %i, -16289 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx290 ret ptr %arrayidx291}292 293; Can't preserved nuw and other flags here as distributing the trunc towards the294; leaves can introduce new wraps.295define ptr @nuw_inbounds_trunc(ptr %p, i128 %i) {296; CHECK-LABEL: @nuw_inbounds_trunc(297; CHECK-NEXT: entry:298; CHECK-NEXT: [[TMP0:%.*]] = trunc i128 [[I:%.*]] to i64299; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[TMP0]]300; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, ptr [[TMP1]], i64 4301; CHECK-NEXT: ret ptr [[ARRAYIDX2]]302;303entry:304 %idx = add nuw i128 %i, 1305 %idx.conv = trunc i128 %idx to i64306 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx.conv307 ret ptr %arrayidx308}309 310; trunc nuw is not a problem.311define ptr @nuw_inbounds_implies_nuw_inbounds_trunc_nuw(ptr %p, i128 %i) {312; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_trunc_nuw(313; CHECK-NEXT: entry:314; CHECK-NEXT: [[TMP0:%.*]] = trunc i128 [[I:%.*]] to i64315; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i32, ptr [[P:%.*]], i64 [[TMP0]]316; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 4317; CHECK-NEXT: ret ptr [[ARRAYIDX2]]318;319entry:320 %idx = add nuw i128 %i, 1321 %idx.conv = trunc nuw i128 %idx to i64322 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx.conv323 ret ptr %arrayidx324}325 326define ptr @nuw_inbounds_implies_nuw_inbounds_sext(ptr %p, i32 %i) {327; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_sext(328; CHECK-NEXT: entry:329; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[I:%.*]] to i64330; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i32, ptr [[P:%.*]], i64 [[TMP0]]331; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 4332; CHECK-NEXT: ret ptr [[ARRAYIDX2]]333;334entry:335 %idx = add nuw i32 %i, 1336 %idx.conv = sext i32 %idx to i64337 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx.conv338 ret ptr %arrayidx339}340 341define ptr @nuw_inbounds_implies_nuw_inbounds_zext(ptr %p, i32 %i) {342; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_zext(343; CHECK-NEXT: entry:344; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[I:%.*]] to i64345; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i32, ptr [[P:%.*]], i64 [[TMP0]]346; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 4347; CHECK-NEXT: ret ptr [[ARRAYIDX2]]348;349entry:350 %idx = add nuw i32 %i, 1351 %idx.conv = zext i32 %idx to i64352 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx.conv353 ret ptr %arrayidx354}355 356define ptr @nuw_inbounds_implies_nuw_inbounds_zext_negative(ptr %p, i8 %i) {357; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_zext_negative(358; CHECK-NEXT: entry:359; CHECK-NEXT: [[IDX_CONV:%.*]] = zext i8 [[I:%.*]] to i64360; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[P:%.*]], i64 [[IDX_CONV]]361; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i8, ptr [[ARRAYIDX]], i64 960362; CHECK-NEXT: ret ptr [[ARRAYIDX2]]363;364entry:365 %idx = add nuw i8 %i, -16366 %idx.conv = zext i8 %idx to i64367 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx.conv368 ret ptr %arrayidx369}370 371 372; This test and the following ones mask most bits of %v off to facilitate373; validation with alive2 while still allowing interesting values.374define ptr @nuw_inbounds_implies_nuw_inbounds_nested(ptr %p, i64 %i, i64 %v) {375; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_nested(376; CHECK-NEXT: entry:377; CHECK-NEXT: [[V_MASKED:%.*]] = and i64 [[V:%.*]], -1152921488500719601378; CHECK-NEXT: [[IDX22:%.*]] = add i64 [[I:%.*]], [[V_MASKED]]379; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i32, ptr [[P:%.*]], i64 [[IDX22]]380; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 4381; CHECK-NEXT: ret ptr [[ARRAYIDX3]]382;383entry:384 %v.masked = and i64 %v, u0xf0000003c000000f385 %idx1 = add nuw i64 %i, 1386 %idx2 = add nuw i64 %idx1, %v.masked387 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx2388 ret ptr %arrayidx389}390 391define ptr @nuw_inbounds_implies_nuw_inbounds_nested_negative(ptr %p, i64 %i, i64 %v) {392; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_nested_negative(393; CHECK-NEXT: entry:394; CHECK-NEXT: [[V:%.*]] = and i64 [[V1:%.*]], -1152921488500719601395; CHECK-NEXT: [[IDX22:%.*]] = add i64 [[I:%.*]], [[V]]396; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i32, ptr [[P:%.*]], i64 [[IDX22]]397; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 -64398; CHECK-NEXT: ret ptr [[ARRAYIDX3]]399;400entry:401 %v.masked = and i64 %v, u0xf0000003c000000f402 %idx1 = add nuw i64 %i, -16403 %idx2 = add nuw i64 %idx1, %v.masked404 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx2405 ret ptr %arrayidx406}407 408define ptr @nuw_implies_nuw_nested(ptr %p, i64 %i, i64 %v) {409; CHECK-LABEL: @nuw_implies_nuw_nested(410; CHECK-NEXT: entry:411; CHECK-NEXT: [[V:%.*]] = and i64 [[V1:%.*]], -1152921488500719601412; CHECK-NEXT: [[IDX22:%.*]] = add i64 [[I:%.*]], [[V]]413; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nuw i32, ptr [[P:%.*]], i64 [[IDX22]]414; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr nuw i8, ptr [[TMP0]], i64 4415; CHECK-NEXT: ret ptr [[ARRAYIDX3]]416;417entry:418 %v.masked = and i64 %v, u0xf0000003c000000f419 %idx1 = add nuw i64 %i, 1420 %idx2 = add nuw i64 %idx1, %v.masked421 %arrayidx = getelementptr nuw i32, ptr %p, i64 %idx2422 ret ptr %arrayidx423}424 425define ptr @nuw_implies_nuw_nested_negative(ptr %p, i64 %i, i64 %v) {426; CHECK-LABEL: @nuw_implies_nuw_nested_negative(427; CHECK-NEXT: entry:428; CHECK-NEXT: [[V:%.*]] = and i64 [[V1:%.*]], -1152921488500719601429; CHECK-NEXT: [[IDX22:%.*]] = add i64 [[I:%.*]], [[V]]430; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nuw i32, ptr [[P:%.*]], i64 [[IDX22]]431; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr nuw i8, ptr [[TMP0]], i64 -64432; CHECK-NEXT: ret ptr [[ARRAYIDX3]]433;434entry:435 %v.masked = and i64 %v, u0xf0000003c000000f436 %idx1 = add nuw i64 %i, -16437 %idx2 = add nuw i64 %idx1, %v.masked438 %arrayidx = getelementptr nuw i32, ptr %p, i64 %idx2439 ret ptr %arrayidx440}441 442define ptr @nuw_nusw_implies_nuw_nusw_nested(ptr %p, i64 %i, i64 %v) {443; CHECK-LABEL: @nuw_nusw_implies_nuw_nusw_nested(444; CHECK-NEXT: entry:445; CHECK-NEXT: [[V:%.*]] = and i64 [[V1:%.*]], -1152921488500719601446; CHECK-NEXT: [[IDX22:%.*]] = add i64 [[I:%.*]], [[V]]447; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nusw nuw i32, ptr [[P:%.*]], i64 [[IDX22]]448; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr nusw nuw i8, ptr [[TMP0]], i64 4449; CHECK-NEXT: ret ptr [[ARRAYIDX3]]450;451entry:452 %v.masked = and i64 %v, u0xf0000003c000000f453 %idx1 = add nuw i64 %i, 1454 %idx2 = add nuw i64 %idx1, %v.masked455 %arrayidx = getelementptr nusw nuw i32, ptr %p, i64 %idx2456 ret ptr %arrayidx457}458 459define ptr @nuw_nusw_implies_nuw_nusw_nested_negative(ptr %p, i64 %i, i64 %v) {460; CHECK-LABEL: @nuw_nusw_implies_nuw_nusw_nested_negative(461; CHECK-NEXT: entry:462; CHECK-NEXT: [[V:%.*]] = and i64 [[V1:%.*]], -1152921488500719601463; CHECK-NEXT: [[IDX22:%.*]] = add i64 [[I:%.*]], [[V]]464; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nusw nuw i32, ptr [[P:%.*]], i64 [[IDX22]]465; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr nusw nuw i8, ptr [[TMP0]], i64 -64466; CHECK-NEXT: ret ptr [[ARRAYIDX3]]467;468entry:469 %v.masked = and i64 %v, u0xf0000003c000000f470 %idx1 = add nuw i64 %i, -16471 %idx2 = add nuw i64 %idx1, %v.masked472 %arrayidx = getelementptr nusw nuw i32, ptr %p, i64 %idx2473 ret ptr %arrayidx474}475 476 477; Neither inbounds nor nuw can be preserved.478define ptr @nuw_inbounds_nested_not_all_nuw(ptr %p, i64 %i, i64 %v) {479; CHECK-LABEL: @nuw_inbounds_nested_not_all_nuw(480; CHECK-NEXT: entry:481; CHECK-NEXT: [[V:%.*]] = and i64 [[V1:%.*]], -1152921488500719601482; CHECK-NEXT: [[IDX22:%.*]] = add i64 [[I:%.*]], [[V]]483; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[IDX22]]484; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr i8, ptr [[TMP0]], i64 4485; CHECK-NEXT: ret ptr [[ARRAYIDX3]]486;487entry:488 %v.masked = and i64 %v, u0xf0000003c000000f489 %idx1 = add nuw i64 %i, 1490 %idx2 = add i64 %idx1, %v.masked491 %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %idx2492 ret ptr %arrayidx493}494 495 496define ptr @nuw_inbounds_implies_nuw_inbounds_multilevel(ptr %src, i64 %i1, i64 %i2) {497; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_multilevel(498; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[SRC:%.*]], i64 [[I1:%.*]], i64 [[I2:%.*]]499; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 24500; CHECK-NEXT: ret ptr [[ARRAYIDX3]]501;502 %idx1 = add nuw i64 %i1, 1503 %idx2 = add nuw i64 2, %i2504 %arrayidx = getelementptr inbounds nuw [4 x i32], ptr %src, i64 %idx1, i64 %idx2505 ret ptr %arrayidx506}507 508; Neither inbounds nor nuw can be preserved.509define ptr @nuw_inbounds_multilevel_not_all_nuw(ptr %src, i64 %i1, i64 %i2) {510; CHECK-LABEL: @nuw_inbounds_multilevel_not_all_nuw(511; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [4 x i32], ptr [[SRC:%.*]], i64 [[I1:%.*]], i64 [[I2:%.*]]512; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr i8, ptr [[TMP1]], i64 24513; CHECK-NEXT: ret ptr [[ARRAYIDX3]]514;515 %idx1 = add nuw i64 %i1, 1516 %idx2 = add i64 2, %i2517 %arrayidx = getelementptr inbounds nuw [4 x i32], ptr %src, i64 %idx1, i64 %idx2518 ret ptr %arrayidx519}520 521; Missing information about non-extracted indices does not matter.522define ptr @nuw_inbounds_implies_nuw_inbounds_multilevel_one_unfolded(ptr %src, i64 %i1, i64 %v) {523; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_multilevel_one_unfolded(524; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[SRC:%.*]], i64 [[I1:%.*]], i64 [[V:%.*]]525; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 16526; CHECK-NEXT: ret ptr [[ARRAYIDX2]]527;528 %idx1 = add nuw i64 %i1, 1529 %arrayidx = getelementptr inbounds nuw [4 x i32], ptr %src, i64 %idx1, i64 %v530 ret ptr %arrayidx531}532 533define ptr @nuw_inbounds_implies_nuw_inbounds_multilevel_other_unfolded(ptr %src, i64 %i1, i64 %v) {534; CHECK-LABEL: @nuw_inbounds_implies_nuw_inbounds_multilevel_other_unfolded(535; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [4 x i32], ptr [[SRC:%.*]], i64 [[V:%.*]], i64 [[I1:%.*]]536; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 4537; CHECK-NEXT: ret ptr [[ARRAYIDX2]]538;539 %idx1 = add nuw i64 %i1, 1540 %arrayidx = getelementptr inbounds nuw [4 x i32], ptr %src, i64 %v, i64 %idx1541 ret ptr %arrayidx542}543