blob: 1939b72e41c12d54b62da7500244a64d57bbe379 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt -passes=loop-load-elim -S < %s | FileCheck %s
;
; Do not forward a load with a non-forwardable store-to-load dependence.
define void @zero_distance_clobber(ptr noalias %A, ptr noalias %Out, i64 %N) {
; CHECK-LABEL: define void @zero_distance_clobber(
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[OUT:%.*]], i64 [[N:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[LOOP]] ]
; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[I]]
; CHECK-NEXT: store i8 7, ptr [[P]], align 1
; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 4
; CHECK-NEXT: [[Z:%.*]] = add i32 [[X]], 1
; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i64 [[I]], 1
; CHECK-NEXT: [[P_NEXT:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[I_NEXT]]
; CHECK-NEXT: store i32 [[Z]], ptr [[P_NEXT]], align 4
; CHECK-NEXT: [[RESULT:%.*]] = getelementptr inbounds i32, ptr [[OUT]], i64 [[I]]
; CHECK-NEXT: store i32 [[Z]], ptr [[RESULT]], align 4
; CHECK-NEXT: [[C:%.*]] = icmp ult i64 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
%p = getelementptr inbounds i32, ptr %A, i64 %i
store i8 7, ptr %p, align 1
%x = load i32, ptr %p, align 4
%z = add i32 %x, 1
%i.next = add nuw nsw i64 %i, 1
%p.next = getelementptr inbounds i32, ptr %A, i64 %i.next
store i32 %z, ptr %p.next, align 4
%result = getelementptr inbounds i32, ptr %Out, i64 %i
store i32 %z, ptr %result, align 4
%c = icmp ult i64 %i.next, %N
br i1 %c, label %loop, label %exit
exit:
ret void
}
define void @nonzero_distance_clobber(ptr noalias %A, ptr noalias %Out,
; CHECK-LABEL: define void @nonzero_distance_clobber(
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[OUT:%.*]], i64 [[N:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[LOOP]] ]
; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[I]]
; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i64 [[I]], 1
; CHECK-NEXT: [[P_NEXT:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[I_NEXT]]
; CHECK-NEXT: store i32 42, ptr [[P_NEXT]], align 4
; CHECK-NEXT: store i8 7, ptr [[P_NEXT]], align 1
; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 4
; CHECK-NEXT: [[Z:%.*]] = add i32 [[X]], 1
; CHECK-NEXT: [[RESULT:%.*]] = getelementptr inbounds i32, ptr [[OUT]], i64 [[I]]
; CHECK-NEXT: store i32 [[Z]], ptr [[RESULT]], align 4
; CHECK-NEXT: [[C:%.*]] = icmp ult i64 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
i64 %N) {
entry:
br label %loop
loop:
%i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
%p = getelementptr inbounds i32, ptr %A, i64 %i
%i.next = add nuw nsw i64 %i, 1
%p.next = getelementptr inbounds i32, ptr %A, i64 %i.next
store i32 42, ptr %p.next, align 4
store i8 7, ptr %p.next, align 1
%x = load i32, ptr %p, align 4
%z = add i32 %x, 1
%result = getelementptr inbounds i32, ptr %Out, i64 %i
store i32 %z, ptr %result, align 4
%c = icmp ult i64 %i.next, %N
br i1 %c, label %loop, label %exit
exit:
ret void
}
define void @overwritten_clobber(ptr noalias %A, ptr noalias %Out, i64 %N) {
; CHECK-LABEL: define void @overwritten_clobber(
; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[OUT:%.*]], i64 [[N:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[LOOP:.*]]
; CHECK: [[LOOP]]:
; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, %[[ENTRY]] ], [ [[I_NEXT:%.*]], %[[LOOP]] ]
; CHECK-NEXT: [[P:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[I]]
; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i64 [[I]], 1
; CHECK-NEXT: [[P_NEXT:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[I_NEXT]]
; CHECK-NEXT: store i8 7, ptr [[P_NEXT]], align 1
; CHECK-NEXT: store i32 42, ptr [[P_NEXT]], align 4
; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 4
; CHECK-NEXT: [[Z:%.*]] = add i32 [[X]], 1
; CHECK-NEXT: [[RESULT:%.*]] = getelementptr inbounds i32, ptr [[OUT]], i64 [[I]]
; CHECK-NEXT: store i32 [[Z]], ptr [[RESULT]], align 4
; CHECK-NEXT: [[C:%.*]] = icmp ult i64 [[I_NEXT]], [[N]]
; CHECK-NEXT: br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
%i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
%p = getelementptr inbounds i32, ptr %A, i64 %i
%i.next = add nuw nsw i64 %i, 1
%p.next = getelementptr inbounds i32, ptr %A, i64 %i.next
store i8 7, ptr %p.next, align 1
store i32 42, ptr %p.next, align 4
%x = load i32, ptr %p, align 4
%z = add i32 %x, 1
%result = getelementptr inbounds i32, ptr %Out, i64 %i
store i32 %z, ptr %result, align 4
%c = icmp ult i64 %i.next, %N
br i1 %c, label %loop, label %exit
exit:
ret void
}