Skip to content

Commit 3f8322e

Browse files
author
v01dxyz
committed
[CodeGenPrepare] Do not despeculate count leading/trailing ones if promotion
For count leading/trailing ones, ie (CTLZ/CTTZ (XOR Op -1)), legalisation should be able to optimise this case when a promotion is necessary. Despeculation should not be applied in this case as it will separate XOR and CTLZ/CTTZ in two different basic blocks. This is particularly problematic with SelectionDAG.
1 parent e6c20e1 commit 3f8322e

File tree

3 files changed

+320
-2
lines changed

3 files changed

+320
-2
lines changed

llvm/lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2310,6 +2310,26 @@ static bool despeculateCountZeros(IntrinsicInst *CountZeros,
23102310
if (Ty->isVectorTy() || SizeInBits > DL->getLargestLegalIntTypeSizeInBits())
23112311
return false;
23122312

2313+
// Do not despeculate if we have (ctlz/cttz (xor op -1)) if the operand is
2314+
// promoted as legalisation should be later able to transform it to:
2315+
//
2316+
// ctlz:
2317+
// (ctlz_zero_undef (lshift (xor (extend op) -1)
2318+
// lshiftamount))
2319+
//
2320+
// cttz:
2321+
// (cttz_zero_undef (xor (zeroextend op) -1))
2322+
//
2323+
// Despeculation is not only useless but also not wanted with SelectionDAG
2324+
// as XOR and CTLZ/CTTZ would be in different basic blocks.
2325+
EVT VTy = TLI->getValueType(*DL, Ty);
2326+
int ISDOpcode = IntrinsicID == Intrinsic::ctlz ? ISD::CTLZ : ISD::CTTZ;
2327+
if (match(CountZeros->getOperand(0), m_Not(m_Value())) &&
2328+
(TLI->getTypeAction(CountZeros->getContext(), VTy) ==
2329+
TargetLowering::TypePromoteInteger ||
2330+
TLI->getOperationAction(ISDOpcode, VTy) == TargetLowering::Promote))
2331+
return false;
2332+
23132333
// Bail if the value is never zero.
23142334
Use &Op = CountZeros->getOperandUse(0);
23152335
if (isKnownNonZero(Op, *DL))

llvm/test/Transforms/CodeGenPrepare/RISCV/cttz-ctlz.ll

Lines changed: 131 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt -S -passes='require<profile-summary>,function(codegenprepare)' < %s | FileCheck %s
3-
2+
; RUN: opt -S -passes='require<profile-summary>,function(codegenprepare)' < %s | FileCheck %s --check-prefixes=CHECK,SLOW
3+
; RUN: opt -S -mattr=+rva22u64 -passes='require<profile-summary>,function(codegenprepare)' < %s | FileCheck %s --check-prefixes=CHECK,FAST
44
target triple = "riscv64-unknown-unknown"
55

66
; Check that despeculating count-zeros intrinsics doesn't crash when those
@@ -24,5 +24,134 @@ define <vscale x 4 x i64> @ctlz_nxv4i64(<vscale x 4 x i64> %x) {
2424
ret <vscale x 4 x i64> %z
2525
}
2626

27+
; If the intrinsic is cheap, nothing should change.
28+
; If the intrinsic is expensive, check if the input is zero to avoid the call.
29+
; This is undoing speculation that may have been created by SimplifyCFG + InstCombine.
30+
31+
define i64 @cttz(i64 %A) {
32+
; SLOW-LABEL: @cttz(
33+
; SLOW-NEXT: entry:
34+
; SLOW-NEXT: [[A_FR:%.*]] = freeze i64 [[A:%.*]]
35+
; SLOW-NEXT: [[CMPZ:%.*]] = icmp eq i64 [[A_FR]], 0
36+
; SLOW-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
37+
; SLOW: cond.false:
38+
; SLOW-NEXT: [[Z:%.*]] = call i64 @llvm.cttz.i64(i64 [[A_FR]], i1 true)
39+
; SLOW-NEXT: br label [[COND_END]]
40+
; SLOW: cond.end:
41+
; SLOW-NEXT: [[CTZ:%.*]] = phi i64 [ 64, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ]
42+
; SLOW-NEXT: ret i64 [[CTZ]]
43+
;
44+
; FAST-LABEL: @cttz(
45+
; FAST-NEXT: entry:
46+
; FAST-NEXT: [[Z:%.*]] = call i64 @llvm.cttz.i64(i64 [[A:%.*]], i1 false)
47+
; FAST-NEXT: ret i64 [[Z]]
48+
;
49+
entry:
50+
%z = call i64 @llvm.cttz.i64(i64 %A, i1 false)
51+
ret i64 %z
52+
}
53+
54+
define i64 @ctlz(i64 %A) {
55+
; SLOW-LABEL: @ctlz(
56+
; SLOW-NEXT: entry:
57+
; SLOW-NEXT: [[A_FR:%.*]] = freeze i64 [[A:%.*]]
58+
; SLOW-NEXT: [[CMPZ:%.*]] = icmp eq i64 [[A_FR]], 0
59+
; SLOW-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
60+
; SLOW: cond.false:
61+
; SLOW-NEXT: [[Z:%.*]] = call i64 @llvm.ctlz.i64(i64 [[A_FR]], i1 true)
62+
; SLOW-NEXT: br label [[COND_END]]
63+
; SLOW: cond.end:
64+
; SLOW-NEXT: [[CTZ:%.*]] = phi i64 [ 64, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ]
65+
; SLOW-NEXT: ret i64 [[CTZ]]
66+
;
67+
; FAST-LABEL: @ctlz(
68+
; FAST-NEXT: entry:
69+
; FAST-NEXT: [[Z:%.*]] = call i64 @llvm.ctlz.i64(i64 [[A:%.*]], i1 false)
70+
; FAST-NEXT: ret i64 [[Z]]
71+
;
72+
entry:
73+
%z = call i64 @llvm.ctlz.i64(i64 %A, i1 false)
74+
ret i64 %z
75+
}
76+
77+
define i8 @cttz_i8(i8 %A) {
78+
; SLOW-LABEL: @cttz_i8(
79+
; SLOW-NEXT: entry:
80+
; SLOW-NEXT: [[A_FR:%.*]] = freeze i8 [[A:%.*]]
81+
; SLOW-NEXT: [[CMPZ:%.*]] = icmp eq i8 [[A_FR]], 0
82+
; SLOW-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
83+
; SLOW: cond.false:
84+
; SLOW-NEXT: [[Z:%.*]] = call i8 @llvm.cttz.i8(i8 [[A_FR]], i1 true)
85+
; SLOW-NEXT: br label [[COND_END]]
86+
; SLOW: cond.end:
87+
; SLOW-NEXT: [[CTZ:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ]
88+
; SLOW-NEXT: ret i8 [[CTZ]]
89+
;
90+
; FAST-LABEL: @cttz_i8(
91+
; FAST-NEXT: entry:
92+
; FAST-NEXT: [[Z:%.*]] = call i8 @llvm.cttz.i8(i8 [[A:%.*]], i1 false)
93+
; FAST-NEXT: ret i8 [[Z]]
94+
;
95+
entry:
96+
%z = call i8 @llvm.cttz.i8(i8 %A, i1 false)
97+
ret i8 %z
98+
}
99+
100+
define i8 @ctlz_i8(i8 %A) {
101+
; SLOW-LABEL: @ctlz_i8(
102+
; SLOW-NEXT: entry:
103+
; SLOW-NEXT: [[A_FR:%.*]] = freeze i8 [[A:%.*]]
104+
; SLOW-NEXT: [[CMPZ:%.*]] = icmp eq i8 [[A_FR]], 0
105+
; SLOW-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
106+
; SLOW: cond.false:
107+
; SLOW-NEXT: [[Z:%.*]] = call i8 @llvm.ctlz.i8(i8 [[A_FR]], i1 true)
108+
; SLOW-NEXT: br label [[COND_END]]
109+
; SLOW: cond.end:
110+
; SLOW-NEXT: [[CTZ:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ]
111+
; SLOW-NEXT: ret i8 [[CTZ]]
112+
;
113+
; FAST-LABEL: @ctlz_i8(
114+
; FAST-NEXT: entry:
115+
; FAST-NEXT: [[Z:%.*]] = call i8 @llvm.ctlz.i8(i8 [[A:%.*]], i1 false)
116+
; FAST-NEXT: ret i8 [[Z]]
117+
;
118+
entry:
119+
%z = call i8 @llvm.ctlz.i8(i8 %A, i1 false)
120+
ret i8 %z
121+
}
122+
123+
; As the operand will be promoted by the type legalizer, no despeculation when counting
124+
; ones.
125+
126+
define i8 @ctto_i8_no_despeculation(i8 %A) {
127+
; CHECK-LABEL: @ctto_i8_no_despeculation(
128+
; CHECK-NEXT: entry:
129+
; CHECK-NEXT: [[A_NOT:%.*]] = xor i8 [[A:%.*]], -1
130+
; CHECK-NEXT: [[Z:%.*]] = call i8 @llvm.cttz.i8(i8 [[A_NOT]], i1 false)
131+
; CHECK-NEXT: ret i8 [[Z]]
132+
;
133+
entry:
134+
%A.not = xor i8 %A, -1
135+
%z = call i8 @llvm.cttz.i8(i8 %A.not, i1 false)
136+
ret i8 %z
137+
}
138+
139+
define i8 @ctlo_i8_no_despeculation(i8 %A) {
140+
; CHECK-LABEL: @ctlo_i8_no_despeculation(
141+
; CHECK-NEXT: entry:
142+
; CHECK-NEXT: [[A_NOT:%.*]] = xor i8 [[A:%.*]], -1
143+
; CHECK-NEXT: [[Z:%.*]] = call i8 @llvm.ctlz.i8(i8 [[A_NOT]], i1 false)
144+
; CHECK-NEXT: ret i8 [[Z]]
145+
;
146+
entry:
147+
%A.not = xor i8 %A, -1
148+
%z = call i8 @llvm.ctlz.i8(i8 %A.not, i1 false)
149+
ret i8 %z
150+
}
151+
27152
declare <vscale x 4 x i64> @llvm.cttz.nxv4i64(<vscale x 4 x i64>, i1)
28153
declare <vscale x 4 x i64> @llvm.ctlz.nxv4i64(<vscale x 4 x i64>, i1)
154+
declare i64 @llvm.cttz.i64(i64, i1)
155+
declare i64 @llvm.ctlz.i64(i64, i1)
156+
declare i8 @llvm.cttz.i8(i8, i1)
157+
declare i8 @llvm.ctlz.i8(i8, i1)

llvm/test/Transforms/CodeGenPrepare/X86/cttz-ctlz.ll

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,175 @@ entry:
109109
ret i64 %z
110110
}
111111

112+
define i8 @cttz_i8(i8 %A) {
113+
; SLOW-LABEL: @cttz_i8(
114+
; SLOW-NEXT: entry:
115+
; SLOW-NEXT: [[Z:%.*]] = call i8 @llvm.cttz.i8(i8 [[A:%.*]], i1 false)
116+
; SLOW-NEXT: ret i8 [[Z]]
117+
;
118+
; FAST_TZ-LABEL: @cttz_i8(
119+
; FAST_TZ-NEXT: entry:
120+
; FAST_TZ-NEXT: [[Z:%.*]] = call i8 @llvm.cttz.i8(i8 [[A:%.*]], i1 false)
121+
; FAST_TZ-NEXT: ret i8 [[Z]]
122+
;
123+
; FAST_LZ-LABEL: @cttz_i8(
124+
; FAST_LZ-NEXT: entry:
125+
; FAST_LZ-NEXT: [[Z:%.*]] = call i8 @llvm.cttz.i8(i8 [[A:%.*]], i1 false)
126+
; FAST_LZ-NEXT: ret i8 [[Z]]
127+
;
128+
; DEBUGINFO-LABEL: @cttz_i8(
129+
; DEBUGINFO-NEXT: entry:
130+
; DEBUGINFO-NEXT: [[Z:%.*]] = call i8 @llvm.cttz.i8(i8 [[A:%.*]], i1 false), !dbg [[DBG22:![0-9]+]]
131+
; DEBUGINFO-NEXT: #dbg_value(i8 [[Z]], [[META20:![0-9]+]], !DIExpression(), [[DBG22]])
132+
; DEBUGINFO-NEXT: ret i8 [[Z]], !dbg [[DBG23:![0-9]+]]
133+
;
134+
entry:
135+
%z = call i8 @llvm.cttz.i8(i8 %A, i1 false)
136+
ret i8 %z
137+
}
138+
139+
define i8 @ctlz_i8(i8 %A) {
140+
; SLOW-LABEL: @ctlz_i8(
141+
; SLOW-NEXT: entry:
142+
; SLOW-NEXT: [[A_FR:%.*]] = freeze i8 [[A:%.*]]
143+
; SLOW-NEXT: [[CMPZ:%.*]] = icmp eq i8 [[A_FR]], 0
144+
; SLOW-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
145+
; SLOW: cond.false:
146+
; SLOW-NEXT: [[Z:%.*]] = call i8 @llvm.ctlz.i8(i8 [[A_FR]], i1 true)
147+
; SLOW-NEXT: br label [[COND_END]]
148+
; SLOW: cond.end:
149+
; SLOW-NEXT: [[CTZ:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ]
150+
; SLOW-NEXT: ret i8 [[CTZ]]
151+
;
152+
; FAST_TZ-LABEL: @ctlz_i8(
153+
; FAST_TZ-NEXT: entry:
154+
; FAST_TZ-NEXT: [[A_FR:%.*]] = freeze i8 [[A:%.*]]
155+
; FAST_TZ-NEXT: [[CMPZ:%.*]] = icmp eq i8 [[A_FR]], 0
156+
; FAST_TZ-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
157+
; FAST_TZ: cond.false:
158+
; FAST_TZ-NEXT: [[Z:%.*]] = call i8 @llvm.ctlz.i8(i8 [[A_FR]], i1 true)
159+
; FAST_TZ-NEXT: br label [[COND_END]]
160+
; FAST_TZ: cond.end:
161+
; FAST_TZ-NEXT: [[CTZ:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ]
162+
; FAST_TZ-NEXT: ret i8 [[CTZ]]
163+
;
164+
; FAST_LZ-LABEL: @ctlz_i8(
165+
; FAST_LZ-NEXT: entry:
166+
; FAST_LZ-NEXT: [[Z:%.*]] = call i8 @llvm.ctlz.i8(i8 [[A:%.*]], i1 false)
167+
; FAST_LZ-NEXT: ret i8 [[Z]]
168+
;
169+
; DEBUGINFO-LABEL: @ctlz_i8(
170+
; DEBUGINFO-NEXT: entry:
171+
; DEBUGINFO-NEXT: [[A_FR:%.*]] = freeze i8 [[A:%.*]], !dbg [[DBG27:![0-9]+]]
172+
; DEBUGINFO-NEXT: [[CMPZ:%.*]] = icmp eq i8 [[A_FR]], 0, !dbg [[DBG27]]
173+
; DEBUGINFO-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]], !dbg [[DBG27]]
174+
; DEBUGINFO: cond.false:
175+
; DEBUGINFO-NEXT: [[Z:%.*]] = call i8 @llvm.ctlz.i8(i8 [[A_FR]], i1 true), !dbg [[DBG27]]
176+
; DEBUGINFO-NEXT: br label [[COND_END]], !dbg [[DBG28:![0-9]+]]
177+
; DEBUGINFO: cond.end:
178+
; DEBUGINFO-NEXT: [[CTZ:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ], !dbg [[DBG28]]
179+
; DEBUGINFO-NEXT: #dbg_value(i8 [[CTZ]], [[META26:![0-9]+]], !DIExpression(), [[DBG27]])
180+
; DEBUGINFO-NEXT: ret i8 [[CTZ]], !dbg [[DBG28]]
181+
;
182+
entry:
183+
%z = call i8 @llvm.ctlz.i8(i8 %A, i1 false)
184+
ret i8 %z
185+
}
186+
187+
; As the operand will be promoted by the DAG legalizer, no despeculation when counting
188+
; ones.
189+
190+
define i8 @ctto_i8_no_despeculation(i8 %A) {
191+
; SLOW-LABEL: @ctto_i8_no_despeculation(
192+
; SLOW-NEXT: entry:
193+
; SLOW-NEXT: [[A_NOT:%.*]] = xor i8 [[A:%.*]], -1
194+
; SLOW-NEXT: [[Z:%.*]] = call i8 @llvm.cttz.i8(i8 [[A_NOT]], i1 false)
195+
; SLOW-NEXT: ret i8 [[Z]]
196+
;
197+
; FAST_TZ-LABEL: @ctto_i8_no_despeculation(
198+
; FAST_TZ-NEXT: entry:
199+
; FAST_TZ-NEXT: [[A_NOT:%.*]] = xor i8 [[A:%.*]], -1
200+
; FAST_TZ-NEXT: [[Z:%.*]] = call i8 @llvm.cttz.i8(i8 [[A_NOT]], i1 false)
201+
; FAST_TZ-NEXT: ret i8 [[Z]]
202+
;
203+
; FAST_LZ-LABEL: @ctto_i8_no_despeculation(
204+
; FAST_LZ-NEXT: entry:
205+
; FAST_LZ-NEXT: [[A_NOT:%.*]] = xor i8 [[A:%.*]], -1
206+
; FAST_LZ-NEXT: [[Z:%.*]] = call i8 @llvm.cttz.i8(i8 [[A_NOT]], i1 false)
207+
; FAST_LZ-NEXT: ret i8 [[Z]]
208+
;
209+
; DEBUGINFO-LABEL: @ctto_i8_no_despeculation(
210+
; DEBUGINFO-NEXT: entry:
211+
; DEBUGINFO-NEXT: [[A_NOT:%.*]] = xor i8 [[A:%.*]], -1, !dbg [[DBG33:![0-9]+]]
212+
; DEBUGINFO-NEXT: #dbg_value(i8 [[A_NOT]], [[META31:![0-9]+]], !DIExpression(), [[DBG33]])
213+
; DEBUGINFO-NEXT: [[Z:%.*]] = call i8 @llvm.cttz.i8(i8 [[A_NOT]], i1 false), !dbg [[DBG34:![0-9]+]]
214+
; DEBUGINFO-NEXT: #dbg_value(i8 [[Z]], [[META32:![0-9]+]], !DIExpression(), [[DBG34]])
215+
; DEBUGINFO-NEXT: ret i8 [[Z]], !dbg [[DBG35:![0-9]+]]
216+
;
217+
entry:
218+
%A.not = xor i8 %A, -1
219+
%z = call i8 @llvm.cttz.i8(i8 %A.not, i1 false)
220+
ret i8 %z
221+
}
222+
223+
; despeculation occurs because with CTLZ i8, the DAG legalization is Custom.
224+
225+
define i8 @ctlo_i8(i8 %A) {
226+
; SLOW-LABEL: @ctlo_i8(
227+
; SLOW-NEXT: entry:
228+
; SLOW-NEXT: [[A_NOT:%.*]] = xor i8 [[A:%.*]], -1
229+
; SLOW-NEXT: [[A_NOT_FR:%.*]] = freeze i8 [[A_NOT]]
230+
; SLOW-NEXT: [[CMPZ:%.*]] = icmp eq i8 [[A_NOT_FR]], 0
231+
; SLOW-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
232+
; SLOW: cond.false:
233+
; SLOW-NEXT: [[Z:%.*]] = call i8 @llvm.ctlz.i8(i8 [[A_NOT_FR]], i1 true)
234+
; SLOW-NEXT: br label [[COND_END]]
235+
; SLOW: cond.end:
236+
; SLOW-NEXT: [[CTZ:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ]
237+
; SLOW-NEXT: ret i8 [[CTZ]]
238+
;
239+
; FAST_TZ-LABEL: @ctlo_i8(
240+
; FAST_TZ-NEXT: entry:
241+
; FAST_TZ-NEXT: [[A_NOT:%.*]] = xor i8 [[A:%.*]], -1
242+
; FAST_TZ-NEXT: [[A_NOT_FR:%.*]] = freeze i8 [[A_NOT]]
243+
; FAST_TZ-NEXT: [[CMPZ:%.*]] = icmp eq i8 [[A_NOT_FR]], 0
244+
; FAST_TZ-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]]
245+
; FAST_TZ: cond.false:
246+
; FAST_TZ-NEXT: [[Z:%.*]] = call i8 @llvm.ctlz.i8(i8 [[A_NOT_FR]], i1 true)
247+
; FAST_TZ-NEXT: br label [[COND_END]]
248+
; FAST_TZ: cond.end:
249+
; FAST_TZ-NEXT: [[CTZ:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ]
250+
; FAST_TZ-NEXT: ret i8 [[CTZ]]
251+
;
252+
; FAST_LZ-LABEL: @ctlo_i8(
253+
; FAST_LZ-NEXT: entry:
254+
; FAST_LZ-NEXT: [[A_NOT:%.*]] = xor i8 [[A:%.*]], -1
255+
; FAST_LZ-NEXT: [[Z:%.*]] = call i8 @llvm.ctlz.i8(i8 [[A_NOT]], i1 false)
256+
; FAST_LZ-NEXT: ret i8 [[Z]]
257+
;
258+
; DEBUGINFO-LABEL: @ctlo_i8(
259+
; DEBUGINFO-NEXT: entry:
260+
; DEBUGINFO-NEXT: [[A_NOT:%.*]] = xor i8 [[A:%.*]], -1, !dbg [[DBG40:![0-9]+]]
261+
; DEBUGINFO-NEXT: #dbg_value(i8 [[A_NOT]], [[META38:![0-9]+]], !DIExpression(), [[DBG40]])
262+
; DEBUGINFO-NEXT: [[A_NOT_FR:%.*]] = freeze i8 [[A_NOT]], !dbg [[DBG41:![0-9]+]]
263+
; DEBUGINFO-NEXT: [[CMPZ:%.*]] = icmp eq i8 [[A_NOT_FR]], 0, !dbg [[DBG41]]
264+
; DEBUGINFO-NEXT: br i1 [[CMPZ]], label [[COND_END:%.*]], label [[COND_FALSE:%.*]], !dbg [[DBG41]]
265+
; DEBUGINFO: cond.false:
266+
; DEBUGINFO-NEXT: [[Z:%.*]] = call i8 @llvm.ctlz.i8(i8 [[A_NOT_FR]], i1 true), !dbg [[DBG41]]
267+
; DEBUGINFO-NEXT: br label [[COND_END]], !dbg [[DBG42:![0-9]+]]
268+
; DEBUGINFO: cond.end:
269+
; DEBUGINFO-NEXT: [[CTZ:%.*]] = phi i8 [ 8, [[ENTRY:%.*]] ], [ [[Z]], [[COND_FALSE]] ], !dbg [[DBG42]]
270+
; DEBUGINFO-NEXT: #dbg_value(i8 [[CTZ]], [[META39:![0-9]+]], !DIExpression(), [[DBG41]])
271+
; DEBUGINFO-NEXT: ret i8 [[CTZ]], !dbg [[DBG42]]
272+
;
273+
entry:
274+
%A.not = xor i8 %A, -1
275+
%z = call i8 @llvm.ctlz.i8(i8 %A.not, i1 false)
276+
ret i8 %z
277+
}
278+
112279
declare i64 @llvm.cttz.i64(i64, i1)
113280
declare i64 @llvm.ctlz.i64(i64, i1)
281+
declare i8 @llvm.cttz.i8(i8, i1)
282+
declare i8 @llvm.ctlz.i8(i8, i1)
114283

0 commit comments

Comments
 (0)