brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.0 KiB · 2575d58 Raw
206 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=memcpyopt -S %s -verify-memoryssa | FileCheck %s3 4; memset -> memcpy forwarding, if memcpy is larger than memset, but trailing5; bytes are known to be undef.6 7 8%T = type { i64, i32, i32 }9 10define void @test_alloca(ptr %result) {11; CHECK-LABEL: @test_alloca(12; CHECK-NEXT:    [[A:%.*]] = alloca [[T:%.*]], align 813; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 12, i1 false)14; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[RESULT:%.*]], i8 0, i64 12, i1 false)15; CHECK-NEXT:    ret void16;17  %a = alloca %T, align 818  call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 12, i1 false)19  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false)20  ret void21}22 23define void @test_alloca_with_lifetimes(ptr %result) {24; CHECK-LABEL: @test_alloca_with_lifetimes(25; CHECK-NEXT:    [[A:%.*]] = alloca [[T:%.*]], align 826; CHECK-NEXT:    call void @llvm.lifetime.start.p0(ptr [[A]])27; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 12, i1 false)28; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[RESULT:%.*]], i8 0, i64 12, i1 false)29; CHECK-NEXT:    call void @llvm.lifetime.end.p0(ptr [[A]])30; CHECK-NEXT:    ret void31;32  %a = alloca %T, align 833  call void @llvm.lifetime.start.p0(ptr %a)34  call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 12, i1 false)35  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false)36  call void @llvm.lifetime.end.p0(ptr %a)37  ret void38}39 40; The trailing bytes are not known to be undef, we can't ignore them.41define void @test_not_undef_memory(ptr %result, ptr %input) {42; CHECK-LABEL: @test_not_undef_memory(43; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[INPUT:%.*]], i8 0, i64 12, i1 false)44; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[RESULT:%.*]], ptr align 8 [[INPUT]], i64 16, i1 false)45; CHECK-NEXT:    ret void46;47  call void @llvm.memset.p0.i64(ptr align 8 %input, i8 0, i64 12, i1 false)48  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %input, i64 16, i1 false)49  ret void50}51 52; Memset is volatile, memcpy is not. Can be optimized.53define void @test_volatile_memset(ptr %result) {54; CHECK-LABEL: @test_volatile_memset(55; CHECK-NEXT:    [[A:%.*]] = alloca [[T:%.*]], align 856; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 12, i1 true)57; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[RESULT:%.*]], i8 0, i64 12, i1 false)58; CHECK-NEXT:    ret void59;60  %a = alloca %T, align 861  call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 12, i1 true)62  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false)63  ret void64}65 66; Memcpy is volatile, memset is not. Cannot be optimized.67define void @test_volatile_memcpy(ptr %result) {68; CHECK-LABEL: @test_volatile_memcpy(69; CHECK-NEXT:    [[A:%.*]] = alloca [[T:%.*]], align 870; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 12, i1 false)71; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[RESULT:%.*]], ptr align 8 [[A]], i64 16, i1 true)72; CHECK-NEXT:    ret void73;74  %a = alloca %T, align 875  call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 12, i1 false)76  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 true)77  ret void78}79 80; Write between memset and memcpy, can't optimize.81define void @test_write_between(ptr %result) {82; CHECK-LABEL: @test_write_between(83; CHECK-NEXT:    [[A:%.*]] = alloca [[T:%.*]], align 884; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 12, i1 false)85; CHECK-NEXT:    store i8 -1, ptr [[A]], align 186; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[RESULT:%.*]], ptr align 8 [[A]], i64 16, i1 false)87; CHECK-NEXT:    ret void88;89  %a = alloca %T, align 890  call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 12, i1 false)91  store i8 -1, ptr %a92  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false)93  ret void94}95 96; A write prior to the memset, which is part of the memset region.97; We could optimize this, but currently don't, because the used memory location is imprecise.98define void @test_write_before_memset_in_memset_region(ptr %result) {99; CHECK-LABEL: @test_write_before_memset_in_memset_region(100; CHECK-NEXT:    [[A:%.*]] = alloca [[T:%.*]], align 8101; CHECK-NEXT:    store i8 -1, ptr [[A]], align 1102; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 8, i1 false)103; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[RESULT:%.*]], ptr align 8 [[A]], i64 16, i1 false)104; CHECK-NEXT:    ret void105;106  %a = alloca %T, align 8107  store i8 -1, ptr %a108  call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 8, i1 false)109  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false)110  ret void111}112 113; A write prior to the memset, which is part of the memcpy (but not memset) region.114; This cannot be optimized.115define void @test_write_before_memset_in_memcpy_region(ptr %result) {116; CHECK-LABEL: @test_write_before_memset_in_memcpy_region(117; CHECK-NEXT:    [[A:%.*]] = alloca [[T:%.*]], align 8118; CHECK-NEXT:    [[C:%.*]] = getelementptr inbounds [[T]], ptr [[A]], i64 0, i32 2119; CHECK-NEXT:    store i32 -1, ptr [[C]], align 4120; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 8, i1 false)121; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[RESULT:%.*]], ptr align 8 [[A]], i64 16, i1 false)122; CHECK-NEXT:    ret void123;124  %a = alloca %T, align 8125  %c = getelementptr inbounds %T, ptr %a, i64 0, i32 2126  store i32 -1, ptr %c127  call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 8, i1 false)128  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false)129  ret void130}131 132; A write prior to the memset, which is part of both the memset and memcpy regions.133; This cannot be optimized.134define void @test_write_before_memset_in_both_regions(ptr %result) {135; CHECK-LABEL: @test_write_before_memset_in_both_regions(136; CHECK-NEXT:    [[A:%.*]] = alloca [[T:%.*]], align 8137; CHECK-NEXT:    [[C:%.*]] = getelementptr inbounds [[T]], ptr [[A]], i64 0, i32 1138; CHECK-NEXT:    store i32 -1, ptr [[C]], align 4139; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 10, i1 false)140; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[RESULT:%.*]], ptr align 8 [[A]], i64 16, i1 false)141; CHECK-NEXT:    ret void142;143  %a = alloca %T, align 8144  %c = getelementptr inbounds %T, ptr %a, i64 0, i32 1145  store i32 -1, ptr %c146  call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 10, i1 false)147  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false)148  ret void149}150 151define void @test_negative_offset_memset(ptr %result) {152; CHECK-LABEL: @test_negative_offset_memset(153; CHECK-NEXT:    [[A1:%.*]] = alloca [16 x i8], align 8154; CHECK-NEXT:    [[A:%.*]] = getelementptr i8, ptr [[A1]], i32 4155; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 12, i1 false)156; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[RESULT:%.*]], ptr align 8 [[A1]], i64 12, i1 false)157; CHECK-NEXT:    ret void158;159  %a = alloca [ 16 x i8 ], align 8160  %b = getelementptr i8, ptr %a, i32 4161  call void @llvm.memset.p0.i64(ptr align 8 %b, i8 0, i64 12, i1 false)162  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 12, i1 false)163  ret void164}165 166define void @test_offset_memsetcpy(ptr %result) {167; CHECK-LABEL: @test_offset_memsetcpy(168; CHECK-NEXT:    [[A1:%.*]] = alloca [16 x i8], align 8169; CHECK-NEXT:    [[A:%.*]] = getelementptr i8, ptr [[A1]], i32 4170; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[A1]], i8 0, i64 12, i1 false)171; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr [[RESULT:%.*]], i8 0, i64 8, i1 false)172; CHECK-NEXT:    ret void173;174  %a = alloca [ 16 x i8 ], align 8175  %b = getelementptr i8, ptr %a, i32 4176  call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 12, i1 false)177  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %b, i64 12, i1 false)178  ret void179}180 181define void @test_two_memset(ptr %result) {182; CHECK-LABEL: @test_two_memset(183; CHECK-NEXT:    [[A:%.*]] = alloca [16 x i8], align 8184; CHECK-NEXT:    [[B:%.*]] = getelementptr i8, ptr [[A]], i32 12185; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[A]], i8 0, i64 12, i1 false)186; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[B]], i8 1, i64 4, i1 false)187; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[RESULT:%.*]], ptr align 8 [[A]], i64 16, i1 false)188; CHECK-NEXT:    ret void189;190  %a = alloca [ 16 x i8 ], align 8191  %b = getelementptr i8, ptr %a, i32 12192  call void @llvm.memset.p0.i64(ptr align 8 %a, i8 0, i64 12, i1 false)193  call void @llvm.memset.p0.i64(ptr align 8 %b, i8 1, i64 4, i1 false)194  call void @llvm.memcpy.p0.p0.i64(ptr %result, ptr align 8 %a, i64 16, i1 false)195  ret void196}197 198declare ptr @malloc(i64)199declare void @free(ptr)200 201declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1)202declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1)203 204declare void @llvm.lifetime.start.p0(ptr nocapture)205declare void @llvm.lifetime.end.p0(ptr nocapture)206