
Now that #149310 has restricted lifetime intrinsics to only work on allocas, we can also drop the explicit size argument. Instead, the size is implied by the alloca. This removes the ability to only mark a prefix of an alloca alive/dead. We never used that capability, so we should remove the need to handle that possibility everywhere (though many key places, including stack coloring, did not actually respect this).
147 lines
5.6 KiB
LLVM
147 lines
5.6 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -aa-pipeline=basic-aa -passes='require<memoryssa>,memcpyopt' -verify-memoryssa -S %s | FileCheck %s
|
|
|
|
; REQUIRES: asserts
|
|
|
|
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-apple-macosx10.15.0"
|
|
|
|
%t = type <{ ptr, [4 x i8], ptr, ptr, i32, [8192 x i8] }>
|
|
|
|
|
|
define i32 @test1(ptr %ptr) {
|
|
; CHECK-LABEL: @test1(
|
|
; CHECK-NEXT: invoke.cont6:
|
|
; CHECK-NEXT: [[P_2:%.*]] = getelementptr inbounds [[T:%.*]], ptr [[PTR:%.*]], i64 0, i32 4
|
|
; CHECK-NEXT: [[P_3:%.*]] = getelementptr inbounds [[T]], ptr [[PTR]], i64 0, i32 5, i64 0
|
|
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[PTR]], i8 0, i64 20, i1 false)
|
|
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[P_2]], i8 0, i64 8195, i1 false)
|
|
; CHECK-NEXT: ret i32 0
|
|
;
|
|
invoke.cont6:
|
|
call void @llvm.memset.p0.i64(ptr %ptr, i8 0, i64 20, i1 false)
|
|
store ptr null, ptr %ptr, align 8
|
|
%p.2 = getelementptr inbounds %t, ptr %ptr, i64 0, i32 4
|
|
store i32 0, ptr %p.2, align 8
|
|
%p.3 = getelementptr inbounds %t, ptr %ptr, i64 0, i32 5, i64 0
|
|
call void @llvm.memset.p0.i64(ptr %p.3, i8 0, i64 8191, i1 false)
|
|
ret i32 0
|
|
}
|
|
|
|
declare ptr @get_ptr()
|
|
|
|
define void @test2(ptr noalias %in) {
|
|
; CHECK-LABEL: @test2(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[CALL_I1_I:%.*]] = tail call ptr @get_ptr()
|
|
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[CALL_I1_I]], ptr [[IN:%.*]], i64 10, i1 false)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%call.i1.i = tail call ptr @get_ptr()
|
|
tail call void @llvm.memset.p0.i64(ptr %call.i1.i, i8 0, i64 10, i1 false)
|
|
tail call void @llvm.memcpy.p0.p0.i64(ptr %call.i1.i, ptr %in, i64 10, i1 false)
|
|
ret void
|
|
}
|
|
|
|
declare ptr @malloc(i64)
|
|
|
|
define i32 @test3(ptr noalias %in) {
|
|
; CHECK-LABEL: @test3(
|
|
; CHECK-NEXT: [[CALL_I_I_I:%.*]] = tail call ptr @malloc(i64 20)
|
|
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[CALL_I_I_I]], ptr [[IN:%.*]], i64 20, i1 false)
|
|
; CHECK-NEXT: ret i32 10
|
|
;
|
|
%call.i.i.i = tail call ptr @malloc(i64 20)
|
|
tail call void @llvm.memmove.p0.p0.i64(ptr %call.i.i.i, ptr %in, i64 20, i1 false)
|
|
ret i32 10
|
|
}
|
|
|
|
define void @test4(i32 %n, ptr noalias %ptr.0, ptr noalias %ptr.1, ptr %ptr.2) unnamed_addr {
|
|
; CHECK-LABEL: @test4(
|
|
; CHECK-NEXT: [[ELEM_I:%.*]] = getelementptr i8, ptr [[PTR_0:%.*]], i64 8
|
|
; CHECK-NEXT: store i32 [[N:%.*]], ptr [[PTR_2:%.*]], align 8
|
|
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[ELEM_I]], ptr [[PTR_1:%.*]], i64 10, i1 false)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%elem.i = getelementptr i8, ptr %ptr.0, i64 8
|
|
call void @llvm.memset.p0.i64(ptr %elem.i, i8 0, i64 10, i1 false)
|
|
store i32 %n, ptr %ptr.2, align 8
|
|
call void @llvm.memcpy.p0.p0.i64(ptr %elem.i, ptr %ptr.1, i64 10, i1 false)
|
|
ret void
|
|
}
|
|
|
|
declare void @decompose(ptr nocapture)
|
|
|
|
define void @test5(ptr %ptr) {
|
|
; CHECK-LABEL: @test5(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[EARLY_DATA:%.*]] = alloca [128 x i8], align 8
|
|
; CHECK-NEXT: [[TMP:%.*]] = alloca [[T:%.*]], align 8
|
|
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[EARLY_DATA]])
|
|
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[PTR:%.*]], align 8
|
|
; CHECK-NEXT: call fastcc void @decompose(ptr [[TMP]])
|
|
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[EARLY_DATA]], ptr [[TMP]], i64 32, i1 false)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
%early_data = alloca [128 x i8], align 8
|
|
%tmp = alloca %t, align 8
|
|
call void @llvm.lifetime.start.p0(ptr %early_data)
|
|
%0 = load i32, ptr %ptr, align 8
|
|
call fastcc void @decompose(ptr %tmp)
|
|
call void @llvm.memcpy.p0.p0.i64(ptr %early_data, ptr %tmp, i64 32, i1 false)
|
|
ret void
|
|
}
|
|
|
|
define void @test7(ptr %ptr) {
|
|
; CHECK-LABEL: @test7(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [4 x i32], ptr [[PTR:%.*]], i64 0, i32 1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [4 x i32], ptr [[PTR]], i64 0, i32 2
|
|
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [4 x i32], ptr [[PTR]], i64 0, i32 3
|
|
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[PTR]], i8 0, i64 16, i1 false)
|
|
; CHECK-NEXT: call void @clobber()
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
store i32 0, ptr %ptr, align 1
|
|
%0 = getelementptr inbounds [4 x i32], ptr %ptr, i64 0, i32 1
|
|
store i32 0, ptr %0, align 1
|
|
%1 = getelementptr inbounds [4 x i32], ptr %ptr, i64 0, i32 2
|
|
store i32 0, ptr %1, align 1
|
|
%2 = getelementptr inbounds [4 x i32], ptr %ptr, i64 0, i32 3
|
|
store i32 0, ptr %2, align 1
|
|
call void @clobber()
|
|
ret void
|
|
}
|
|
|
|
define void @test8(ptr noalias %src, ptr %dst) {
|
|
; CHECK-LABEL: @test8(
|
|
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[DST:%.*]], ptr align 1 [[SRC:%.*]], i64 8224, i1 false)
|
|
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[SRC]], i8 0, i64 8224, i1 false)
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%1 = load %t, ptr %src
|
|
store %t zeroinitializer, ptr %src
|
|
store %t %1, ptr %dst
|
|
ret void
|
|
}
|
|
|
|
declare void @clobber()
|
|
|
|
; Function Attrs: argmemonly nounwind willreturn
|
|
declare void @llvm.lifetime.start.p0(ptr nocapture) #0
|
|
|
|
; Function Attrs: argmemonly nounwind willreturn
|
|
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #0
|
|
|
|
; Function Attrs: argmemonly nounwind willreturn writeonly
|
|
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #1
|
|
|
|
; Function Attrs: argmemonly nounwind willreturn
|
|
declare void @llvm.memmove.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1 immarg) #0
|
|
|
|
attributes #0 = { argmemonly nounwind willreturn }
|
|
attributes #1 = { argmemonly nounwind willreturn writeonly }
|