Skip to content

Commit 5197d27

Browse files
Martin Sebornikic
authored andcommitted
[SimplifyLibCalls] Move handling of constant char earlier (NFC)
Handle the simple constant char case before the bitmask optimization. This will allow extending the code to handle a non-constant size argument in a followup change. Split out from https://reviews.llvm.org/D122836.
1 parent d333b38 commit 5197d27

File tree

1 file changed

+43
-44
lines changed

1 file changed

+43
-44
lines changed

llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,16 @@ Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilderBase &B) {
917917
// return null if we don't find the char.
918918
Str = Str.substr(0, LenC->getZExtValue());
919919

920+
if (CharC) {
921+
// Compute the offset.
922+
size_t I = Str.find(CharC->getSExtValue() & 0xFF);
923+
if (I == StringRef::npos) // Didn't find the char. memchr returns null.
924+
return Constant::getNullValue(CI->getType());
925+
926+
// memchr(s+n,c,l) -> gep(s+n+i,c)
927+
return B.CreateGEP(B.getInt8Ty(), SrcStr, B.getInt64(I), "memchr");
928+
}
929+
920930
// If the char is variable but the input str and length are not we can turn
921931
// this memchr call into a simple bit field test. Of course this only works
922932
// when the return value is only checked against null.
@@ -927,58 +937,47 @@ Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilderBase &B) {
927937
// memchr("\r\n", C, 2) != nullptr -> (1 << C & ((1 << '\r') | (1 << '\n')))
928938
// != 0
929939
// after bounds check.
930-
if (!CharC && !Str.empty() && isOnlyUsedInZeroEqualityComparison(CI)) {
931-
unsigned char Max =
932-
*std::max_element(reinterpret_cast<const unsigned char *>(Str.begin()),
933-
reinterpret_cast<const unsigned char *>(Str.end()));
934-
935-
// Make sure the bit field we're about to create fits in a register on the
936-
// target.
937-
// FIXME: On a 64 bit architecture this prevents us from using the
938-
// interesting range of alpha ascii chars. We could do better by emitting
939-
// two bitfields or shifting the range by 64 if no lower chars are used.
940-
if (!DL.fitsInLegalInteger(Max + 1))
941-
return nullptr;
942-
943-
// For the bit field use a power-of-2 type with at least 8 bits to avoid
944-
// creating unnecessary illegal types.
945-
unsigned char Width = NextPowerOf2(std::max((unsigned char)7, Max));
940+
if (Str.empty() || !isOnlyUsedInZeroEqualityComparison(CI))
941+
return nullptr;
946942

947-
// Now build the bit field.
948-
APInt Bitfield(Width, 0);
949-
for (char C : Str)
950-
Bitfield.setBit((unsigned char)C);
951-
Value *BitfieldC = B.getInt(Bitfield);
943+
unsigned char Max =
944+
*std::max_element(reinterpret_cast<const unsigned char *>(Str.begin()),
945+
reinterpret_cast<const unsigned char *>(Str.end()));
952946

953-
// Adjust width of "C" to the bitfield width, then mask off the high bits.
954-
Value *C = B.CreateZExtOrTrunc(CharVal, BitfieldC->getType());
955-
C = B.CreateAnd(C, B.getIntN(Width, 0xFF));
947+
// Make sure the bit field we're about to create fits in a register on the
948+
// target.
949+
// FIXME: On a 64 bit architecture this prevents us from using the
950+
// interesting range of alpha ascii chars. We could do better by emitting
951+
// two bitfields or shifting the range by 64 if no lower chars are used.
952+
if (!DL.fitsInLegalInteger(Max + 1))
953+
return nullptr;
956954

957-
// First check that the bit field access is within bounds.
958-
Value *Bounds = B.CreateICmp(ICmpInst::ICMP_ULT, C, B.getIntN(Width, Width),
959-
"memchr.bounds");
955+
// For the bit field use a power-of-2 type with at least 8 bits to avoid
956+
// creating unnecessary illegal types.
957+
unsigned char Width = NextPowerOf2(std::max((unsigned char)7, Max));
960958

961-
// Create code that checks if the given bit is set in the field.
962-
Value *Shl = B.CreateShl(B.getIntN(Width, 1ULL), C);
963-
Value *Bits = B.CreateIsNotNull(B.CreateAnd(Shl, BitfieldC), "memchr.bits");
959+
// Now build the bit field.
960+
APInt Bitfield(Width, 0);
961+
for (char C : Str)
962+
Bitfield.setBit((unsigned char)C);
963+
Value *BitfieldC = B.getInt(Bitfield);
964964

965-
// Finally merge both checks and cast to pointer type. The inttoptr
966-
// implicitly zexts the i1 to intptr type.
967-
return B.CreateIntToPtr(B.CreateLogicalAnd(Bounds, Bits, "memchr"),
968-
CI->getType());
969-
}
965+
// Adjust width of "C" to the bitfield width, then mask off the high bits.
966+
Value *C = B.CreateZExtOrTrunc(CharVal, BitfieldC->getType());
967+
C = B.CreateAnd(C, B.getIntN(Width, 0xFF));
970968

971-
// Check if all arguments are constants. If so, we can constant fold.
972-
if (!CharC)
973-
return nullptr;
969+
// First check that the bit field access is within bounds.
970+
Value *Bounds = B.CreateICmp(ICmpInst::ICMP_ULT, C, B.getIntN(Width, Width),
971+
"memchr.bounds");
974972

975-
// Compute the offset.
976-
size_t I = Str.find(CharC->getSExtValue() & 0xFF);
977-
if (I == StringRef::npos) // Didn't find the char. memchr returns null.
978-
return Constant::getNullValue(CI->getType());
973+
// Create code that checks if the given bit is set in the field.
974+
Value *Shl = B.CreateShl(B.getIntN(Width, 1ULL), C);
975+
Value *Bits = B.CreateIsNotNull(B.CreateAnd(Shl, BitfieldC), "memchr.bits");
979976

980-
// memchr(s+n,c,l) -> gep(s+n+i,c)
981-
return B.CreateGEP(B.getInt8Ty(), SrcStr, B.getInt64(I), "memchr");
977+
// Finally merge both checks and cast to pointer type. The inttoptr
978+
// implicitly zexts the i1 to intptr type.
979+
return B.CreateIntToPtr(B.CreateLogicalAnd(Bounds, Bits, "memchr"),
980+
CI->getType());
982981
}
983982

984983
static Value *optimizeMemCmpConstantSize(CallInst *CI, Value *LHS, Value *RHS,

0 commit comments

Comments
 (0)