Invariant.group's are not sufficiently handled by LICM. Specifically, if a given invariant.group loaded pointer is not overwritten between the start of a loop, and its use in the load, it can be hoisted. The invariant.group (on an already invariant pointer operand) ensures the result is the same. If it is not overwritten between the start of the loop and the load, it is therefore legal to hoist. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D144053
70 lines
2.7 KiB
LLVM
70 lines
2.7 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=licm < %s -S | FileCheck %s
|
|
|
|
define void @test(ptr %arg, ptr %arg1) {
|
|
; CHECK-LABEL: @test(
|
|
; CHECK-NEXT: bb2:
|
|
; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARG1:%.*]], align 4, !invariant.group !0
|
|
; CHECK-NEXT: br label [[BB5:%.*]]
|
|
; CHECK: bb5:
|
|
; CHECK-NEXT: [[TMP6:%.*]] = phi i64 [ 0, [[BB2:%.*]] ], [ [[TMP10:%.*]], [[BB5]] ]
|
|
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[ARG:%.*]], i64 [[TMP6]]
|
|
; CHECK-NEXT: store i32 [[TMP3]], ptr [[TMP7]], align 8
|
|
; CHECK-NEXT: [[TMP10]] = add nuw nsw i64 [[TMP6]], 1
|
|
; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], 200
|
|
; CHECK-NEXT: br i1 [[TMP11]], label [[BB12:%.*]], label [[BB5]]
|
|
; CHECK: bb12:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
bb2: ; preds = %bb
|
|
br label %bb5
|
|
|
|
bb5: ; preds = %bb5, %bb2
|
|
%tmp6 = phi i64 [ 0, %bb2 ], [ %tmp10, %bb5 ]
|
|
%tmp3 = load i32, ptr %arg1, align 4, !invariant.group !0
|
|
%tmp7 = getelementptr inbounds i32, ptr %arg, i64 %tmp6
|
|
store i32 %tmp3, ptr %tmp7, align 8
|
|
%tmp10 = add nuw nsw i64 %tmp6, 1
|
|
%tmp11 = icmp eq i64 %tmp10, 200
|
|
br i1 %tmp11, label %bb12, label %bb5
|
|
|
|
bb12: ; preds = %bb5, %bb
|
|
ret void
|
|
}
|
|
|
|
|
|
define void @test_fail(ptr %arg, ptr %arg1) {
|
|
; CHECK-LABEL: @test_fail(
|
|
; CHECK-NEXT: bb2:
|
|
; CHECK-NEXT: br label [[BB5:%.*]]
|
|
; CHECK: bb5:
|
|
; CHECK-NEXT: [[TMP6:%.*]] = phi i64 [ 0, [[BB2:%.*]] ], [ [[TMP10:%.*]], [[BB5]] ]
|
|
; CHECK-NEXT: store i32 3, ptr [[ARG1:%.*]], align 4
|
|
; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[ARG1]], align 4, !invariant.group !0
|
|
; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, ptr [[ARG:%.*]], i64 [[TMP6]]
|
|
; CHECK-NEXT: store i32 [[TMP3]], ptr [[TMP7]], align 8
|
|
; CHECK-NEXT: [[TMP10]] = add nuw nsw i64 [[TMP6]], 1
|
|
; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i64 [[TMP10]], 200
|
|
; CHECK-NEXT: br i1 [[TMP11]], label [[BB12:%.*]], label [[BB5]]
|
|
; CHECK: bb12:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
bb2: ; preds = %bb
|
|
br label %bb5
|
|
|
|
bb5: ; preds = %bb5, %bb2
|
|
%tmp6 = phi i64 [ 0, %bb2 ], [ %tmp10, %bb5 ]
|
|
store i32 3, ptr %arg1
|
|
%tmp3 = load i32, ptr %arg1, align 4, !invariant.group !0
|
|
%tmp7 = getelementptr inbounds i32, ptr %arg, i64 %tmp6
|
|
store i32 %tmp3, ptr %tmp7, align 8
|
|
%tmp10 = add nuw nsw i64 %tmp6, 1
|
|
%tmp11 = icmp eq i64 %tmp10, 200
|
|
br i1 %tmp11, label %bb12, label %bb5
|
|
|
|
bb12: ; preds = %bb5, %bb
|
|
ret void
|
|
}
|
|
|
|
!0 = !{}
|