Index: lib/IR/IRBuilder.cpp =================================================================== --- lib/IR/IRBuilder.cpp +++ lib/IR/IRBuilder.cpp @@ -104,7 +104,7 @@ Value *Ops[] = {Ptr, Val, Size, getInt1(isVolatile)}; Type *Tys[] = { Ptr->getType(), Size->getType() }; Module *M = BB->getParent()->getParent(); - Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys); + Function *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys); CallInst *CI = createCallHelper(TheFn, Ops, this); @@ -121,6 +121,8 @@ if (NoAliasTag) CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + TheFn->addParamAttr(0, Attribute::NonNull); + return CI; } @@ -166,7 +168,7 @@ Value *Ops[] = {Dst, Src, Size, getInt1(isVolatile)}; Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() }; Module *M = BB->getParent()->getParent(); - Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memcpy, Tys); + Function *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memcpy, Tys); CallInst *CI = createCallHelper(TheFn, Ops, this); @@ -190,6 +192,9 @@ if (NoAliasTag) CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + TheFn->addParamAttr(0, Attribute::NonNull); + TheFn->addParamAttr(1, Attribute::NonNull); + return CI; } @@ -246,7 +251,7 @@ Value *Ops[] = {Dst, Src, Size, getInt1(isVolatile)}; Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() }; Module *M = BB->getParent()->getParent(); - Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memmove, Tys); + Function *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memmove, Tys); CallInst *CI = createCallHelper(TheFn, Ops, this); @@ -265,6 +270,9 @@ if (NoAliasTag) CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + + TheFn->addParamAttr(0, Attribute::NonNull); + TheFn->addParamAttr(1, Attribute::NonNull); return CI; } Index: lib/Transforms/Utils/BuildLibCalls.cpp =================================================================== --- lib/Transforms/Utils/BuildLibCalls.cpp +++ lib/Transforms/Utils/BuildLibCalls.cpp @@ -37,7 +37,8 @@ STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture"); STATISTIC(NumReadOnlyArg, "Number of arguments inferred as readonly"); STATISTIC(NumNoAlias, "Number of function returns inferred as noalias"); -STATISTIC(NumNonNull, "Number of function returns inferred as nonnull returns"); +STATISTIC(NumRetNonNull, "Number of function returns inferred as nonnull returns"); +STATISTIC(NumArgNonNull, "Number of function arguments inferred as nonnull"); static bool setDoesNotAccessMemory(Function &F) { if (F.doesNotAccessMemory()) @@ -95,13 +96,21 @@ return true; } +static bool setArgNotNull(Function &F, unsigned ArgNo) { + if (F.hasParamAttribute(ArgNo, Attribute::NonNull)) + return false; + F.addParamAttr(ArgNo, Attribute::NonNull); + ++NumArgNonNull; + return true; +} + static bool setRetNonNull(Function &F) { assert(F.getReturnType()->isPointerTy() && "nonnull applies only to pointers"); if (F.hasAttribute(AttributeList::ReturnIndex, Attribute::NonNull)) return false; F.addAttribute(AttributeList::ReturnIndex, Attribute::NonNull); - ++NumNonNull; + ++NumRetNonNull; return true; } @@ -129,11 +138,13 @@ Changed |= setDoesNotThrow(F); Changed |= setOnlyAccessesArgMemory(F); Changed |= setDoesNotCapture(F, 0); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_strchr: case LibFunc_strrchr: Changed |= setOnlyReadsMemory(F); Changed |= setDoesNotThrow(F); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_strtol: case LibFunc_strtod: @@ -145,6 +156,7 @@ Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 0); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_strcpy: case LibFunc_stpcpy: @@ -155,6 +167,8 @@ Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 1); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_strxfrm: Changed |= setDoesNotThrow(F); @@ -173,28 +187,35 @@ Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 1); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_strstr: case LibFunc_strpbrk: Changed |= setOnlyReadsMemory(F); Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 1); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_strtok: case LibFunc_strtok_r: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 1); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_scanf: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); Changed |= setOnlyReadsMemory(F, 0); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_setbuf: case LibFunc_setvbuf: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_strdup: case LibFunc_strndup: @@ -202,6 +223,7 @@ Changed |= setRetDoesNotAlias(F); Changed |= setDoesNotCapture(F, 0); Changed |= setOnlyReadsMemory(F, 0); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_stat: case LibFunc_statvfs: @@ -216,18 +238,22 @@ Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 0); Changed |= setOnlyReadsMemory(F, 1); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_sprintf: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 1); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_snprintf: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 2); Changed |= setOnlyReadsMemory(F, 2); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_setitimer: Changed |= setDoesNotThrow(F); @@ -249,11 +275,14 @@ Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 1); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_memchr: case LibFunc_memrchr: Changed |= setOnlyReadsMemory(F); Changed |= setDoesNotThrow(F); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_modf: case LibFunc_modff: @@ -268,6 +297,8 @@ Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 1); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_memcpy_chk: Changed |= setDoesNotThrow(F); @@ -327,16 +358,21 @@ Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 0); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_bcmp: Changed |= setDoesNotThrow(F); Changed |= setOnlyReadsMemory(F); Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 1); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_bzero: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_calloc: Changed |= setDoesNotThrow(F); @@ -361,6 +397,7 @@ Changed |= setDoesNotThrow(F); Changed |= setOnlyReadsMemory(F); Changed |= setDoesNotCapture(F, 0); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_access: Changed |= setDoesNotThrow(F); @@ -374,6 +411,7 @@ Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 0); Changed |= setOnlyReadsMemory(F, 1); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_fdopen: Changed |= setDoesNotThrow(F); @@ -406,6 +444,10 @@ return Changed; case LibFunc_fputc: case LibFunc_fputc_unlocked: + Changed |= setDoesNotThrow(F); + Changed |= setDoesNotCapture(F, 1); + Changed |= setArgNotNull(F, 0); + return Changed; case LibFunc_fstat: case LibFunc_frexp: case LibFunc_frexpf: @@ -418,18 +460,23 @@ case LibFunc_fgets_unlocked: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 2); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_fread: case LibFunc_fread_unlocked: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 3); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 3); return Changed; case LibFunc_fwrite: case LibFunc_fwrite_unlocked: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 3); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 3); // FIXME: readonly #1? return Changed; case LibFunc_fputs: @@ -438,6 +485,8 @@ Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 0); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_fscanf: case LibFunc_fprintf: @@ -445,6 +494,8 @@ Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 1); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_fgetpos: Changed |= setDoesNotThrow(F); @@ -456,6 +507,7 @@ case LibFunc_getc_unlocked: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_getenv: Changed |= setDoesNotThrow(F); @@ -506,6 +558,7 @@ case LibFunc_putc_unlocked: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 1); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_puts: case LibFunc_printf: @@ -513,6 +566,7 @@ Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); Changed |= setOnlyReadsMemory(F, 0); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_pread: // May throw; "pread" is a valid pthread cancellation point. @@ -619,6 +673,8 @@ case LibFunc_qsort: // May throw; places call through function pointer. Changed |= setDoesNotCapture(F, 3); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 3); return Changed; case LibFunc_dunder_strdup: case LibFunc_dunder_strndup: @@ -626,19 +682,24 @@ Changed |= setRetDoesNotAlias(F); Changed |= setDoesNotCapture(F, 0); Changed |= setOnlyReadsMemory(F, 0); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_dunder_strtok_r: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 1); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_under_IO_getc: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 0); + Changed |= setArgNotNull(F, 0); return Changed; case LibFunc_under_IO_putc: Changed |= setDoesNotThrow(F); Changed |= setDoesNotCapture(F, 1); + Changed |= setArgNotNull(F, 1); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_dunder_isoc99_scanf: Changed |= setDoesNotThrow(F); @@ -659,6 +720,8 @@ Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 0); Changed |= setOnlyReadsMemory(F, 1); + Changed |= setArgNotNull(F, 0); + Changed |= setArgNotNull(F, 1); return Changed; case LibFunc_fopen64: Changed |= setDoesNotThrow(F); @@ -710,11 +773,13 @@ // TODO: add LibFunc entries for: // case LibFunc_memset_pattern4: // case LibFunc_memset_pattern8: + case LibFunc_memset: case LibFunc_memset_pattern16: Changed |= setOnlyAccessesArgMemory(F); Changed |= setDoesNotCapture(F, 0); Changed |= setDoesNotCapture(F, 1); Changed |= setOnlyReadsMemory(F, 1); + Changed |= setArgNotNull(F, 0); return Changed; // int __nvvm_reflect(const char *) case LibFunc_nvvm_reflect: