Skip to content
SimplifyLibCalls.cpp 77.6 KiB
Newer Older
          !FTy->getParamType(0)->isPointerTy() ||
          !FTy->getParamType(1)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
      setDoesNotCapture(F, 2);
    }
    break;
  case 'p':
    if (Name == "putc") {
      if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 2);
    } else if (Name == "puts" ||
               Name == "printf" ||
               Name == "perror") {
      if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
    } else if (Name == "pread" ||
               Name == "pwrite") {
      if (FTy->getNumParams() != 4 || !FTy->getParamType(1)->isPointerTy())
        return;
      // May throw; these are valid pthread cancellation points.
      setDoesNotCapture(F, 2);
    } else if (Name == "putchar") {
      setDoesNotThrow(F);
    } else if (Name == "popen") {
      if (FTy->getNumParams() != 2 ||
          !FTy->getReturnType()->isPointerTy() ||
          !FTy->getParamType(0)->isPointerTy() ||
          !FTy->getParamType(1)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotAlias(F, 0);
      setDoesNotCapture(F, 1);
      setDoesNotCapture(F, 2);
    } else if (Name == "pclose") {
      if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
    }
    break;
  case 'v':
    if (Name == "vscanf") {
      if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
    } else if (Name == "vsscanf" ||
               Name == "vfscanf") {
      if (FTy->getNumParams() != 3 ||
          !FTy->getParamType(1)->isPointerTy() ||
          !FTy->getParamType(2)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
      setDoesNotCapture(F, 2);
    } else if (Name == "valloc") {
      if (!FTy->getReturnType()->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotAlias(F, 0);
    } else if (Name == "vprintf") {
      if (FTy->getNumParams() != 2 || !FTy->getParamType(0)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
    } else if (Name == "vfprintf" ||
               Name == "vsprintf") {
      if (FTy->getNumParams() != 3 ||
          !FTy->getParamType(0)->isPointerTy() ||
          !FTy->getParamType(1)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
      setDoesNotCapture(F, 2);
    } else if (Name == "vsnprintf") {
      if (FTy->getNumParams() != 4 ||
          !FTy->getParamType(0)->isPointerTy() ||
          !FTy->getParamType(2)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
      setDoesNotCapture(F, 3);
    }
    break;
  case 'o':
    if (Name == "open") {
      if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
        return;
      // May throw; "open" is a valid pthread cancellation point.
      setDoesNotCapture(F, 1);
    } else if (Name == "opendir") {
      if (FTy->getNumParams() != 1 ||
          !FTy->getReturnType()->isPointerTy() ||
          !FTy->getParamType(0)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotAlias(F, 0);
      setDoesNotCapture(F, 1);
    }
    break;
  case 't':
    if (Name == "tmpfile") {
      if (!FTy->getReturnType()->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotAlias(F, 0);
    } else if (Name == "times") {
      if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
    }
    break;
  case 'h':
    if (Name == "htonl" ||
        Name == "htons") {
      setDoesNotThrow(F);
      setDoesNotAccessMemory(F);
    }
    break;
  case 'n':
    if (Name == "ntohl" ||
        Name == "ntohs") {
      setDoesNotThrow(F);
      setDoesNotAccessMemory(F);
    }
    break;
  case 'l':
    if (Name == "lstat") {
      if (FTy->getNumParams() != 2 ||
          !FTy->getParamType(0)->isPointerTy() ||
          !FTy->getParamType(1)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
      setDoesNotCapture(F, 2);
    } else if (Name == "lchown") {
      if (FTy->getNumParams() != 3 || !FTy->getParamType(0)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
    }
    break;
  case 'q':
    if (Name == "qsort") {
      if (FTy->getNumParams() != 4 || !FTy->getParamType(3)->isPointerTy())
        return;
      // May throw; places call through function pointer.
      setDoesNotCapture(F, 4);
    }
    break;
  case '_':
    if (Name == "__strdup" ||
        Name == "__strndup") {
      if (FTy->getNumParams() < 1 ||
          !FTy->getReturnType()->isPointerTy() ||
          !FTy->getParamType(0)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotAlias(F, 0);
      setDoesNotCapture(F, 1);
    } else if (Name == "__strtok_r") {
      if (FTy->getNumParams() != 3 ||
          !FTy->getParamType(1)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 2);
    } else if (Name == "_IO_getc") {
      if (FTy->getNumParams() != 1 || !FTy->getParamType(0)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
    } else if (Name == "_IO_putc") {
      if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 2);
    }
    break;
  case 1:
    if (Name == "\1__isoc99_scanf") {
      if (FTy->getNumParams() < 1 ||
          !FTy->getParamType(0)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
    } else if (Name == "\1stat64" ||
               Name == "\1lstat64" ||
               Name == "\1statvfs64" ||
               Name == "\1__isoc99_sscanf") {
      if (FTy->getNumParams() < 1 ||
          !FTy->getParamType(0)->isPointerTy() ||
          !FTy->getParamType(1)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
      setDoesNotCapture(F, 2);
    } else if (Name == "\1fopen64") {
      if (FTy->getNumParams() != 2 ||
          !FTy->getReturnType()->isPointerTy() ||
          !FTy->getParamType(0)->isPointerTy() ||
          !FTy->getParamType(1)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotAlias(F, 0);
      setDoesNotCapture(F, 1);
      setDoesNotCapture(F, 2);
    } else if (Name == "\1fseeko64" ||
               Name == "\1ftello64") {
      if (FTy->getNumParams() == 0 || !FTy->getParamType(0)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 1);
    } else if (Name == "\1tmpfile64") {
      if (!FTy->getReturnType()->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotAlias(F, 0);
    } else if (Name == "\1fstat64" ||
               Name == "\1fstatvfs64") {
      if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
        return;
      setDoesNotThrow(F);
      setDoesNotCapture(F, 2);
    } else if (Name == "\1open64") {
      if (FTy->getNumParams() < 2 || !FTy->getParamType(0)->isPointerTy())
        return;
      // May throw; "open" is a valid pthread cancellation point.
      setDoesNotCapture(F, 1);
    }
    break;
  }
}

/// doInitialization - Add attributes to well-known functions.
bool SimplifyLibCalls::doInitialization(Module &M) {
  Modified = false;
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
    Function &F = *I;
    if (F.isDeclaration() && F.hasName())
      inferPrototypeAttributes(F);

// 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'
//
// 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)
//
// 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)
//
// tan, tanf, tanl:
//   * tan(atan(x)) -> x
//
// trunc, truncf, truncl:
//   * trunc(cnst) -> cnst'
//
//