aboutsummaryrefslogtreecommitdiffstats
path: root/include/llvm/Transforms/Utils/SimplifyLibCalls.h
blob: 41159603aae5ead751143e7bf2ba666435d4aef6 (plain)
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
//===- SimplifyLibCalls.h - Library call simplifier -------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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/ADT/StringRef.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/IRBuilder.h"

namespace llvm {
class Value;
class CallInst;
class DataLayout;
class Instruction;
class TargetLibraryInfo;
class BasicBlock;
class Function;

/// \brief 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);

  /// \brief 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 Func);
  Value *optimizeStrpNCpyChk(CallInst *CI, IRBuilder<> &B, LibFunc::Func Func);

  /// \brief Checks whether the call \p CI to a fortified libcall is foldable
  /// to the non-fortified version.
  bool isFortifiedCallFoldable(CallInst *CI, unsigned ObjSizeOp,
                               unsigned SizeOp, bool isString);
};

/// 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;
  bool UnsafeFPShrink;
  function_ref<void(Instruction *, Value *)> Replacer;

  /// \brief 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);

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

public:
  LibCallSimplifier(const DataLayout &DL, const TargetLibraryInfo *TLI,
                    function_ref<void(Instruction *, Value *)> Replacer =
                        &replaceAllUsesWithDefault);

  /// 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 *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 *optimizeMemCmp(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B);
  Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B);
  // Wrapper for all String/Memory Library Call Optimizations
  Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B);

  // Math Library Optimizations
  Value *optimizeUnaryDoubleFP(CallInst *CI, IRBuilder<> &B, bool CheckRetType);
  Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B);
  Value *optimizeCos(CallInst *CI, IRBuilder<> &B);
  Value *optimizePow(CallInst *CI, IRBuilder<> &B);
  Value *optimizeExp2(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFabs(CallInst *CI, IRBuilder<> &B);
  Value *optimizeSqrt(CallInst *CI, IRBuilder<> &B);
  Value *optimizeSinCosPi(CallInst *CI, IRBuilder<> &B);

  // Integer Library Call Optimizations
  Value *optimizeFFS(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);

  // 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 *optimizeFPrintF(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFWrite(CallInst *CI, IRBuilder<> &B);
  Value *optimizeFPuts(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, BasicBlock *BB, bool IsFloat,
                      SmallVectorImpl<CallInst *> &SinCalls,
                      SmallVectorImpl<CallInst *> &CosCalls,
                      SmallVectorImpl<CallInst *> &SinCosCalls);
  void replaceTrigInsts(SmallVectorImpl<CallInst *> &Calls, Value *Res);
  Value *optimizePrintFString(CallInst *CI, IRBuilder<> &B);
  Value *optimizeSPrintFString(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);
};
} // End llvm namespace

#endif