| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 1 | //===-- LowerBitSets.cpp - Bitset lowering pass ---------------------------===// | 
|  | 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 | // This pass lowers bitset metadata and calls to the llvm.bitset.test intrinsic. | 
|  | 11 | // See http://llvm.org/docs/LangRef.html#bitsets for more information. | 
|  | 12 | // | 
|  | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
|  | 15 | #include "llvm/Transforms/IPO/LowerBitSets.h" | 
|  | 16 | #include "llvm/Transforms/IPO.h" | 
|  | 17 | #include "llvm/ADT/EquivalenceClasses.h" | 
|  | 18 | #include "llvm/ADT/Statistic.h" | 
| Peter Collingbourne | c9f277f | 2015-03-14 00:00:49 +0000 | [diff] [blame] | 19 | #include "llvm/ADT/Triple.h" | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 20 | #include "llvm/IR/Constant.h" | 
|  | 21 | #include "llvm/IR/Constants.h" | 
|  | 22 | #include "llvm/IR/GlobalVariable.h" | 
|  | 23 | #include "llvm/IR/IRBuilder.h" | 
|  | 24 | #include "llvm/IR/Instructions.h" | 
|  | 25 | #include "llvm/IR/Intrinsics.h" | 
|  | 26 | #include "llvm/IR/Module.h" | 
|  | 27 | #include "llvm/IR/Operator.h" | 
|  | 28 | #include "llvm/Pass.h" | 
|  | 29 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" | 
|  | 30 |  | 
|  | 31 | using namespace llvm; | 
|  | 32 |  | 
|  | 33 | #define DEBUG_TYPE "lowerbitsets" | 
|  | 34 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 35 | STATISTIC(ByteArraySizeBits, "Byte array size in bits"); | 
|  | 36 | STATISTIC(ByteArraySizeBytes, "Byte array size in bytes"); | 
|  | 37 | STATISTIC(NumByteArraysCreated, "Number of byte arrays created"); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 38 | STATISTIC(NumBitSetCallsLowered, "Number of bitset calls lowered"); | 
|  | 39 | STATISTIC(NumBitSetDisjointSets, "Number of disjoint sets of bitsets"); | 
|  | 40 |  | 
| Peter Collingbourne | 994ba3d | 2015-03-19 22:02:10 +0000 | [diff] [blame] | 41 | static cl::opt<bool> AvoidReuse( | 
|  | 42 | "lowerbitsets-avoid-reuse", | 
|  | 43 | cl::desc("Try to avoid reuse of byte array addresses using aliases"), | 
|  | 44 | cl::Hidden, cl::init(true)); | 
|  | 45 |  | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 46 | bool BitSetInfo::containsGlobalOffset(uint64_t Offset) const { | 
|  | 47 | if (Offset < ByteOffset) | 
|  | 48 | return false; | 
|  | 49 |  | 
|  | 50 | if ((Offset - ByteOffset) % (uint64_t(1) << AlignLog2) != 0) | 
|  | 51 | return false; | 
|  | 52 |  | 
|  | 53 | uint64_t BitOffset = (Offset - ByteOffset) >> AlignLog2; | 
|  | 54 | if (BitOffset >= BitSize) | 
|  | 55 | return false; | 
|  | 56 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 57 | return Bits.count(BitOffset); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 58 | } | 
|  | 59 |  | 
|  | 60 | bool BitSetInfo::containsValue( | 
| Mehdi Amini | a28d91d | 2015-03-10 02:37:25 +0000 | [diff] [blame] | 61 | const DataLayout &DL, | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 62 | const DenseMap<GlobalVariable *, uint64_t> &GlobalLayout, Value *V, | 
|  | 63 | uint64_t COffset) const { | 
|  | 64 | if (auto GV = dyn_cast<GlobalVariable>(V)) { | 
|  | 65 | auto I = GlobalLayout.find(GV); | 
|  | 66 | if (I == GlobalLayout.end()) | 
|  | 67 | return false; | 
|  | 68 | return containsGlobalOffset(I->second + COffset); | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | if (auto GEP = dyn_cast<GEPOperator>(V)) { | 
| Mehdi Amini | a28d91d | 2015-03-10 02:37:25 +0000 | [diff] [blame] | 72 | APInt APOffset(DL.getPointerSizeInBits(0), 0); | 
|  | 73 | bool Result = GEP->accumulateConstantOffset(DL, APOffset); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 74 | if (!Result) | 
|  | 75 | return false; | 
|  | 76 | COffset += APOffset.getZExtValue(); | 
|  | 77 | return containsValue(DL, GlobalLayout, GEP->getPointerOperand(), | 
|  | 78 | COffset); | 
|  | 79 | } | 
|  | 80 |  | 
|  | 81 | if (auto Op = dyn_cast<Operator>(V)) { | 
|  | 82 | if (Op->getOpcode() == Instruction::BitCast) | 
|  | 83 | return containsValue(DL, GlobalLayout, Op->getOperand(0), COffset); | 
|  | 84 |  | 
|  | 85 | if (Op->getOpcode() == Instruction::Select) | 
|  | 86 | return containsValue(DL, GlobalLayout, Op->getOperand(1), COffset) && | 
|  | 87 | containsValue(DL, GlobalLayout, Op->getOperand(2), COffset); | 
|  | 88 | } | 
|  | 89 |  | 
|  | 90 | return false; | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 | BitSetInfo BitSetBuilder::build() { | 
|  | 94 | if (Min > Max) | 
|  | 95 | Min = 0; | 
|  | 96 |  | 
|  | 97 | // Normalize each offset against the minimum observed offset, and compute | 
|  | 98 | // the bitwise OR of each of the offsets. The number of trailing zeros | 
|  | 99 | // in the mask gives us the log2 of the alignment of all offsets, which | 
|  | 100 | // allows us to compress the bitset by only storing one bit per aligned | 
|  | 101 | // address. | 
|  | 102 | uint64_t Mask = 0; | 
|  | 103 | for (uint64_t &Offset : Offsets) { | 
|  | 104 | Offset -= Min; | 
|  | 105 | Mask |= Offset; | 
|  | 106 | } | 
|  | 107 |  | 
|  | 108 | BitSetInfo BSI; | 
|  | 109 | BSI.ByteOffset = Min; | 
|  | 110 |  | 
|  | 111 | BSI.AlignLog2 = 0; | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 112 | if (Mask != 0) | 
|  | 113 | BSI.AlignLog2 = countTrailingZeros(Mask, ZB_Undefined); | 
|  | 114 |  | 
|  | 115 | // Build the compressed bitset while normalizing the offsets against the | 
|  | 116 | // computed alignment. | 
|  | 117 | BSI.BitSize = ((Max - Min) >> BSI.AlignLog2) + 1; | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 118 | for (uint64_t Offset : Offsets) { | 
|  | 119 | Offset >>= BSI.AlignLog2; | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 120 | BSI.Bits.insert(Offset); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 121 | } | 
|  | 122 |  | 
|  | 123 | return BSI; | 
|  | 124 | } | 
|  | 125 |  | 
| Peter Collingbourne | 1baeaa3 | 2015-02-24 23:17:02 +0000 | [diff] [blame] | 126 | void GlobalLayoutBuilder::addFragment(const std::set<uint64_t> &F) { | 
|  | 127 | // Create a new fragment to hold the layout for F. | 
|  | 128 | Fragments.emplace_back(); | 
|  | 129 | std::vector<uint64_t> &Fragment = Fragments.back(); | 
|  | 130 | uint64_t FragmentIndex = Fragments.size() - 1; | 
|  | 131 |  | 
|  | 132 | for (auto ObjIndex : F) { | 
|  | 133 | uint64_t OldFragmentIndex = FragmentMap[ObjIndex]; | 
|  | 134 | if (OldFragmentIndex == 0) { | 
|  | 135 | // We haven't seen this object index before, so just add it to the current | 
|  | 136 | // fragment. | 
|  | 137 | Fragment.push_back(ObjIndex); | 
|  | 138 | } else { | 
|  | 139 | // This index belongs to an existing fragment. Copy the elements of the | 
|  | 140 | // old fragment into this one and clear the old fragment. We don't update | 
|  | 141 | // the fragment map just yet, this ensures that any further references to | 
|  | 142 | // indices from the old fragment in this fragment do not insert any more | 
|  | 143 | // indices. | 
|  | 144 | std::vector<uint64_t> &OldFragment = Fragments[OldFragmentIndex]; | 
|  | 145 | Fragment.insert(Fragment.end(), OldFragment.begin(), OldFragment.end()); | 
|  | 146 | OldFragment.clear(); | 
|  | 147 | } | 
|  | 148 | } | 
|  | 149 |  | 
|  | 150 | // Update the fragment map to point our object indices to this fragment. | 
|  | 151 | for (uint64_t ObjIndex : Fragment) | 
|  | 152 | FragmentMap[ObjIndex] = FragmentIndex; | 
|  | 153 | } | 
|  | 154 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 155 | void ByteArrayBuilder::allocate(const std::set<uint64_t> &Bits, | 
|  | 156 | uint64_t BitSize, uint64_t &AllocByteOffset, | 
|  | 157 | uint8_t &AllocMask) { | 
|  | 158 | // Find the smallest current allocation. | 
|  | 159 | unsigned Bit = 0; | 
|  | 160 | for (unsigned I = 1; I != BitsPerByte; ++I) | 
|  | 161 | if (BitAllocs[I] < BitAllocs[Bit]) | 
|  | 162 | Bit = I; | 
|  | 163 |  | 
|  | 164 | AllocByteOffset = BitAllocs[Bit]; | 
|  | 165 |  | 
|  | 166 | // Add our size to it. | 
|  | 167 | unsigned ReqSize = AllocByteOffset + BitSize; | 
|  | 168 | BitAllocs[Bit] = ReqSize; | 
|  | 169 | if (Bytes.size() < ReqSize) | 
|  | 170 | Bytes.resize(ReqSize); | 
|  | 171 |  | 
|  | 172 | // Set our bits. | 
|  | 173 | AllocMask = 1 << Bit; | 
|  | 174 | for (uint64_t B : Bits) | 
|  | 175 | Bytes[AllocByteOffset + B] |= AllocMask; | 
|  | 176 | } | 
|  | 177 |  | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 178 | namespace { | 
|  | 179 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 180 | struct ByteArrayInfo { | 
|  | 181 | std::set<uint64_t> Bits; | 
|  | 182 | uint64_t BitSize; | 
|  | 183 | GlobalVariable *ByteArray; | 
|  | 184 | Constant *Mask; | 
|  | 185 | }; | 
|  | 186 |  | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 187 | struct LowerBitSets : public ModulePass { | 
|  | 188 | static char ID; | 
|  | 189 | LowerBitSets() : ModulePass(ID) { | 
|  | 190 | initializeLowerBitSetsPass(*PassRegistry::getPassRegistry()); | 
|  | 191 | } | 
|  | 192 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 193 | Module *M; | 
|  | 194 |  | 
| Peter Collingbourne | c9f277f | 2015-03-14 00:00:49 +0000 | [diff] [blame] | 195 | bool LinkerSubsectionsViaSymbols; | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 196 | IntegerType *Int1Ty; | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 197 | IntegerType *Int8Ty; | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 198 | IntegerType *Int32Ty; | 
|  | 199 | Type *Int32PtrTy; | 
|  | 200 | IntegerType *Int64Ty; | 
|  | 201 | Type *IntPtrTy; | 
|  | 202 |  | 
|  | 203 | // The llvm.bitsets named metadata. | 
|  | 204 | NamedMDNode *BitSetNM; | 
|  | 205 |  | 
|  | 206 | // Mapping from bitset mdstrings to the call sites that test them. | 
|  | 207 | DenseMap<MDString *, std::vector<CallInst *>> BitSetTestCallSites; | 
|  | 208 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 209 | std::vector<ByteArrayInfo> ByteArrayInfos; | 
|  | 210 |  | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 211 | BitSetInfo | 
|  | 212 | buildBitSet(MDString *BitSet, | 
|  | 213 | const DenseMap<GlobalVariable *, uint64_t> &GlobalLayout); | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 214 | ByteArrayInfo *createByteArray(BitSetInfo &BSI); | 
|  | 215 | void allocateByteArrays(); | 
|  | 216 | Value *createBitSetTest(IRBuilder<> &B, BitSetInfo &BSI, ByteArrayInfo *&BAI, | 
|  | 217 | Value *BitOffset); | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 218 | Value * | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 219 | lowerBitSetCall(CallInst *CI, BitSetInfo &BSI, ByteArrayInfo *&BAI, | 
|  | 220 | GlobalVariable *CombinedGlobal, | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 221 | const DenseMap<GlobalVariable *, uint64_t> &GlobalLayout); | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 222 | void buildBitSetsFromGlobals(const std::vector<MDString *> &BitSets, | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 223 | const std::vector<GlobalVariable *> &Globals); | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 224 | bool buildBitSets(); | 
|  | 225 | bool eraseBitSetMetadata(); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 226 |  | 
|  | 227 | bool doInitialization(Module &M) override; | 
|  | 228 | bool runOnModule(Module &M) override; | 
|  | 229 | }; | 
|  | 230 |  | 
|  | 231 | } // namespace | 
|  | 232 |  | 
|  | 233 | INITIALIZE_PASS_BEGIN(LowerBitSets, "lowerbitsets", | 
|  | 234 | "Lower bitset metadata", false, false) | 
|  | 235 | INITIALIZE_PASS_END(LowerBitSets, "lowerbitsets", | 
|  | 236 | "Lower bitset metadata", false, false) | 
|  | 237 | char LowerBitSets::ID = 0; | 
|  | 238 |  | 
|  | 239 | ModulePass *llvm::createLowerBitSetsPass() { return new LowerBitSets; } | 
|  | 240 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 241 | bool LowerBitSets::doInitialization(Module &Mod) { | 
|  | 242 | M = &Mod; | 
| Mehdi Amini | a28d91d | 2015-03-10 02:37:25 +0000 | [diff] [blame] | 243 | const DataLayout &DL = Mod.getDataLayout(); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 244 |  | 
| Peter Collingbourne | c9f277f | 2015-03-14 00:00:49 +0000 | [diff] [blame] | 245 | Triple TargetTriple(M->getTargetTriple()); | 
|  | 246 | LinkerSubsectionsViaSymbols = TargetTriple.isMacOSX(); | 
|  | 247 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 248 | Int1Ty = Type::getInt1Ty(M->getContext()); | 
|  | 249 | Int8Ty = Type::getInt8Ty(M->getContext()); | 
|  | 250 | Int32Ty = Type::getInt32Ty(M->getContext()); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 251 | Int32PtrTy = PointerType::getUnqual(Int32Ty); | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 252 | Int64Ty = Type::getInt64Ty(M->getContext()); | 
| Mehdi Amini | a28d91d | 2015-03-10 02:37:25 +0000 | [diff] [blame] | 253 | IntPtrTy = DL.getIntPtrType(M->getContext(), 0); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 254 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 255 | BitSetNM = M->getNamedMetadata("llvm.bitsets"); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 256 |  | 
|  | 257 | BitSetTestCallSites.clear(); | 
|  | 258 |  | 
|  | 259 | return false; | 
|  | 260 | } | 
|  | 261 |  | 
| NAKAMURA Takumi | 6c24684 | 2015-02-22 09:51:42 +0000 | [diff] [blame] | 262 | /// Build a bit set for BitSet using the object layouts in | 
|  | 263 | /// GlobalLayout. | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 264 | BitSetInfo LowerBitSets::buildBitSet( | 
|  | 265 | MDString *BitSet, | 
|  | 266 | const DenseMap<GlobalVariable *, uint64_t> &GlobalLayout) { | 
|  | 267 | BitSetBuilder BSB; | 
|  | 268 |  | 
|  | 269 | // Compute the byte offset of each element of this bitset. | 
|  | 270 | if (BitSetNM) { | 
|  | 271 | for (MDNode *Op : BitSetNM->operands()) { | 
|  | 272 | if (Op->getOperand(0) != BitSet || !Op->getOperand(1)) | 
|  | 273 | continue; | 
|  | 274 | auto OpGlobal = cast<GlobalVariable>( | 
|  | 275 | cast<ConstantAsMetadata>(Op->getOperand(1))->getValue()); | 
|  | 276 | uint64_t Offset = | 
|  | 277 | cast<ConstantInt>(cast<ConstantAsMetadata>(Op->getOperand(2)) | 
|  | 278 | ->getValue())->getZExtValue(); | 
|  | 279 |  | 
|  | 280 | Offset += GlobalLayout.find(OpGlobal)->second; | 
|  | 281 |  | 
|  | 282 | BSB.addOffset(Offset); | 
|  | 283 | } | 
|  | 284 | } | 
|  | 285 |  | 
|  | 286 | return BSB.build(); | 
|  | 287 | } | 
|  | 288 |  | 
| NAKAMURA Takumi | 6c24684 | 2015-02-22 09:51:42 +0000 | [diff] [blame] | 289 | /// Build a test that bit BitOffset mod sizeof(Bits)*8 is set in | 
|  | 290 | /// Bits. This pattern matches to the bt instruction on x86. | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 291 | static Value *createMaskedBitTest(IRBuilder<> &B, Value *Bits, | 
|  | 292 | Value *BitOffset) { | 
|  | 293 | auto BitsType = cast<IntegerType>(Bits->getType()); | 
|  | 294 | unsigned BitWidth = BitsType->getBitWidth(); | 
|  | 295 |  | 
|  | 296 | BitOffset = B.CreateZExtOrTrunc(BitOffset, BitsType); | 
|  | 297 | Value *BitIndex = | 
|  | 298 | B.CreateAnd(BitOffset, ConstantInt::get(BitsType, BitWidth - 1)); | 
|  | 299 | Value *BitMask = B.CreateShl(ConstantInt::get(BitsType, 1), BitIndex); | 
|  | 300 | Value *MaskedBits = B.CreateAnd(Bits, BitMask); | 
|  | 301 | return B.CreateICmpNE(MaskedBits, ConstantInt::get(BitsType, 0)); | 
|  | 302 | } | 
|  | 303 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 304 | ByteArrayInfo *LowerBitSets::createByteArray(BitSetInfo &BSI) { | 
|  | 305 | // Create globals to stand in for byte arrays and masks. These never actually | 
|  | 306 | // get initialized, we RAUW and erase them later in allocateByteArrays() once | 
|  | 307 | // we know the offset and mask to use. | 
|  | 308 | auto ByteArrayGlobal = new GlobalVariable( | 
|  | 309 | *M, Int8Ty, /*isConstant=*/true, GlobalValue::PrivateLinkage, nullptr); | 
|  | 310 | auto MaskGlobal = new GlobalVariable( | 
|  | 311 | *M, Int8Ty, /*isConstant=*/true, GlobalValue::PrivateLinkage, nullptr); | 
|  | 312 |  | 
|  | 313 | ByteArrayInfos.emplace_back(); | 
|  | 314 | ByteArrayInfo *BAI = &ByteArrayInfos.back(); | 
|  | 315 |  | 
|  | 316 | BAI->Bits = BSI.Bits; | 
|  | 317 | BAI->BitSize = BSI.BitSize; | 
|  | 318 | BAI->ByteArray = ByteArrayGlobal; | 
|  | 319 | BAI->Mask = ConstantExpr::getPtrToInt(MaskGlobal, Int8Ty); | 
|  | 320 | return BAI; | 
|  | 321 | } | 
|  | 322 |  | 
|  | 323 | void LowerBitSets::allocateByteArrays() { | 
|  | 324 | std::stable_sort(ByteArrayInfos.begin(), ByteArrayInfos.end(), | 
|  | 325 | [](const ByteArrayInfo &BAI1, const ByteArrayInfo &BAI2) { | 
|  | 326 | return BAI1.BitSize > BAI2.BitSize; | 
|  | 327 | }); | 
|  | 328 |  | 
|  | 329 | std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size()); | 
|  | 330 |  | 
|  | 331 | ByteArrayBuilder BAB; | 
|  | 332 | for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) { | 
|  | 333 | ByteArrayInfo *BAI = &ByteArrayInfos[I]; | 
|  | 334 |  | 
|  | 335 | uint8_t Mask; | 
|  | 336 | BAB.allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[I], Mask); | 
|  | 337 |  | 
|  | 338 | BAI->Mask->replaceAllUsesWith(ConstantInt::get(Int8Ty, Mask)); | 
|  | 339 | cast<GlobalVariable>(BAI->Mask->getOperand(0))->eraseFromParent(); | 
|  | 340 | } | 
|  | 341 |  | 
|  | 342 | Constant *ByteArrayConst = ConstantDataArray::get(M->getContext(), BAB.Bytes); | 
|  | 343 | auto ByteArray = | 
|  | 344 | new GlobalVariable(*M, ByteArrayConst->getType(), /*isConstant=*/true, | 
|  | 345 | GlobalValue::PrivateLinkage, ByteArrayConst); | 
|  | 346 |  | 
|  | 347 | for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) { | 
|  | 348 | ByteArrayInfo *BAI = &ByteArrayInfos[I]; | 
|  | 349 |  | 
|  | 350 | Constant *Idxs[] = {ConstantInt::get(IntPtrTy, 0), | 
|  | 351 | ConstantInt::get(IntPtrTy, ByteArrayOffsets[I])}; | 
| David Blaikie | 4a2e73b | 2015-04-02 18:55:32 +0000 | [diff] [blame] | 352 | Constant *GEP = ConstantExpr::getInBoundsGetElementPtr( | 
|  | 353 | ByteArrayConst->getType(), ByteArray, Idxs); | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 354 |  | 
|  | 355 | // Create an alias instead of RAUW'ing the gep directly. On x86 this ensures | 
|  | 356 | // that the pc-relative displacement is folded into the lea instead of the | 
|  | 357 | // test instruction getting another displacement. | 
| Peter Collingbourne | ad0bdcd | 2015-03-16 23:36:24 +0000 | [diff] [blame] | 358 | if (LinkerSubsectionsViaSymbols) { | 
|  | 359 | BAI->ByteArray->replaceAllUsesWith(GEP); | 
|  | 360 | } else { | 
| David Blaikie | f64246b | 2015-04-29 21:22:39 +0000 | [diff] [blame] | 361 | GlobalAlias *Alias = | 
|  | 362 | GlobalAlias::create(PointerType::getUnqual(Int8Ty), | 
|  | 363 | GlobalValue::PrivateLinkage, "bits", GEP, M); | 
| Peter Collingbourne | ad0bdcd | 2015-03-16 23:36:24 +0000 | [diff] [blame] | 364 | BAI->ByteArray->replaceAllUsesWith(Alias); | 
|  | 365 | } | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 366 | BAI->ByteArray->eraseFromParent(); | 
|  | 367 | } | 
|  | 368 |  | 
|  | 369 | ByteArraySizeBits = BAB.BitAllocs[0] + BAB.BitAllocs[1] + BAB.BitAllocs[2] + | 
|  | 370 | BAB.BitAllocs[3] + BAB.BitAllocs[4] + BAB.BitAllocs[5] + | 
|  | 371 | BAB.BitAllocs[6] + BAB.BitAllocs[7]; | 
|  | 372 | ByteArraySizeBytes = BAB.Bytes.size(); | 
|  | 373 | } | 
|  | 374 |  | 
| NAKAMURA Takumi | 6c24684 | 2015-02-22 09:51:42 +0000 | [diff] [blame] | 375 | /// Build a test that bit BitOffset is set in BSI, where | 
|  | 376 | /// BitSetGlobal is a global containing the bits in BSI. | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 377 | Value *LowerBitSets::createBitSetTest(IRBuilder<> &B, BitSetInfo &BSI, | 
|  | 378 | ByteArrayInfo *&BAI, Value *BitOffset) { | 
|  | 379 | if (BSI.BitSize <= 64) { | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 380 | // If the bit set is sufficiently small, we can avoid a load by bit testing | 
|  | 381 | // a constant. | 
|  | 382 | IntegerType *BitsTy; | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 383 | if (BSI.BitSize <= 32) | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 384 | BitsTy = Int32Ty; | 
|  | 385 | else | 
|  | 386 | BitsTy = Int64Ty; | 
|  | 387 |  | 
|  | 388 | uint64_t Bits = 0; | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 389 | for (auto Bit : BSI.Bits) | 
|  | 390 | Bits |= uint64_t(1) << Bit; | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 391 | Constant *BitsConst = ConstantInt::get(BitsTy, Bits); | 
|  | 392 | return createMaskedBitTest(B, BitsConst, BitOffset); | 
|  | 393 | } else { | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 394 | if (!BAI) { | 
|  | 395 | ++NumByteArraysCreated; | 
|  | 396 | BAI = createByteArray(BSI); | 
|  | 397 | } | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 398 |  | 
| Peter Collingbourne | 994ba3d | 2015-03-19 22:02:10 +0000 | [diff] [blame] | 399 | Constant *ByteArray = BAI->ByteArray; | 
| David Blaikie | 93c5444 | 2015-04-03 19:41:44 +0000 | [diff] [blame] | 400 | Type *Ty = BAI->ByteArray->getValueType(); | 
| Peter Collingbourne | 994ba3d | 2015-03-19 22:02:10 +0000 | [diff] [blame] | 401 | if (!LinkerSubsectionsViaSymbols && AvoidReuse) { | 
|  | 402 | // Each use of the byte array uses a different alias. This makes the | 
|  | 403 | // backend less likely to reuse previously computed byte array addresses, | 
|  | 404 | // improving the security of the CFI mechanism based on this pass. | 
| David Blaikie | f64246b | 2015-04-29 21:22:39 +0000 | [diff] [blame] | 405 | ByteArray = GlobalAlias::create(BAI->ByteArray->getType(), | 
| David Blaikie | 93c5444 | 2015-04-03 19:41:44 +0000 | [diff] [blame] | 406 | GlobalValue::PrivateLinkage, "bits_use", | 
|  | 407 | ByteArray, M); | 
| Peter Collingbourne | 994ba3d | 2015-03-19 22:02:10 +0000 | [diff] [blame] | 408 | } | 
|  | 409 |  | 
| David Blaikie | 93c5444 | 2015-04-03 19:41:44 +0000 | [diff] [blame] | 410 | Value *ByteAddr = B.CreateGEP(Ty, ByteArray, BitOffset); | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 411 | Value *Byte = B.CreateLoad(ByteAddr); | 
|  | 412 |  | 
|  | 413 | Value *ByteAndMask = B.CreateAnd(Byte, BAI->Mask); | 
|  | 414 | return B.CreateICmpNE(ByteAndMask, ConstantInt::get(Int8Ty, 0)); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 415 | } | 
|  | 416 | } | 
|  | 417 |  | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 418 | /// Lower a llvm.bitset.test call to its implementation. Returns the value to | 
|  | 419 | /// replace the call with. | 
|  | 420 | Value *LowerBitSets::lowerBitSetCall( | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 421 | CallInst *CI, BitSetInfo &BSI, ByteArrayInfo *&BAI, | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 422 | GlobalVariable *CombinedGlobal, | 
|  | 423 | const DenseMap<GlobalVariable *, uint64_t> &GlobalLayout) { | 
|  | 424 | Value *Ptr = CI->getArgOperand(0); | 
| Mehdi Amini | a28d91d | 2015-03-10 02:37:25 +0000 | [diff] [blame] | 425 | const DataLayout &DL = M->getDataLayout(); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 426 |  | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 427 | if (BSI.containsValue(DL, GlobalLayout, Ptr)) | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 428 | return ConstantInt::getTrue(CombinedGlobal->getParent()->getContext()); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 429 |  | 
|  | 430 | Constant *GlobalAsInt = ConstantExpr::getPtrToInt(CombinedGlobal, IntPtrTy); | 
|  | 431 | Constant *OffsetedGlobalAsInt = ConstantExpr::getAdd( | 
|  | 432 | GlobalAsInt, ConstantInt::get(IntPtrTy, BSI.ByteOffset)); | 
|  | 433 |  | 
|  | 434 | BasicBlock *InitialBB = CI->getParent(); | 
|  | 435 |  | 
|  | 436 | IRBuilder<> B(CI); | 
|  | 437 |  | 
|  | 438 | Value *PtrAsInt = B.CreatePtrToInt(Ptr, IntPtrTy); | 
|  | 439 |  | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 440 | if (BSI.isSingleOffset()) | 
|  | 441 | return B.CreateICmpEQ(PtrAsInt, OffsetedGlobalAsInt); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 442 |  | 
|  | 443 | Value *PtrOffset = B.CreateSub(PtrAsInt, OffsetedGlobalAsInt); | 
|  | 444 |  | 
|  | 445 | Value *BitOffset; | 
|  | 446 | if (BSI.AlignLog2 == 0) { | 
|  | 447 | BitOffset = PtrOffset; | 
|  | 448 | } else { | 
|  | 449 | // We need to check that the offset both falls within our range and is | 
|  | 450 | // suitably aligned. We can check both properties at the same time by | 
|  | 451 | // performing a right rotate by log2(alignment) followed by an integer | 
|  | 452 | // comparison against the bitset size. The rotate will move the lower | 
|  | 453 | // order bits that need to be zero into the higher order bits of the | 
|  | 454 | // result, causing the comparison to fail if they are nonzero. The rotate | 
|  | 455 | // also conveniently gives us a bit offset to use during the load from | 
|  | 456 | // the bitset. | 
|  | 457 | Value *OffsetSHR = | 
|  | 458 | B.CreateLShr(PtrOffset, ConstantInt::get(IntPtrTy, BSI.AlignLog2)); | 
|  | 459 | Value *OffsetSHL = B.CreateShl( | 
| Mehdi Amini | a28d91d | 2015-03-10 02:37:25 +0000 | [diff] [blame] | 460 | PtrOffset, | 
|  | 461 | ConstantInt::get(IntPtrTy, DL.getPointerSizeInBits(0) - BSI.AlignLog2)); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 462 | BitOffset = B.CreateOr(OffsetSHR, OffsetSHL); | 
|  | 463 | } | 
|  | 464 |  | 
|  | 465 | Constant *BitSizeConst = ConstantInt::get(IntPtrTy, BSI.BitSize); | 
|  | 466 | Value *OffsetInRange = B.CreateICmpULT(BitOffset, BitSizeConst); | 
|  | 467 |  | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 468 | // If the bit set is all ones, testing against it is unnecessary. | 
|  | 469 | if (BSI.isAllOnes()) | 
|  | 470 | return OffsetInRange; | 
|  | 471 |  | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 472 | TerminatorInst *Term = SplitBlockAndInsertIfThen(OffsetInRange, CI, false); | 
|  | 473 | IRBuilder<> ThenB(Term); | 
|  | 474 |  | 
|  | 475 | // Now that we know that the offset is in range and aligned, load the | 
|  | 476 | // appropriate bit from the bitset. | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 477 | Value *Bit = createBitSetTest(ThenB, BSI, BAI, BitOffset); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 478 |  | 
|  | 479 | // The value we want is 0 if we came directly from the initial block | 
|  | 480 | // (having failed the range or alignment checks), or the loaded bit if | 
|  | 481 | // we came from the block in which we loaded it. | 
|  | 482 | B.SetInsertPoint(CI); | 
|  | 483 | PHINode *P = B.CreatePHI(Int1Ty, 2); | 
|  | 484 | P->addIncoming(ConstantInt::get(Int1Ty, 0), InitialBB); | 
|  | 485 | P->addIncoming(Bit, ThenB.GetInsertBlock()); | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 486 | return P; | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 487 | } | 
|  | 488 |  | 
|  | 489 | /// Given a disjoint set of bitsets and globals, layout the globals, build the | 
|  | 490 | /// bit sets and lower the llvm.bitset.test calls. | 
|  | 491 | void LowerBitSets::buildBitSetsFromGlobals( | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 492 | const std::vector<MDString *> &BitSets, | 
|  | 493 | const std::vector<GlobalVariable *> &Globals) { | 
|  | 494 | // Build a new global with the combined contents of the referenced globals. | 
|  | 495 | std::vector<Constant *> GlobalInits; | 
| Mehdi Amini | a28d91d | 2015-03-10 02:37:25 +0000 | [diff] [blame] | 496 | const DataLayout &DL = M->getDataLayout(); | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 497 | for (GlobalVariable *G : Globals) { | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 498 | GlobalInits.push_back(G->getInitializer()); | 
| Mehdi Amini | a28d91d | 2015-03-10 02:37:25 +0000 | [diff] [blame] | 499 | uint64_t InitSize = DL.getTypeAllocSize(G->getInitializer()->getType()); | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 500 |  | 
|  | 501 | // Compute the amount of padding required to align the next element to the | 
|  | 502 | // next power of 2. | 
|  | 503 | uint64_t Padding = NextPowerOf2(InitSize - 1) - InitSize; | 
|  | 504 |  | 
|  | 505 | // Cap at 128 was found experimentally to have a good data/instruction | 
|  | 506 | // overhead tradeoff. | 
|  | 507 | if (Padding > 128) | 
|  | 508 | Padding = RoundUpToAlignment(InitSize, 128) - InitSize; | 
|  | 509 |  | 
|  | 510 | GlobalInits.push_back( | 
|  | 511 | ConstantAggregateZero::get(ArrayType::get(Int8Ty, Padding))); | 
|  | 512 | } | 
|  | 513 | if (!GlobalInits.empty()) | 
|  | 514 | GlobalInits.pop_back(); | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 515 | Constant *NewInit = ConstantStruct::getAnon(M->getContext(), GlobalInits); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 516 | auto CombinedGlobal = | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 517 | new GlobalVariable(*M, NewInit->getType(), /*isConstant=*/true, | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 518 | GlobalValue::PrivateLinkage, NewInit); | 
|  | 519 |  | 
|  | 520 | const StructLayout *CombinedGlobalLayout = | 
| Mehdi Amini | a28d91d | 2015-03-10 02:37:25 +0000 | [diff] [blame] | 521 | DL.getStructLayout(cast<StructType>(NewInit->getType())); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 522 |  | 
|  | 523 | // Compute the offsets of the original globals within the new global. | 
|  | 524 | DenseMap<GlobalVariable *, uint64_t> GlobalLayout; | 
|  | 525 | for (unsigned I = 0; I != Globals.size(); ++I) | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 526 | // Multiply by 2 to account for padding elements. | 
|  | 527 | GlobalLayout[Globals[I]] = CombinedGlobalLayout->getElementOffset(I * 2); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 528 |  | 
|  | 529 | // For each bitset in this disjoint set... | 
|  | 530 | for (MDString *BS : BitSets) { | 
|  | 531 | // Build the bitset. | 
|  | 532 | BitSetInfo BSI = buildBitSet(BS, GlobalLayout); | 
|  | 533 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 534 | ByteArrayInfo *BAI = 0; | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 535 |  | 
|  | 536 | // Lower each call to llvm.bitset.test for this bitset. | 
|  | 537 | for (CallInst *CI : BitSetTestCallSites[BS]) { | 
|  | 538 | ++NumBitSetCallsLowered; | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 539 | Value *Lowered = lowerBitSetCall(CI, BSI, BAI, CombinedGlobal, GlobalLayout); | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 540 | CI->replaceAllUsesWith(Lowered); | 
|  | 541 | CI->eraseFromParent(); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 542 | } | 
|  | 543 | } | 
|  | 544 |  | 
|  | 545 | // Build aliases pointing to offsets into the combined global for each | 
|  | 546 | // global from which we built the combined global, and replace references | 
|  | 547 | // to the original globals with references to the aliases. | 
|  | 548 | for (unsigned I = 0; I != Globals.size(); ++I) { | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 549 | // Multiply by 2 to account for padding elements. | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 550 | Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0), | 
| Peter Collingbourne | eba7f73 | 2015-02-25 20:42:41 +0000 | [diff] [blame] | 551 | ConstantInt::get(Int32Ty, I * 2)}; | 
| David Blaikie | 4a2e73b | 2015-04-02 18:55:32 +0000 | [diff] [blame] | 552 | Constant *CombinedGlobalElemPtr = ConstantExpr::getGetElementPtr( | 
|  | 553 | NewInit->getType(), CombinedGlobal, CombinedGlobalIdxs); | 
| Peter Collingbourne | ad0bdcd | 2015-03-16 23:36:24 +0000 | [diff] [blame] | 554 | if (LinkerSubsectionsViaSymbols) { | 
|  | 555 | Globals[I]->replaceAllUsesWith(CombinedGlobalElemPtr); | 
|  | 556 | } else { | 
| David Blaikie | f64246b | 2015-04-29 21:22:39 +0000 | [diff] [blame] | 557 | GlobalAlias *GAlias = | 
|  | 558 | GlobalAlias::create(Globals[I]->getType(), Globals[I]->getLinkage(), | 
| Peter Collingbourne | 4fc603d | 2015-06-17 18:31:02 +0000 | [diff] [blame] | 559 | "", CombinedGlobalElemPtr, M); | 
|  | 560 | GAlias->takeName(Globals[I]); | 
| Peter Collingbourne | ad0bdcd | 2015-03-16 23:36:24 +0000 | [diff] [blame] | 561 | Globals[I]->replaceAllUsesWith(GAlias); | 
|  | 562 | } | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 563 | Globals[I]->eraseFromParent(); | 
|  | 564 | } | 
|  | 565 | } | 
|  | 566 |  | 
|  | 567 | /// Lower all bit sets in this module. | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 568 | bool LowerBitSets::buildBitSets() { | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 569 | Function *BitSetTestFunc = | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 570 | M->getFunction(Intrinsic::getName(Intrinsic::bitset_test)); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 571 | if (!BitSetTestFunc) | 
|  | 572 | return false; | 
|  | 573 |  | 
|  | 574 | // Equivalence class set containing bitsets and the globals they reference. | 
|  | 575 | // This is used to partition the set of bitsets in the module into disjoint | 
|  | 576 | // sets. | 
|  | 577 | typedef EquivalenceClasses<PointerUnion<GlobalVariable *, MDString *>> | 
|  | 578 | GlobalClassesTy; | 
|  | 579 | GlobalClassesTy GlobalClasses; | 
|  | 580 |  | 
|  | 581 | for (const Use &U : BitSetTestFunc->uses()) { | 
|  | 582 | auto CI = cast<CallInst>(U.getUser()); | 
|  | 583 |  | 
|  | 584 | auto BitSetMDVal = dyn_cast<MetadataAsValue>(CI->getArgOperand(1)); | 
|  | 585 | if (!BitSetMDVal || !isa<MDString>(BitSetMDVal->getMetadata())) | 
|  | 586 | report_fatal_error( | 
|  | 587 | "Second argument of llvm.bitset.test must be metadata string"); | 
|  | 588 | auto BitSet = cast<MDString>(BitSetMDVal->getMetadata()); | 
|  | 589 |  | 
|  | 590 | // Add the call site to the list of call sites for this bit set. We also use | 
|  | 591 | // BitSetTestCallSites to keep track of whether we have seen this bit set | 
|  | 592 | // before. If we have, we don't need to re-add the referenced globals to the | 
|  | 593 | // equivalence class. | 
|  | 594 | std::pair<DenseMap<MDString *, std::vector<CallInst *>>::iterator, | 
|  | 595 | bool> Ins = | 
|  | 596 | BitSetTestCallSites.insert( | 
|  | 597 | std::make_pair(BitSet, std::vector<CallInst *>())); | 
|  | 598 | Ins.first->second.push_back(CI); | 
|  | 599 | if (!Ins.second) | 
|  | 600 | continue; | 
|  | 601 |  | 
|  | 602 | // Add the bitset to the equivalence class. | 
|  | 603 | GlobalClassesTy::iterator GCI = GlobalClasses.insert(BitSet); | 
|  | 604 | GlobalClassesTy::member_iterator CurSet = GlobalClasses.findLeader(GCI); | 
|  | 605 |  | 
|  | 606 | if (!BitSetNM) | 
|  | 607 | continue; | 
|  | 608 |  | 
|  | 609 | // Verify the bitset metadata and add the referenced globals to the bitset's | 
|  | 610 | // equivalence class. | 
|  | 611 | for (MDNode *Op : BitSetNM->operands()) { | 
|  | 612 | if (Op->getNumOperands() != 3) | 
|  | 613 | report_fatal_error( | 
|  | 614 | "All operands of llvm.bitsets metadata must have 3 elements"); | 
|  | 615 |  | 
|  | 616 | if (Op->getOperand(0) != BitSet || !Op->getOperand(1)) | 
|  | 617 | continue; | 
|  | 618 |  | 
|  | 619 | auto OpConstMD = dyn_cast<ConstantAsMetadata>(Op->getOperand(1)); | 
|  | 620 | if (!OpConstMD) | 
|  | 621 | report_fatal_error("Bit set element must be a constant"); | 
|  | 622 | auto OpGlobal = dyn_cast<GlobalVariable>(OpConstMD->getValue()); | 
|  | 623 | if (!OpGlobal) | 
|  | 624 | report_fatal_error("Bit set element must refer to global"); | 
|  | 625 |  | 
|  | 626 | auto OffsetConstMD = dyn_cast<ConstantAsMetadata>(Op->getOperand(2)); | 
|  | 627 | if (!OffsetConstMD) | 
|  | 628 | report_fatal_error("Bit set element offset must be a constant"); | 
|  | 629 | auto OffsetInt = dyn_cast<ConstantInt>(OffsetConstMD->getValue()); | 
|  | 630 | if (!OffsetInt) | 
|  | 631 | report_fatal_error( | 
|  | 632 | "Bit set element offset must be an integer constant"); | 
|  | 633 |  | 
|  | 634 | CurSet = GlobalClasses.unionSets( | 
|  | 635 | CurSet, GlobalClasses.findLeader(GlobalClasses.insert(OpGlobal))); | 
|  | 636 | } | 
|  | 637 | } | 
|  | 638 |  | 
|  | 639 | if (GlobalClasses.empty()) | 
|  | 640 | return false; | 
|  | 641 |  | 
|  | 642 | // For each disjoint set we found... | 
|  | 643 | for (GlobalClassesTy::iterator I = GlobalClasses.begin(), | 
|  | 644 | E = GlobalClasses.end(); | 
|  | 645 | I != E; ++I) { | 
|  | 646 | if (!I->isLeader()) continue; | 
|  | 647 |  | 
|  | 648 | ++NumBitSetDisjointSets; | 
|  | 649 |  | 
|  | 650 | // Build the list of bitsets and referenced globals in this disjoint set. | 
|  | 651 | std::vector<MDString *> BitSets; | 
|  | 652 | std::vector<GlobalVariable *> Globals; | 
| Peter Collingbourne | 1baeaa3 | 2015-02-24 23:17:02 +0000 | [diff] [blame] | 653 | llvm::DenseMap<MDString *, uint64_t> BitSetIndices; | 
|  | 654 | llvm::DenseMap<GlobalVariable *, uint64_t> GlobalIndices; | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 655 | for (GlobalClassesTy::member_iterator MI = GlobalClasses.member_begin(I); | 
|  | 656 | MI != GlobalClasses.member_end(); ++MI) { | 
| Peter Collingbourne | 1baeaa3 | 2015-02-24 23:17:02 +0000 | [diff] [blame] | 657 | if ((*MI).is<MDString *>()) { | 
|  | 658 | BitSetIndices[MI->get<MDString *>()] = BitSets.size(); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 659 | BitSets.push_back(MI->get<MDString *>()); | 
| Peter Collingbourne | 1baeaa3 | 2015-02-24 23:17:02 +0000 | [diff] [blame] | 660 | } else { | 
|  | 661 | GlobalIndices[MI->get<GlobalVariable *>()] = Globals.size(); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 662 | Globals.push_back(MI->get<GlobalVariable *>()); | 
| Peter Collingbourne | 1baeaa3 | 2015-02-24 23:17:02 +0000 | [diff] [blame] | 663 | } | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 664 | } | 
|  | 665 |  | 
| Peter Collingbourne | 1baeaa3 | 2015-02-24 23:17:02 +0000 | [diff] [blame] | 666 | // For each bitset, build a set of indices that refer to globals referenced | 
|  | 667 | // by the bitset. | 
|  | 668 | std::vector<std::set<uint64_t>> BitSetMembers(BitSets.size()); | 
|  | 669 | if (BitSetNM) { | 
|  | 670 | for (MDNode *Op : BitSetNM->operands()) { | 
|  | 671 | // Op = { bitset name, global, offset } | 
|  | 672 | if (!Op->getOperand(1)) | 
|  | 673 | continue; | 
|  | 674 | auto I = BitSetIndices.find(cast<MDString>(Op->getOperand(0))); | 
|  | 675 | if (I == BitSetIndices.end()) | 
|  | 676 | continue; | 
|  | 677 |  | 
|  | 678 | auto OpGlobal = cast<GlobalVariable>( | 
|  | 679 | cast<ConstantAsMetadata>(Op->getOperand(1))->getValue()); | 
|  | 680 | BitSetMembers[I->second].insert(GlobalIndices[OpGlobal]); | 
|  | 681 | } | 
|  | 682 | } | 
|  | 683 |  | 
|  | 684 | // Order the sets of indices by size. The GlobalLayoutBuilder works best | 
|  | 685 | // when given small index sets first. | 
|  | 686 | std::stable_sort( | 
|  | 687 | BitSetMembers.begin(), BitSetMembers.end(), | 
|  | 688 | [](const std::set<uint64_t> &O1, const std::set<uint64_t> &O2) { | 
|  | 689 | return O1.size() < O2.size(); | 
|  | 690 | }); | 
|  | 691 |  | 
|  | 692 | // Create a GlobalLayoutBuilder and provide it with index sets as layout | 
|  | 693 | // fragments. The GlobalLayoutBuilder tries to lay out members of fragments | 
|  | 694 | // as close together as possible. | 
|  | 695 | GlobalLayoutBuilder GLB(Globals.size()); | 
|  | 696 | for (auto &&MemSet : BitSetMembers) | 
|  | 697 | GLB.addFragment(MemSet); | 
|  | 698 |  | 
|  | 699 | // Build a vector of globals with the computed layout. | 
|  | 700 | std::vector<GlobalVariable *> OrderedGlobals(Globals.size()); | 
|  | 701 | auto OGI = OrderedGlobals.begin(); | 
|  | 702 | for (auto &&F : GLB.Fragments) | 
|  | 703 | for (auto &&Offset : F) | 
|  | 704 | *OGI++ = Globals[Offset]; | 
|  | 705 |  | 
|  | 706 | // Order bitsets by name for determinism. | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 707 | std::sort(BitSets.begin(), BitSets.end(), [](MDString *S1, MDString *S2) { | 
|  | 708 | return S1->getString() < S2->getString(); | 
|  | 709 | }); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 710 |  | 
|  | 711 | // Build the bitsets from this disjoint set. | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 712 | buildBitSetsFromGlobals(BitSets, OrderedGlobals); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 713 | } | 
|  | 714 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 715 | allocateByteArrays(); | 
|  | 716 |  | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 717 | return true; | 
|  | 718 | } | 
|  | 719 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 720 | bool LowerBitSets::eraseBitSetMetadata() { | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 721 | if (!BitSetNM) | 
|  | 722 | return false; | 
|  | 723 |  | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 724 | M->eraseNamedMetadata(BitSetNM); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 725 | return true; | 
|  | 726 | } | 
|  | 727 |  | 
|  | 728 | bool LowerBitSets::runOnModule(Module &M) { | 
| Peter Collingbourne | da2dbf2 | 2015-03-03 00:49:28 +0000 | [diff] [blame] | 729 | bool Changed = buildBitSets(); | 
|  | 730 | Changed |= eraseBitSetMetadata(); | 
| Peter Collingbourne | e6909c8 | 2015-02-20 20:30:47 +0000 | [diff] [blame] | 731 | return Changed; | 
|  | 732 | } |