181 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; Redundant memmove.5define i32 @redundant_memmove() {6; CHECK-LABEL: @redundant_memmove(7; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 168; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 104, i1 false)9; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 410; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY]], align 1611; CHECK-NEXT: ret i32 [[VAL]]12;13 %array = alloca [26 x i32], align 1614 call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 104, i1 false)15 %array.idx = getelementptr inbounds i8, ptr %array, i64 416 call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 100, i1 false)17 %val = load i32, ptr %array, align 1618 ret i32 %val19}20 21; Used memmove, buffer is reset to zero.22define i32 @used_memmove_1() {23; CHECK-LABEL: @used_memmove_1(24; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 1625; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 104, i1 false)26; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 427; CHECK-NEXT: store i32 1, ptr [[ARRAY_IDX]], align 428; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX]], i64 100, i1 false)29; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY_IDX]], align 430; CHECK-NEXT: ret i32 [[VAL]]31;32 %array = alloca [26 x i32], align 1633 call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 104, i1 false)34 %array.idx = getelementptr inbounds i8, ptr %array, i64 435 store i32 1, ptr %array.idx36 call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 100, i1 false)37 %val = load i32, ptr %array.idx, align 438 ret i32 %val39}40 41; Used memmove.42define i32 @used_memmove_2() {43; CHECK-LABEL: @used_memmove_2(44; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 1645; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 104, i1 false)46; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 447; CHECK-NEXT: store i32 1, ptr [[ARRAY]], align 448; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX]], i64 100, i1 false)49; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY_IDX]], align 450; CHECK-NEXT: ret i32 [[VAL]]51;52 %array = alloca [26 x i32], align 1653 call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 104, i1 false)54 %array.idx = getelementptr inbounds i8, ptr %array, i64 455 store i32 1, ptr %array56 call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 100, i1 false)57 %val = load i32, ptr %array.idx, align 458 ret i32 %val59}60 61; Used memmove, buffer clobbered by opaque.62define i32 @used_memmove_3() {63; CHECK-LABEL: @used_memmove_3(64; CHECK-NEXT: [[ARRAY:%.*]] = alloca [25 x i32], align 1665; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 100, i1 false)66; CHECK-NEXT: call void @opaque(ptr [[ARRAY]])67; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 468; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX]], i64 96, i1 false)69; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY]], align 1670; CHECK-NEXT: ret i32 [[VAL]]71;72 %array = alloca [25 x i32], align 1673 call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 100, i1 false)74 call void @opaque(ptr %array)75 %array.idx = getelementptr inbounds i8, ptr %array, i64 476 call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 96, i1 false)77 %val = load i32, ptr %array, align 1678 ret i32 %val79}80 81; Redundant memmove, not within the same basic block.82define i32 @redundant_memmove_different_bbs() {83; CHECK-LABEL: @redundant_memmove_different_bbs(84; CHECK-NEXT: entry:85; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 1686; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 104, i1 false)87; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 488; CHECK-NEXT: br label [[USE:%.*]]89; CHECK: use:90; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY]], align 1691; CHECK-NEXT: ret i32 [[VAL]]92;93entry:94 %array = alloca [26 x i32], align 1695 call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 104, i1 false)96 %array.idx = getelementptr inbounds i8, ptr %array, i64 497 br label %use98 99use: ; preds = %entry100 call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 100, i1 false)101 %val = load i32, ptr %array, align 16102 ret i32 %val103}104 105@g_var = global [26 x i32] zeroinitializer, align 16106 107; Redundant memmove on a global variable.108define ptr @redundant_memmove_memset_global_variable() {109; CHECK-LABEL: @redundant_memmove_memset_global_variable(110; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 @g_var, i8 0, i64 104, i1 false)111; CHECK-NEXT: ret ptr @g_var112;113 call void @llvm.memset.p0.i64(ptr align 16 @g_var, i8 0, i64 104, i1 false)114 call void @llvm.memmove.p0.p0.i64(ptr align 16 @g_var, ptr align 4 getelementptr inbounds nuw (i8, ptr @g_var, i64 4), i64 100, i1 false)115 ret ptr @g_var116}117 118; Memset only partial.119define i32 @partial_memset() {120; CHECK-LABEL: @partial_memset(121; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 16122; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 92123; CHECK-NEXT: store i32 1, ptr [[ARRAY_IDX]], align 4124; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 26, i1 false)125; CHECK-NEXT: [[ARRAY_IDX_2:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 4126; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX_2]], i64 100, i1 false)127; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY_IDX]], align 4128; CHECK-NEXT: ret i32 [[VAL]]129;130 %array = alloca [26 x i32], align 16131 %array.idx = getelementptr inbounds i8, ptr %array, i64 92132 store i32 1, ptr %array.idx133 call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 26, i1 false)134 %array.idx.2 = getelementptr inbounds i8, ptr %array, i64 4135 call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx.2, i64 100, i1 false)136 %val = load i32, ptr %array.idx, align 4137 ret i32 %val138}139 140; Memset length not constant.141define i32 @memset_length_not_constant(i64 %size) {142; CHECK-LABEL: @memset_length_not_constant(143; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 16144; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 [[SIZE:%.*]], i1 false)145; CHECK-NEXT: [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 4146; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX]], i64 100, i1 false)147; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY]], align 16148; CHECK-NEXT: ret i32 [[VAL]]149;150 %array = alloca [26 x i32], align 16151 call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 %size, i1 false)152 %array.idx = getelementptr inbounds i8, ptr %array, i64 4153 call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 100, i1 false)154 %val = load i32, ptr %array, align 16155 ret i32 %val156}157 158; Memmove buffer not memset'd, different buffers.159define i32 @memset_memmove_dest_buffers_not_alias() {160; CHECK-LABEL: @memset_memmove_dest_buffers_not_alias(161; CHECK-NEXT: [[ARRAY:%.*]] = alloca [26 x i32], align 16162; CHECK-NEXT: [[ARRAY2:%.*]] = alloca [26 x i32], align 16163; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY]], i8 0, i64 104, i1 false)164; CHECK-NEXT: [[ARRAY2_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY2]], i64 4165; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY2]], ptr align 4 [[ARRAY2_IDX]], i64 100, i1 false)166; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[ARRAY2]], align 16167; CHECK-NEXT: ret i32 [[VAL]]168;169 %array = alloca [26 x i32], align 16170 %array2 = alloca [26 x i32], align 16171 call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 104, i1 false)172 %array2.idx = getelementptr inbounds i8, ptr %array2, i64 4173 call void @llvm.memmove.p0.p0.i64(ptr align 16 %array2, ptr align 4 %array2.idx, i64 100, i1 false)174 %val = load i32, ptr %array2, align 16175 ret i32 %val176}177 178declare void @opaque(ptr)179declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1)180declare void @llvm.memmove.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1)181