| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: opt -passes=instcombine %s -S | FileCheck %s |
| |
| define ptr @pos_pow2_2(ptr %foo, i64 %x) { |
| ; CHECK-LABEL: define ptr @pos_pow2_2( |
| ; CHECK-SAME: ptr [[FOO:%.*]], i64 [[X:%.*]]) { |
| ; CHECK-NEXT: [[IDX_MASK:%.*]] = and i64 [[X]], 1 |
| ; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 [[IDX_MASK]] |
| ; CHECK-NEXT: ret ptr [[P1]] |
| ; |
| %idx = srem i64 %x, 2 |
| %p = getelementptr inbounds nuw i8, ptr %foo, i64 %idx |
| ret ptr %p |
| } |
| |
| define ptr @pos_pow2_4(ptr %foo, i64 %x) { |
| ; CHECK-LABEL: define ptr @pos_pow2_4( |
| ; CHECK-SAME: ptr [[FOO:%.*]], i64 [[X:%.*]]) { |
| ; CHECK-NEXT: [[IDX_MASK:%.*]] = and i64 [[X]], 3 |
| ; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 [[IDX_MASK]] |
| ; CHECK-NEXT: ret ptr [[P1]] |
| ; |
| %idx = srem i64 %x, 4 |
| %p = getelementptr inbounds nuw i8, ptr %foo, i64 %idx |
| ret ptr %p |
| } |
| |
| define ptr @pos_pow2_8(ptr %foo, i64 %x) { |
| ; CHECK-LABEL: define ptr @pos_pow2_8( |
| ; CHECK-SAME: ptr [[FOO:%.*]], i64 [[X:%.*]]) { |
| ; CHECK-NEXT: [[IDX_MASK:%.*]] = and i64 [[X]], 7 |
| ; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 [[IDX_MASK]] |
| ; CHECK-NEXT: ret ptr [[P1]] |
| ; |
| %idx = srem i64 %x, 8 |
| %p = getelementptr inbounds nuw i8, ptr %foo, i64 %idx |
| ret ptr %p |
| } |
| |
| define ptr @pos_not_i8(ptr %foo, i64 %x) { |
| ; CHECK-LABEL: define ptr @pos_not_i8( |
| ; CHECK-SAME: ptr [[FOO:%.*]], i64 [[X:%.*]]) { |
| ; CHECK-NEXT: [[IDX1:%.*]] = and i64 [[X]], 3 |
| ; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds nuw [4 x i8], ptr [[FOO]], i64 [[IDX1]] |
| ; CHECK-NEXT: ret ptr [[P2]] |
| ; |
| %idx = srem i64 %x, 4 |
| %p = getelementptr inbounds nuw i32, ptr %foo, i64 %idx |
| ret ptr %p |
| } |
| |
| ; srem x, 1 is always 0, and mask is 0. GEP should be folded to %foo. |
| define ptr @pos_pow2_1(ptr %foo, i64 %x) { |
| ; CHECK-LABEL: define ptr @pos_pow2_1( |
| ; CHECK-SAME: ptr [[FOO:%.*]], i64 [[X:%.*]]) { |
| ; CHECK-NEXT: ret ptr [[FOO]] |
| ; |
| %idx = srem i64 %x, 1 |
| %p = getelementptr inbounds nuw i8, ptr %foo, i64 %idx |
| ret ptr %p |
| } |
| |
| ; Non-power-of-two constant divisor |
| define ptr @neg_non_pow2_6(ptr %foo, i64 %x) { |
| ; CHECK-LABEL: define ptr @neg_non_pow2_6( |
| ; CHECK-SAME: ptr [[FOO:%.*]], i64 [[X:%.*]]) { |
| ; CHECK-NEXT: [[IDX:%.*]] = srem i64 [[X]], 6 |
| ; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 [[IDX]] |
| ; CHECK-NEXT: ret ptr [[P]] |
| ; |
| %idx = srem i64 %x, 6 |
| %p = getelementptr inbounds nuw i8, ptr %foo, i64 %idx |
| ret ptr %p |
| } |
| |
| ; Missing 'no unsigned wrap' |
| define ptr @neg_missing_nuw(ptr %foo, i64 %x) { |
| ; CHECK-LABEL: define ptr @neg_missing_nuw( |
| ; CHECK-SAME: ptr [[FOO:%.*]], i64 [[X:%.*]]) { |
| ; CHECK-NEXT: [[IDX:%.*]] = srem i64 [[X]], 4 |
| ; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds i8, ptr [[FOO]], i64 [[IDX]] |
| ; CHECK-NEXT: ret ptr [[P]] |
| ; |
| %idx = srem i64 %x, 4 |
| %p = getelementptr inbounds i8, ptr %foo, i64 %idx |
| ret ptr %p |
| } |
| |
| ; Missing 'inbounds' |
| define ptr @neg_missing_inbounds(ptr %foo, i64 %x) { |
| ; CHECK-LABEL: define ptr @neg_missing_inbounds( |
| ; CHECK-SAME: ptr [[FOO:%.*]], i64 [[X:%.*]]) { |
| ; CHECK-NEXT: [[IDX:%.*]] = srem i64 [[X]], 4 |
| ; CHECK-NEXT: [[P:%.*]] = getelementptr nuw i8, ptr [[FOO]], i64 [[IDX]] |
| ; CHECK-NEXT: ret ptr [[P]] |
| ; |
| %idx = srem i64 %x, 4 |
| %p = getelementptr nuw i8, ptr %foo, i64 %idx |
| ret ptr %p |
| } |
| |
| define ptr @neg_nonconst_divisor(ptr %foo, i64 %x, i64 %d) { |
| ; CHECK-LABEL: define ptr @neg_nonconst_divisor( |
| ; CHECK-SAME: ptr [[FOO:%.*]], i64 [[X:%.*]], i64 [[D:%.*]]) { |
| ; CHECK-NEXT: [[IDX:%.*]] = srem i64 [[X]], [[D]] |
| ; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 [[IDX]] |
| ; CHECK-NEXT: ret ptr [[P]] |
| ; |
| %idx = srem i64 %x, %d |
| %p = getelementptr inbounds nuw i8, ptr %foo, i64 %idx |
| ret ptr %p |
| } |
| |
| declare void @use(i8) |
| |
| define ptr @neg_multi_use(ptr %foo, i64 %x) { |
| ; CHECK-LABEL: define ptr @neg_multi_use( |
| ; CHECK-SAME: ptr [[FOO:%.*]], i64 [[X:%.*]]) { |
| ; CHECK-NEXT: [[IDX:%.*]] = srem i64 [[X]], 4 |
| ; CHECK-NEXT: call void @use(i64 [[IDX]]) |
| ; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 [[IDX]] |
| ; CHECK-NEXT: ret ptr [[P]] |
| ; |
| %idx = srem i64 %x, 4 |
| call void @use(i64 %idx) |
| %p = getelementptr inbounds nuw i8, ptr %foo, i64 %idx |
| ret ptr %p |
| } |