Skip to content
SimplifyLibCalls.cpp 94.3 KiB
Newer Older
          setDoesNotCapture(F, 1);
          setDoesNotCapture(F, 2);
        } else if (NameLen == 6 && !strcmp(NameStr, "fdopen")) {
          if (FTy->getNumParams() != 2 ||
              !isa<PointerType>(FTy->getReturnType()) ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotAlias(F, 0);
          setDoesNotCapture(F, 2);
        } else if ((NameLen == 4 && !strcmp(NameStr, "feof")) ||
                   (NameLen == 4 && !strcmp(NameStr, "free")) ||
                   (NameLen == 5 && !strcmp(NameStr, "fseek")) ||
                   (NameLen == 5 && !strcmp(NameStr, "ftell")) ||
                   (NameLen == 5 && !strcmp(NameStr, "fgetc")) ||
                   (NameLen == 6 && !strcmp(NameStr, "fseeko")) ||
                   (NameLen == 6 && !strcmp(NameStr, "ftello")) ||
                   (NameLen == 6 && !strcmp(NameStr, "fileno")) ||
                   (NameLen == 6 && !strcmp(NameStr, "fflush")) ||
                   (NameLen == 6 && !strcmp(NameStr, "fclose")) ||
                   (NameLen == 7 && !strcmp(NameStr, "fsetpos")) ||
                   (NameLen == 9 && !strcmp(NameStr, "flockfile")) ||
                   (NameLen == 11 && !strcmp(NameStr, "funlockfile")) ||
                   (NameLen == 12 && !strcmp(NameStr, "ftrylockfile"))) {
          if (FTy->getNumParams() == 0 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        } else if (NameLen == 6 && !strcmp(NameStr, "ferror")) {
          if (FTy->getNumParams() != 1 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
          setOnlyReadsMemory(F);
        } else if ((NameLen == 5 && !strcmp(NameStr, "fputc")) ||
                   (NameLen == 5 && !strcmp(NameStr, "fstat")) ||
                   (NameLen == 5 && !strcmp(NameStr, "frexp")) ||
                   (NameLen == 6 && !strcmp(NameStr, "frexpf")) ||
                   (NameLen == 6 && !strcmp(NameStr, "frexpl")) ||
                   (NameLen == 8 && !strcmp(NameStr, "fstatvfs"))) {
          if (FTy->getNumParams() != 2 ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 2);
        } else if (NameLen == 5 && !strcmp(NameStr, "fgets")) {
          if (FTy->getNumParams() != 3 ||
              !isa<PointerType>(FTy->getParamType(0)) ||
              !isa<PointerType>(FTy->getParamType(2)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 3);
        } else if ((NameLen == 5 && !strcmp(NameStr, "fread")) ||
                   (NameLen == 6 && !strcmp(NameStr, "fwrite"))) {
          if (FTy->getNumParams() != 4 ||
              !isa<PointerType>(FTy->getParamType(0)) ||
              !isa<PointerType>(FTy->getParamType(3)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
          setDoesNotCapture(F, 4);
        } else if ((NameLen == 5 && !strcmp(NameStr, "fputs")) ||
                   (NameLen == 6 && !strcmp(NameStr, "fscanf")) ||
                   (NameLen == 7 && !strcmp(NameStr, "fprintf")) ||
                   (NameLen == 7 && !strcmp(NameStr, "fgetpos"))) {
          if (FTy->getNumParams() < 2 ||
              !isa<PointerType>(FTy->getParamType(0)) ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
          setDoesNotCapture(F, 2);
        }
        break;
      case 'g':
        if ((NameLen == 4 && !strcmp(NameStr, "getc")) ||
            (NameLen == 10 && !strcmp(NameStr, "getlogin_r")) ||
            (NameLen == 13 && !strcmp(NameStr, "getc_unlocked"))) {
          if (FTy->getNumParams() == 0 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        } else if (NameLen == 6 && !strcmp(NameStr, "getenv")) {
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setOnlyReadsMemory(F);
          setDoesNotCapture(F, 1);
        } else if ((NameLen == 4 && !strcmp(NameStr, "gets")) ||
                   (NameLen == 7 && !strcmp(NameStr, "getchar"))) {
          setDoesNotThrow(F);
        } else if (NameLen == 9 && !strcmp(NameStr, "getitimer")) {
          if (FTy->getNumParams() != 2 ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 2);
        } else if (NameLen == 8 && !strcmp(NameStr, "getpwnam")) {
          if (FTy->getNumParams() != 1 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        if (NameLen == 6 && !strcmp(NameStr, "ungetc")) {
          if (FTy->getNumParams() != 2 ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 2);
        } else if ((NameLen == 5 && !strcmp(NameStr, "uname")) ||
                   (NameLen == 6 && !strcmp(NameStr, "unlink")) ||
                   (NameLen == 8 && !strcmp(NameStr, "unsetenv"))) {
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        } else if ((NameLen == 5 && !strcmp(NameStr, "utime")) ||
                   (NameLen == 6 && !strcmp(NameStr, "utimes"))) {
          if (FTy->getNumParams() != 2 ||
              !isa<PointerType>(FTy->getParamType(0)) ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
          setDoesNotCapture(F, 2);
        }
        break;
      case 'p':
        if (NameLen == 4 && !strcmp(NameStr, "putc")) {
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 2);
        } else if ((NameLen == 4 && !strcmp(NameStr, "puts")) ||
                   (NameLen == 6 && !strcmp(NameStr, "printf")) ||
                   (NameLen == 6 && !strcmp(NameStr, "perror"))) {
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        } else if ((NameLen == 5 && !strcmp(NameStr, "pread")) ||
                   (NameLen == 6 && !strcmp(NameStr, "pwrite"))) {
          if (FTy->getNumParams() != 4 ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          // May throw; these are valid pthread cancellation points.
          setDoesNotCapture(F, 2);
        } else if (NameLen == 7 && !strcmp(NameStr, "putchar")) {
          setDoesNotThrow(F);
        } else if (NameLen == 5 && !strcmp(NameStr, "popen")) {
          if (FTy->getNumParams() != 2 ||
              !isa<PointerType>(FTy->getReturnType()) ||
              !isa<PointerType>(FTy->getParamType(0)) ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotAlias(F, 0);
          setDoesNotCapture(F, 1);
          setDoesNotCapture(F, 2);
        } else if (NameLen == 6 && !strcmp(NameStr, "pclose")) {
          if (FTy->getNumParams() != 1 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        }
        break;
      case 'v':
        if (NameLen == 6 && !strcmp(NameStr, "vscanf")) {
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        } else if ((NameLen == 7 && !strcmp(NameStr, "vsscanf")) ||
                   (NameLen == 7 && !strcmp(NameStr, "vfscanf"))) {
              !isa<PointerType>(FTy->getParamType(1)) ||
              !isa<PointerType>(FTy->getParamType(2)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
          setDoesNotCapture(F, 2);
        } else if (NameLen == 6 && !strcmp(NameStr, "valloc")) {
          if (!isa<PointerType>(FTy->getReturnType()))
            continue;
          setDoesNotThrow(F);
          setDoesNotAlias(F, 0);
        } else if (NameLen == 7 && !strcmp(NameStr, "vprintf")) {
          if (FTy->getNumParams() != 2 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        } else if ((NameLen == 8 && !strcmp(NameStr, "vfprintf")) ||
                   (NameLen == 8 && !strcmp(NameStr, "vsprintf"))) {
          if (FTy->getNumParams() != 3 ||
              !isa<PointerType>(FTy->getParamType(0)) ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
          setDoesNotCapture(F, 2);
        } else if (NameLen == 9 && !strcmp(NameStr, "vsnprintf")) {
          if (FTy->getNumParams() != 4 ||
              !isa<PointerType>(FTy->getParamType(0)) ||
              !isa<PointerType>(FTy->getParamType(2)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
          setDoesNotCapture(F, 3);
        if (NameLen == 4 && !strcmp(NameStr, "open")) {
          if (FTy->getNumParams() < 2 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          // May throw; "open" is a valid pthread cancellation point.
          setDoesNotCapture(F, 1);
        } else if (NameLen == 7 && !strcmp(NameStr, "opendir")) {
          if (FTy->getNumParams() != 1 ||
              !isa<PointerType>(FTy->getReturnType()) ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotAlias(F, 0);
        }
        break;
      case 't':
        if (NameLen == 7 && !strcmp(NameStr, "tmpfile")) {
          if (!isa<PointerType>(FTy->getReturnType()))
            continue;
          setDoesNotThrow(F);
          setDoesNotAlias(F, 0);
        } else if (NameLen == 5 && !strcmp(NameStr, "times")) {
          if (FTy->getNumParams() != 1 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
      case 'h':
        if ((NameLen == 5 && !strcmp(NameStr, "htonl")) ||
            (NameLen == 5 && !strcmp(NameStr, "htons"))) {
          setDoesNotThrow(F);
          setDoesNotAccessMemory(F);
        }
        break;
      case 'n':
        if ((NameLen == 5 && !strcmp(NameStr, "ntohl")) ||
            (NameLen == 5 && !strcmp(NameStr, "ntohs"))) {
          setDoesNotThrow(F);
          setDoesNotAccessMemory(F);
        }
        break;
      case 'l':
        if (NameLen == 5 && !strcmp(NameStr, "lstat")) {
          if (FTy->getNumParams() != 2 ||
              !isa<PointerType>(FTy->getParamType(0)) ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
          setDoesNotCapture(F, 2);
        } else if (NameLen == 6 && !strcmp(NameStr, "lchown")) {
          if (FTy->getNumParams() != 3 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        }
        break;
      case 'q':
        if (NameLen == 5 && !strcmp(NameStr, "qsort")) {
          if (FTy->getNumParams() != 4 ||
              !isa<PointerType>(FTy->getParamType(3)))
            continue;
          // May throw; places call through function pointer.
          setDoesNotCapture(F, 4);
        }
        break;
      case '_':
        if ((NameLen == 8 && !strcmp(NameStr, "__strdup")) ||
            (NameLen == 9 && !strcmp(NameStr, "__strndup"))) {
          if (FTy->getNumParams() < 1 ||
              !isa<PointerType>(FTy->getReturnType()) ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotAlias(F, 0);
          setDoesNotCapture(F, 1);
        } else if (NameLen == 10 && !strcmp(NameStr, "__strtok_r")) {
          if (FTy->getNumParams() != 3 ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 2);
        } else if (NameLen == 8 && !strcmp(NameStr, "_IO_getc")) {
          if (FTy->getNumParams() != 1 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        } else if (NameLen == 8 && !strcmp(NameStr, "_IO_putc")) {
          if (FTy->getNumParams() != 2 ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 2);
        }
      case 1:
        if (NameLen == 15 && !strcmp(NameStr, "\1__isoc99_scanf")) {
          if (FTy->getNumParams() < 1 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        } else if ((NameLen == 7 && !strcmp(NameStr, "\1stat64")) ||
                   (NameLen == 8 && !strcmp(NameStr, "\1lstat64")) ||
                   (NameLen == 10 && !strcmp(NameStr, "\1statvfs64")) ||
                   (NameLen == 16 && !strcmp(NameStr, "\1__isoc99_sscanf"))) {
              !isa<PointerType>(FTy->getParamType(0)) ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
          setDoesNotCapture(F, 2);
        } else if (NameLen == 8 && !strcmp(NameStr, "\1fopen64")) {
          if (FTy->getNumParams() != 2 ||
              !isa<PointerType>(FTy->getReturnType()) ||
              !isa<PointerType>(FTy->getParamType(0)) ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
          setDoesNotAlias(F, 0);
          setDoesNotCapture(F, 1);
          setDoesNotCapture(F, 2);
        } else if ((NameLen == 9 && !strcmp(NameStr, "\1fseeko64")) ||
                   (NameLen == 9 && !strcmp(NameStr, "\1ftello64"))) {
          if (FTy->getNumParams() == 0 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          setDoesNotThrow(F);
          setDoesNotCapture(F, 1);
        } else if (NameLen == 10 && !strcmp(NameStr, "\1tmpfile64")) {
          if (!isa<PointerType>(FTy->getReturnType()))
            continue;
          setDoesNotThrow(F);
          setDoesNotAlias(F, 0);
        } else if ((NameLen == 8 && !strcmp(NameStr, "\1fstat64")) ||
                   (NameLen == 11 && !strcmp(NameStr, "\1fstatvfs64"))) {
          if (FTy->getNumParams() != 2 ||
              !isa<PointerType>(FTy->getParamType(1)))
            continue;
          setDoesNotThrow(F);
        } else if (NameLen == 7 && !strcmp(NameStr, "\1open64")) {
          if (FTy->getNumParams() < 2 ||
              !isa<PointerType>(FTy->getParamType(0)))
            continue;
          // May throw; "open" is a valid pthread cancellation point.
          setDoesNotCapture(F, 1);

// TODO:
//   Additional cases that we need to add to this file:
//
// cbrt:
//   * cbrt(expN(X))  -> expN(x/3)
//   * cbrt(sqrt(x))  -> pow(x,1/6)
//   * cbrt(sqrt(x))  -> pow(x,1/9)
//
// cos, cosf, cosl:
//   * cos(-x)  -> cos(x)
//
// exp, expf, expl:
//   * exp(log(x))  -> x
//
// log, logf, logl:
//   * log(exp(x))   -> x
//   * log(x**y)     -> y*log(x)
//   * log(exp(y))   -> y*log(e)
//   * log(exp2(y))  -> y*log(2)
//   * log(exp10(y)) -> y*log(10)
//   * log(sqrt(x))  -> 0.5*log(x)
//   * log(pow(x,y)) -> y*log(x)
//
// lround, lroundf, lroundl:
//   * lround(cnst) -> cnst'
//
// memcmp:
//   * memcmp(x,y,l)   -> cnst
//      (if all arguments are constant and strlen(x) <= l and strlen(y) <= l)
//
// pow, powf, powl:
//   * pow(exp(x),y)  -> exp(x*y)
//   * pow(sqrt(x),y) -> pow(x,y*0.5)
//   * pow(pow(x,y),z)-> pow(x,y*z)
//
// puts:
//   * puts("") -> putchar("\n")
//
// round, roundf, roundl:
//   * round(cnst) -> cnst'
//
// signbit:
//   * signbit(cnst) -> cnst'
//   * signbit(nncst) -> 0 (if pstv is a non-negative constant)
//
// sqrt, sqrtf, sqrtl:
//   * sqrt(expN(x))  -> expN(x*0.5)
//   * sqrt(Nroot(x)) -> pow(x,1/(2*N))
//   * sqrt(pow(x,y)) -> pow(|x|,y*0.5)
//
// stpcpy:
//   * stpcpy(str, "literal") ->
//           llvm.memcpy(str,"literal",strlen("literal")+1,1)
// strrchr:
//   * strrchr(s,c) -> reverse_offset_of_in(c,s)
//      (if c is a constant integer and s is a constant string)
//   * strrchr(s1,0) -> strchr(s1,0)
//
// strpbrk:
//   * strpbrk(s,a) -> offset_in_for(s,a)
//      (if s and a are both constant strings)
//   * strpbrk(s,"") -> 0
//   * strpbrk(s,a) -> strchr(s,a[0]) (if a is constant string of length 1)
//
// strspn, strcspn:
//   * strspn(s,a)   -> const_int (if both args are constant)
//   * strspn("",a)  -> 0
//   * strspn(s,"")  -> 0
//   * strcspn(s,a)  -> const_int (if both args are constant)
//   * strcspn("",a) -> 0
//   * strcspn(s,"") -> strlen(a)
//
// strstr:
//   * strstr(x,x)  -> x
//   * strstr(s1,s2) -> offset_of_s2_in(s1)
//       (if s1 and s2 are constant strings)
//
// tan, tanf, tanl:
//   * tan(atan(x)) -> x
//
// trunc, truncf, truncl:
//   * trunc(cnst) -> cnst'
//
//