reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
//===- SimplifyLibCalls.h - Library call simplifier -------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file exposes an interface to build some C language libcalls for
// optimization passes that need to call the various functions.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H
#define LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H

#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/IRBuilder.h"

namespace llvm {
class StringRef;
class Value;
class CallInst;
class DataLayout;
class Instruction;
class TargetLibraryInfo;
class BasicBlock;
class Function;
class OptimizationRemarkEmitter;
class BlockFrequencyInfo;
class ProfileSummaryInfo;

/// This class implements simplifications for calls to fortified library
/// functions (__st*cpy_chk, __memcpy_chk, __memmove_chk, __memset_chk), to,
/// when possible, replace them with their non-checking counterparts.
/// Other optimizations can also be done, but it's possible to disable them and
/// only simplify needless use of the checking versions (when the object size
/// is unknown) by passing true for OnlyLowerUnknownSize.
class FortifiedLibCallSimplifier {
private:
  const TargetLibraryInfo *TLI;
  bool OnlyLowerUnknownSize;

public:
  FortifiedLibCallSimplifier(const TargetLibraryInfo *TLI,
                             bool OnlyLowerUnknownSize = false);

  /// Take the given call instruction and return a more
  /// optimal value to replace the instruction with or 0 if a more
  /// optimal form can't be found.
  /// The call must not be an indirect call.
  Value *optimizeCall(CallInst *CI);

private:
  Value *optimizeMemCpyChk(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemMoveChk(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemSetChk(CallInst *CI, IRBuilder<> &B);

  /// Str/Stp cpy are similar enough to be handled in the same functions.
  Value *optimizeStrpCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
  Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc Func);
  Value *optimizeMemCCpyChk(CallInst *CI, IRBuilder<> &B);
  Value *optimizeSNPrintfChk(CallInst *CI, IRBuilder<> &B);
  Value *optimizeSPrintfChk(CallInst *CI,IRBuilder<> &B);
  Value *optimizeStrCatChk(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrLCat(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrNCatChk(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrLCpyChk(CallInst *CI, IRBuilder<> &B);
  Value *optimizeVSNPrintfChk(CallInst *CI, IRBuilder<> &B);
  Value *optimizeVSPrintfChk(CallInst *CI, IRBuilder<> &B);

  /// Checks whether the call \p CI to a fortified libcall is foldable
  /// to the non-fortified version.
  ///
  /// \param CI the call to the fortified libcall.
  ///
  /// \param ObjSizeOp the index of the object size parameter of this chk
  /// function. Not optional since this is mandatory.
  ///
  /// \param SizeOp optionally set to the parameter index of an explicit buffer
  /// size argument. For instance, set to '2' for __strncpy_chk.
  ///
  /// \param StrOp optionally set to the parameter index of the source string
  /// parameter to strcpy-like functions, where only the strlen of the source
  /// will be writtin into the destination.
  ///
  /// \param FlagsOp optionally set to the parameter index of a 'flags'
  /// parameter. These are used by an implementation to opt-into stricter
  /// checking.
  bool isFortifiedCallFoldable(CallInst *CI, unsigned ObjSizeOp,
                               Optional<unsigned> SizeOp = None,
                               Optional<unsigned> StrOp = None,
                               Optional<unsigned> FlagsOp = None);
};

/// LibCallSimplifier - This class implements a collection of optimizations
/// that replace well formed calls to library functions with a more optimal
/// form.  For example, replacing 'printf("Hello!")' with 'puts("Hello!")'.
class LibCallSimplifier {
private:
  FortifiedLibCallSimplifier FortifiedSimplifier;
  const DataLayout &DL;
  const TargetLibraryInfo *TLI;
  OptimizationRemarkEmitter &ORE;
  BlockFrequencyInfo *BFI;
  ProfileSummaryInfo *PSI;
  bool UnsafeFPShrink;
  function_ref<void(Instruction *, Value *)> Replacer;
  function_ref<void(Instruction *)> Eraser;

  /// Internal wrapper for RAUW that is the default implementation.
  ///
  /// Other users may provide an alternate function with this signature instead
  /// of this one.
  static void replaceAllUsesWithDefault(Instruction *I, Value *With) {
    I->replaceAllUsesWith(With);
  }

  /// Internal wrapper for eraseFromParent that is the default implementation.
  static void eraseFromParentDefault(Instruction *I) { I->eraseFromParent(); }

  /// Replace an instruction's uses with a value using our replacer.
  void replaceAllUsesWith(Instruction *I, Value *With);

  /// Erase an instruction from its parent with our eraser.
  void eraseFromParent(Instruction *I);

  /// Replace an instruction with a value and erase it from its parent.
  void substituteInParent(Instruction *I, Value *With) {
    replaceAllUsesWith(I, With);
    eraseFromParent(I);
  }

  Value *foldMallocMemset(CallInst *Memset, IRBuilder<> &B);

public:
  LibCallSimplifier(
      const DataLayout &DL, const TargetLibraryInfo *TLI,
      OptimizationRemarkEmitter &ORE,
      BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI,
      function_ref<void(Instruction *, Value *)> Replacer =
          &replaceAllUsesWithDefault,
      function_ref<void(Instruction *)> Eraser = &eraseFromParentDefault);

  /// optimizeCall - Take the given call instruction and return a more
  /// optimal value to replace the instruction with or 0 if a more
  /// optimal form can't be found.  Note that the returned value may
  /// be equal to the instruction being optimized.  In this case all
  /// other instructions that use the given instruction were modified
  /// and the given instruction is dead.
  /// The call must not be an indirect call.
  Value *optimizeCall(CallInst *CI);

private:
  // String and Memory Library Call Optimizations
  Value *optimizeStrCat(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrNCat(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrChr(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrRChr(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrCmp(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrNCmp(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrNDup(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrCpy(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStpCpy(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrNCpy(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrLen(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrPBrk(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrTo(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrSpn(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrCSpn(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrStr(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemChr(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemRChr(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemCmp(CallInst *CI, IRBuilder<> &B);
  Value *optimizeBCmp(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemCmpBCmpCommon(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemPCpy(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B);
  Value *optimizeRealloc(CallInst *CI, IRBuilder<> &B);
  Value *optimizeWcslen(CallInst *CI, IRBuilder<> &B);
  Value *optimizeBCopy(CallInst *CI, IRBuilder<> &B);
  // Wrapper for all String/Memory Library Call Optimizations
  Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B);

  // Math Library Optimizations
  Value *optimizeCAbs(CallInst *CI, IRBuilder<> &B);
  Value *optimizePow(CallInst *CI, IRBuilder<> &B);
  Value *replacePowWithExp(CallInst *Pow, IRBuilder<> &B);
  Value *replacePowWithSqrt(CallInst *Pow, IRBuilder<> &B);
  Value *optimizeExp2(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFMinFMax(CallInst *CI, IRBuilder<> &B);
  Value *optimizeLog(CallInst *CI, IRBuilder<> &B);
  Value *optimizeSqrt(CallInst *CI, IRBuilder<> &B);
  Value *optimizeSinCosPi(CallInst *CI, IRBuilder<> &B);
  Value *optimizeTan(CallInst *CI, IRBuilder<> &B);
  // Wrapper for all floating point library call optimizations
  Value *optimizeFloatingPointLibCall(CallInst *CI, LibFunc Func,
                                      IRBuilder<> &B);

  // Integer Library Call Optimizations
  Value *optimizeFFS(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFls(CallInst *CI, IRBuilder<> &B);
  Value *optimizeAbs(CallInst *CI, IRBuilder<> &B);
  Value *optimizeIsDigit(CallInst *CI, IRBuilder<> &B);
  Value *optimizeIsAscii(CallInst *CI, IRBuilder<> &B);
  Value *optimizeToAscii(CallInst *CI, IRBuilder<> &B);
  Value *optimizeAtoi(CallInst *CI, IRBuilder<> &B);
  Value *optimizeStrtol(CallInst *CI, IRBuilder<> &B);

  // Formatting and IO Library Call Optimizations
  Value *optimizeErrorReporting(CallInst *CI, IRBuilder<> &B,
                                int StreamArg = -1);
  Value *optimizePrintF(CallInst *CI, IRBuilder<> &B);
  Value *optimizeSPrintF(CallInst *CI, IRBuilder<> &B);
  Value *optimizeSnPrintF(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFPrintF(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFWrite(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFRead(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFPuts(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFGets(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFPutc(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFGetc(CallInst *CI, IRBuilder<> &B);
  Value *optimizePuts(CallInst *CI, IRBuilder<> &B);

  // Helper methods
  Value *emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len, IRBuilder<> &B);
  void classifyArgUse(Value *Val, Function *F, bool IsFloat,
                      SmallVectorImpl<CallInst *> &SinCalls,
                      SmallVectorImpl<CallInst *> &CosCalls,
                      SmallVectorImpl<CallInst *> &SinCosCalls);
  Value *optimizePrintFString(CallInst *CI, IRBuilder<> &B);
  Value *optimizeSPrintFString(CallInst *CI, IRBuilder<> &B);
  Value *optimizeSnPrintFString(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFPrintFString(CallInst *CI, IRBuilder<> &B);

  /// hasFloatVersion - Checks if there is a float version of the specified
  /// function by checking for an existing function with name FuncName + f
  bool hasFloatVersion(StringRef FuncName);

  /// Shared code to optimize strlen+wcslen.
  Value *optimizeStringLength(CallInst *CI, IRBuilder<> &B, unsigned CharSize);
};
} // End llvm namespace

#endif