; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s declare void @use(i32) readonly ; We prefer to canonicalize the machine width gep indices early define void @test(ptr %p, i32 %index) { ; CHECK-LABEL: define void @test( ; CHECK-SAME: ptr [[P:%.*]], i32 [[INDEX:%.*]]) { ; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[INDEX]] to i64 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr [4 x i8], ptr [[P]], i64 [[TMP1]] ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ADDR]], align 4 ; CHECK-NEXT: call void @use(i32 [[VAL]]) ; CHECK-NEXT: ret void ; %addr = getelementptr i32, ptr %p, i32 %index %val = load i32, ptr %addr call void @use(i32 %val) ret void } ; If they've already been canonicalized via zext, that's fine define void @test2(ptr %p, i32 %index) { ; CHECK-LABEL: define void @test2( ; CHECK-SAME: ptr [[P:%.*]], i32 [[INDEX:%.*]]) { ; CHECK-NEXT: [[I:%.*]] = zext i32 [[INDEX]] to i64 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr [4 x i8], ptr [[P]], i64 [[I]] ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ADDR]], align 4 ; CHECK-NEXT: call void @use(i32 [[VAL]]) ; CHECK-NEXT: ret void ; %i = zext i32 %index to i64 %addr = getelementptr i32, ptr %p, i64 %i %val = load i32, ptr %addr call void @use(i32 %val) ret void } ; If we can use a zext, we prefer that. This requires ; knowing that the index is positive. define void @test3(ptr %p, i32 %index) { ; CHECK-LABEL: define void @test3( ; CHECK-SAME: ptr [[P:%.*]], i32 [[INDEX:%.*]]) { ; CHECK-NEXT: [[ADDR_BEGIN:%.*]] = getelementptr i8, ptr [[P]], i64 160 ; CHECK-NEXT: [[ADDR_FIXED:%.*]] = getelementptr i8, ptr [[P]], i64 352 ; CHECK-NEXT: [[VAL_FIXED:%.*]] = load i32, ptr [[ADDR_FIXED]], align 4, !range [[RNG0:![0-9]+]] ; CHECK-NEXT: [[TMP1:%.*]] = zext nneg i32 [[VAL_FIXED]] to i64 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr [4 x i8], ptr [[ADDR_BEGIN]], i64 [[TMP1]] ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ADDR]], align 4 ; CHECK-NEXT: call void @use(i32 [[VAL]]) ; CHECK-NEXT: ret void ; %addr_begin = getelementptr i32, ptr %p, i64 40 %addr_fixed = getelementptr i32, ptr %addr_begin, i64 48 %val_fixed = load i32, ptr %addr_fixed, !range !0 %addr = getelementptr i32, ptr %addr_begin, i32 %val_fixed %val = load i32, ptr %addr call void @use(i32 %val) ret void } ; Replace sext with zext where possible define void @test4(ptr %p, i32 %index) { ; CHECK-LABEL: define void @test4( ; CHECK-SAME: ptr [[P:%.*]], i32 [[INDEX:%.*]]) { ; CHECK-NEXT: [[ADDR_BEGIN:%.*]] = getelementptr i8, ptr [[P]], i64 160 ; CHECK-NEXT: [[ADDR_FIXED:%.*]] = getelementptr i8, ptr [[P]], i64 352 ; CHECK-NEXT: [[VAL_FIXED:%.*]] = load i32, ptr [[ADDR_FIXED]], align 4, !range [[RNG0]] ; CHECK-NEXT: [[I:%.*]] = zext nneg i32 [[VAL_FIXED]] to i64 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr [4 x i8], ptr [[ADDR_BEGIN]], i64 [[I]] ; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ADDR]], align 4 ; CHECK-NEXT: call void @use(i32 [[VAL]]) ; CHECK-NEXT: ret void ; %addr_begin = getelementptr i32, ptr %p, i64 40 %addr_fixed = getelementptr i32, ptr %addr_begin, i64 48 %val_fixed = load i32, ptr %addr_fixed, !range !0 %i = sext i32 %val_fixed to i64 %addr = getelementptr i32, ptr %addr_begin, i64 %i %val = load i32, ptr %addr call void @use(i32 %val) ret void } ;; !range !0 !0 = !{i32 0, i32 2147483647} ;. ; CHECK: [[RNG0]] = !{i32 0, i32 2147483647} ;.