Skip to content

Commit 1d7f98f

Browse files
author
Joe Shajrawi
committed
[SILOptimizer] Add ‘llvm.cttz.*’ Intrinsic support to Constant Folding
rdar://problem/29522851
1 parent 0d27af4 commit 1d7f98f

File tree

2 files changed

+71
-25
lines changed

2 files changed

+71
-25
lines changed

lib/SILOptimizer/Utils/ConstantFolding.cpp

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,44 @@ constantFoldBinaryWithOverflow(BuiltinInst *BI, BuiltinValueKind ID,
278278
ResultsInError);
279279
}
280280

281+
static SILValue countZeros(BuiltinInst *BI, llvm::Intrinsic::ID ID) {
282+
assert(BI->getArguments().size() == 2 && "Ctlz should have 2 args.");
283+
OperandValueArrayRef Args = BI->getArguments();
284+
285+
// Fold for integer constant arguments.
286+
auto *LHS = dyn_cast<IntegerLiteralInst>(Args[0]);
287+
if (!LHS) {
288+
return nullptr;
289+
}
290+
APInt LHSI = LHS->getValue();
291+
unsigned LZ = 0;
292+
// Check corner-case of source == zero
293+
if (LHSI == 0) {
294+
auto *RHS = dyn_cast<IntegerLiteralInst>(Args[1]);
295+
if (!RHS || RHS->getValue() != 0) {
296+
// Undefined
297+
return nullptr;
298+
}
299+
LZ = LHSI.getBitWidth();
300+
} else {
301+
switch (ID) {
302+
default:
303+
return nullptr;
304+
case llvm::Intrinsic::ctlz: {
305+
LZ = LHSI.countLeadingZeros();
306+
break;
307+
}
308+
case llvm::Intrinsic::cttz: {
309+
LZ = LHSI.countTrailingZeros();
310+
break;
311+
}
312+
}
313+
}
314+
APInt LZAsAPInt = APInt(LHSI.getBitWidth(), LZ);
315+
SILBuilderWithScope B(BI);
316+
return B.createIntegerLiteral(BI->getLoc(), LHS->getType(), LZAsAPInt);
317+
}
318+
281319
static SILValue constantFoldIntrinsic(BuiltinInst *BI, llvm::Intrinsic::ID ID,
282320
Optional<bool> &ResultsInError) {
283321
switch (ID) {
@@ -291,31 +329,9 @@ static SILValue constantFoldIntrinsic(BuiltinInst *BI, llvm::Intrinsic::ID ID,
291329
return Op1;
292330
}
293331

294-
case llvm::Intrinsic::ctlz: {
295-
assert(BI->getArguments().size() == 2 && "Ctlz should have 2 args.");
296-
OperandValueArrayRef Args = BI->getArguments();
297-
298-
// Fold for integer constant arguments.
299-
auto *LHS = dyn_cast<IntegerLiteralInst>(Args[0]);
300-
if (!LHS) {
301-
return nullptr;
302-
}
303-
APInt LHSI = LHS->getValue();
304-
unsigned LZ = 0;
305-
// Check corner-case of source == zero
306-
if (LHSI == 0) {
307-
auto *RHS = dyn_cast<IntegerLiteralInst>(Args[1]);
308-
if (!RHS || RHS->getValue() != 0) {
309-
// Undefined
310-
return nullptr;
311-
}
312-
LZ = LHSI.getBitWidth();
313-
} else {
314-
LZ = LHSI.countLeadingZeros();
315-
}
316-
APInt LZAsAPInt = APInt(LHSI.getBitWidth(), LZ);
317-
SILBuilderWithScope B(BI);
318-
return B.createIntegerLiteral(BI->getLoc(), LHS->getType(), LZAsAPInt);
332+
case llvm::Intrinsic::ctlz:
333+
case llvm::Intrinsic::cttz: {
334+
return countZeros(BI, ID);
319335
}
320336

321337
case llvm::Intrinsic::sadd_with_overflow:

test/SILOptimizer/constant_propagation.sil

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,36 @@ bb0:
5050
// CHECK-NEXT: return [[RES]] : $Builtin.Int64
5151
}
5252

53+
sil @count_trailing_zeros_corner_case : $@convention(thin) () -> Builtin.Int64 {
54+
bb0:
55+
%zero64 = integer_literal $Builtin.Int64, 0
56+
%zero1 = integer_literal $Builtin.Int1, 0
57+
%cttz = builtin "int_cttz_Int64"(%zero64 : $Builtin.Int64, %zero1 : $Builtin.Int1) : $Builtin.Int64
58+
return %cttz : $Builtin.Int64
59+
60+
// CHECK-LABEL: sil @count_trailing_zeros_corner_case
61+
// CHECK-NOT: integer_literal $Builtin.Int64, 0
62+
// CHECK-NOT: integer_literal $Builtin.Int1, 0
63+
// CHECK-NOT: builtin
64+
// CHECK: [[RES:%.*]] = integer_literal $Builtin.Int64, 64
65+
// CHECK-NEXT: return [[RES]] : $Builtin.Int64
66+
}
67+
68+
sil @count_trailing_zeros : $@convention(thin) () -> Builtin.Int64 {
69+
bb0:
70+
%zero64 = integer_literal $Builtin.Int64, 2
71+
%zero1 = integer_literal $Builtin.Int1, 0
72+
%cttz = builtin "int_cttz_Int64"(%zero64 : $Builtin.Int64, %zero1 : $Builtin.Int1) : $Builtin.Int64
73+
return %cttz : $Builtin.Int64
74+
75+
// CHECK-LABEL: sil @count_trailing_zeros
76+
// CHECK-NOT: integer_literal $Builtin.Int64, 2
77+
// CHECK-NOT: integer_literal $Builtin.Int1, 0
78+
// CHECK-NOT: builtin
79+
// CHECK: [[RES:%.*]] = integer_literal $Builtin.Int64, 1
80+
// CHECK-NEXT: return [[RES]] : $Builtin.Int64
81+
}
82+
5383
// Compute an expression using a chain of arithmetic with overflow instructions: 2 * (2 + 3) - 3
5484
sil @fold_arithmetic_with_overflow : $@convention(thin) () -> Builtin.Int64 {
5585
bb0:

0 commit comments

Comments
 (0)