[LLVMdev] strlen in fast-isel is missed
Reed Kotler
rkotler at mips.com
Wed Jan 28 12:54:42 PST 2015
-fno-builtin
will also make this problem go away.
On 01/28/2015 12:33 PM, Reed Kotler wrote:
> Seems like it might possible to override TargetLIbraryInfo during the
> creation of the fast-isel object.
>
> I will look into this.
>
> namespace llvm {
> FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
> const TargetLibraryInfo *libInfo) {
> return new MipsFastISel(funcInfo, libInfo);
> }
> }
>
>
> On 01/28/2015 11:03 AM, Reed Kotler wrote:
>> This issue occurs in a many library functions.
>> strlen, strcmp, ... many others.
>> I'm surprised nobody has noticed this because many basic blocks will
>> fail to be compiled as fast-isel in this case.
>>
>> It seems like just a bug in:
>> bool FastISel::selectInstruction(const Instruction *I) {
>>
>> this function returns false but then it causes fast-isel to just do a
>> miss on the function. there is no way to override the behavior.
>>
>> Since this is happening on a call instructtion, it's going to drop back
>> and print as a missed fast isel call.
>>
>> It seems like this test in
>> bool FastISel::selectInstruction(const Instruction *I)
>>
>> should just be deleted.
>>
>> Thoughts?
>>
>>
>> // As a special case, don't handle calls to builtin library
>> functions that
>> // may be translated directly to target instructions.
>> if (F && !F->hasLocalLinkage() && F->hasName() &&
>> LibInfo->getLibFunc(F->getName(), Func) &&
>> LibInfo->hasOptimizedCodeGen(Func))
>> return false;
>>
>>
>> This is called from void SelectionDAGISel::SelectAllBasicBlocks(const
>> Function &Fn)
>>
>> if (FastIS->selectInstruction(Inst)) {
>> --NumFastIselRemaining;
>> ++NumFastIselSuccess;
>> // If fast isel succeeded, skip over all the folded
>> instructions, and
>> // then see if there is a load right before the selected
>> instructions.
>> // Try to fold the load if so.
>> const Instruction *BeforeInst = Inst;
>> while (BeforeInst != Begin) {
>> BeforeInst =
>> std::prev(BasicBlock::const_iterator(BeforeInst));
>> if (!isFoldedOrDeadInstruction(BeforeInst, FuncInfo))
>> break;
>> }
>> if (BeforeInst != Inst && isa<LoadInst>(BeforeInst) &&
>> BeforeInst->hasOneUse() &&
>> FastIS->tryToFoldLoad(cast<LoadInst>(BeforeInst), Inst)) {
>> // If we succeeded, don't re-select the load.
>> BI = std::next(BasicBlock::const_iterator(BeforeInst));
>> --NumFastIselRemaining;
>> ++NumFastIselSuccess;
>> }
>> continue;
>> }
>>
>> #ifndef NDEBUG
>> if (EnableFastISelVerbose2)
>> collectFailStats(Inst);
>> #endif
>>
>> // Then handle certain instructions as single-LLVM-Instruction
>> blocks.
>> if (isa<CallInst>(Inst)) {
>>
>> if (EnableFastISelVerbose || EnableFastISelAbort) {
>> dbgs() << "FastISel missed call: ";
>> Inst->dump();
>>
>>
>>
>> On 01/20/2015 02:35 PM, reed kotler wrote:
>>> It seems that fast-isel for intel does not handle strlen. It's a general
>>> problem in fast-isel .
>>>
>>>
>>> ~/llvmw/build/Deb~/llvmw/build/Debug+Asserts/bin/clang -O0 -mllvm
>>> -fast-isel-verbose -mllvm -fast-isel strlen1.c
>>> strlen1.c:12:3: warning: implicitly declaring library function 'printf'
>>> with
>>> type 'int (const char *, ...)'
>>> printf("%i\n", len);
>>> ^
>>> strlen1.c:12:3: note: include the header <stdio.h> or explicitly
>>> provide a
>>> declaration for 'printf'
>>> FastISel missed call: %call = call i64 @strlen(i8* %0) #3
>>> 1 warning generated.
>>>
>>> #include <string.h>
>>>
>>> char *hello = "hello";
>>> int len;
>>>
>>> void foo() {
>>> len = strlen(hello);
>>> }
>>>
>>> int main() {
>>> foo();
>>> printf("%i\n", len);
>>> }
More information about the llvm-dev
mailing list