| ; 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 |
| } |