OSDN Git Service

Sort the remaining #include lines in include/... and lib/....
[android-x86/external-llvm.git] / lib / Target / Hexagon / HexagonGenExtract.cpp
1 //===--- HexagonGenExtract.cpp --------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/ADT/APInt.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/IR/BasicBlock.h"
13 #include "llvm/IR/CFG.h"
14 #include "llvm/IR/Constants.h"
15 #include "llvm/IR/Dominators.h"
16 #include "llvm/IR/Function.h"
17 #include "llvm/IR/IRBuilder.h"
18 #include "llvm/IR/Instruction.h"
19 #include "llvm/IR/Instructions.h"
20 #include "llvm/IR/Intrinsics.h"
21 #include "llvm/IR/PatternMatch.h"
22 #include "llvm/IR/Type.h"
23 #include "llvm/IR/Value.h"
24 #include "llvm/Pass.h"
25 #include "llvm/Support/CommandLine.h"
26 #include <algorithm>
27 #include <cstdint>
28 #include <iterator>
29
30 using namespace llvm;
31
32 static cl::opt<unsigned> ExtractCutoff("extract-cutoff", cl::init(~0U),
33   cl::Hidden, cl::desc("Cutoff for generating \"extract\""
34   " instructions"));
35
36 // This prevents generating extract instructions that have the offset of 0.
37 // One of the reasons for "extract" is to put a sequence of bits in a regis-
38 // ter, starting at offset 0 (so that these bits can then be used by an
39 // "insert"). If the bits are already at offset 0, it is better not to gene-
40 // rate "extract", since logical bit operations can be merged into compound
41 // instructions (as opposed to "extract").
42 static cl::opt<bool> NoSR0("extract-nosr0", cl::init(true), cl::Hidden,
43   cl::desc("No extract instruction with offset 0"));
44
45 static cl::opt<bool> NeedAnd("extract-needand", cl::init(true), cl::Hidden,
46   cl::desc("Require & in extract patterns"));
47
48 namespace llvm {
49
50   void initializeHexagonGenExtractPass(PassRegistry&);
51   FunctionPass *createHexagonGenExtract();
52
53 } // end namespace llvm
54
55 namespace {
56
57   class HexagonGenExtract : public FunctionPass {
58   public:
59     static char ID;
60
61     HexagonGenExtract() : FunctionPass(ID), ExtractCount(0) {
62       initializeHexagonGenExtractPass(*PassRegistry::getPassRegistry());
63     }
64
65     StringRef getPassName() const override {
66       return "Hexagon generate \"extract\" instructions";
67     }
68
69     bool runOnFunction(Function &F) override;
70
71     void getAnalysisUsage(AnalysisUsage &AU) const override {
72       AU.addRequired<DominatorTreeWrapperPass>();
73       AU.addPreserved<DominatorTreeWrapperPass>();
74       FunctionPass::getAnalysisUsage(AU);
75     }
76
77   private:
78     bool visitBlock(BasicBlock *B);
79     bool convert(Instruction *In);
80
81     unsigned ExtractCount;
82     DominatorTree *DT;
83   };
84
85   char HexagonGenExtract::ID = 0;
86
87 } // end anonymous namespace
88
89 INITIALIZE_PASS_BEGIN(HexagonGenExtract, "hextract", "Hexagon generate "
90   "\"extract\" instructions", false, false)
91 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
92 INITIALIZE_PASS_END(HexagonGenExtract, "hextract", "Hexagon generate "
93   "\"extract\" instructions", false, false)
94
95 bool HexagonGenExtract::convert(Instruction *In) {
96   using namespace PatternMatch;
97
98   Value *BF = nullptr;
99   ConstantInt *CSL = nullptr, *CSR = nullptr, *CM = nullptr;
100   BasicBlock *BB = In->getParent();
101   LLVMContext &Ctx = BB->getContext();
102   bool LogicalSR;
103
104   // (and (shl (lshr x, #sr), #sl), #m)
105   LogicalSR = true;
106   bool Match = match(In, m_And(m_Shl(m_LShr(m_Value(BF), m_ConstantInt(CSR)),
107                                m_ConstantInt(CSL)),
108                          m_ConstantInt(CM)));
109
110   if (!Match) {
111     // (and (shl (ashr x, #sr), #sl), #m)
112     LogicalSR = false;
113     Match = match(In, m_And(m_Shl(m_AShr(m_Value(BF), m_ConstantInt(CSR)),
114                             m_ConstantInt(CSL)),
115                       m_ConstantInt(CM)));
116   }
117   if (!Match) {
118     // (and (shl x, #sl), #m)
119     LogicalSR = true;
120     CSR = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
121     Match = match(In, m_And(m_Shl(m_Value(BF), m_ConstantInt(CSL)),
122                       m_ConstantInt(CM)));
123     if (Match && NoSR0)
124       return false;
125   }
126   if (!Match) {
127     // (and (lshr x, #sr), #m)
128     LogicalSR = true;
129     CSL = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
130     Match = match(In, m_And(m_LShr(m_Value(BF), m_ConstantInt(CSR)),
131                             m_ConstantInt(CM)));
132   }
133   if (!Match) {
134     // (and (ashr x, #sr), #m)
135     LogicalSR = false;
136     CSL = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
137     Match = match(In, m_And(m_AShr(m_Value(BF), m_ConstantInt(CSR)),
138                             m_ConstantInt(CM)));
139   }
140   if (!Match) {
141     CM = nullptr;
142     // (shl (lshr x, #sr), #sl)
143     LogicalSR = true;
144     Match = match(In, m_Shl(m_LShr(m_Value(BF), m_ConstantInt(CSR)),
145                             m_ConstantInt(CSL)));
146   }
147   if (!Match) {
148     CM = nullptr;
149     // (shl (ashr x, #sr), #sl)
150     LogicalSR = false;
151     Match = match(In, m_Shl(m_AShr(m_Value(BF), m_ConstantInt(CSR)),
152                             m_ConstantInt(CSL)));
153   }
154   if (!Match)
155     return false;
156
157   Type *Ty = BF->getType();
158   if (!Ty->isIntegerTy())
159     return false;
160   unsigned BW = Ty->getPrimitiveSizeInBits();
161   if (BW != 32 && BW != 64)
162     return false;
163
164   uint32_t SR = CSR->getZExtValue();
165   uint32_t SL = CSL->getZExtValue();
166
167   if (!CM) {
168     // If there was no and, and the shift left did not remove all potential
169     // sign bits created by the shift right, then extractu cannot reproduce
170     // this value.
171     if (!LogicalSR && (SR > SL))
172       return false;
173     APInt A = APInt(BW, ~0ULL).lshr(SR).shl(SL);
174     CM = ConstantInt::get(Ctx, A);
175   }
176
177   // CM is the shifted-left mask. Shift it back right to remove the zero
178   // bits on least-significant positions.
179   APInt M = CM->getValue().lshr(SL);
180   uint32_t T = M.countTrailingOnes();
181
182   // During the shifts some of the bits will be lost. Calculate how many
183   // of the original value will remain after shift right and then left.
184   uint32_t U = BW - std::max(SL, SR);
185   // The width of the extracted field is the minimum of the original bits
186   // that remain after the shifts and the number of contiguous 1s in the mask.
187   uint32_t W = std::min(U, T);
188   if (W == 0)
189     return false;
190
191   // Check if the extracted bits are contained within the mask that it is
192   // and-ed with. The extract operation will copy these bits, and so the
193   // mask cannot any holes in it that would clear any of the bits of the
194   // extracted field.
195   if (!LogicalSR) {
196     // If the shift right was arithmetic, it could have included some 1 bits.
197     // It is still ok to generate extract, but only if the mask eliminates
198     // those bits (i.e. M does not have any bits set beyond U).
199     APInt C = APInt::getHighBitsSet(BW, BW-U);
200     if (M.intersects(C) || !M.isMask(W))
201       return false;
202   } else {
203     // Check if M starts with a contiguous sequence of W times 1 bits. Get
204     // the low U bits of M (which eliminates the 0 bits shifted in on the
205     // left), and check if the result is APInt's "mask":
206     if (!M.getLoBits(U).isMask(W))
207       return false;
208   }
209
210   IRBuilder<> IRB(In);
211   Intrinsic::ID IntId = (BW == 32) ? Intrinsic::hexagon_S2_extractu
212                                    : Intrinsic::hexagon_S2_extractup;
213   Module *Mod = BB->getParent()->getParent();
214   Value *ExtF = Intrinsic::getDeclaration(Mod, IntId);
215   Value *NewIn = IRB.CreateCall(ExtF, {BF, IRB.getInt32(W), IRB.getInt32(SR)});
216   if (SL != 0)
217     NewIn = IRB.CreateShl(NewIn, SL, CSL->getName());
218   In->replaceAllUsesWith(NewIn);
219   return true;
220 }
221
222 bool HexagonGenExtract::visitBlock(BasicBlock *B) {
223   // Depth-first, bottom-up traversal.
224   for (auto *DTN : children<DomTreeNode*>(DT->getNode(B)))
225     visitBlock(DTN->getBlock());
226
227   // Allow limiting the number of generated extracts for debugging purposes.
228   bool HasCutoff = ExtractCutoff.getPosition();
229   unsigned Cutoff = ExtractCutoff;
230
231   bool Changed = false;
232   BasicBlock::iterator I = std::prev(B->end()), NextI, Begin = B->begin();
233   while (true) {
234     if (HasCutoff && (ExtractCount >= Cutoff))
235       return Changed;
236     bool Last = (I == Begin);
237     if (!Last)
238       NextI = std::prev(I);
239     Instruction *In = &*I;
240     bool Done = convert(In);
241     if (HasCutoff && Done)
242       ExtractCount++;
243     Changed |= Done;
244     if (Last)
245       break;
246     I = NextI;
247   }
248   return Changed;
249 }
250
251 bool HexagonGenExtract::runOnFunction(Function &F) {
252   if (skipFunction(F))
253     return false;
254
255   DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
256   bool Changed;
257
258   // Traverse the function bottom-up, to see super-expressions before their
259   // sub-expressions.
260   BasicBlock *Entry = GraphTraits<Function*>::getEntryNode(&F);
261   Changed = visitBlock(Entry);
262
263   return Changed;
264 }
265
266 FunctionPass *llvm::createHexagonGenExtract() {
267   return new HexagonGenExtract();
268 }