blob: 7fd52c949f30337ea3834321725bda64c7e3e0ba [file] [log] [blame]
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +00001//===--- 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
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000010#include "llvm/ADT/APInt.h"
11#include "llvm/ADT/StringRef.h"
12#include "llvm/IR/BasicBlock.h"
13#include "llvm/IR/CFG.h"
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000014#include "llvm/IR/Constants.h"
15#include "llvm/IR/Dominators.h"
16#include "llvm/IR/Function.h"
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000017#include "llvm/IR/Instruction.h"
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000018#include "llvm/IR/Instructions.h"
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000019#include "llvm/IR/Intrinsics.h"
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000020#include "llvm/IR/IRBuilder.h"
21#include "llvm/IR/PatternMatch.h"
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000022#include "llvm/IR/Type.h"
23#include "llvm/IR/Value.h"
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000024#include "llvm/Pass.h"
25#include "llvm/Support/CommandLine.h"
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000026#include <algorithm>
27#include <cstdint>
28#include <iterator>
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000029
30using namespace llvm;
31
32static 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").
42static cl::opt<bool> NoSR0("extract-nosr0", cl::init(true), cl::Hidden,
43 cl::desc("No extract instruction with offset 0"));
44
45static cl::opt<bool> NeedAnd("extract-needand", cl::init(true), cl::Hidden,
46 cl::desc("Require & in extract patterns"));
47
48namespace llvm {
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000049
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000050 void initializeHexagonGenExtractPass(PassRegistry&);
51 FunctionPass *createHexagonGenExtract();
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000052
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000053} // end namespace llvm
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000054
55namespace {
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000056
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000057 class HexagonGenExtract : public FunctionPass {
58 public:
59 static char ID;
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000060
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000061 HexagonGenExtract() : FunctionPass(ID), ExtractCount(0) {
62 initializeHexagonGenExtractPass(*PassRegistry::getPassRegistry());
63 }
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000064
65 StringRef getPassName() const override {
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000066 return "Hexagon generate \"extract\" instructions";
67 }
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000068
69 bool runOnFunction(Function &F) override;
70
71 void getAnalysisUsage(AnalysisUsage &AU) const override {
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000072 AU.addRequired<DominatorTreeWrapperPass>();
73 AU.addPreserved<DominatorTreeWrapperPass>();
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000074 FunctionPass::getAnalysisUsage(AU);
75 }
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000076
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000077 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;
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000086
87} // end anonymous namespace
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000088
89INITIALIZE_PASS_BEGIN(HexagonGenExtract, "hextract", "Hexagon generate "
90 "\"extract\" instructions", false, false)
91INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
92INITIALIZE_PASS_END(HexagonGenExtract, "hextract", "Hexagon generate "
93 "\"extract\" instructions", false, false)
94
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +000095bool HexagonGenExtract::convert(Instruction *In) {
96 using namespace PatternMatch;
Eugene Zelenkof9f8c682016-12-14 22:50:46 +000097
98 Value *BF = nullptr;
99 ConstantInt *CSL = nullptr, *CSR = nullptr, *CM = nullptr;
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +0000100 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) {
Eugene Zelenkof9f8c682016-12-14 22:50:46 +0000141 CM = nullptr;
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +0000142 // (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) {
Eugene Zelenkof9f8c682016-12-14 22:50:46 +0000148 CM = nullptr;
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +0000149 // (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) || !APIntOps::isMask(W, M))
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 (!APIntOps::isMask(W, M.getLoBits(U)))
207 return false;
208 }
209
Duncan P. N. Exon Smitha72c6e22015-10-20 00:46:39 +0000210 IRBuilder<> IRB(In);
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +0000211 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
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +0000222bool HexagonGenExtract::visitBlock(BasicBlock *B) {
223 // Depth-first, bottom-up traversal.
Daniel Berlin58a6e572017-02-09 20:37:24 +0000224 for (auto *DTN : graph_children<DomTreeNode*>(DT->getNode(B)))
225 visitBlock(DTN->getBlock());
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +0000226
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
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +0000251bool HexagonGenExtract::runOnFunction(Function &F) {
Andrew Kaylor5b444a22016-04-26 19:46:28 +0000252 if (skipFunction(F))
253 return false;
254
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +0000255 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
Krzysztof Parzyszeka0ecf072015-07-14 17:07:24 +0000266FunctionPass *llvm::createHexagonGenExtract() {
267 return new HexagonGenExtract();
268}