-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[SILOptimizer] Add ‘llvm.cttz.*’ Intrinsic support to Constant Folding #23720
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -278,6 +278,44 @@ constantFoldBinaryWithOverflow(BuiltinInst *BI, BuiltinValueKind ID, | |
ResultsInError); | ||
} | ||
|
||
static SILValue countZeros(BuiltinInst *BI, llvm::Intrinsic::ID ID) { | ||
assert(BI->getArguments().size() == 2 && "Ctlz should have 2 args."); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bad assert message. You are handling both ctlz and cttz. |
||
OperandValueArrayRef Args = BI->getArguments(); | ||
|
||
// Fold for integer constant arguments. | ||
auto *LHS = dyn_cast<IntegerLiteralInst>(Args[0]); | ||
if (!LHS) { | ||
return nullptr; | ||
} | ||
APInt LHSI = LHS->getValue(); | ||
unsigned LZ = 0; | ||
// Check corner-case of source == zero | ||
if (LHSI == 0) { | ||
auto *RHS = dyn_cast<IntegerLiteralInst>(Args[1]); | ||
if (!RHS || RHS->getValue() != 0) { | ||
// Undefined | ||
return nullptr; | ||
} | ||
LZ = LHSI.getBitWidth(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you do an early exit here? |
||
} else { | ||
switch (ID) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My suggestion: Use an inline constructor: unsigned LZ = [&] { Also. Do you really think we are going to support more types of intrinsics here? Why not just put in an assert or something like that. |
||
default: | ||
return nullptr; | ||
case llvm::Intrinsic::ctlz: { | ||
LZ = LHSI.countLeadingZeros(); | ||
break; | ||
} | ||
case llvm::Intrinsic::cttz: { | ||
LZ = LHSI.countTrailingZeros(); | ||
break; | ||
} | ||
} | ||
} | ||
APInt LZAsAPInt = APInt(LHSI.getBitWidth(), LZ); | ||
SILBuilderWithScope B(BI); | ||
return B.createIntegerLiteral(BI->getLoc(), LHS->getType(), LZAsAPInt); | ||
} | ||
|
||
static SILValue constantFoldIntrinsic(BuiltinInst *BI, llvm::Intrinsic::ID ID, | ||
Optional<bool> &ResultsInError) { | ||
switch (ID) { | ||
|
@@ -291,31 +329,9 @@ static SILValue constantFoldIntrinsic(BuiltinInst *BI, llvm::Intrinsic::ID ID, | |
return Op1; | ||
} | ||
|
||
case llvm::Intrinsic::ctlz: { | ||
assert(BI->getArguments().size() == 2 && "Ctlz should have 2 args."); | ||
OperandValueArrayRef Args = BI->getArguments(); | ||
|
||
// Fold for integer constant arguments. | ||
auto *LHS = dyn_cast<IntegerLiteralInst>(Args[0]); | ||
if (!LHS) { | ||
return nullptr; | ||
} | ||
APInt LHSI = LHS->getValue(); | ||
unsigned LZ = 0; | ||
// Check corner-case of source == zero | ||
if (LHSI == 0) { | ||
auto *RHS = dyn_cast<IntegerLiteralInst>(Args[1]); | ||
if (!RHS || RHS->getValue() != 0) { | ||
// Undefined | ||
return nullptr; | ||
} | ||
LZ = LHSI.getBitWidth(); | ||
} else { | ||
LZ = LHSI.countLeadingZeros(); | ||
} | ||
APInt LZAsAPInt = APInt(LHSI.getBitWidth(), LZ); | ||
SILBuilderWithScope B(BI); | ||
return B.createIntegerLiteral(BI->getLoc(), LHS->getType(), LZAsAPInt); | ||
case llvm::Intrinsic::ctlz: | ||
case llvm::Intrinsic::cttz: { | ||
return countZeros(BI, ID); | ||
} | ||
|
||
case llvm::Intrinsic::sadd_with_overflow: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this name means nothing and this needs a comment. My suggestion:
/// Count either the leading or trailing zeros.
Also, do you really need the intrinsic id here? Couldn't you just pass in a bool stating which of the two you are handling?