| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: opt -aa-pipeline= -passes=dse -S %s | FileCheck %s | |
| target datalayout = "p:64:64:64:8-p2:64:64:64:64" | |
| ; %k == %d + 1 due to wrapping, so the store to %d clobbers %k. | |
| define i32 @wrap_not_redundant(ptr %b) { | |
| ; CHECK-LABEL: define i32 @wrap_not_redundant( | |
| ; CHECK-SAME: ptr [[B:%.*]]) { | |
| ; CHECK-NEXT: [[D:%.*]] = getelementptr i8, ptr [[B]], i8 127 | |
| ; CHECK-NEXT: [[K:%.*]] = getelementptr i8, ptr [[B]], i8 -128 | |
| ; CHECK-NEXT: store i32 1, ptr [[K]], align 1 | |
| ; CHECK-NEXT: store i32 2, ptr [[D]], align 1 | |
| ; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[K]], align 1 | |
| ; CHECK-NEXT: store i32 1, ptr [[K]], align 1 | |
| ; CHECK-NEXT: ret i32 [[V]] | |
| ; | |
| %d = getelementptr i8, ptr %b, i8 127 | |
| %k = getelementptr i8, ptr %b, i8 -128 | |
| store i32 1, ptr %k, align 1 | |
| store i32 2, ptr %d, align 1 | |
| %v = load i32, ptr %k, align 1 | |
| store i32 1, ptr %k, align 1 | |
| ret i32 %v | |
| } | |
| ; The store to %k does not overwrite the first byte of the store to %d, which | |
| ; wraps around the end of the 64-bit index range. | |
| define void @wrap_i64(ptr addrspace(2) %b) { | |
| ; CHECK-LABEL: define void @wrap_i64( | |
| ; CHECK-SAME: ptr addrspace(2) [[B:%.*]]) { | |
| ; CHECK-NEXT: [[D:%.*]] = getelementptr i8, ptr addrspace(2) [[B]], i64 9223372036854775807 | |
| ; CHECK-NEXT: [[K:%.*]] = getelementptr i8, ptr addrspace(2) [[B]], i64 -9223372036854775808 | |
| ; CHECK-NEXT: store i32 1, ptr addrspace(2) [[D]], align 1 | |
| ; CHECK-NEXT: store i64 2, ptr addrspace(2) [[K]], align 1 | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %d = getelementptr i8, ptr addrspace(2) %b, i64 9223372036854775807 | |
| %k = getelementptr i8, ptr addrspace(2) %b, i64 -9223372036854775808 | |
| store i32 1, ptr addrspace(2) %d, align 1 | |
| store i64 2, ptr addrspace(2) %k, align 1 | |
| ret void | |
| } | |
| ; The store to %k (bytes 126 to -123) completely overwrites the store to %d. | |
| define void @wrap_complete(ptr %b) { | |
| ; CHECK-LABEL: define void @wrap_complete( | |
| ; CHECK-SAME: ptr [[B:%.*]]) { | |
| ; CHECK-NEXT: [[K:%.*]] = getelementptr i8, ptr [[B]], i8 126 | |
| ; CHECK-NEXT: store i64 2, ptr [[K]], align 1 | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %d = getelementptr i8, ptr %b, i8 -128 | |
| %k = getelementptr i8, ptr %b, i8 126 | |
| store i32 1, ptr %d, align 1 | |
| store i64 2, ptr %k, align 1 | |
| ret void | |
| } | |
| ; The memset (bytes 120 to -121) can be shortened at the end. | |
| define void @shorten_end_wrap(ptr %b, i64 %x) { | |
| ; CHECK-LABEL: define void @shorten_end_wrap( | |
| ; CHECK-SAME: ptr [[B:%.*]], i64 [[X:%.*]]) { | |
| ; CHECK-NEXT: [[D:%.*]] = getelementptr i8, ptr [[B]], i8 120 | |
| ; CHECK-NEXT: [[K:%.*]] = getelementptr i8, ptr [[B]], i8 -128 | |
| ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[D]], i8 0, i64 8, i1 false) | |
| ; CHECK-NEXT: store i64 [[X]], ptr [[K]], align 1 | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %d = getelementptr i8, ptr %b, i8 120 | |
| %k = getelementptr i8, ptr %b, i8 -128 | |
| call void @llvm.memset.p0.i64(ptr align 1 %d, i8 0, i64 16, i1 false) | |
| store i64 %x, ptr %k, align 1 | |
| ret void | |
| } | |
| ; The memset (bytes -128 to -113) can be shortened at the beginning. | |
| define void @shorten_begin_wrap(ptr %b, i64 %x) { | |
| ; CHECK-LABEL: define void @shorten_begin_wrap( | |
| ; CHECK-SAME: ptr [[B:%.*]], i64 [[X:%.*]]) { | |
| ; CHECK-NEXT: [[D:%.*]] = getelementptr i8, ptr [[B]], i8 -128 | |
| ; CHECK-NEXT: [[K:%.*]] = getelementptr i8, ptr [[B]], i8 126 | |
| ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[D]], i64 6 | |
| ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP1]], i8 0, i64 10, i1 false) | |
| ; CHECK-NEXT: store i64 [[X]], ptr [[K]], align 1 | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %d = getelementptr i8, ptr %b, i8 -128 | |
| %k = getelementptr i8, ptr %b, i8 126 | |
| call void @llvm.memset.p0.i64(ptr align 1 %d, i8 0, i64 16, i1 false) | |
| store i64 %x, ptr %k, align 1 | |
| ret void | |
| } | |
| ; Pointers with different index widths are not analyzed. | |
| define void @mixed_idx_width(ptr addrspace(2) %b) { | |
| ; CHECK-LABEL: define void @mixed_idx_width( | |
| ; CHECK-SAME: ptr addrspace(2) [[B:%.*]]) { | |
| ; CHECK-NEXT: [[C:%.*]] = addrspacecast ptr addrspace(2) [[B]] to ptr | |
| ; CHECK-NEXT: [[D:%.*]] = getelementptr i8, ptr [[C]], i8 1 | |
| ; CHECK-NEXT: [[K:%.*]] = getelementptr i8, ptr addrspace(2) [[B]], i64 1000 | |
| ; CHECK-NEXT: store i32 1, ptr [[D]], align 1 | |
| ; CHECK-NEXT: store i32 2, ptr addrspace(2) [[K]], align 1 | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %c = addrspacecast ptr addrspace(2) %b to ptr | |
| %d = getelementptr i8, ptr %c, i8 1 | |
| %k = getelementptr i8, ptr addrspace(2) %b, i64 1000 | |
| store i32 1, ptr %d, align 1 | |
| store i32 2, ptr addrspace(2) %k, align 1 | |
| ret void | |
| } |