1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -dse %s -S | FileCheck --check-prefixes=CHECK %s
3
4
5%struct.ham = type { [3 x double], [3 x double]}
6
7declare void @may_throw()
8declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg)
9
10; We miss this case, because of an aggressive limit of partial overlap analysis.
11; With a larger partial store limit, we remove the memset.
12define void @overlap1(%struct.ham* %arg, i1 %cond) {
13; CHECK-LABEL: @overlap1(
14; CHECK-NEXT:  bb:
15; CHECK-NEXT:    [[TMP:%.*]] = getelementptr inbounds [[STRUCT_HAM:%.*]], %struct.ham* [[ARG:%.*]], i64 0, i32 0, i64 2
16; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_HAM]], %struct.ham* [[ARG]], i64 0, i32 0, i64 1
17; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_HAM]], %struct.ham* [[ARG]], i64 0, i32 0, i64 0
18; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_HAM]], %struct.ham* [[ARG]], i64 0, i32 1, i64 2
19; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_HAM]], %struct.ham* [[ARG]], i64 0, i32 1, i64 1
20; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_HAM]], %struct.ham* [[ARG]], i64 0, i32 1, i32 0
21; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB7:%.*]], label [[BB8:%.*]]
22; CHECK:       bb7:
23; CHECK-NEXT:    br label [[BB9:%.*]]
24; CHECK:       bb8:
25; CHECK-NEXT:    br label [[BB9]]
26; CHECK:       bb9:
27; CHECK-NEXT:    store double 1.000000e+00, double* [[TMP2]], align 8
28; CHECK-NEXT:    store double 2.000000e+00, double* [[TMP1]], align 8
29; CHECK-NEXT:    store double 3.000000e+00, double* [[TMP]], align 8
30; CHECK-NEXT:    store double 4.000000e+00, double* [[TMP5]], align 8
31; CHECK-NEXT:    store double 5.000000e+00, double* [[TMP4]], align 8
32; CHECK-NEXT:    store double 6.000000e+00, double* [[TMP3]], align 8
33; CHECK-NEXT:    ret void
34;
35bb:
36  %tmp = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0, i32 0, i64 2
37  %tmp1 = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0, i32 0, i64 1
38  %tmp2 = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0, i32 0, i64 0
39  %tmp3 = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0,i32 1, i64 2
40  %tmp4 = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0, i32 1, i64 1
41  %tmp5 = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0, i32 1, i32 0
42  %tmp6 = bitcast double* %tmp2 to i8*
43  call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(48) %tmp6, i8 0, i64 48, i1 false)
44  br i1 %cond, label %bb7, label %bb8
45
46bb7:                                              ; preds = %bb
47  br label %bb9
48
49bb8:                                              ; preds = %bb
50  br label %bb9
51
52bb9:                                              ; preds = %bb8, %bb7
53  store double 1.0, double* %tmp2, align 8
54  store double 2.0, double* %tmp1, align 8
55  store double 3.0, double* %tmp, align 8
56  store double 4.0, double* %tmp5, align 8
57  store double 5.0, double* %tmp4, align 8
58  store double 6.0, double* %tmp3, align 8
59  ret void
60}
61
62define void @overlap2(%struct.ham* %arg, i1 %cond) {
63; CHECK-LABEL: @overlap2(
64; CHECK-NEXT:  bb:
65; CHECK-NEXT:    [[TMP:%.*]] = getelementptr inbounds [[STRUCT_HAM:%.*]], %struct.ham* [[ARG:%.*]], i64 0, i32 0, i64 2
66; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_HAM]], %struct.ham* [[ARG]], i64 0, i32 0, i64 1
67; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_HAM]], %struct.ham* [[ARG]], i64 0, i32 0, i64 0
68; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds [[STRUCT_HAM]], %struct.ham* [[ARG]], i64 0, i32 1, i64 2
69; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds [[STRUCT_HAM]], %struct.ham* [[ARG]], i64 0, i32 1, i64 1
70; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_HAM]], %struct.ham* [[ARG]], i64 0, i32 1, i32 0
71; CHECK-NEXT:    [[TMP6:%.*]] = bitcast double* [[TMP2]] to i8*
72; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(48) [[TMP6]], i8 0, i64 48, i1 false)
73; CHECK-NEXT:    br i1 [[COND:%.*]], label [[BB7:%.*]], label [[BB8:%.*]]
74; CHECK:       bb7:
75; CHECK-NEXT:    call void @may_throw()
76; CHECK-NEXT:    br label [[BB9:%.*]]
77; CHECK:       bb8:
78; CHECK-NEXT:    br label [[BB9]]
79; CHECK:       bb9:
80; CHECK-NEXT:    store double 1.000000e+00, double* [[TMP2]], align 8
81; CHECK-NEXT:    store double 2.000000e+00, double* [[TMP1]], align 8
82; CHECK-NEXT:    store double 3.000000e+00, double* [[TMP]], align 8
83; CHECK-NEXT:    store double 4.000000e+00, double* [[TMP5]], align 8
84; CHECK-NEXT:    store double 5.000000e+00, double* [[TMP4]], align 8
85; CHECK-NEXT:    store double 6.000000e+00, double* [[TMP3]], align 8
86; CHECK-NEXT:    ret void
87;
88bb:
89  %tmp = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0, i32 0, i64 2
90  %tmp1 = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0, i32 0, i64 1
91  %tmp2 = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0, i32 0, i64 0
92  %tmp3 = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0,i32 1, i64 2
93  %tmp4 = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0, i32 1, i64 1
94  %tmp5 = getelementptr inbounds %struct.ham, %struct.ham* %arg, i64 0, i32 1, i32 0
95  %tmp6 = bitcast double* %tmp2 to i8*
96  call void @llvm.memset.p0i8.i64(i8* nonnull align 8 dereferenceable(48) %tmp6, i8 0, i64 48, i1 false)
97  br i1 %cond, label %bb7, label %bb8
98
99bb7:                                              ; preds = %bb
100  call void @may_throw()
101  br label %bb9
102
103bb8:                                              ; preds = %bb
104  br label %bb9
105
106bb9:                                              ; preds = %bb8, %bb7
107  store double 1.0, double* %tmp2, align 8
108  store double 2.0, double* %tmp1, align 8
109  store double 3.0, double* %tmp, align 8
110  store double 4.0, double* %tmp5, align 8
111  store double 5.0, double* %tmp4, align 8
112  store double 6.0, double* %tmp3, align 8
113  ret void
114}
115
116; Test case from PR46513. Make sure we do not crash.
117; TODO: we should be able to shorten store i32 844283136, i32* %cast.i32 to a
118; store of i16.
119define void @overlap_no_dominance([4 x i8]* %arg, i1 %c)  {
120; CHECK-LABEL: @overlap_no_dominance(
121; CHECK-NEXT:  bb:
122; CHECK-NEXT:    br i1 [[C:%.*]], label [[BB13:%.*]], label [[BB9:%.*]]
123; CHECK:       bb9:
124; CHECK-NEXT:    [[CAST_I32:%.*]] = bitcast [4 x i8]* [[ARG:%.*]] to i32*
125; CHECK-NEXT:    store i32 844283136, i32* [[CAST_I32]], align 4
126; CHECK-NEXT:    br label [[BB13]]
127; CHECK:       bb13:
128; CHECK-NEXT:    [[CAST_I16:%.*]] = bitcast [4 x i8]* [[ARG]] to i16*
129; CHECK-NEXT:    store i16 0, i16* [[CAST_I16]], align 4
130; CHECK-NEXT:    ret void
131;
132bb:
133  br i1 %c, label %bb13, label %bb9
134
135bb9:                                              ; preds = %bb
136  %cast.i32 = bitcast [4 x i8]* %arg to i32*
137  store i32 844283136, i32* %cast.i32, align 4
138  br label %bb13
139
140bb13:                                             ; preds = %bb9, %bb
141  %cast.i16 = bitcast [4 x i8]* %arg to i16*
142  store i16 0, i16* %cast.i16, align 4
143  ret void
144}
145