llvm.org GIT mirror llvm / 4aabf12
Revert r310055, it caused PR34074. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310123 91177308-0d34-0410-b5e6-96231b3b80d8 Nico Weber 2 years ago
5 changed file(s) with 5 addition(s) and 480 deletion(s). Raw diff Collapse all Expand all
3333 #include "llvm/IR/GlobalVariable.h"
3434 #include "llvm/IR/Instructions.h"
3535 #include "llvm/IR/IntrinsicInst.h"
36 #include "llvm/IR/LLVMContext.h"
3736 #include "llvm/Pass.h"
3837 #include "llvm/Support/CommandLine.h"
3938 #include "llvm/Support/Debug.h"
4948 STATISTIC(NumFastStores, "Number of stores deleted");
5049 STATISTIC(NumFastOther , "Number of other instrs removed");
5150 STATISTIC(NumCompletePartials, "Number of stores dead by later partials");
52 STATISTIC(NumModifiedStores, "Number of stores modified");
5351
5452 static cl::opt
5553 EnablePartialOverwriteTracking("enable-dse-partial-overwrite-tracking",
5654 cl::init(true), cl::Hidden,
5755 cl::desc("Enable partial-overwrite tracking in DSE"));
58
59 static cl::opt
60 EnablePartialStoreMerging("enable-dse-partial-store-merging",
61 cl::init(true), cl::Hidden,
62 cl::desc("Enable partial store merging in DSE"));
6356
6457
6558 //===----------------------------------------------------------------------===//
293286 }
294287
295288 namespace {
296 enum OverwriteResult {
297 OW_Begin,
298 OW_Complete,
299 OW_End,
300 OW_PartialEarlierWithFullLater,
301 OW_Unknown
302 };
289 enum OverwriteResult { OW_Begin, OW_Complete, OW_End, OW_Unknown };
303290 }
304291
305292 /// Return 'OW_Complete' if a store to the 'Later' location completely
306293 /// overwrites a store to the 'Earlier' location, 'OW_End' if the end of the
307294 /// 'Earlier' location is completely overwritten by 'Later', 'OW_Begin' if the
308 /// beginning of the 'Earlier' location is overwritten by 'Later'.
309 /// 'OW_PartialEarlierWithFullLater' means that an earlier (big) store was
310 /// overwritten by a latter (smaller) store which doesn't write outside the big
311 /// store's memory locations. Returns 'OW_Unknown' if nothing can be determined.
295 /// beginning of the 'Earlier' location is overwritten by 'Later', or
296 /// 'OW_Unknown' if nothing can be determined.
312297 static OverwriteResult isOverwrite(const MemoryLocation &Later,
313298 const MemoryLocation &Earlier,
314299 const DataLayout &DL,
439424 ++NumCompletePartials;
440425 return OW_Complete;
441426 }
442 }
443
444 // Check for an earlier store which writes to all the memory locations that
445 // the later store writes to.
446 if (EnablePartialStoreMerging && LaterOff >= EarlierOff &&
447 int64_t(EarlierOff + Earlier.Size) > LaterOff &&
448 uint64_t(LaterOff - EarlierOff) + Later.Size <= Earlier.Size) {
449 DEBUG(dbgs() << "DSE: Partial overwrite an earlier load [" << EarlierOff
450 << ", " << int64_t(EarlierOff + Earlier.Size)
451 << ") by a later store [" << LaterOff << ", "
452 << int64_t(LaterOff + Later.Size) << ")\n");
453 // TODO: Maybe come up with a better name?
454 return OW_PartialEarlierWithFullLater;
455427 }
456428
457429 // Another interesting case is if the later store overwrites the end of the
11211093 // If we find a write that is a) removable (i.e., non-volatile), b) is
11221094 // completely obliterated by the store to 'Loc', and c) which we know that
11231095 // 'Inst' doesn't load from, then we can remove it.
1124 // Also try to merge two stores if a latter one only touches memory
1125 // written to by the earlier one.
11261096 if (isRemovable(DepWrite) &&
11271097 !isPossibleSelfRead(Inst, Loc, DepWrite, *TLI, *AA)) {
11281098 int64_t InstWriteOffset, DepWriteOffset;
11521122 bool IsOverwriteEnd = (OR == OW_End);
11531123 MadeChange |= tryToShorten(DepWrite, DepWriteOffset, EarlierSize,
11541124 InstWriteOffset, LaterSize, IsOverwriteEnd);
1155 } else if (EnablePartialStoreMerging &&
1156 OR == OW_PartialEarlierWithFullLater) {
1157 auto *Earlier = dyn_cast(DepWrite);
1158 auto *Later = dyn_cast(Inst);
1159 if (Earlier && isa(Earlier->getValueOperand()) &&
1160 Later && isa(Later->getValueOperand())) {
1161 // If the store we find is:
1162 // a) partially overwritten by the store to 'Loc'
1163 // b) the latter store is fully contained in the earlier one and
1164 // c) They both have a contant value
1165 // Merge the two stores, replacing the earlier store's value with a
1166 // merge of both values.
1167 // TODO: Deal with other constant types (vectors, etc), and probably
1168 // some mem intrinsics (if needed)
1169
1170 APInt EarlierValue =
1171 cast(Earlier->getValueOperand())->getValue();
1172 APInt LaterValue =
1173 cast(Later->getValueOperand())->getValue();
1174 unsigned LaterBits = LaterValue.getBitWidth();
1175 assert(EarlierValue.getBitWidth() > LaterValue.getBitWidth());
1176 LaterValue = LaterValue.zext(EarlierValue.getBitWidth());
1177
1178 // Offset of the smaller store inside the larger store
1179 unsigned BitOffsetDiff = (InstWriteOffset - DepWriteOffset) * 8;
1180 unsigned LShiftAmount =
1181 DL.isBigEndian()
1182 ? EarlierValue.getBitWidth() - BitOffsetDiff - LaterBits
1183 : BitOffsetDiff;
1184 APInt Mask =
1185 APInt::getBitsSet(EarlierValue.getBitWidth(), LShiftAmount,
1186 LShiftAmount + LaterBits);
1187 // Clear the bits we'll be replacing, then OR with the smaller
1188 // store, shifted appropriately.
1189 APInt Merged =
1190 (EarlierValue & ~Mask) | (LaterValue << LShiftAmount);
1191 DEBUG(dbgs() << "DSE: Merge Stores:\n Earlier: " << *DepWrite
1192 << "\n Later: " << *Inst
1193 << "\n Merged Value: " << Merged << '\n');
1194
1195 auto *SI = new StoreInst(
1196 ConstantInt::get(Earlier->getValueOperand()->getType(), Merged),
1197 Earlier->getPointerOperand(), false, Earlier->getAlignment(),
1198 Earlier->getOrdering(), Earlier->getSyncScopeID(), DepWrite);
1199
1200 unsigned MDToKeep[] = {LLVMContext::MD_dbg, LLVMContext::MD_tbaa,
1201 LLVMContext::MD_alias_scope,
1202 LLVMContext::MD_noalias,
1203 LLVMContext::MD_nontemporal};
1204 SI->copyMetadata(*DepWrite, MDToKeep);
1205 ++NumModifiedStores;
1206
1207 // Remove earlier, wider, store
1208 size_t Idx = InstrOrdering.lookup(DepWrite);
1209 InstrOrdering.erase(DepWrite);
1210 InstrOrdering.insert(std::make_pair(SI, Idx));
1211
1212 // Delete the old stores and now-dead instructions that feed them.
1213 deleteDeadInstruction(Inst, &BBI, *MD, *TLI, IOL, &InstrOrdering);
1214 deleteDeadInstruction(DepWrite, &BBI, *MD, *TLI, IOL,
1215 &InstrOrdering);
1216 MadeChange = true;
1217
1218 //// We erased DepWrite; start over.
1219 InstDep = MD->getDependency(SI);
1220 continue;
1221 }
12221125 }
12231126 }
12241127
None ; RUN: opt < %s -basicaa -dse -enable-dse-partial-store-merging=false -S | FileCheck %s
0 ; RUN: opt < %s -basicaa -dse -S | FileCheck %s
11 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"
22
33 ; Ensure that the dead store is deleted in this case. It is wholely
None ; RUN: opt -S -dse -enable-dse-partial-store-merging=false < %s | FileCheck %s
0 ; RUN: opt -S -dse < %s | FileCheck %s
11 target datalayout = "E-m:e-i64:64-n32:64"
22 target triple = "powerpc64-bgq-linux"
33
+0
-173
test/Transforms/DeadStoreElimination/merge-stores-big-endian.ll less more
None ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -dse -enable-dse-partial-store-merging -S < %s | FileCheck %s
2 target datalayout = "E-m:e-i64:64-i128:128-n32:64-S128"
3
4 define void @byte_by_byte_replacement(i32 *%ptr) {
5 ; CHECK-LABEL: @byte_by_byte_replacement(
6 ; CHECK-NEXT: entry:
7 ; CHECK-NEXT: store i32 151653132, i32* [[PTR:%.*]]
8 ; CHECK-NEXT: ret void
9 ;
10 entry:
11 ;; This store's value should be modified as it should be better to use one
12 ;; larger store than several smaller ones.
13 ;; store will turn into 0x090A0B0C == 151653132
14 store i32 305419896, i32* %ptr ; 0x12345678
15 %bptr = bitcast i32* %ptr to i8*
16 %bptr1 = getelementptr inbounds i8, i8* %bptr, i64 1
17 %bptr2 = getelementptr inbounds i8, i8* %bptr, i64 2
18 %bptr3 = getelementptr inbounds i8, i8* %bptr, i64 3
19
20 ;; We should be able to merge these four stores with the i32 above
21 ; value (and bytes) stored before ; 0x12345678
22 store i8 9, i8* %bptr ; 09
23 store i8 10, i8* %bptr1 ; 0A
24 store i8 11, i8* %bptr2 ; 0B
25 store i8 12, i8* %bptr3 ; 0C
26 ; 0x090A0B0C
27
28 ret void
29 }
30
31 define void @word_replacement(i64 *%ptr) {
32 ; CHECK-LABEL: @word_replacement(
33 ; CHECK-NEXT: entry:
34 ; CHECK-NEXT: store i64 72638273700655232, i64* [[PTR:%.*]]
35 ; CHECK-NEXT: ret void
36 ;
37 entry:
38 store i64 72623859790382856, i64* %ptr ; 0x0102030405060708
39
40 %wptr = bitcast i64* %ptr to i16*
41 %wptr1 = getelementptr inbounds i16, i16* %wptr, i64 1
42 %wptr2 = getelementptr inbounds i16, i16* %wptr, i64 2
43 %wptr3 = getelementptr inbounds i16, i16* %wptr, i64 3
44
45 ;; We should be able to merge these two stores with the i64 one above
46 ; value (and bytes) stored before ; 0x0102030405060708
47 store i16 4128, i16* %wptr1 ; 1020
48 store i16 28800, i16* %wptr3 ; 7080
49 ; 0x0102102005067080
50
51 ret void
52 }
53
54
55 define void @differently_sized_replacements(i64 *%ptr) {
56 ; CHECK-LABEL: @differently_sized_replacements(
57 ; CHECK-NEXT: entry:
58 ; CHECK-NEXT: store i64 289077004501059343, i64* [[PTR:%.*]]
59 ; CHECK-NEXT: ret void
60 ;
61 entry:
62 store i64 579005069656919567, i64* %ptr ; 0x08090a0b0c0d0e0f
63
64 %bptr = bitcast i64* %ptr to i8*
65 %bptr6 = getelementptr inbounds i8, i8* %bptr, i64 6
66 %wptr = bitcast i64* %ptr to i16*
67 %wptr2 = getelementptr inbounds i16, i16* %wptr, i64 2
68 %dptr = bitcast i64* %ptr to i32*
69
70 ;; We should be able to merge all these stores with the i64 one above
71 ; value (and bytes) stored before ; 0x08090a0b0c0d0e0f
72 store i8 7, i8* %bptr6 ; 07
73 store i16 1541, i16* %wptr2 ; 0605
74 store i32 67305985, i32* %dptr ; 04030201
75 ; 0x040302010605070f
76 ret void
77 }
78
79
80 define void @multiple_replacements_to_same_byte(i64 *%ptr) {
81 ; CHECK-LABEL: @multiple_replacements_to_same_byte(
82 ; CHECK-NEXT: entry:
83 ; CHECK-NEXT: store i64 289077004602248719, i64* [[PTR:%.*]]
84 ; CHECK-NEXT: ret void
85 ;
86 entry:
87 store i64 579005069656919567, i64* %ptr ; 0x08090a0b0c0d0e0f
88
89 %bptr = bitcast i64* %ptr to i8*
90 %bptr3 = getelementptr inbounds i8, i8* %bptr, i64 3
91 %wptr = bitcast i64* %ptr to i16*
92 %wptr1 = getelementptr inbounds i16, i16* %wptr, i64 1
93 %dptr = bitcast i64* %ptr to i32*
94
95 ;; We should be able to merge all these stores with the i64 one above
96 ; value (and bytes) stored before ; 0x08090a0b0c0d0e0f
97 store i8 7, i8* %bptr3 ; 07
98 store i16 1541, i16* %wptr1 ; 0605
99 store i32 67305985, i32* %dptr ; 04030201
100 ; 0x040302010c0d0e0f
101 ret void
102 }
103
104 define void @merged_merges(i64 *%ptr) {
105 ; CHECK-LABEL: @merged_merges(
106 ; CHECK-NEXT: entry:
107 ; CHECK-NEXT: store i64 289081428418563599, i64* [[PTR:%.*]]
108 ; CHECK-NEXT: ret void
109 ;
110 entry:
111 store i64 579005069656919567, i64* %ptr ; 0x08090a0b0c0d0e0f
112
113 %bptr = bitcast i64* %ptr to i8*
114 %bptr3 = getelementptr inbounds i8, i8* %bptr, i64 3
115 %wptr = bitcast i64* %ptr to i16*
116 %wptr1 = getelementptr inbounds i16, i16* %wptr, i64 1
117 %dptr = bitcast i64* %ptr to i32*
118
119 ;; We should be able to merge all these stores with the i64 one above
120 ; value (not bytes) stored before ; 0x08090a0b0c0d0e0f
121 store i32 67305985, i32* %dptr ; 04030201
122 store i16 1541, i16* %wptr1 ; 0605
123 store i8 7, i8* %bptr3 ; 07
124 ; 0x040306070c0d0e0f
125 ret void
126 }
127
128 define signext i8 @shouldnt_merge_since_theres_a_full_overlap(i64 *%ptr) {
129 ; CHECK-LABEL: @shouldnt_merge_since_theres_a_full_overlap(
130 ; CHECK-NEXT: entry:
131 ; CHECK-NEXT: [[BPTR:%.*]] = bitcast i64* [[PTR:%.*]] to i8*
132 ; CHECK-NEXT: [[BPTRM1:%.*]] = getelementptr inbounds i8, i8* [[BPTR]], i64 -1
133 ; CHECK-NEXT: [[BPTR3:%.*]] = getelementptr inbounds i8, i8* [[BPTR]], i64 3
134 ; CHECK-NEXT: [[DPTR:%.*]] = bitcast i8* [[BPTRM1]] to i32*
135 ; CHECK-NEXT: [[QPTR:%.*]] = bitcast i8* [[BPTR3]] to i64*
136 ; CHECK-NEXT: store i32 1234, i32* [[DPTR]], align 1
137 ; CHECK-NEXT: store i64 5678, i64* [[QPTR]], align 1
138 ; CHECK-NEXT: ret i8 0
139 ;
140 entry:
141
142 store i64 0, i64* %ptr
143
144 %bptr = bitcast i64* %ptr to i8*
145 %bptrm1 = getelementptr inbounds i8, i8* %bptr, i64 -1
146 %bptr3 = getelementptr inbounds i8, i8* %bptr, i64 3
147 %dptr = bitcast i8* %bptrm1 to i32*
148 %qptr = bitcast i8* %bptr3 to i64*
149
150 store i32 1234, i32* %dptr, align 1
151 store i64 5678, i64* %qptr, align 1
152
153 ret i8 0
154 }
155
156 ;; Test case from PR31777
157 %union.U = type { i64 }
158
159 define void @foo(%union.U* nocapture %u) {
160 ; CHECK-LABEL: @foo(
161 ; CHECK-NEXT: entry:
162 ; CHECK-NEXT: [[I:%.*]] = getelementptr inbounds [[UNION_U:%.*]], %union.U* [[U:%.*]], i64 0, i32 0
163 ; CHECK-NEXT: store i64 11821949021847552, i64* [[I]], align 8
164 ; CHECK-NEXT: ret void
165 ;
166 entry:
167 %i = getelementptr inbounds %union.U, %union.U* %u, i64 0, i32 0
168 store i64 0, i64* %i, align 8
169 %s = bitcast %union.U* %u to i16*
170 store i16 42, i16* %s, align 8
171 ret void
172 }
+0
-205
test/Transforms/DeadStoreElimination/merge-stores.ll less more
None ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -dse -enable-dse-partial-store-merging -S < %s | FileCheck %s
2 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-f128:128:128-n8:16:32:64"
3
4 define void @byte_by_byte_replacement(i32 *%ptr) {
5 ; CHECK-LABEL: @byte_by_byte_replacement(
6 ; CHECK-NEXT: entry:
7 ; CHECK-NEXT: store i32 202050057, i32* [[PTR:%.*]]
8 ; CHECK-NEXT: ret void
9 ;
10 entry:
11 ;; This store's value should be modified as it should be better to use one
12 ;; larger store than several smaller ones.
13 ;; store will turn into 0x0C0B0A09 == 202050057
14 store i32 305419896, i32* %ptr ; 0x12345678
15 %bptr = bitcast i32* %ptr to i8*
16 %bptr1 = getelementptr inbounds i8, i8* %bptr, i64 1
17 %bptr2 = getelementptr inbounds i8, i8* %bptr, i64 2
18 %bptr3 = getelementptr inbounds i8, i8* %bptr, i64 3
19
20 ;; We should be able to merge these four stores with the i32 above
21 ; value (and bytes) stored before ; 0x12345678
22 store i8 9, i8* %bptr ; 09
23 store i8 10, i8* %bptr1 ; 0A
24 store i8 11, i8* %bptr2 ; 0B
25 store i8 12, i8* %bptr3 ; 0C
26 ; 0x0C0B0A09
27 ret void
28 }
29
30 define void @word_replacement(i64 *%ptr) {
31 ; CHECK-LABEL: @word_replacement(
32 ; CHECK-NEXT: entry:
33 ; CHECK-NEXT: store i64 8106482645252179720, i64* [[PTR:%.*]]
34 ; CHECK-NEXT: ret void
35 ;
36 entry:
37 store i64 72623859790382856, i64* %ptr ; 0x0102030405060708
38
39 %wptr = bitcast i64* %ptr to i16*
40 %wptr1 = getelementptr inbounds i16, i16* %wptr, i64 1
41 %wptr2 = getelementptr inbounds i16, i16* %wptr, i64 2
42 %wptr3 = getelementptr inbounds i16, i16* %wptr, i64 3
43
44 ;; We should be able to merge these two stores with the i64 one above
45 ; value (not bytes) stored before ; 0x0102030405060708
46 store i16 4128, i16* %wptr1 ; 1020
47 store i16 28800, i16* %wptr3 ; 7080
48 ; 0x7080030410200708
49 ret void
50 }
51
52
53 define void @differently_sized_replacements(i64 *%ptr) {
54 ; CHECK-LABEL: @differently_sized_replacements(
55 ; CHECK-NEXT: entry:
56 ; CHECK-NEXT: store i64 578437695752307201, i64* [[PTR:%.*]]
57 ; CHECK-NEXT: ret void
58 ;
59 entry:
60 store i64 579005069656919567, i64* %ptr ; 0x08090a0b0c0d0e0f
61
62 %bptr = bitcast i64* %ptr to i8*
63 %bptr6 = getelementptr inbounds i8, i8* %bptr, i64 6
64 %wptr = bitcast i64* %ptr to i16*
65 %wptr2 = getelementptr inbounds i16, i16* %wptr, i64 2
66 %dptr = bitcast i64* %ptr to i32*
67
68 ;; We should be able to merge all these stores with the i64 one above
69 ; value (not bytes) stored before ; 0x08090a0b0c0d0e0f
70 store i8 7, i8* %bptr6 ; 07
71 store i16 1541, i16* %wptr2 ; 0605
72 store i32 67305985, i32* %dptr ; 04030201
73 ; 0x0807060504030201
74 ret void
75 }
76
77
78 define void @multiple_replacements_to_same_byte(i64 *%ptr) {
79 ; CHECK-LABEL: @multiple_replacements_to_same_byte(
80 ; CHECK-NEXT: entry:
81 ; CHECK-NEXT: store i64 579005069522043393, i64* [[PTR:%.*]]
82 ; CHECK-NEXT: ret void
83 ;
84 entry:
85 store i64 579005069656919567, i64* %ptr ; 0x08090a0b0c0d0e0f
86
87 %bptr = bitcast i64* %ptr to i8*
88 %bptr3 = getelementptr inbounds i8, i8* %bptr, i64 3
89 %wptr = bitcast i64* %ptr to i16*
90 %wptr1 = getelementptr inbounds i16, i16* %wptr, i64 1
91 %dptr = bitcast i64* %ptr to i32*
92
93 ;; We should be able to merge all these stores with the i64 one above
94 ; value (not bytes) stored before ; 0x08090a0b0c0d0e0f
95 store i8 7, i8* %bptr3 ; 07
96 store i16 1541, i16* %wptr1 ; 0605
97 store i32 67305985, i32* %dptr ; 04030201
98 ; 0x08090a0b04030201
99 ret void
100 }
101
102 define void @merged_merges(i64 *%ptr) {
103 ; CHECK-LABEL: @merged_merges(
104 ; CHECK-NEXT: entry:
105 ; CHECK-NEXT: store i64 579005069572506113, i64* [[PTR:%.*]]
106 ; CHECK-NEXT: ret void
107 ;
108 entry:
109 store i64 579005069656919567, i64* %ptr ; 0x08090a0b0c0d0e0f
110
111 %bptr = bitcast i64* %ptr to i8*
112 %bptr3 = getelementptr inbounds i8, i8* %bptr, i64 3
113 %wptr = bitcast i64* %ptr to i16*
114 %wptr1 = getelementptr inbounds i16, i16* %wptr, i64 1
115 %dptr = bitcast i64* %ptr to i32*
116
117 ;; We should be able to merge all these stores with the i64 one above
118 ; value (not bytes) stored before ; 0x08090a0b0c0d0e0f
119 store i32 67305985, i32* %dptr ; 04030201
120 store i16 1541, i16* %wptr1 ; 0605
121 store i8 7, i8* %bptr3 ; 07
122 ; 0x08090a0b07050201
123 ret void
124 }
125
126 define signext i8 @shouldnt_merge_since_theres_a_full_overlap(i64 *%ptr) {
127 ; CHECK-LABEL: @shouldnt_merge_since_theres_a_full_overlap(
128 ; CHECK-NEXT: entry:
129 ; CHECK-NEXT: [[BPTR:%.*]] = bitcast i64* [[PTR:%.*]] to i8*
130 ; CHECK-NEXT: [[BPTRM1:%.*]] = getelementptr inbounds i8, i8* [[BPTR]], i64 -1
131 ; CHECK-NEXT: [[BPTR3:%.*]] = getelementptr inbounds i8, i8* [[BPTR]], i64 3
132 ; CHECK-NEXT: [[DPTR:%.*]] = bitcast i8* [[BPTRM1]] to i32*
133 ; CHECK-NEXT: [[QPTR:%.*]] = bitcast i8* [[BPTR3]] to i64*
134 ; CHECK-NEXT: store i32 1234, i32* [[DPTR]], align 1
135 ; CHECK-NEXT: store i64 5678, i64* [[QPTR]], align 1
136 ; CHECK-NEXT: ret i8 0
137 ;
138 entry:
139
140 ; Also check that alias.scope metadata doesn't get dropped
141 store i64 0, i64* %ptr, !alias.scope !32
142
143 %bptr = bitcast i64* %ptr to i8*
144 %bptrm1 = getelementptr inbounds i8, i8* %bptr, i64 -1
145 %bptr3 = getelementptr inbounds i8, i8* %bptr, i64 3
146 %dptr = bitcast i8* %bptrm1 to i32*
147 %qptr = bitcast i8* %bptr3 to i64*
148
149 store i32 1234, i32* %dptr, align 1
150 store i64 5678, i64* %qptr, align 1
151
152 ret i8 0
153 }
154
155 ;; Test case from PR31777
156 %union.U = type { i64 }
157
158 define void @foo(%union.U* nocapture %u) {
159 ; CHECK-LABEL: @foo(
160 ; CHECK-NEXT: entry:
161 ; CHECK-NEXT: [[I:%.*]] = getelementptr inbounds [[UNION_U:%.*]], %union.U* [[U:%.*]], i64 0, i32 0
162 ; CHECK-NEXT: store i64 42, i64* [[I]], align 8
163 ; CHECK-NEXT: ret void
164 ;
165 entry:
166 %i = getelementptr inbounds %union.U, %union.U* %u, i64 0, i32 0
167 store i64 0, i64* %i, align 8, !dbg !22, !tbaa !26, !noalias !30, !nontemporal !29
168 %s = bitcast %union.U* %u to i16*
169 store i16 42, i16* %s, align 8
170 ret void
171 }
172
173 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 5.0.0 (trunk 306512)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
174 !1 = !DIFile(filename: "me.cpp", directory: "/compiler-explorer")
175 !2 = !{}
176 !7 = distinct !DISubprogram(name: "foo", linkageName: "foo(U*)", scope: !1, file: !1, line: 9, type: !8, isLocal: false, isDefinition: true, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !20)
177 !8 = !DISubroutineType(types: !9)
178 !9 = !{null, !10}
179 !10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64)
180 !11 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "U", file: !1, line: 4, size: 64, elements: !12, identifier: "typeinfo name for U")
181 !12 = !{!13, !17}
182 !13 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !11, file: !1, line: 5, baseType: !14, size: 64)
183 !14 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint64_t", file: !15, line: 55, baseType: !16)
184 !15 = !DIFile(filename: "/usr/include/stdint.h", directory: "/compiler-explorer")
185 !16 = !DIBasicType(name: "long unsigned int", size: 64, encoding: DW_ATE_unsigned)
186 !17 = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: !11, file: !1, line: 6, baseType: !18, size: 16)
187 !18 = !DIDerivedType(tag: DW_TAG_typedef, name: "uint16_t", file: !15, line: 49, baseType: !19)
188 !19 = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned)
189 !20 = !{!21}
190 !21 = !DILocalVariable(name: "u", arg: 1, scope: !7, file: !1, line: 9, type: !10)
191 !22 = !DILocation(line: 10, column: 8, scope: !7)
192
193 !26 = !{!27, !27, i64 0}
194 !27 = !{!"omnipotent char", !28, i64 0}
195 !28 = !{!"Simple C++ TBAA"}
196
197 !29 = !{i32 1}
198
199 ; Domains and scopes which might alias
200 !30 = !{!30}
201 !31 = !{!31, !30}
202
203 !32 = !{!32}
204 !33 = !{!33, !32}