• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt -S -codegenprepare %s -o - | FileCheck %s
2; RUN: opt -S -codegenprepare -addr-sink-using-gep=1 %s -o - | FileCheck -check-prefix=CHECK-GEP %s
3; This file tests the different cases what are involved when codegen prepare
4; tries to get sign/zero extension out of the way of addressing mode.
5; This tests require an actual target as addressing mode decisions depends
6; on the target.
7
8target datalayout = "e-i64:64-f80:128-s:64-n8:16:32:64-S128"
9target triple = "x86_64-apple-macosx"
10
11
12; Check that we correctly promote both operands of the promotable add.
13; CHECK-LABEL: @twoArgsPromotion
14; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg1 to i64
15; CHECK: [[ARG2SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg2 to i64
16; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], [[ARG2SEXT]]
17; CHECK: inttoptr i64 [[PROMOTED]] to i8*
18; CHECK: ret
19define i8 @twoArgsPromotion(i32 %arg1, i32 %arg2) {
20  %add = add nsw i32 %arg1, %arg2
21  %sextadd = sext i32 %add to i64
22  %base = inttoptr i64 %sextadd to i8*
23  %res = load i8, i8* %base
24  ret i8 %res
25}
26
27; Check that we do not promote both operands of the promotable add when
28; the instruction will not be folded into the addressing mode.
29; Otherwise, we will increase the number of instruction executed.
30; (This is a heuristic of course, because the new sext could have been
31; merged with something else.)
32; CHECK-LABEL: @twoArgsNoPromotion
33; CHECK: add nsw i32 %arg1, %arg2
34; CHECK: ret
35define i8 @twoArgsNoPromotion(i32 %arg1, i32 %arg2, i8* %base) {
36  %add = add nsw i32 %arg1, %arg2
37  %sextadd = sext i32 %add to i64
38  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
39  %res = load i8, i8* %arrayidx
40  ret i8 %res
41}
42
43; Check that we do not promote when the related instruction does not have
44; the nsw flag.
45; CHECK-LABEL: @noPromotion
46; CHECK-NOT: add i64
47; CHECK: ret
48define i8 @noPromotion(i32 %arg1, i32 %arg2, i8* %base) {
49  %add = add i32 %arg1, %arg2
50  %sextadd = sext i32 %add to i64
51  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
52  %res = load i8, i8* %arrayidx
53  ret i8 %res
54}
55
56; Check that we correctly promote constant arguments.
57; CHECK-LABEL: @oneArgPromotion
58; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i32 %arg1 to i64
59; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
60; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
61; CHECK: ret
62define i8 @oneArgPromotion(i32 %arg1, i8* %base) {
63  %add = add nsw i32 %arg1, 1
64  %sextadd = sext i32 %add to i64
65  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
66  %res = load i8, i8* %arrayidx
67  ret i8 %res
68}
69
70; Check that we are able to merge a sign extension with a zero extension.
71; CHECK-LABEL: @oneArgPromotionZExt
72; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64
73; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1ZEXT]], 1
74; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
75; CHECK: ret
76define i8 @oneArgPromotionZExt(i8 %arg1, i8* %base) {
77  %zext = zext i8 %arg1 to i32
78  %add = add nsw i32 %zext, 1
79  %sextadd = sext i32 %add to i64
80  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
81  %res = load i8, i8* %arrayidx
82  ret i8 %res
83}
84
85; When promoting a constant zext, the IR builder returns a constant,
86; not an instruction. Make sure this is properly handled. This used
87; to crash.
88; Note: The constant zext is promoted, but does not help matching
89; more thing in the addressing mode. Therefore the modification is
90; rolled back.
91; Still, this test case exercises the desired code path.
92; CHECK-LABEL: @oneArgPromotionCstZExt
93; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 0, 1
94; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
95; CHECK: ret
96define i8 @oneArgPromotionCstZExt(i8* %base) {
97  %cst = zext i16 undef to i32
98  %add = add nsw i32 %cst, 1
99  %sextadd = sext i32 %add to i64
100  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
101  %res = load i8, i8* %arrayidx
102  ret i8 %res
103}
104
105; Check that we do not promote truncate when we cannot determine the
106; bits that are dropped.
107; CHECK-LABEL: @oneArgPromotionBlockTrunc1
108; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 %arg1 to i8
109; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64
110; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
111; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
112; CHECK: ret
113define i8 @oneArgPromotionBlockTrunc1(i32 %arg1, i8* %base) {
114  %trunc = trunc i32 %arg1 to i8
115  %add = add nsw i8 %trunc, 1
116  %sextadd = sext i8 %add to i64
117  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
118  %res = load i8, i8* %arrayidx
119  ret i8 %res
120}
121
122; Check that we do not promote truncate when we cannot determine all the
123; bits that are dropped.
124; CHECK-LABEL: @oneArgPromotionBlockTrunc2
125; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i16 %arg1 to i32
126; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[ARG1SEXT]] to i8
127; CHECK: [[ARG1SEXT64:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64
128; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT64]], 1
129; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
130; CHECK: ret
131define i8 @oneArgPromotionBlockTrunc2(i16 %arg1, i8* %base) {
132  %sextarg1 = sext i16 %arg1 to i32
133  %trunc = trunc i32 %sextarg1 to i8
134  %add = add nsw i8 %trunc, 1
135  %sextadd = sext i8 %add to i64
136  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
137  %res = load i8, i8* %arrayidx
138  ret i8 %res
139}
140
141; Check that we are able to promote truncate when we know all the bits
142; that are dropped.
143; CHECK-LABEL: @oneArgPromotionPassTruncKeepSExt
144; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i64
145; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
146; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
147; CHECK: ret
148define i8 @oneArgPromotionPassTruncKeepSExt(i1 %arg1, i8* %base) {
149  %sextarg1 = sext i1 %arg1 to i32
150  %trunc = trunc i32 %sextarg1 to i8
151  %add = add nsw i8 %trunc, 1
152  %sextadd = sext i8 %add to i64
153  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
154  %res = load i8, i8* %arrayidx
155  ret i8 %res
156}
157
158; On X86 truncate are free. Check that we are able to promote the add
159; to be used as addressing mode and that we insert a truncate for the other
160; use.
161; CHECK-LABEL: @oneArgPromotionTruncInsert
162; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64
163; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
164; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i64 [[PROMOTED]] to i8
165; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
166; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, i8* [[GEP]]
167; CHECK: add i8 [[LOAD]], [[TRUNC]]
168; CHECK: ret
169define i8 @oneArgPromotionTruncInsert(i8 %arg1, i8* %base) {
170  %add = add nsw i8 %arg1, 1
171  %sextadd = sext i8 %add to i64
172  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
173  %res = load i8, i8* %arrayidx
174  %finalres = add i8 %res, %add
175  ret i8 %finalres
176}
177
178; Cannot sext from a larger type than the promoted type.
179; CHECK-LABEL: @oneArgPromotionLargerType
180; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i128 %arg1 to i8
181; CHECK: [[ARG1SEXT64:%[a-zA-Z_0-9-]+]] = sext i8 [[ARG1TRUNC]] to i64
182; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT64]], 1
183; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
184; CHECK: ret
185define i8 @oneArgPromotionLargerType(i128 %arg1, i8* %base) {
186  %trunc = trunc i128 %arg1 to i8
187  %add = add nsw i8 %trunc, 1
188  %sextadd = sext i8 %add to i64
189  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
190  %res = load i8, i8* %arrayidx
191  %finalres = add i8 %res, %add
192  ret i8 %finalres
193}
194
195; Use same inserted trunc
196; On X86 truncate are free. Check that we are able to promote the add
197; to be used as addressing mode and that we insert a truncate for
198; *all* the other uses.
199; CHECK-LABEL: @oneArgPromotionTruncInsertSeveralUse
200; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64
201; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
202; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i64 [[PROMOTED]] to i8
203; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
204; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, i8* [[GEP]]
205; CHECK: [[ADDRES:%[a-zA-Z_0-9-]+]] = add i8 [[LOAD]], [[TRUNC]]
206; CHECK: add i8 [[ADDRES]], [[TRUNC]]
207; CHECK: ret
208define i8 @oneArgPromotionTruncInsertSeveralUse(i8 %arg1, i8* %base) {
209  %add = add nsw i8 %arg1, 1
210  %sextadd = sext i8 %add to i64
211  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
212  %res = load i8, i8* %arrayidx
213  %almostfinalres = add i8 %res, %add
214  %finalres = add i8 %almostfinalres, %add
215  ret i8 %finalres
216}
217
218; Check that the promoted instruction is used for all uses of the original
219; sign extension.
220; CHECK-LABEL: @oneArgPromotionSExtSeveralUse
221; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i8 %arg1 to i64
222; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nsw i64 [[ARG1SEXT]], 1
223; CHECK: [[GEP:%[a-zA-Z_0-9-]+]] = getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
224; CHECK: [[LOAD:%[a-zA-Z_0-9-]+]] = load i8, i8* [[GEP]]
225; CHECK: [[ADDRES:%[a-zA-Z_0-9-]+]] = zext i8 [[LOAD]] to i64
226; CHECK: add i64 [[ADDRES]], [[PROMOTED]]
227; CHECK: ret
228define i64 @oneArgPromotionSExtSeveralUse(i8 %arg1, i8* %base) {
229  %add = add nsw i8 %arg1, 1
230  %sextadd = sext i8 %add to i64
231  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
232  %res = load i8, i8* %arrayidx
233  %almostfinalres = zext i8 %res to i64
234  %finalres = add i64 %almostfinalres, %sextadd
235  ret i64 %finalres
236}
237
238; Check all types of rollback mechanism.
239; For this test, the sign extension stays in place.
240; However, the matching process goes until promoting both the operands
241; of the first promotable add implies.
242; At this point the rollback mechanism kicks in and restores the states
243; until the addressing mode matcher is able to match something: in that
244; case promote nothing.
245; Along the way, the promotion mechanism involves:
246; - Mutating the type of %promotableadd1 and %promotableadd2.
247; - Creating a sext for %arg1 and %arg2.
248; - Creating a trunc for a use of %promotableadd1.
249; - Replacing a bunch of uses.
250; - Setting the operands of the promoted instruction with the promoted values.
251; - Moving instruction around (mainly sext when promoting instruction).
252; Each type of those promotions has to be undo at least once during this
253; specific test.
254; CHECK-LABEL: @twoArgsPromotionNest
255; CHECK: [[ORIG:%[a-zA-Z_0-9-]+]] = add nsw i32 %arg1, %arg2
256; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[ORIG]], [[ORIG]]
257; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64
258; CHECK: getelementptr inbounds i8, i8* %base, i64 [[SEXT]]
259; CHECK: ret
260define i8 @twoArgsPromotionNest(i32 %arg1, i32 %arg2, i8* %base) {
261  %promotableadd1 = add nsw i32 %arg1, %arg2
262  %promotableadd2 = add nsw i32 %promotableadd1, %promotableadd1
263  %sextadd = sext i32 %promotableadd2 to i64
264  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
265  %res = load i8, i8* %arrayidx
266  ret i8 %res
267}
268
269; Test the InstructionRemover undo, which was the only one not
270; kicked in the previous test.
271; The matcher first promotes the add, removes the trunc and promotes
272; the sext of arg1.
273; Then, the matcher cannot use an addressing mode r + r + r, thus it
274; rolls back.
275; CHECK-LABEL: @twoArgsNoPromotionRemove
276; CHECK: [[SEXTARG1:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i32
277; CHECK: [[TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[SEXTARG1]] to i8
278; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i8 [[TRUNC]], %arg2
279; CHECK: [[SEXT:%[a-zA-Z_0-9-]+]] = sext i8 [[ADD]] to i64
280; CHECK: getelementptr inbounds i8, i8* %base, i64 [[SEXT]]
281; CHECK: ret
282define i8 @twoArgsNoPromotionRemove(i1 %arg1, i8 %arg2, i8* %base) {
283  %sextarg1 = sext i1 %arg1 to i32
284  %trunc = trunc i32 %sextarg1 to i8
285  %add = add nsw i8 %trunc, %arg2
286  %sextadd = sext i8 %add to i64
287  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %sextadd
288  %res = load i8, i8* %arrayidx
289  ret i8 %res
290}
291
292; Ensure that when the profitability checks kicks in, the IR is not modified
293; will IgnoreProfitability is on.
294; The profitabily check happens when a candidate instruction has several uses.
295; The matcher will create a new matcher for each use and check if the
296; instruction is in the list of the matched instructions of this new matcher.
297; All changes made by the new matchers must be dropped before pursuing
298; otherwise the state of the original matcher will be wrong.
299;
300; Without the profitability check, when checking for the second use of
301; arrayidx, the matcher promotes everything all the way to %arg1, %arg2.
302; Check that we did not promote anything in the final matching.
303;
304; <rdar://problem/16020230>
305; CHECK-LABEL: @checkProfitability
306; CHECK-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg1 to i64
307; CHECK-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg2 to i64
308; CHECK: [[SHL:%[a-zA-Z_0-9-]+]] = shl nsw i32 %arg1, 1
309; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[SHL]], %arg2
310; CHECK: [[SEXTADD:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64
311; BB then
312; CHECK: [[BASE1:%[a-zA-Z_0-9-]+]] = add i64 [[SEXTADD]], 48
313; CHECK: [[ADDR1:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[BASE1]] to i32*
314; CHECK: load i32, i32* [[ADDR1]]
315; BB else
316; CHECK: [[BASE2:%[a-zA-Z_0-9-]+]] = add i64 [[SEXTADD]], 48
317; CHECK: [[ADDR2:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[BASE2]] to i32*
318; CHECK: load i32, i32* [[ADDR2]]
319; CHECK: ret
320; CHECK-GEP-LABEL: @checkProfitability
321; CHECK-GEP-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg1 to i64
322; CHECK-GEP-NOT: {{%[a-zA-Z_0-9-]+}} = sext i32 %arg2 to i64
323; CHECK-GEP: [[SHL:%[a-zA-Z_0-9-]+]] = shl nsw i32 %arg1, 1
324; CHECK-GEP: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 [[SHL]], %arg2
325; CHECK-GEP: [[SEXTADD:%[a-zA-Z_0-9-]+]] = sext i32 [[ADD]] to i64
326; BB then
327; CHECK-GEP: [[BASE1:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[SEXTADD]] to i32*
328; CHECK-GEP: [[BCC1:%[a-zA-Z_0-9-]+]] = bitcast i32* [[BASE1]] to i8*
329; CHECK-GEP: [[FULL1:%[a-zA-Z_0-9-]+]] = getelementptr i8, i8* [[BCC1]], i64 48
330; CHECK-GEP: [[ADDR1:%[a-zA-Z_0-9-]+]] = bitcast i8* [[FULL1]] to i32*
331; CHECK-GEP: load i32, i32* [[ADDR1]]
332; BB else
333; CHECK-GEP: [[BASE2:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[SEXTADD]] to i32*
334; CHECK-GEP: [[BCC2:%[a-zA-Z_0-9-]+]] = bitcast i32* [[BASE2]] to i8*
335; CHECK-GEP: [[FULL2:%[a-zA-Z_0-9-]+]] = getelementptr i8, i8* [[BCC2]], i64 48
336; CHECK-GEP: [[ADDR2:%[a-zA-Z_0-9-]+]] = bitcast i8* [[FULL2]] to i32*
337; CHECK-GEP: load i32, i32* [[ADDR2]]
338; CHECK-GEP: ret
339define i32 @checkProfitability(i32 %arg1, i32 %arg2, i1 %test) {
340  %shl = shl nsw i32 %arg1, 1
341  %add1 = add nsw i32 %shl, %arg2
342  %sextidx1 = sext i32 %add1 to i64
343  %tmpptr = inttoptr i64 %sextidx1 to i32*
344  %arrayidx1 = getelementptr i32, i32* %tmpptr, i64 12
345  br i1 %test, label %then, label %else
346then:
347  %res1 = load i32, i32* %arrayidx1
348  br label %end
349else:
350  %res2 = load i32, i32* %arrayidx1
351  br label %end
352end:
353  %tmp = phi i32 [%res1, %then], [%res2, %else]
354  %res = add i32 %tmp, %add1
355  %addr = inttoptr i32 %res to i32*
356  %final = load i32, i32* %addr
357  ret i32 %final
358}
359
360%struct.dns_packet = type { i32, i32, %union.anon }
361%union.anon = type { i32 }
362
363@a = common global i32 0, align 4
364@b = common global i16 0, align 2
365
366; We used to crash on this function because we did not return the right
367; promoted instruction for %conv.i.
368; Make sure we generate the right code now.
369; CHECK-LABEL: @fn3
370; %conv.i is used twice and only one of its use is being promoted.
371; Use it at the starting point for the matching.
372; CHECK: %conv.i = zext i16 [[PLAIN_OPND:%[.a-zA-Z_0-9-]+]] to i32
373; CHECK-NEXT: [[PROMOTED_CONV:%[.a-zA-Z_0-9-]+]] = zext i16 [[PLAIN_OPND]] to i64
374; CHECK-NEXT: [[BASE:%[a-zA-Z_0-9-]+]] = ptrtoint %struct.dns_packet* %P to i64
375; CHECK-NEXT: [[ADD:%[a-zA-Z_0-9-]+]] = add i64 [[BASE]], [[PROMOTED_CONV]]
376; CHECK-NEXT: [[ADDR:%[a-zA-Z_0-9-]+]] = add i64 [[ADD]], 7
377; CHECK-NEXT: [[CAST:%[a-zA-Z_0-9-]+]] = inttoptr i64 [[ADDR]] to i8*
378; CHECK-NEXT: load i8, i8* [[CAST]], align 1
379define signext i16 @fn3(%struct.dns_packet* nocapture readonly %P) {
380entry:
381  %tmp = getelementptr inbounds %struct.dns_packet, %struct.dns_packet* %P, i64 0, i32 2
382  %data.i.i = bitcast %union.anon* %tmp to [0 x i8]*
383  br label %while.body.i.i
384
385while.body.i.i:                                   ; preds = %while.body.i.i, %entry
386  %src.addr.0.i.i = phi i16 [ 0, %entry ], [ %inc.i.i, %while.body.i.i ]
387  %inc.i.i = add i16 %src.addr.0.i.i, 1
388  %idxprom.i.i = sext i16 %src.addr.0.i.i to i64
389  %arrayidx.i.i = getelementptr inbounds [0 x i8], [0 x i8]* %data.i.i, i64 0, i64 %idxprom.i.i
390  %tmp1 = load i8, i8* %arrayidx.i.i, align 1
391  %conv2.i.i = zext i8 %tmp1 to i32
392  %and.i.i = and i32 %conv2.i.i, 15
393  store i32 %and.i.i, i32* @a, align 4
394  %tobool.i.i = icmp eq i32 %and.i.i, 0
395  br i1 %tobool.i.i, label %while.body.i.i, label %fn1.exit.i
396
397fn1.exit.i:                                       ; preds = %while.body.i.i
398  %inc.i.i.lcssa = phi i16 [ %inc.i.i, %while.body.i.i ]
399  %conv.i = zext i16 %inc.i.i.lcssa to i32
400  %sub.i = add nsw i32 %conv.i, -1
401  %idxprom.i = sext i32 %sub.i to i64
402  %arrayidx.i = getelementptr inbounds [0 x i8], [0 x i8]* %data.i.i, i64 0, i64 %idxprom.i
403  %tmp2 = load i8, i8* %arrayidx.i, align 1
404  %conv2.i = sext i8 %tmp2 to i16
405  store i16 %conv2.i, i16* @b, align 2
406  %sub4.i = sub nsw i32 0, %conv.i
407  %conv5.i = zext i16 %conv2.i to i32
408  %cmp.i = icmp sgt i32 %conv5.i, %sub4.i
409  br i1 %cmp.i, label %if.then.i, label %fn2.exit
410
411if.then.i:                                        ; preds = %fn1.exit.i
412  %end.i = getelementptr inbounds %struct.dns_packet, %struct.dns_packet* %P, i64 0, i32 1
413  %tmp3 = load i32, i32* %end.i, align 4
414  %sub7.i = add i32 %tmp3, 65535
415  %conv8.i = trunc i32 %sub7.i to i16
416  br label %fn2.exit
417
418fn2.exit:                                         ; preds = %if.then.i, %fn1.exit.i
419  %retval.0.i = phi i16 [ %conv8.i, %if.then.i ], [ undef, %fn1.exit.i ]
420  ret i16 %retval.0.i
421}
422
423; Check that we do not promote an extension if the non-wrapping flag does not
424; match the kind of the extension.
425; CHECK-LABEL: @noPromotionFlag
426; CHECK: [[ADD:%[a-zA-Z_0-9-]+]] = add nsw i32 %arg1, %arg2
427; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = zext i32 [[ADD]] to i64
428; CHECK: inttoptr i64 [[PROMOTED]] to i8*
429; CHECK: ret
430define i8 @noPromotionFlag(i32 %arg1, i32 %arg2) {
431  %add = add nsw i32 %arg1, %arg2
432  %zextadd = zext i32 %add to i64
433  %base = inttoptr i64 %zextadd to i8*
434  %res = load i8, i8* %base
435  ret i8 %res
436}
437
438; Check that we correctly promote both operands of the promotable add with zext.
439; CHECK-LABEL: @twoArgsPromotionZExt
440; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i32 %arg1 to i64
441; CHECK: [[ARG2ZEXT:%[a-zA-Z_0-9-]+]] = zext i32 %arg2 to i64
442; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], [[ARG2ZEXT]]
443; CHECK: inttoptr i64 [[PROMOTED]] to i8*
444; CHECK: ret
445define i8 @twoArgsPromotionZExt(i32 %arg1, i32 %arg2) {
446  %add = add nuw i32 %arg1, %arg2
447  %zextadd = zext i32 %add to i64
448  %base = inttoptr i64 %zextadd to i8*
449  %res = load i8, i8* %base
450  ret i8 %res
451}
452
453; Check that we correctly promote constant arguments.
454; CHECK-LABEL: @oneArgPromotionNegativeCstZExt
455; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64
456; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 255
457; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
458; CHECK: ret
459define i8 @oneArgPromotionNegativeCstZExt(i8 %arg1, i8* %base) {
460  %add = add nuw i8 %arg1, -1
461  %zextadd = zext i8 %add to i64
462  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
463  %res = load i8, i8* %arrayidx
464  ret i8 %res
465}
466
467; Check that we are able to merge two zero extensions.
468; CHECK-LABEL: @oneArgPromotionZExtZExt
469; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 %arg1 to i64
470; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
471; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
472; CHECK: ret
473define i8 @oneArgPromotionZExtZExt(i8 %arg1, i8* %base) {
474  %zext = zext i8 %arg1 to i32
475  %add = add nuw i32 %zext, 1
476  %zextadd = zext i32 %add to i64
477  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
478  %res = load i8, i8* %arrayidx
479  ret i8 %res
480}
481
482; Check that we do not promote truncate when the dropped bits
483; are of a different kind.
484; CHECK-LABEL: @oneArgPromotionBlockTruncZExt
485; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i32
486; CHECK: [[ARG1TRUNC:%[a-zA-Z_0-9-]+]] = trunc i32 [[ARG1SEXT]] to i8
487; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 [[ARG1TRUNC]] to i64
488; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
489; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
490; CHECK: ret
491define i8 @oneArgPromotionBlockTruncZExt(i1 %arg1, i8* %base) {
492  %sextarg1 = sext i1 %arg1 to i32
493  %trunc = trunc i32 %sextarg1 to i8
494  %add = add nuw i8 %trunc, 1
495  %zextadd = zext i8 %add to i64
496  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
497  %res = load i8, i8* %arrayidx
498  ret i8 %res
499}
500
501; Check that we are able to promote truncate when we know all the bits
502; that are dropped.
503; CHECK-LABEL: @oneArgPromotionPassTruncZExt
504; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i1 %arg1 to i64
505; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
506; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
507; CHECK: ret
508define i8 @oneArgPromotionPassTruncZExt(i1 %arg1, i8* %base) {
509  %sextarg1 = zext i1 %arg1 to i32
510  %trunc = trunc i32 %sextarg1 to i8
511  %add = add nuw i8 %trunc, 1
512  %zextadd = zext i8 %add to i64
513  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
514  %res = load i8, i8* %arrayidx
515  ret i8 %res
516}
517
518; Check that we do not promote sext with zext.
519; CHECK-LABEL: @oneArgPromotionBlockSExtZExt
520; CHECK: [[ARG1SEXT:%[a-zA-Z_0-9-]+]] = sext i1 %arg1 to i8
521; CHECK: [[ARG1ZEXT:%[a-zA-Z_0-9-]+]] = zext i8 [[ARG1SEXT]] to i64
522; CHECK: [[PROMOTED:%[a-zA-Z_0-9-]+]] = add nuw i64 [[ARG1ZEXT]], 1
523; CHECK: getelementptr inbounds i8, i8* %base, i64 [[PROMOTED]]
524; CHECK: ret
525define i8 @oneArgPromotionBlockSExtZExt(i1 %arg1, i8* %base) {
526  %sextarg1 = sext i1 %arg1 to i8
527  %add = add nuw i8 %sextarg1, 1
528  %zextadd = zext i8 %add to i64
529  %arrayidx = getelementptr inbounds i8, i8* %base, i64 %zextadd
530  %res = load i8, i8* %arrayidx
531  ret i8 %res
532}
533