brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.1 KiB · 0d21a99 Raw
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