OLD | NEW |
(Empty) | |
| 1 //===- BackendCanonicalize.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 // Clean up some toolchain-side PNaCl ABI simplification passes. These passes |
| 11 // allow PNaCl to have a simple and stable ABI, but they sometimes lead to |
| 12 // harder-to-optimize code. This is desirable because LLVM's definition of |
| 13 // "canonical" evolves over time, meaning that PNaCl's simple ABI can stay |
| 14 // simple yet still take full advantage of LLVM's backend by having this pass |
| 15 // massage the code into something that the backend prefers handling. |
| 16 // |
| 17 // It currently: |
| 18 // - Re-generates shufflevector (not part of the PNaCl ABI) from insertelement / |
| 19 // extractelement combinations. This is done by duplicating some of |
| 20 // instcombine's implementation, and ignoring optimizations that should |
| 21 // already have taken place. |
| 22 // - Re-materializes constant loads, especially of vectors. This requires doing |
| 23 // constant folding through bitcasts. |
| 24 // |
| 25 // The pass also performs limited DCE on instructions it knows to be dead, |
| 26 // instead of performing a full global DCE. |
| 27 // |
| 28 //===----------------------------------------------------------------------===// |
| 29 |
| 30 #include "llvm/Analysis/ConstantFolding.h" |
| 31 #include "llvm/IR/BasicBlock.h" |
| 32 #include "llvm/IR/DataLayout.h" |
| 33 #include "llvm/IR/IRBuilder.h" |
| 34 #include "llvm/IR/Instruction.h" |
| 35 #include "llvm/IR/Instructions.h" |
| 36 #include "llvm/IR/Operator.h" |
| 37 #include "llvm/IR/InstVisitor.h" |
| 38 #include "llvm/Pass.h" |
| 39 #include "llvm/Target/TargetLibraryInfo.h" |
| 40 #include "llvm/Transforms/NaCl.h" |
| 41 #include "llvm/Transforms/Utils/Local.h" |
| 42 |
| 43 using namespace llvm; |
| 44 |
| 45 // ============================================================================= |
| 46 // TODO(jfb) The following functions are as-is from instcombine. Make them |
| 47 // reusable instead. |
| 48 |
| 49 /// CollectSingleShuffleElements - If V is a shuffle of values that ONLY returns |
| 50 /// elements from either LHS or RHS, return the shuffle mask and true. |
| 51 /// Otherwise, return false. |
| 52 static bool CollectSingleShuffleElements(Value *V, Value *LHS, Value *RHS, |
| 53 SmallVectorImpl<Constant*> &Mask) { |
| 54 assert(LHS->getType() == RHS->getType() && |
| 55 "Invalid CollectSingleShuffleElements"); |
| 56 unsigned NumElts = V->getType()->getVectorNumElements(); |
| 57 |
| 58 if (isa<UndefValue>(V)) { |
| 59 Mask.assign(NumElts, UndefValue::get(Type::getInt32Ty(V->getContext()))); |
| 60 return true; |
| 61 } |
| 62 |
| 63 if (V == LHS) { |
| 64 for (unsigned i = 0; i != NumElts; ++i) |
| 65 Mask.push_back(ConstantInt::get(Type::getInt32Ty(V->getContext()), i)); |
| 66 return true; |
| 67 } |
| 68 |
| 69 if (V == RHS) { |
| 70 for (unsigned i = 0; i != NumElts; ++i) |
| 71 Mask.push_back(ConstantInt::get(Type::getInt32Ty(V->getContext()), |
| 72 i+NumElts)); |
| 73 return true; |
| 74 } |
| 75 |
| 76 if (InsertElementInst *IEI = dyn_cast<InsertElementInst>(V)) { |
| 77 // If this is an insert of an extract from some other vector, include it. |
| 78 Value *VecOp = IEI->getOperand(0); |
| 79 Value *ScalarOp = IEI->getOperand(1); |
| 80 Value *IdxOp = IEI->getOperand(2); |
| 81 |
| 82 if (!isa<ConstantInt>(IdxOp)) |
| 83 return false; |
| 84 unsigned InsertedIdx = cast<ConstantInt>(IdxOp)->getZExtValue(); |
| 85 |
| 86 if (isa<UndefValue>(ScalarOp)) { // inserting undef into vector. |
| 87 // We can handle this if the vector we are inserting into is |
| 88 // transitively ok. |
| 89 if (CollectSingleShuffleElements(VecOp, LHS, RHS, Mask)) { |
| 90 // If so, update the mask to reflect the inserted undef. |
| 91 Mask[InsertedIdx] = UndefValue::get(Type::getInt32Ty(V->getContext())); |
| 92 return true; |
| 93 } |
| 94 } else if (ExtractElementInst *EI = dyn_cast<ExtractElementInst>(ScalarOp)){ |
| 95 if (isa<ConstantInt>(EI->getOperand(1))) { |
| 96 unsigned ExtractedIdx = |
| 97 cast<ConstantInt>(EI->getOperand(1))->getZExtValue(); |
| 98 unsigned NumLHSElts = LHS->getType()->getVectorNumElements(); |
| 99 |
| 100 // This must be extracting from either LHS or RHS. |
| 101 if (EI->getOperand(0) == LHS || EI->getOperand(0) == RHS) { |
| 102 // We can handle this if the vector we are inserting into is |
| 103 // transitively ok. |
| 104 if (CollectSingleShuffleElements(VecOp, LHS, RHS, Mask)) { |
| 105 // If so, update the mask to reflect the inserted value. |
| 106 if (EI->getOperand(0) == LHS) { |
| 107 Mask[InsertedIdx % NumElts] = |
| 108 ConstantInt::get(Type::getInt32Ty(V->getContext()), |
| 109 ExtractedIdx); |
| 110 } else { |
| 111 assert(EI->getOperand(0) == RHS); |
| 112 Mask[InsertedIdx % NumElts] = |
| 113 ConstantInt::get(Type::getInt32Ty(V->getContext()), |
| 114 ExtractedIdx + NumLHSElts); |
| 115 } |
| 116 return true; |
| 117 } |
| 118 } |
| 119 } |
| 120 } |
| 121 } |
| 122 |
| 123 return false; |
| 124 } |
| 125 |
| 126 /// We are building a shuffle to create V, which is a sequence of insertelement, |
| 127 /// extractelement pairs. If PermittedRHS is set, then we must either use it or |
| 128 /// not rely on the second vector source. Return a std::pair containing the |
| 129 /// left and right vectors of the proposed shuffle (or 0), and set the Mask |
| 130 /// parameter as required. |
| 131 /// |
| 132 /// Note: we intentionally don't try to fold earlier shuffles since they have |
| 133 /// often been chosen carefully to be efficiently implementable on the target. |
| 134 typedef std::pair<Value *, Value *> ShuffleOps; |
| 135 |
| 136 static ShuffleOps CollectShuffleElements(Value *V, |
| 137 SmallVectorImpl<Constant *> &Mask, |
| 138 Value *PermittedRHS) { |
| 139 assert(V->getType()->isVectorTy() && "Invalid shuffle!"); |
| 140 unsigned NumElts = cast<VectorType>(V->getType())->getNumElements(); |
| 141 |
| 142 if (isa<UndefValue>(V)) { |
| 143 Mask.assign(NumElts, UndefValue::get(Type::getInt32Ty(V->getContext()))); |
| 144 return std::make_pair( |
| 145 PermittedRHS ? UndefValue::get(PermittedRHS->getType()) : V, nullptr); |
| 146 } |
| 147 |
| 148 if (isa<ConstantAggregateZero>(V)) { |
| 149 Mask.assign(NumElts, ConstantInt::get(Type::getInt32Ty(V->getContext()),0)); |
| 150 return std::make_pair(V, nullptr); |
| 151 } |
| 152 |
| 153 if (InsertElementInst *IEI = dyn_cast<InsertElementInst>(V)) { |
| 154 // If this is an insert of an extract from some other vector, include it. |
| 155 Value *VecOp = IEI->getOperand(0); |
| 156 Value *ScalarOp = IEI->getOperand(1); |
| 157 Value *IdxOp = IEI->getOperand(2); |
| 158 |
| 159 if (ExtractElementInst *EI = dyn_cast<ExtractElementInst>(ScalarOp)) { |
| 160 if (isa<ConstantInt>(EI->getOperand(1)) && isa<ConstantInt>(IdxOp)) { |
| 161 unsigned ExtractedIdx = |
| 162 cast<ConstantInt>(EI->getOperand(1))->getZExtValue(); |
| 163 unsigned InsertedIdx = cast<ConstantInt>(IdxOp)->getZExtValue(); |
| 164 |
| 165 // Either the extracted from or inserted into vector must be RHSVec, |
| 166 // otherwise we'd end up with a shuffle of three inputs. |
| 167 if (EI->getOperand(0) == PermittedRHS || PermittedRHS == nullptr) { |
| 168 Value *RHS = EI->getOperand(0); |
| 169 ShuffleOps LR = CollectShuffleElements(VecOp, Mask, RHS); |
| 170 assert(LR.second == nullptr || LR.second == RHS); |
| 171 |
| 172 if (LR.first->getType() != RHS->getType()) { |
| 173 // We tried our best, but we can't find anything compatible with RHS |
| 174 // further up the chain. Return a trivial shuffle. |
| 175 for (unsigned i = 0; i < NumElts; ++i) |
| 176 Mask[i] = ConstantInt::get(Type::getInt32Ty(V->getContext()), i); |
| 177 return std::make_pair(V, nullptr); |
| 178 } |
| 179 |
| 180 unsigned NumLHSElts = RHS->getType()->getVectorNumElements(); |
| 181 Mask[InsertedIdx % NumElts] = |
| 182 ConstantInt::get(Type::getInt32Ty(V->getContext()), |
| 183 NumLHSElts+ExtractedIdx); |
| 184 return std::make_pair(LR.first, RHS); |
| 185 } |
| 186 |
| 187 if (VecOp == PermittedRHS) { |
| 188 // We've gone as far as we can: anything on the other side of the |
| 189 // extractelement will already have been converted into a shuffle. |
| 190 unsigned NumLHSElts = |
| 191 EI->getOperand(0)->getType()->getVectorNumElements(); |
| 192 for (unsigned i = 0; i != NumElts; ++i) |
| 193 Mask.push_back(ConstantInt::get( |
| 194 Type::getInt32Ty(V->getContext()), |
| 195 i == InsertedIdx ? ExtractedIdx : NumLHSElts + i)); |
| 196 return std::make_pair(EI->getOperand(0), PermittedRHS); |
| 197 } |
| 198 |
| 199 // If this insertelement is a chain that comes from exactly these two |
| 200 // vectors, return the vector and the effective shuffle. |
| 201 if (EI->getOperand(0)->getType() == PermittedRHS->getType() && |
| 202 CollectSingleShuffleElements(IEI, EI->getOperand(0), PermittedRHS, |
| 203 Mask)) |
| 204 return std::make_pair(EI->getOperand(0), PermittedRHS); |
| 205 } |
| 206 } |
| 207 } |
| 208 |
| 209 // Otherwise, can't do anything fancy. Return an identity vector. |
| 210 for (unsigned i = 0; i != NumElts; ++i) |
| 211 Mask.push_back(ConstantInt::get(Type::getInt32Ty(V->getContext()), i)); |
| 212 return std::make_pair(V, nullptr); |
| 213 } |
| 214 |
| 215 // ============================================================================= |
| 216 |
| 217 |
| 218 namespace { |
| 219 |
| 220 class BackendCanonicalize : public FunctionPass, |
| 221 public InstVisitor<BackendCanonicalize, bool> { |
| 222 public: |
| 223 static char ID; // Pass identification, replacement for typeid |
| 224 BackendCanonicalize() : FunctionPass(ID), DL(0), TLI(0) { |
| 225 initializeBackendCanonicalizePass(*PassRegistry::getPassRegistry()); |
| 226 } |
| 227 virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
| 228 AU.addRequired<DataLayoutPass>(); |
| 229 AU.addRequired<TargetLibraryInfo>(); |
| 230 FunctionPass::getAnalysisUsage(AU); |
| 231 } |
| 232 |
| 233 virtual bool runOnFunction(Function &F); |
| 234 |
| 235 // InstVisitor implementation. Unhandled instructions stay as-is. |
| 236 bool visitInstruction(Instruction &I) { return false; } |
| 237 bool visitInsertElementInst(InsertElementInst &IE); |
| 238 bool visitBitCastInst(BitCastInst &C); |
| 239 bool visitLoadInst(LoadInst &L); |
| 240 |
| 241 private: |
| 242 const DataLayout *DL; |
| 243 const TargetLibraryInfo *TLI; |
| 244 |
| 245 // List of instructions that are now obsolete, and should be DCE'd. |
| 246 typedef SmallVector<Instruction *, 512> KillList; |
| 247 KillList Kill; |
| 248 |
| 249 /// Helper that constant folds an instruction. |
| 250 bool visitConstantFoldableInstruction(Instruction *I); |
| 251 |
| 252 /// Empty the kill list, making sure that all other dead instructions |
| 253 /// up the chain (but in the current basic block) also get killed. |
| 254 static void emptyKillList(KillList &Kill); |
| 255 }; |
| 256 |
| 257 } // anonymous namespace |
| 258 |
| 259 char BackendCanonicalize::ID = 0; |
| 260 INITIALIZE_PASS(BackendCanonicalize, "backend-canonicalize", |
| 261 "Canonicalize PNaCl bitcode for LLVM backends", false, false) |
| 262 |
| 263 bool BackendCanonicalize::runOnFunction(Function &F) { |
| 264 bool Modified = false; |
| 265 DL = &getAnalysis<DataLayoutPass>().getDataLayout(); |
| 266 TLI = &getAnalysis<TargetLibraryInfo>(); |
| 267 |
| 268 for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) |
| 269 for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) |
| 270 Modified |= visit(&*BI); |
| 271 emptyKillList(Kill); |
| 272 return Modified; |
| 273 } |
| 274 |
| 275 // This function is *almost* as-is from instcombine, avoiding silly |
| 276 // cases that should already have been optimized. |
| 277 bool BackendCanonicalize::visitInsertElementInst(InsertElementInst &IE) { |
| 278 Value *ScalarOp = IE.getOperand(1); |
| 279 Value *IdxOp = IE.getOperand(2); |
| 280 |
| 281 // If the inserted element was extracted from some other vector, and if the |
| 282 // indexes are constant, try to turn this into a shufflevector operation. |
| 283 if (ExtractElementInst *EI = dyn_cast<ExtractElementInst>(ScalarOp)) { |
| 284 if (isa<ConstantInt>(EI->getOperand(1)) && isa<ConstantInt>(IdxOp)) { |
| 285 unsigned NumInsertVectorElts = IE.getType()->getNumElements(); |
| 286 unsigned NumExtractVectorElts = |
| 287 EI->getOperand(0)->getType()->getVectorNumElements(); |
| 288 unsigned ExtractedIdx = |
| 289 cast<ConstantInt>(EI->getOperand(1))->getZExtValue(); |
| 290 unsigned InsertedIdx = cast<ConstantInt>(IdxOp)->getZExtValue(); |
| 291 |
| 292 if (ExtractedIdx >= NumExtractVectorElts) // Out of range extract. |
| 293 return false; |
| 294 |
| 295 if (InsertedIdx >= NumInsertVectorElts) // Out of range insert. |
| 296 return false; |
| 297 |
| 298 // If this insertelement isn't used by some other insertelement, turn it |
| 299 // (and any insertelements it points to), into one big shuffle. |
| 300 if (!IE.hasOneUse() || !isa<InsertElementInst>(IE.user_back())) { |
| 301 typedef SmallVector<Constant *, 16> MaskT; |
| 302 MaskT Mask; |
| 303 Value *LHS, *RHS; |
| 304 std::tie(LHS, RHS) = CollectShuffleElements(&IE, Mask, nullptr); |
| 305 if (!RHS) |
| 306 RHS = UndefValue::get(LHS->getType()); |
| 307 // We now have a shuffle of LHS, RHS, Mask. |
| 308 |
| 309 if (isa<UndefValue>(LHS) && !isa<UndefValue>(RHS)) { |
| 310 // Canonicalize shufflevector to always have undef on the RHS, |
| 311 // and adjust the mask. |
| 312 std::swap(LHS, RHS); |
| 313 for (MaskT::iterator I = Mask.begin(), E = Mask.end(); I != E; ++I) { |
| 314 unsigned Idx = cast<ConstantInt>(*I)->getZExtValue(); |
| 315 unsigned NewIdx = Idx >= NumInsertVectorElts |
| 316 ? Idx - NumInsertVectorElts |
| 317 : Idx + NumInsertVectorElts; |
| 318 *I = ConstantInt::get(Type::getInt32Ty(RHS->getContext()), NewIdx); |
| 319 } |
| 320 } |
| 321 |
| 322 IRBuilder<> IRB(&IE); |
| 323 IE.replaceAllUsesWith( |
| 324 IRB.CreateShuffleVector(LHS, RHS, ConstantVector::get(Mask))); |
| 325 // The chain of now-dead insertelement / extractelement |
| 326 // instructions can be deleted. |
| 327 Kill.push_back(&IE); |
| 328 |
| 329 return true; |
| 330 } |
| 331 } |
| 332 } |
| 333 |
| 334 return false; |
| 335 } |
| 336 |
| 337 bool BackendCanonicalize::visitBitCastInst(BitCastInst &B) { |
| 338 return visitConstantFoldableInstruction(&B); |
| 339 } |
| 340 |
| 341 bool BackendCanonicalize::visitLoadInst(LoadInst &L) { |
| 342 return visitConstantFoldableInstruction(&L); |
| 343 } |
| 344 |
| 345 bool BackendCanonicalize::visitConstantFoldableInstruction(Instruction *I) { |
| 346 if (Constant *Folded = ConstantFoldInstruction(I, DL, TLI)) { |
| 347 I->replaceAllUsesWith(Folded); |
| 348 Kill.push_back(I); |
| 349 return true; |
| 350 } |
| 351 return false; |
| 352 } |
| 353 |
| 354 void BackendCanonicalize::emptyKillList(KillList &Kill) { |
| 355 while (!Kill.empty()) |
| 356 RecursivelyDeleteTriviallyDeadInstructions(Kill.pop_back_val()); |
| 357 } |
| 358 |
| 359 FunctionPass *llvm::createBackendCanonicalizePass() { |
| 360 return new BackendCanonicalize(); |
| 361 } |
OLD | NEW |