1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -aa-pipeline=basic-aa -passes=dse -S | FileCheck %s
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind
declare void @llvm.memset.element.unordered.atomic.p0.i64(ptr nocapture, i8, i64, i32) nounwind
declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
declare void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i32) nounwind
declare void @llvm.init.trampoline(ptr, ptr, ptr)
;; Overwrite of memset by memcpy.
define void @test17(ptr %P, ptr noalias %Q) nounwind ssp {
; CHECK-LABEL: @test17(
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)
; CHECK-NEXT: ret void
;
tail call void @llvm.memset.p0.i64(ptr %P, i8 42, i64 8, i1 false)
tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)
ret void
}
;; Overwrite of memset by memcpy.
define void @test17_atomic(ptr %P, ptr noalias %Q) nounwind ssp {
; CHECK-LABEL: @test17_atomic(
; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i32 1)
; CHECK-NEXT: ret void
;
tail call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 1 %P, i8 42, i64 8, i32 1)
tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)
ret void
}
;; Overwrite of memset by memcpy. Overwrite is stronger atomicity. We can
;; remove the memset.
define void @test17_atomic_weaker(ptr %P, ptr noalias %Q) nounwind ssp {
; CHECK-LABEL: @test17_atomic_weaker(
; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i32 1)
; CHECK-NEXT: ret void
;
tail call void @llvm.memset.p0.i64(ptr align 1 %P, i8 42, i64 8, i1 false)
tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)
ret void
}
;; Overwrite of memset by memcpy. Overwrite is weaker atomicity. We can remove
;; the memset.
define void @test17_atomic_weaker_2(ptr %P, ptr noalias %Q) nounwind ssp {
; CHECK-LABEL: @test17_atomic_weaker_2(
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i1 false)
; CHECK-NEXT: ret void
;
tail call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 1 %P, i8 42, i64 8, i32 1)
tail call void @llvm.memcpy.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i1 false)
ret void
}
; Should not delete the volatile memset.
define void @test17v(ptr %P, ptr %Q) nounwind ssp {
; CHECK-LABEL: @test17v(
; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 42, i64 8, i1 true)
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[Q:%.*]], i64 12, i1 false)
; CHECK-NEXT: ret void
;
tail call void @llvm.memset.p0.i64(ptr %P, i8 42, i64 8, i1 true)
tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)
ret void
}
; See PR11763 - LLVM allows memcpy's source and destination to be equal (but not
; inequal and overlapping).
define void @test18(ptr %P, ptr %Q, ptr %R) nounwind ssp {
; CHECK-LABEL: @test18(
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[R:%.*]], i64 12, i1 false)
; CHECK-NEXT: ret void
;
tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)
tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %R, i64 12, i1 false)
ret void
}
define void @test18_atomic(ptr %P, ptr %Q, ptr %R) nounwind ssp {
; CHECK-LABEL: @test18_atomic(
; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i32 1)
; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 [[P]], ptr align 1 [[R:%.*]], i64 12, i32 1)
; CHECK-NEXT: ret void
;
tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i32 1)
tail call void @llvm.memcpy.element.unordered.atomic.p0.p0.i64(ptr align 1 %P, ptr align 1 %R, i64 12, i32 1)
ret void
}
define void @test_memset_memcpy_inline(ptr noalias %P, ptr noalias %Q) {
; CHECK-LABEL: @test_memset_memcpy_inline(
; CHECK-NEXT: tail call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 [[P:%.*]], ptr align 1 [[Q:%.*]], i64 12, i1 false)
; CHECK-NEXT: ret void
;
tail call void @llvm.memset.p0.i64(ptr %P, i8 42, i64 8, i1 false)
tail call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 12, i1 false)
ret void
}
define void @test_store_memcpy_inline(ptr noalias %P, ptr noalias %Q) {
; CHECK-LABEL: @test_store_memcpy_inline(
; CHECK-NEXT: [[P_4:%.*]] = getelementptr i8, ptr [[P:%.*]], i64 4
; CHECK-NEXT: store i8 4, ptr [[P_4]], align 1
; CHECK-NEXT: tail call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 [[P]], ptr align 1 [[Q:%.*]], i64 4, i1 false)
; CHECK-NEXT: ret void
;
store i8 0, ptr %P
%P.1 = getelementptr i8, ptr %P, i64 1
store i8 1, ptr %P.1
%P.4 = getelementptr i8, ptr %P, i64 4
store i8 4, ptr %P.4
tail call void @llvm.memcpy.inline.p0.p0.i64(ptr align 1 %P, ptr align 1 %Q, i64 4, i1 false)
ret void
}
;; Overwrite of memset.pattern by memcpy.
define void @memset_pattern_overwrite(ptr %P, ptr noalias %Q) nounwind ssp {
; CHECK-LABEL: @memset_pattern_overwrite(
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)
; CHECK-NEXT: ret void
;
tail call void @llvm.experimental.memset.pattern.p0.i64(ptr %P, i8 42, i64 8, i1 false)
tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)
ret void
}
define void @memset_pattern_overwrite2(ptr %P, ptr noalias %Q) nounwind ssp {
; CHECK-LABEL: @memset_pattern_overwrite2(
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[P:%.*]], ptr [[Q:%.*]], i64 12, i1 false)
; CHECK-NEXT: ret void
;
tail call void @llvm.experimental.memset.pattern(ptr %P, i16 270, i64 4, i1 false)
tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)
ret void
}
define void @memset_pattern_value_noalias(ptr %P, ptr noalias %Q) nounwind ssp {
; CHECK-LABEL: @memset_pattern_value_noalias(
; CHECK-NEXT: tail call void @llvm.experimental.memset.pattern.p0.p0.i64(ptr [[Q:%.*]], ptr [[P:%.*]], i64 8, i1 false)
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[Q]], i64 12, i1 false)
; CHECK-NEXT: ret void
;
tail call void @llvm.memset.p0.i64(ptr %P, i8 42, i64 8, i1 false)
tail call void @llvm.experimental.memset.pattern.p0.i64(ptr %Q, ptr %P, i64 8, i1 false)
tail call void @llvm.memcpy.p0.p0.i64(ptr %P, ptr %Q, i64 12, i1 false)
ret void
}
define void @memset_pattern_value_noalias2(ptr %P) nounwind ssp {;
; CHECK-LABEL: @memset_pattern_value_noalias2(
; CHECK-NEXT: tail call void @llvm.experimental.memset.pattern.p0.p0.i64(ptr [[P:%.*]], ptr [[P]], i64 8, i1 false)
; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr [[P]], i8 42, i64 200, i1 false)
; CHECK-NEXT: ret void
;
tail call void @llvm.experimental.memset.pattern.p0.i64(ptr %P, ptr %P, i64 8, i1 false)
tail call void @llvm.memset.p0.i64(ptr %P, i8 42, i64 200, i1 false)
ret void
}
define void @memset_pattern_value_noalias3(ptr %P) nounwind ssp {
; CHECK-LABEL: @memset_pattern_value_noalias3(
; CHECK-NEXT: [[Q:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 8
; CHECK-NEXT: tail call void @llvm.experimental.memset.pattern.p0.p0.i64(ptr [[Q]], ptr [[P]], i64 8, i1 false)
; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr [[Q]], i8 42, i64 200, i1 false)
; CHECK-NEXT: ret void
;
%q = getelementptr i8, ptr %P, i32 8
tail call void @llvm.experimental.memset.pattern.p0.i64(ptr %q, ptr %P, i64 8, i1 false)
tail call void @llvm.memset.p0.i64(ptr %q, i8 42, i64 200, i1 false)
ret void
}
declare void @llvm.memcpy.inline.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64 immarg, i1 immarg)
|