183 lines
5.5 KiB
LLVM
183 lines
5.5 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -S -hotcoldsplit -hotcoldsplit-threshold=0 < %s 2>&1 | FileCheck %s
|
|
|
|
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
|
|
|
|
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
|
|
|
|
declare void @cold_use(i8*) cold
|
|
|
|
declare void @use(i8*)
|
|
|
|
; In this CFG, splitting will extract the blocks extract{1,2}. I.e., it will
|
|
; extract a lifetime.start marker, but not the corresponding lifetime.end
|
|
; marker. Make sure that a lifetime.start marker is emitted before the call to
|
|
; the split function, and *only* that marker.
|
|
;
|
|
; entry
|
|
; / \
|
|
; extract1 no-extract1
|
|
; (lt.start) |
|
|
; / |
|
|
; extract2 |
|
|
; \_____ |
|
|
; \ /
|
|
; exit
|
|
; (lt.end)
|
|
;
|
|
; After splitting, we should see:
|
|
;
|
|
; entry
|
|
; / \
|
|
; codeRepl no-extract1
|
|
; (lt.start) |
|
|
; \ /
|
|
; exit
|
|
; (lt.end)
|
|
define void @only_lifetime_start_is_cold() {
|
|
; CHECK-LABEL: @only_lifetime_start_is_cold(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256
|
|
; CHECK-NEXT: [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
|
|
; CHECK-NEXT: br i1 undef, label [[CODEREPL:%.*]], label [[NO_EXTRACT1:%.*]]
|
|
; CHECK: codeRepl:
|
|
; CHECK-NEXT: [[LT_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
|
|
; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 -1, i8* [[LT_CAST]])
|
|
; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @only_lifetime_start_is_cold.cold.1(i8* [[LOCAL1_CAST]]) #3
|
|
; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[NO_EXTRACT1]], label [[EXIT:%.*]]
|
|
; CHECK: no-extract1:
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[LOCAL1_CAST]])
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%local1 = alloca i256
|
|
%local1_cast = bitcast i256* %local1 to i8*
|
|
br i1 undef, label %extract1, label %no-extract1
|
|
|
|
extract1:
|
|
; lt.start
|
|
call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast)
|
|
call void @cold_use(i8* %local1_cast)
|
|
br i1 undef, label %extract2, label %no-extract1
|
|
|
|
extract2:
|
|
br label %exit
|
|
|
|
no-extract1:
|
|
br label %exit
|
|
|
|
exit:
|
|
; lt.end
|
|
call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
|
|
ret void
|
|
}
|
|
|
|
; In this CFG, splitting will extract the block extract1. I.e., it will extract
|
|
; a lifetime.end marker, but not the corresponding lifetime.start marker. Do
|
|
; not emit a lifetime.end marker after the call to the split function.
|
|
;
|
|
; entry
|
|
; (lt.start)
|
|
; / \
|
|
; no-extract1 extract1
|
|
; (lt.end) (lt.end)
|
|
; \ /
|
|
; exit
|
|
;
|
|
; After splitting, we should see:
|
|
;
|
|
; entry
|
|
; (lt.start)
|
|
; / \
|
|
; no-extract1 codeRepl
|
|
; (lt.end)
|
|
; \ /
|
|
; exit
|
|
define void @only_lifetime_end_is_cold() {
|
|
; CHECK-LABEL: @only_lifetime_end_is_cold(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256
|
|
; CHECK-NEXT: [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
|
|
; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[LOCAL1_CAST]])
|
|
; CHECK-NEXT: br i1 undef, label [[NO_EXTRACT1:%.*]], label [[CODEREPL:%.*]]
|
|
; CHECK: no-extract1:
|
|
; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* [[LOCAL1_CAST]])
|
|
; CHECK-NEXT: br label [[EXIT:%.*]]
|
|
; CHECK: codeRepl:
|
|
; CHECK-NEXT: call void @only_lifetime_end_is_cold.cold.1(i8* [[LOCAL1_CAST]]) #3
|
|
; CHECK-NEXT: br label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
; lt.start
|
|
%local1 = alloca i256
|
|
%local1_cast = bitcast i256* %local1 to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast)
|
|
br i1 undef, label %no-extract1, label %extract1
|
|
|
|
no-extract1:
|
|
; lt.end
|
|
call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
|
|
br label %exit
|
|
|
|
extract1:
|
|
; lt.end
|
|
call void @cold_use(i8* %local1_cast)
|
|
call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; In this CFG, splitting will extract the blocks extract{1,2,3}. Lifting the
|
|
; lifetime.end marker would be a miscompile.
|
|
define void @do_not_lift_lifetime_end() {
|
|
; CHECK-LABEL: @do_not_lift_lifetime_end(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[LOCAL1:%.*]] = alloca i256
|
|
; CHECK-NEXT: [[LOCAL1_CAST:%.*]] = bitcast i256* [[LOCAL1]] to i8*
|
|
; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* [[LOCAL1_CAST]])
|
|
; CHECK-NEXT: br label [[HEADER:%.*]]
|
|
; CHECK: header:
|
|
; CHECK-NEXT: call void @use(i8* [[LOCAL1_CAST]])
|
|
; CHECK-NEXT: br i1 undef, label [[EXIT:%.*]], label [[CODEREPL:%.*]]
|
|
; CHECK: codeRepl:
|
|
; CHECK-NEXT: [[TARGETBLOCK:%.*]] = call i1 @do_not_lift_lifetime_end.cold.1(i8* [[LOCAL1_CAST]]) #3
|
|
; CHECK-NEXT: br i1 [[TARGETBLOCK]], label [[HEADER]], label [[EXIT]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
; lt.start
|
|
%local1 = alloca i256
|
|
%local1_cast = bitcast i256* %local1 to i8*
|
|
call void @llvm.lifetime.start.p0i8(i64 1, i8* %local1_cast)
|
|
br label %header
|
|
|
|
header:
|
|
; If the lifetime.end marker is lifted, this use becomes dead the second time
|
|
; the header block is executed.
|
|
call void @use(i8* %local1_cast)
|
|
br i1 undef, label %exit, label %extract1
|
|
|
|
extract1:
|
|
call void @cold_use(i8* %local1_cast)
|
|
br i1 undef, label %extract2, label %extract3
|
|
|
|
extract2:
|
|
; Backedge.
|
|
br label %header
|
|
|
|
extract3:
|
|
; lt.end
|
|
call void @llvm.lifetime.end.p0i8(i64 1, i8* %local1_cast)
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|