1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -basicaa -dse -S | FileCheck %s 3 4define void @write4to7(i32* nocapture %p) { 5; CHECK-LABEL: @write4to7( 6; CHECK-NEXT: entry: 7; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1 8; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8* 9; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4 10; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false) 11; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1 12; CHECK-NEXT: store i32 1, i32* [[ARRAYIDX1]], align 4 13; CHECK-NEXT: ret void 14; 15entry: 16 %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1 17 %p3 = bitcast i32* %arrayidx0 to i8* 18 call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i1 false) 19 %arrayidx1 = getelementptr inbounds i32, i32* %p, i64 1 20 store i32 1, i32* %arrayidx1, align 4 21 ret void 22} 23 24define void @write4to7_atomic(i32* nocapture %p) { 25; CHECK-LABEL: @write4to7_atomic( 26; CHECK-NEXT: entry: 27; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1 28; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8* 29; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i32 4) 30; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1 31; CHECK-NEXT: store atomic i32 1, i32* [[ARRAYIDX1]] unordered, align 4 32; CHECK-NEXT: ret void 33; 34entry: 35 %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1 36 %p3 = bitcast i32* %arrayidx0 to i8* 37 call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i32 4) 38 %arrayidx1 = getelementptr inbounds i32, i32* %p, i64 1 39 store atomic i32 1, i32* %arrayidx1 unordered, align 4 40 ret void 41} 42 43define void @write0to3(i32* nocapture %p) { 44; CHECK-LABEL: @write0to3( 45; CHECK-NEXT: entry: 46; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8* 47; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4 48; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false) 49; CHECK-NEXT: store i32 1, i32* [[P]], align 4 50; CHECK-NEXT: ret void 51; 52entry: 53 %p3 = bitcast i32* %p to i8* 54 call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i1 false) 55 store i32 1, i32* %p, align 4 56 ret void 57} 58 59define void @write0to3_atomic(i32* nocapture %p) { 60; CHECK-LABEL: @write0to3_atomic( 61; CHECK-NEXT: entry: 62; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8* 63; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i32 4) 64; CHECK-NEXT: store atomic i32 1, i32* [[P]] unordered, align 4 65; CHECK-NEXT: ret void 66; 67entry: 68 %p3 = bitcast i32* %p to i8* 69 call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i32 4) 70 store atomic i32 1, i32* %p unordered, align 4 71 ret void 72} 73 74; Atomicity of the store is weaker from the memset 75define void @write0to3_atomic_weaker(i32* nocapture %p) { 76; CHECK-LABEL: @write0to3_atomic_weaker( 77; CHECK-NEXT: entry: 78; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8* 79; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i32 4) 80; CHECK-NEXT: store i32 1, i32* [[P]], align 4 81; CHECK-NEXT: ret void 82; 83entry: 84 %p3 = bitcast i32* %p to i8* 85 call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i32 4) 86 store i32 1, i32* %p, align 4 87 ret void 88} 89 90define void @write0to7(i32* nocapture %p) { 91; CHECK-LABEL: @write0to7( 92; CHECK-NEXT: entry: 93; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8* 94; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 8 95; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false) 96; CHECK-NEXT: [[P4:%.*]] = bitcast i32* [[P]] to i64* 97; CHECK-NEXT: store i64 1, i64* [[P4]], align 8 98; CHECK-NEXT: ret void 99; 100entry: 101 %p3 = bitcast i32* %p to i8* 102 call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i1 false) 103 %p4 = bitcast i32* %p to i64* 104 store i64 1, i64* %p4, align 8 105 ret void 106} 107 108; Changing the memset start and length is okay here because the 109; store is a multiple of the memset element size 110define void @write0to7_atomic(i32* nocapture %p) { 111; CHECK-LABEL: @write0to7_atomic( 112; CHECK-NEXT: entry: 113; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8* 114; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 32, i32 4) 115; CHECK-NEXT: [[P4:%.*]] = bitcast i32* [[P]] to i64* 116; CHECK-NEXT: store atomic i64 1, i64* [[P4]] unordered, align 8 117; CHECK-NEXT: ret void 118; 119entry: 120 %p3 = bitcast i32* %p to i8* 121 call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i32 4) 122 %p4 = bitcast i32* %p to i64* 123 store atomic i64 1, i64* %p4 unordered, align 8 124 ret void 125} 126 127define void @write0to7_2(i32* nocapture %p) { 128; CHECK-LABEL: @write0to7_2( 129; CHECK-NEXT: entry: 130; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1 131; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8* 132; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4 133; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false) 134; CHECK-NEXT: [[P4:%.*]] = bitcast i32* [[P]] to i64* 135; CHECK-NEXT: store i64 1, i64* [[P4]], align 8 136; CHECK-NEXT: ret void 137; 138entry: 139 %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1 140 %p3 = bitcast i32* %arrayidx0 to i8* 141 call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i1 false) 142 %p4 = bitcast i32* %p to i64* 143 store i64 1, i64* %p4, align 8 144 ret void 145} 146 147define void @write0to7_2_atomic(i32* nocapture %p) { 148; CHECK-LABEL: @write0to7_2_atomic( 149; CHECK-NEXT: entry: 150; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1 151; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8* 152; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i32 4) 153; CHECK-NEXT: [[P4:%.*]] = bitcast i32* [[P]] to i64* 154; CHECK-NEXT: store atomic i64 1, i64* [[P4]] unordered, align 8 155; CHECK-NEXT: ret void 156; 157entry: 158 %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1 159 %p3 = bitcast i32* %arrayidx0 to i8* 160 call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i32 4) 161 %p4 = bitcast i32* %p to i64* 162 store atomic i64 1, i64* %p4 unordered, align 8 163 ret void 164} 165 166; We do not trim the beginning of the eariler write if the alignment of the 167; start pointer is changed. 168define void @dontwrite0to3_align8(i32* nocapture %p) { 169; CHECK-LABEL: @dontwrite0to3_align8( 170; CHECK-NEXT: entry: 171; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8* 172; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 8 [[P3]], i8 0, i64 32, i1 false) 173; CHECK-NEXT: store i32 1, i32* [[P]], align 4 174; CHECK-NEXT: ret void 175; 176entry: 177 %p3 = bitcast i32* %p to i8* 178 call void @llvm.memset.p0i8.i64(i8* align 8 %p3, i8 0, i64 32, i1 false) 179 store i32 1, i32* %p, align 4 180 ret void 181} 182 183define void @dontwrite0to3_align8_atomic(i32* nocapture %p) { 184; CHECK-LABEL: @dontwrite0to3_align8_atomic( 185; CHECK-NEXT: entry: 186; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8* 187; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 [[P3]], i8 0, i64 32, i32 4) 188; CHECK-NEXT: store atomic i32 1, i32* [[P]] unordered, align 4 189; CHECK-NEXT: ret void 190; 191entry: 192 %p3 = bitcast i32* %p to i8* 193 call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 %p3, i8 0, i64 32, i32 4) 194 store atomic i32 1, i32* %p unordered, align 4 195 ret void 196} 197 198define void @dontwrite0to1(i32* nocapture %p) { 199; CHECK-LABEL: @dontwrite0to1( 200; CHECK-NEXT: entry: 201; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8* 202; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 32, i1 false) 203; CHECK-NEXT: [[P4:%.*]] = bitcast i32* [[P]] to i16* 204; CHECK-NEXT: store i16 1, i16* [[P4]], align 4 205; CHECK-NEXT: ret void 206; 207entry: 208 %p3 = bitcast i32* %p to i8* 209 call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i1 false) 210 %p4 = bitcast i32* %p to i16* 211 store i16 1, i16* %p4, align 4 212 ret void 213} 214 215define void @dontwrite0to1_atomic(i32* nocapture %p) { 216; CHECK-LABEL: @dontwrite0to1_atomic( 217; CHECK-NEXT: entry: 218; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8* 219; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 32, i32 4) 220; CHECK-NEXT: [[P4:%.*]] = bitcast i32* [[P]] to i16* 221; CHECK-NEXT: store atomic i16 1, i16* [[P4]] unordered, align 4 222; CHECK-NEXT: ret void 223; 224entry: 225 %p3 = bitcast i32* %p to i8* 226 call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i32 4) 227 %p4 = bitcast i32* %p to i16* 228 store atomic i16 1, i16* %p4 unordered, align 4 229 ret void 230} 231 232define void @dontwrite2to9(i32* nocapture %p) { 233; CHECK-LABEL: @dontwrite2to9( 234; CHECK-NEXT: entry: 235; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1 236; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8* 237; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 32, i1 false) 238; CHECK-NEXT: [[P4:%.*]] = bitcast i32* [[P]] to i16* 239; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i16, i16* [[P4]], i64 1 240; CHECK-NEXT: [[P5:%.*]] = bitcast i16* [[ARRAYIDX2]] to i64* 241; CHECK-NEXT: store i64 1, i64* [[P5]], align 8 242; CHECK-NEXT: ret void 243; 244entry: 245 %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1 246 %p3 = bitcast i32* %arrayidx0 to i8* 247 call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i1 false) 248 %p4 = bitcast i32* %p to i16* 249 %arrayidx2 = getelementptr inbounds i16, i16* %p4, i64 1 250 %p5 = bitcast i16* %arrayidx2 to i64* 251 store i64 1, i64* %p5, align 8 252 ret void 253} 254 255define void @dontwrite2to9_atomic(i32* nocapture %p) { 256; CHECK-LABEL: @dontwrite2to9_atomic( 257; CHECK-NEXT: entry: 258; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1 259; CHECK-NEXT: [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8* 260; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 32, i32 4) 261; CHECK-NEXT: [[P4:%.*]] = bitcast i32* [[P]] to i16* 262; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i16, i16* [[P4]], i64 1 263; CHECK-NEXT: [[P5:%.*]] = bitcast i16* [[ARRAYIDX2]] to i64* 264; CHECK-NEXT: store atomic i64 1, i64* [[P5]] unordered, align 8 265; CHECK-NEXT: ret void 266; 267entry: 268 %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1 269 %p3 = bitcast i32* %arrayidx0 to i8* 270 call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i32 4) 271 %p4 = bitcast i32* %p to i16* 272 %arrayidx2 = getelementptr inbounds i16, i16* %p4, i64 1 273 %p5 = bitcast i16* %arrayidx2 to i64* 274 store atomic i64 1, i64* %p5 unordered, align 8 275 ret void 276} 277 278define void @write8To15AndThen0To7(i64* nocapture %P) { 279; CHECK-LABEL: @write8To15AndThen0To7( 280; CHECK-NEXT: entry: 281; CHECK-NEXT: [[BASE0:%.*]] = bitcast i64* [[P:%.*]] to i8* 282; CHECK-NEXT: [[MYBASE0:%.*]] = getelementptr inbounds i8, i8* [[BASE0]], i64 0 283; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[MYBASE0]], i64 16 284; CHECK-NEXT: tail call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP0]], i8 0, i64 16, i1 false) 285; CHECK-NEXT: [[BASE64_0:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 0 286; CHECK-NEXT: [[BASE64_1:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 1 287; CHECK-NEXT: store i64 1, i64* [[BASE64_1]] 288; CHECK-NEXT: store i64 2, i64* [[BASE64_0]] 289; CHECK-NEXT: ret void 290; 291entry: 292 293 %base0 = bitcast i64* %P to i8* 294 %mybase0 = getelementptr inbounds i8, i8* %base0, i64 0 295 tail call void @llvm.memset.p0i8.i64(i8* align 8 %mybase0, i8 0, i64 32, i1 false) 296 297 %base64_0 = getelementptr inbounds i64, i64* %P, i64 0 298 %base64_1 = getelementptr inbounds i64, i64* %P, i64 1 299 300 store i64 1, i64* %base64_1 301 store i64 2, i64* %base64_0 302 ret void 303} 304 305define void @write8To15AndThen0To7_atomic(i64* nocapture %P) { 306; CHECK-LABEL: @write8To15AndThen0To7_atomic( 307; CHECK-NEXT: entry: 308; CHECK-NEXT: [[BASE0:%.*]] = bitcast i64* [[P:%.*]] to i8* 309; CHECK-NEXT: [[MYBASE0:%.*]] = getelementptr inbounds i8, i8* [[BASE0]], i64 0 310; CHECK-NEXT: tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 [[MYBASE0]], i8 0, i64 32, i32 8) 311; CHECK-NEXT: [[BASE64_0:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 0 312; CHECK-NEXT: [[BASE64_1:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 1 313; CHECK-NEXT: store atomic i64 1, i64* [[BASE64_1]] unordered, align 8 314; CHECK-NEXT: store atomic i64 2, i64* [[BASE64_0]] unordered, align 8 315; CHECK-NEXT: ret void 316; 317entry: 318 319 %base0 = bitcast i64* %P to i8* 320 %mybase0 = getelementptr inbounds i8, i8* %base0, i64 0 321 tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 %mybase0, i8 0, i64 32, i32 8) 322 323 %base64_0 = getelementptr inbounds i64, i64* %P, i64 0 324 %base64_1 = getelementptr inbounds i64, i64* %P, i64 1 325 326 store atomic i64 1, i64* %base64_1 unordered, align 8 327 store atomic i64 2, i64* %base64_0 unordered, align 8 328 ret void 329} 330 331define void @write8To15AndThen0To7_atomic_weaker(i64* nocapture %P) { 332; CHECK-LABEL: @write8To15AndThen0To7_atomic_weaker( 333; CHECK-NEXT: entry: 334; CHECK-NEXT: [[BASE0:%.*]] = bitcast i64* [[P:%.*]] to i8* 335; CHECK-NEXT: [[MYBASE0:%.*]] = getelementptr inbounds i8, i8* [[BASE0]], i64 0 336; CHECK-NEXT: tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 [[MYBASE0]], i8 0, i64 32, i32 8) 337; CHECK-NEXT: [[BASE64_0:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 0 338; CHECK-NEXT: [[BASE64_1:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 1 339; CHECK-NEXT: store atomic i64 1, i64* [[BASE64_1]] unordered, align 8 340; CHECK-NEXT: store i64 2, i64* [[BASE64_0]], align 8 341; CHECK-NEXT: ret void 342; 343entry: 344 345 %base0 = bitcast i64* %P to i8* 346 %mybase0 = getelementptr inbounds i8, i8* %base0, i64 0 347 tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 %mybase0, i8 0, i64 32, i32 8) 348 349 %base64_0 = getelementptr inbounds i64, i64* %P, i64 0 350 %base64_1 = getelementptr inbounds i64, i64* %P, i64 1 351 352 store atomic i64 1, i64* %base64_1 unordered, align 8 353 store i64 2, i64* %base64_0, align 8 354 ret void 355} 356 357define void @write8To15AndThen0To7_atomic_weaker_2(i64* nocapture %P) { 358; CHECK-LABEL: @write8To15AndThen0To7_atomic_weaker_2( 359; CHECK-NEXT: entry: 360; CHECK-NEXT: [[BASE0:%.*]] = bitcast i64* [[P:%.*]] to i8* 361; CHECK-NEXT: [[MYBASE0:%.*]] = getelementptr inbounds i8, i8* [[BASE0]], i64 0 362; CHECK-NEXT: tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 [[MYBASE0]], i8 0, i64 32, i32 8) 363; CHECK-NEXT: [[BASE64_0:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 0 364; CHECK-NEXT: [[BASE64_1:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 1 365; CHECK-NEXT: store i64 1, i64* [[BASE64_1]], align 8 366; CHECK-NEXT: store atomic i64 2, i64* [[BASE64_0]] unordered, align 8 367; CHECK-NEXT: ret void 368; 369entry: 370 371 %base0 = bitcast i64* %P to i8* 372 %mybase0 = getelementptr inbounds i8, i8* %base0, i64 0 373 tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 %mybase0, i8 0, i64 32, i32 8) 374 375 %base64_0 = getelementptr inbounds i64, i64* %P, i64 0 376 %base64_1 = getelementptr inbounds i64, i64* %P, i64 1 377 378 store i64 1, i64* %base64_1, align 8 379 store atomic i64 2, i64* %base64_0 unordered, align 8 380 ret void 381} 382 383declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind 384declare void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* nocapture, i8, i64, i32) nounwind 385 386