1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt < %s -S -passes=instcombine | FileCheck %s 3 4declare void @use64(i64) 5declare void @useptr(ptr) 6 7define ptr @test_zero(ptr %base, i64 %a) { 8; CHECK-LABEL: define ptr @test_zero( 9; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[A]] 12; CHECK-NEXT: ret ptr [[P2]] 13; 14entry: 15 %p1 = getelementptr i8, ptr %base, i64 -4 16 %index = add i64 %a, 1 17 %p2 = getelementptr i32, ptr %p1, i64 %index 18 ret ptr %p2 19} 20 21define ptr @test_nonzero(ptr %base, i64 %a) { 22; CHECK-LABEL: define ptr @test_nonzero( 23; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 24; CHECK-NEXT: entry: 25; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BASE]], i64 4 26; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]] 27; CHECK-NEXT: ret ptr [[P2]] 28; 29entry: 30 %p1 = getelementptr i8, ptr %base, i64 -4 31 %index = add i64 %a, 2 32 %p2 = getelementptr i32, ptr %p1, i64 %index 33 ret ptr %p2 34} 35 36define ptr @test_or_disjoint(ptr %base, i64 %a) { 37; CHECK-LABEL: define ptr @test_or_disjoint( 38; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 39; CHECK-NEXT: entry: 40; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[A]] 41; CHECK-NEXT: ret ptr [[P2]] 42; 43entry: 44 %p1 = getelementptr i8, ptr %base, i64 -4 45 %index = or disjoint i64 %a, 1 46 %p2 = getelementptr i32, ptr %p1, i64 %index 47 ret ptr %p2 48} 49 50define ptr @test_zero_multiuse_index(ptr %base, i64 %a) { 51; CHECK-LABEL: define ptr @test_zero_multiuse_index( 52; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 53; CHECK-NEXT: entry: 54; CHECK-NEXT: [[INDEX:%.*]] = add i64 [[A]], 1 55; CHECK-NEXT: call void @use64(i64 [[INDEX]]) 56; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[A]] 57; CHECK-NEXT: ret ptr [[P2]] 58; 59entry: 60 %p1 = getelementptr i8, ptr %base, i64 -4 61 %index = add i64 %a, 1 62 call void @use64(i64 %index) 63 %p2 = getelementptr i32, ptr %p1, i64 %index 64 ret ptr %p2 65} 66 67define ptr @test_zero_multiuse_ptr(ptr %base, i64 %a) { 68; CHECK-LABEL: define ptr @test_zero_multiuse_ptr( 69; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 70; CHECK-NEXT: entry: 71; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4 72; CHECK-NEXT: call void @useptr(ptr [[P1]]) 73; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[A]] 74; CHECK-NEXT: ret ptr [[P2]] 75; 76entry: 77 %p1 = getelementptr i8, ptr %base, i64 -4 78 call void @useptr(ptr %p1) 79 %index = add i64 %a, 1 80 %p2 = getelementptr i32, ptr %p1, i64 %index 81 ret ptr %p2 82} 83 84define ptr @test_zero_sext_add_nsw(ptr %base, i32 %a) { 85; CHECK-LABEL: define ptr @test_zero_sext_add_nsw( 86; CHECK-SAME: ptr [[BASE:%.*]], i32 [[A:%.*]]) { 87; CHECK-NEXT: entry: 88; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4 89; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[A]] to i64 90; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[P1]], i64 [[TMP0]] 91; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[TMP1]], i64 4 92; CHECK-NEXT: ret ptr [[P2]] 93; 94entry: 95 %p1 = getelementptr i8, ptr %base, i64 -4 96 %index = add nsw i32 %a, 1 97 %p2 = getelementptr i32, ptr %p1, i32 %index 98 ret ptr %p2 99} 100 101define ptr @test_zero_trunc_add(ptr %base, i128 %a) { 102; CHECK-LABEL: define ptr @test_zero_trunc_add( 103; CHECK-SAME: ptr [[BASE:%.*]], i128 [[A:%.*]]) { 104; CHECK-NEXT: entry: 105; CHECK-NEXT: [[TMP0:%.*]] = trunc i128 [[A]] to i64 106; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[TMP0]] 107; CHECK-NEXT: ret ptr [[P2]] 108; 109entry: 110 %p1 = getelementptr i8, ptr %base, i64 -4 111 %index = add i128 %a, 1 112 %p2 = getelementptr i32, ptr %p1, i128 %index 113 ret ptr %p2 114} 115 116define ptr @test_non_i8(ptr %base, i64 %a) { 117; CHECK-LABEL: define ptr @test_non_i8( 118; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 119; CHECK-NEXT: entry: 120; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4 121; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P1]], i64 [[A]] 122; CHECK-NEXT: ret ptr [[TMP0]] 123; 124entry: 125 %p1 = getelementptr i16, ptr %base, i64 -4 126 %index = add i64 %a, 1 127 %p2 = getelementptr i32, ptr %p1, i64 %index 128 ret ptr %p2 129} 130 131define ptr @test_non_const(ptr %base, i64 %a, i64 %b) { 132; CHECK-LABEL: define ptr @test_non_const( 133; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 134; CHECK-NEXT: entry: 135; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[B]] 136; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P1]], i64 [[A]] 137; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 4 138; CHECK-NEXT: ret ptr [[P2]] 139; 140entry: 141 %p1 = getelementptr i8, ptr %base, i64 %b 142 %index = add i64 %a, 1 143 %p2 = getelementptr i32, ptr %p1, i64 %index 144 ret ptr %p2 145} 146 147define ptr @test_too_many_indices(ptr %base, i64 %a, i64 %b) { 148; CHECK-LABEL: define ptr @test_too_many_indices( 149; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 150; CHECK-NEXT: entry: 151; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[B]] 152; CHECK-NEXT: [[INDEX:%.*]] = add i64 [[A]], 1 153; CHECK-NEXT: [[P2:%.*]] = getelementptr [8 x i32], ptr [[P1]], i64 1, i64 [[INDEX]] 154; CHECK-NEXT: ret ptr [[P2]] 155; 156entry: 157 %p1 = getelementptr i8, ptr %base, i64 %b 158 %index = add i64 %a, 1 159 %p2 = getelementptr [8 x i32], ptr %p1, i64 1, i64 %index 160 ret ptr %p2 161} 162 163define ptr @test_wrong_op(ptr %base, i64 %a) { 164; CHECK-LABEL: define ptr @test_wrong_op( 165; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 166; CHECK-NEXT: entry: 167; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4 168; CHECK-NEXT: [[INDEX:%.*]] = xor i64 [[A]], 1 169; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[P1]], i64 [[INDEX]] 170; CHECK-NEXT: ret ptr [[P2]] 171; 172entry: 173 %p1 = getelementptr i8, ptr %base, i64 -4 174 %index = xor i64 %a, 1 175 %p2 = getelementptr i32, ptr %p1, i64 %index 176 ret ptr %p2 177} 178 179define ptr @test_sext_add_without_nsw(ptr %base, i32 %a) { 180; CHECK-LABEL: define ptr @test_sext_add_without_nsw( 181; CHECK-SAME: ptr [[BASE:%.*]], i32 [[A:%.*]]) { 182; CHECK-NEXT: entry: 183; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4 184; CHECK-NEXT: [[INDEX:%.*]] = add i32 [[A]], 1 185; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[INDEX]] to i64 186; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[P1]], i64 [[TMP0]] 187; CHECK-NEXT: ret ptr [[P2]] 188; 189entry: 190 %p1 = getelementptr i8, ptr %base, i64 -4 191 %index = add i32 %a, 1 192 %p2 = getelementptr i32, ptr %p1, i32 %index 193 ret ptr %p2 194} 195 196define ptr @test_or_without_disjoint(ptr %base, i64 %a) { 197; CHECK-LABEL: define ptr @test_or_without_disjoint( 198; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 199; CHECK-NEXT: entry: 200; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4 201; CHECK-NEXT: [[INDEX:%.*]] = or i64 [[A]], 1 202; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[P1]], i64 [[INDEX]] 203; CHECK-NEXT: ret ptr [[P2]] 204; 205entry: 206 %p1 = getelementptr i8, ptr %base, i64 -4 207 %index = or i64 %a, 1 208 %p2 = getelementptr i32, ptr %p1, i64 %index 209 ret ptr %p2 210} 211 212define ptr @test_smul_overflow(ptr %base, i64 %a) { 213; CHECK-LABEL: define ptr @test_smul_overflow( 214; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 215; CHECK-NEXT: entry: 216; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -12 217; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P1]], i64 [[A]] 218; CHECK-NEXT: ret ptr [[TMP0]] 219; 220entry: 221 %p1 = getelementptr i8, ptr %base, i64 -4 222 %index = add i64 %a, 9223372036854775806 223 %p2 = getelementptr i32, ptr %p1, i64 %index 224 ret ptr %p2 225} 226 227define ptr @test_sadd_overflow(ptr %base, i64 %a) { 228; CHECK-LABEL: define ptr @test_sadd_overflow( 229; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 230; CHECK-NEXT: entry: 231; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -9223372036854775808 232; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P1]], i64 [[A]] 233; CHECK-NEXT: ret ptr [[TMP0]] 234; 235entry: 236 %p1 = getelementptr i8, ptr %base, i64 9223372036854775804 237 %index = add i64 %a, 1 238 %p2 = getelementptr i32, ptr %p1, i64 %index 239 ret ptr %p2 240} 241 242define ptr @test_nonzero_multiuse_index(ptr %base, i64 %a) { 243; CHECK-LABEL: define ptr @test_nonzero_multiuse_index( 244; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 245; CHECK-NEXT: entry: 246; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4 247; CHECK-NEXT: [[INDEX:%.*]] = add i64 [[A]], 2 248; CHECK-NEXT: call void @use64(i64 [[INDEX]]) 249; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[P1]], i64 [[INDEX]] 250; CHECK-NEXT: ret ptr [[P2]] 251; 252entry: 253 %p1 = getelementptr i8, ptr %base, i64 -4 254 %index = add i64 %a, 2 255 call void @use64(i64 %index) 256 %p2 = getelementptr i32, ptr %p1, i64 %index 257 ret ptr %p2 258} 259 260define ptr @test_nonzero_multiuse_ptr(ptr %base, i64 %a) { 261; CHECK-LABEL: define ptr @test_nonzero_multiuse_ptr( 262; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 263; CHECK-NEXT: entry: 264; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4 265; CHECK-NEXT: call void @useptr(ptr [[P1]]) 266; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i32, ptr [[P1]], i64 [[A]] 267; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[TMP0]], i64 8 268; CHECK-NEXT: ret ptr [[P2]] 269; 270entry: 271 %p1 = getelementptr i8, ptr %base, i64 -4 272 call void @useptr(ptr %p1) 273 %index = add i64 %a, 2 274 %p2 = getelementptr i32, ptr %p1, i64 %index 275 ret ptr %p2 276} 277 278define ptr @test_scalable(ptr %base, i64 %a) { 279; CHECK-LABEL: define ptr @test_scalable( 280; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) { 281; CHECK-NEXT: entry: 282; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 -4 283; CHECK-NEXT: [[INDEX:%.*]] = add i64 [[A]], 1 284; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64() 285; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[TMP0]], 4 286; CHECK-NEXT: [[P2_IDX:%.*]] = mul i64 [[INDEX]], [[TMP1]] 287; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P1]], i64 [[P2_IDX]] 288; CHECK-NEXT: ret ptr [[P2]] 289; 290entry: 291 %p1 = getelementptr i8, ptr %base, i64 -4 292 %index = add i64 %a, 1 293 %p2 = getelementptr <vscale x 4 x i32>, ptr %p1, i64 %index 294 ret ptr %p2 295} 296