diff --git a/llvm/lib/Target/DirectX/DXILPrepare.cpp b/llvm/lib/Target/DirectX/DXILPrepare.cpp --- a/llvm/lib/Target/DirectX/DXILPrepare.cpp +++ b/llvm/lib/Target/DirectX/DXILPrepare.cpp @@ -94,8 +94,10 @@ Builder.SetInsertPoint(&Inst); // This code only gets hit in opaque-pointer mode, so the type of the // pointer doesn't matter. - return Builder.Insert(CastInst::Create(Instruction::BitCast, Operand, - Builder.getInt8PtrTy())); + PointerType *PtrTy = cast(Operand->getType()); + return Builder.Insert( + CastInst::Create(Instruction::BitCast, Operand, + Builder.getInt8PtrTy(PtrTy->getAddressSpace()))); } public: diff --git a/llvm/lib/Target/DirectX/DXILWriter/CMakeLists.txt b/llvm/lib/Target/DirectX/DXILWriter/CMakeLists.txt --- a/llvm/lib/Target/DirectX/DXILWriter/CMakeLists.txt +++ b/llvm/lib/Target/DirectX/DXILWriter/CMakeLists.txt @@ -1,3 +1,5 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../) + add_llvm_component_library(LLVMDXILBitWriter DXILBitcodeWriter.cpp DXILValueEnumerator.cpp diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp --- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp +++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp @@ -12,6 +12,7 @@ #include "DXILBitcodeWriter.h" #include "DXILValueEnumerator.h" +#include "PointerTypeAnalysis.h" #include "llvm/ADT/Triple.h" #include "llvm/Bitcode/BitcodeCommon.h" #include "llvm/Bitcode/BitcodeReader.h" @@ -88,6 +89,10 @@ FUNCTION_INST_GEP_ABBREV, }; + // Cache some types + Type *I8Ty; + Type *I8PtrTy; + /// The stream created and owned by the client. BitstreamWriter &Stream; @@ -117,14 +122,23 @@ /// The start bit of the identification block. uint64_t BitcodeStartBit; + /// This maps values to their typed pointers + PointerTypeMap PointerMap; + public: /// Constructs a ModuleBitcodeWriter object for the given Module, /// writing to the provided \p Buffer. DXILBitcodeWriter(const Module &M, SmallVectorImpl &Buffer, StringTableBuilder &StrtabBuilder, BitstreamWriter &Stream) - : Stream(Stream), StrtabBuilder(StrtabBuilder), M(M), VE(M, true), - Buffer(Buffer), BitcodeStartBit(Stream.GetCurrentBitNo()) { + : I8Ty(Type::getInt8Ty(M.getContext())), + I8PtrTy(TypedPointerType::get(I8Ty, 0)), Stream(Stream), + StrtabBuilder(StrtabBuilder), M(M), VE(M, I8PtrTy), Buffer(Buffer), + BitcodeStartBit(Stream.GetCurrentBitNo()), + PointerMap(PointerTypeAnalysis::run(M)) { GlobalValueId = VE.getValues().size(); + // Enumerate the typed pointers + for (auto El : PointerMap) + VE.EnumerateType(El.second); } /// Emit the current module to the bitstream. @@ -329,6 +343,9 @@ unsigned getEncodedSyncScopeID(SyncScope::ID SSID) { return unsigned(SSID); } unsigned getEncodedAlign(MaybeAlign Alignment) { return encode(Alignment); } + + unsigned getTypeID(Type *T, const Value *V = nullptr); + unsigned getTypeID(Type *T, const Function *F); }; } // namespace dxil @@ -532,6 +549,22 @@ } } +unsigned DXILBitcodeWriter::getTypeID(Type *T, const Value *V) { + if (!T->isOpaquePointerTy()) + return VE.getTypeID(T); + auto It = PointerMap.find(V); + if (It != PointerMap.end()) + return VE.getTypeID(It->second); + return VE.getTypeID(I8PtrTy); +} + +unsigned DXILBitcodeWriter::getTypeID(Type *T, const Function *F) { + auto It = PointerMap.find(F); + if (It != PointerMap.end()) + return VE.getTypeID(It->second); + return VE.getTypeID(T); +} + unsigned DXILBitcodeWriter::getEncodedRMWOperation(AtomicRMWInst::BinOp Op) { switch (Op) { default: @@ -993,7 +1026,6 @@ case Type::BFloatTyID: case Type::X86_AMXTyID: case Type::TokenTyID: - case Type::DXILPointerTyID: llvm_unreachable("These should never be used!!!"); break; case Type::VoidTyID: @@ -1031,25 +1063,46 @@ Code = bitc::TYPE_CODE_INTEGER; TypeVals.push_back(cast(T)->getBitWidth()); break; - case Type::PointerTyID: { - PointerType *PTy = cast(T); + case Type::DXILPointerTyID: { + TypedPointerType *PTy = cast(T); // POINTER: [pointee type, address space] Code = bitc::TYPE_CODE_POINTER; - TypeVals.push_back(VE.getTypeID(PTy->getNonOpaquePointerElementType())); + TypeVals.push_back(getTypeID(PTy->getElementType())); unsigned AddressSpace = PTy->getAddressSpace(); TypeVals.push_back(AddressSpace); if (AddressSpace == 0) AbbrevToUse = PtrAbbrev; break; } + case Type::PointerTyID: { + PointerType *PTy = cast(T); + // POINTER: [pointee type, address space] + Code = bitc::TYPE_CODE_POINTER; + // Emitting an empty struct type for the opaque pointer's type allows + // this to be order-independent. Non-struct types must be emitted in + // bitcode before they can be referenced. + if (PTy->isOpaquePointerTy()) { + TypeVals.push_back(false); + Code = bitc::TYPE_CODE_OPAQUE; + writeStringRecord(Stream, bitc::TYPE_CODE_STRUCT_NAME, + "dxilOpaquePtrReservedName", StructNameAbbrev); + } else { + TypeVals.push_back(getTypeID(PTy->getNonOpaquePointerElementType())); + unsigned AddressSpace = PTy->getAddressSpace(); + TypeVals.push_back(AddressSpace); + if (AddressSpace == 0) + AbbrevToUse = PtrAbbrev; + } + break; + } case Type::FunctionTyID: { FunctionType *FT = cast(T); // FUNCTION: [isvararg, retty, paramty x N] Code = bitc::TYPE_CODE_FUNCTION; TypeVals.push_back(FT->isVarArg()); - TypeVals.push_back(VE.getTypeID(FT->getReturnType())); + TypeVals.push_back(getTypeID(FT->getReturnType())); for (Type *PTy : FT->params()) - TypeVals.push_back(VE.getTypeID(PTy)); + TypeVals.push_back(getTypeID(PTy)); AbbrevToUse = FunctionAbbrev; break; } @@ -1059,7 +1112,7 @@ TypeVals.push_back(ST->isPacked()); // Output all of the element types. for (Type *ElTy : ST->elements()) - TypeVals.push_back(VE.getTypeID(ElTy)); + TypeVals.push_back(getTypeID(ElTy)); if (ST->isLiteral()) { Code = bitc::TYPE_CODE_STRUCT_ANON; @@ -1084,7 +1137,7 @@ // ARRAY: [numelts, eltty] Code = bitc::TYPE_CODE_ARRAY; TypeVals.push_back(AT->getNumElements()); - TypeVals.push_back(VE.getTypeID(AT->getElementType())); + TypeVals.push_back(getTypeID(AT->getElementType())); AbbrevToUse = ArrayAbbrev; break; } @@ -1094,7 +1147,7 @@ // VECTOR [numelts, eltty] Code = bitc::TYPE_CODE_VECTOR; TypeVals.push_back(VT->getElementCount().getKnownMinValue()); - TypeVals.push_back(VE.getTypeID(VT->getElementType())); + TypeVals.push_back(getTypeID(VT->getElementType())); break; } } @@ -1151,7 +1204,7 @@ }; for (const GlobalVariable &GV : M.globals()) { UpdateMaxAlignment(GV.getAlign()); - MaxGlobalType = std::max(MaxGlobalType, VE.getTypeID(GV.getValueType())); + MaxGlobalType = std::max(MaxGlobalType, getTypeID(GV.getValueType(), &GV)); if (GV.hasSection()) { // Give section names unique ID's. unsigned &Entry = SectionMap[std::string(GV.getSection())]; @@ -1187,7 +1240,8 @@ // Emit abbrev for globals, now that we know # sections and max alignment. unsigned SimpleGVarAbbrev = 0; if (!M.global_empty()) { - // Add an abbrev for common globals with no visibility or thread localness. + // Add an abbrev for common globals with no visibility or thread + // localness. auto Abbv = std::make_shared(); Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_GLOBALVAR)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, @@ -1222,7 +1276,7 @@ // linkage, alignment, section, visibility, threadlocal, // unnamed_addr, externally_initialized, dllstorageclass, // comdat] - Vals.push_back(VE.getTypeID(GV.getValueType())); + Vals.push_back(getTypeID(GV.getValueType(), &GV)); Vals.push_back( GV.getType()->getAddressSpace() << 2 | 2 | (GV.isConstant() ? 1 : 0)); // HLSL Change - bitwise | was used with @@ -1258,7 +1312,7 @@ // FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment, // section, visibility, gc, unnamed_addr, prologuedata, // dllstorageclass, comdat, prefixdata, personalityfn] - Vals.push_back(VE.getTypeID(F.getFunctionType())); + Vals.push_back(getTypeID(F.getFunctionType(), &F)); Vals.push_back(F.getCallingConv()); Vals.push_back(F.isDeclaration()); Vals.push_back(getEncodedLinkage(F)); @@ -1286,7 +1340,7 @@ // Emit the alias information. for (const GlobalAlias &A : M.aliases()) { // ALIAS: [alias type, aliasee val#, linkage, visibility] - Vals.push_back(VE.getTypeID(A.getValueType())); + Vals.push_back(getTypeID(A.getValueType(), &A)); Vals.push_back(VE.getValueID(A.getAliasee())); Vals.push_back(getEncodedLinkage(A)); Vals.push_back(getEncodedVisibility(A)); @@ -1303,7 +1357,7 @@ const ValueAsMetadata *MD, SmallVectorImpl &Record) { // Mimic an MDNode with a value as one operand. Value *V = MD->getValue(); - Record.push_back(VE.getTypeID(V->getType())); + Record.push_back(getTypeID(V->getType())); Record.push_back(VE.getValueID(V)); Stream.EmitRecord(bitc::METADATA_VALUE, Record, 0); Record.clear(); @@ -1907,7 +1961,7 @@ // If we need to switch types, do so now. if (V->getType() != LastTy) { LastTy = V->getType(); - Record.push_back(VE.getTypeID(LastTy)); + Record.push_back(getTypeID(LastTy)); Stream.EmitRecord(bitc::CST_CODE_SETTYPE, Record, CONSTANTS_SETTYPE_ABBREV); Record.clear(); @@ -2042,7 +2096,7 @@ if (Instruction::isCast(CE->getOpcode())) { Code = bitc::CST_CODE_CE_CAST; Record.push_back(getEncodedCastOpcode(CE->getOpcode())); - Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + Record.push_back(getTypeID(C->getOperand(0)->getType())); Record.push_back(VE.getValueID(C->getOperand(0))); AbbrevToUse = CONSTANTS_CE_CAST_Abbrev; } else { @@ -2061,9 +2115,9 @@ const auto *GO = cast(C); if (GO->isInBounds()) Code = bitc::CST_CODE_CE_INBOUNDS_GEP; - Record.push_back(VE.getTypeID(GO->getSourceElementType())); + Record.push_back(getTypeID(GO->getSourceElementType())); for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) { - Record.push_back(VE.getTypeID(C->getOperand(i)->getType())); + Record.push_back(getTypeID(C->getOperand(i)->getType())); Record.push_back(VE.getValueID(C->getOperand(i))); } break; @@ -2076,16 +2130,16 @@ break; case Instruction::ExtractElement: Code = bitc::CST_CODE_CE_EXTRACTELT; - Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + Record.push_back(getTypeID(C->getOperand(0)->getType())); Record.push_back(VE.getValueID(C->getOperand(0))); - Record.push_back(VE.getTypeID(C->getOperand(1)->getType())); + Record.push_back(getTypeID(C->getOperand(1)->getType())); Record.push_back(VE.getValueID(C->getOperand(1))); break; case Instruction::InsertElement: Code = bitc::CST_CODE_CE_INSERTELT; Record.push_back(VE.getValueID(C->getOperand(0))); Record.push_back(VE.getValueID(C->getOperand(1))); - Record.push_back(VE.getTypeID(C->getOperand(2)->getType())); + Record.push_back(getTypeID(C->getOperand(2)->getType())); Record.push_back(VE.getValueID(C->getOperand(2))); break; case Instruction::ShuffleVector: @@ -2097,7 +2151,7 @@ Code = bitc::CST_CODE_CE_SHUFFLEVEC; } else { Code = bitc::CST_CODE_CE_SHUFVEC_EX; - Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + Record.push_back(getTypeID(C->getOperand(0)->getType())); } Record.push_back(VE.getValueID(C->getOperand(0))); Record.push_back(VE.getValueID(C->getOperand(1))); @@ -2106,7 +2160,7 @@ case Instruction::ICmp: case Instruction::FCmp: Code = bitc::CST_CODE_CE_CMP; - Record.push_back(VE.getTypeID(C->getOperand(0)->getType())); + Record.push_back(getTypeID(C->getOperand(0)->getType())); Record.push_back(VE.getValueID(C->getOperand(0))); Record.push_back(VE.getValueID(C->getOperand(1))); Record.push_back(CE->getPredicate()); @@ -2114,7 +2168,7 @@ } } else if (const BlockAddress *BA = dyn_cast(C)) { Code = bitc::CST_CODE_BLOCKADDRESS; - Record.push_back(VE.getTypeID(BA->getFunction()->getType())); + Record.push_back(getTypeID(BA->getFunction()->getType())); Record.push_back(VE.getValueID(BA->getFunction())); Record.push_back(VE.getGlobalBasicBlockID(BA->getBasicBlock())); } else { @@ -2157,7 +2211,7 @@ // Make encoding relative to the InstID. Vals.push_back(InstID - ValID); if (ValID >= InstID) { - Vals.push_back(VE.getTypeID(V->getType())); + Vals.push_back(getTypeID(V->getType(), V)); return true; } return false; @@ -2190,7 +2244,7 @@ Code = bitc::FUNC_CODE_INST_CAST; if (!pushValueAndType(I.getOperand(0), InstID, Vals)) AbbrevToUse = (unsigned)FUNCTION_INST_CAST_ABBREV; - Vals.push_back(VE.getTypeID(I.getType())); + Vals.push_back(getTypeID(I.getType(), &I)); Vals.push_back(getEncodedCastOpcode(I.getOpcode())); } else { assert(isa(I) && "Unknown instruction!"); @@ -2213,7 +2267,7 @@ AbbrevToUse = (unsigned)FUNCTION_INST_GEP_ABBREV; auto &GEPInst = cast(I); Vals.push_back(GEPInst.isInBounds()); - Vals.push_back(VE.getTypeID(GEPInst.getSourceElementType())); + Vals.push_back(getTypeID(GEPInst.getSourceElementType())); for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) pushValueAndType(I.getOperand(i), InstID, Vals); break; @@ -2294,7 +2348,7 @@ case Instruction::Switch: { Code = bitc::FUNC_CODE_INST_SWITCH; const SwitchInst &SI = cast(I); - Vals.push_back(VE.getTypeID(SI.getCondition()->getType())); + Vals.push_back(getTypeID(SI.getCondition()->getType())); pushValue(SI.getCondition(), InstID, Vals); Vals.push_back(VE.getValueID(SI.getDefaultDest())); for (auto Case : SI.cases()) { @@ -2304,7 +2358,7 @@ } break; case Instruction::IndirectBr: Code = bitc::FUNC_CODE_INST_INDIRECTBR; - Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); + Vals.push_back(getTypeID(I.getOperand(0)->getType())); // Encode the address operand as relative, but not the basic blocks. pushValue(I.getOperand(0), InstID, Vals); for (unsigned i = 1, e = I.getNumOperands(); i != e; ++i) @@ -2321,7 +2375,7 @@ Vals.push_back(II->getCallingConv() | 1 << 13); Vals.push_back(VE.getValueID(II->getNormalDest())); Vals.push_back(VE.getValueID(II->getUnwindDest())); - Vals.push_back(VE.getTypeID(FTy)); + Vals.push_back(getTypeID(FTy)); pushValueAndType(Callee, InstID, Vals); // Emit value #'s for the fixed parameters. @@ -2352,7 +2406,7 @@ // negative valued IDs. This is most common for PHIs, so we use // signed VBRs. SmallVector Vals64; - Vals64.push_back(VE.getTypeID(PN.getType())); + Vals64.push_back(getTypeID(PN.getType())); for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { pushValueSigned(PN.getIncomingValue(i), InstID, Vals64); Vals64.push_back(VE.getValueID(PN.getIncomingBlock(i))); @@ -2366,7 +2420,7 @@ case Instruction::LandingPad: { const LandingPadInst &LP = cast(I); Code = bitc::FUNC_CODE_INST_LANDINGPAD; - Vals.push_back(VE.getTypeID(LP.getType())); + Vals.push_back(getTypeID(LP.getType())); Vals.push_back(LP.isCleanup()); Vals.push_back(LP.getNumClauses()); for (unsigned I = 0, E = LP.getNumClauses(); I != E; ++I) { @@ -2382,8 +2436,8 @@ case Instruction::Alloca: { Code = bitc::FUNC_CODE_INST_ALLOCA; const AllocaInst &AI = cast(I); - Vals.push_back(VE.getTypeID(AI.getAllocatedType())); - Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); + Vals.push_back(getTypeID(AI.getAllocatedType())); + Vals.push_back(getTypeID(I.getOperand(0)->getType())); Vals.push_back(VE.getValueID(I.getOperand(0))); // size. using APV = AllocaPackedValues; unsigned Record = 0; @@ -2406,7 +2460,7 @@ if (!pushValueAndType(I.getOperand(0), InstID, Vals)) // ptr AbbrevToUse = (unsigned)FUNCTION_INST_LOAD_ABBREV; } - Vals.push_back(VE.getTypeID(I.getType())); + Vals.push_back(getTypeID(I.getType())); Vals.push_back(Log2_32(cast(I).getAlignment()) + 1); Vals.push_back(cast(I).isVolatile()); if (cast(I).isAtomic()) { @@ -2468,7 +2522,7 @@ Vals.push_back(VE.getAttributeListID(CI.getAttributes())); Vals.push_back((CI.getCallingConv() << 1) | unsigned(CI.isTailCall()) | unsigned(CI.isMustTailCall()) << 14 | 1 << 15); - Vals.push_back(VE.getTypeID(FTy)); + Vals.push_back(getTypeID(FTy, CI.getCalledFunction())); pushValueAndType(CI.getCalledOperand(), InstID, Vals); // Callee // Emit value #'s for the fixed parameters. @@ -2489,9 +2543,9 @@ } case Instruction::VAArg: Code = bitc::FUNC_CODE_INST_VAARG; - Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); // valistty - pushValue(I.getOperand(0), InstID, Vals); // valist. - Vals.push_back(VE.getTypeID(I.getType())); // restype. + Vals.push_back(getTypeID(I.getOperand(0)->getType())); // valistty + pushValue(I.getOperand(0), InstID, Vals); // valist. + Vals.push_back(getTypeID(I.getType())); // restype. break; } @@ -2582,9 +2636,6 @@ } void DXILBitcodeWriter::writeUseListBlock(const Function *F) { - assert(VE.shouldPreserveUseListOrder() && - "Expected to be preserving use-list order"); - auto hasMore = [&]() { return !VE.UseListOrders.empty() && VE.UseListOrders.back().F == F; }; @@ -2667,8 +2718,8 @@ if (NeedsMetadataAttachment) writeFunctionMetadataAttachment(F); - if (VE.shouldPreserveUseListOrder()) - writeUseListBlock(&F); + + writeUseListBlock(&F); VE.purgeFunction(); Stream.ExitBlock(); } @@ -2896,8 +2947,7 @@ writeFunctionLevelValueSymbolTable(M.getValueSymbolTable()); // Emit module-level use-lists. - if (VE.shouldPreserveUseListOrder()) - writeUseListBlock(nullptr); + writeUseListBlock(nullptr); // Emit function bodies. for (const Function &F : M) diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.h b/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.h --- a/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.h +++ b/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.h @@ -106,8 +106,6 @@ }; SmallDenseMap FunctionMDInfo; - bool ShouldPreserveUseListOrder; - using AttributeGroupMapType = DenseMap; AttributeGroupMapType AttributeGroupMap; std::vector AttributeGroups; @@ -141,7 +139,7 @@ unsigned FirstInstID; public: - ValueEnumerator(const Module &M, bool ShouldPreserveUseListOrder); + ValueEnumerator(const Module &M, Type *PrefixType); ValueEnumerator(const ValueEnumerator &) = delete; ValueEnumerator &operator=(const ValueEnumerator &) = delete; @@ -164,8 +162,6 @@ unsigned numMDs() const { return MDs.size(); } - bool shouldPreserveUseListOrder() const { return ShouldPreserveUseListOrder; } - unsigned getTypeID(Type *T) const { TypeMapType::const_iterator I = TypeMap.find(T); assert(I != TypeMap.end() && "Type not in ValueEnumerator!"); @@ -242,8 +238,9 @@ void purgeFunction(); uint64_t computeBitsRequiredForTypeIndicies() const; + void EnumerateType(Type *T); + private: - void OptimizeConstants(unsigned CstStart, unsigned CstEnd); /// Reorder the reachable metadata. /// @@ -298,7 +295,6 @@ void EnumerateFunctionLocalListMetadata(unsigned F, const DIArgList *Arglist); void EnumerateNamedMDNode(const NamedMDNode *NMD); void EnumerateValue(const Value *V); - void EnumerateType(Type *T); void EnumerateOperandType(const Value *V); void EnumerateAttributes(AttributeList PAL); diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.cpp --- a/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.cpp +++ b/llvm/lib/Target/DirectX/DXILWriter/DXILValueEnumerator.cpp @@ -358,15 +358,10 @@ return Stack; } -static bool isIntOrIntVectorValue(const std::pair &V) { - return V.first->getType()->isIntOrIntVectorTy(); -} - -ValueEnumerator::ValueEnumerator(const Module &M, - bool ShouldPreserveUseListOrder) - : ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) { - if (ShouldPreserveUseListOrder) - UseListOrders = predictUseListOrder(M); +ValueEnumerator::ValueEnumerator(const Module &M, Type *PrefixType) { + EnumerateType(PrefixType); + + UseListOrders = predictUseListOrder(M); // Enumerate the global variables. for (const GlobalVariable &GV : M.globals()) { @@ -393,9 +388,6 @@ EnumerateType(GIF.getValueType()); } - // Remember what is the cutoff between globalvalue's and other constants. - unsigned FirstConstant = Values.size(); - // Enumerate the global variable initializers and attributes. for (const GlobalVariable &GV : M.globals()) { if (GV.hasInitializer()) @@ -499,9 +491,6 @@ } } - // Optimize constant ordering. - OptimizeConstants(FirstConstant, Values.size()); - // Organize metadata ordering. organizeMetadata(); } @@ -579,38 +568,6 @@ } } -/// OptimizeConstants - Reorder constant pool for denser encoding. -void ValueEnumerator::OptimizeConstants(unsigned CstStart, unsigned CstEnd) { - if (CstStart == CstEnd || CstStart + 1 == CstEnd) - return; - - if (ShouldPreserveUseListOrder) - // Optimizing constants makes the use-list order difficult to predict. - // Disable it for now when trying to preserve the order. - return; - - std::stable_sort(Values.begin() + CstStart, Values.begin() + CstEnd, - [this](const std::pair &LHS, - const std::pair &RHS) { - // Sort by plane. - if (LHS.first->getType() != RHS.first->getType()) - return getTypeID(LHS.first->getType()) < - getTypeID(RHS.first->getType()); - // Then by frequency. - return LHS.second > RHS.second; - }); - - // Ensure that integer and vector of integer constants are at the start of the - // constant pool. This is important so that GEP structure indices come before - // gep constant exprs. - std::stable_partition(Values.begin() + CstStart, Values.begin() + CstEnd, - isIntOrIntVectorValue); - - // Rebuild the modified portion of ValueMap. - for (; CstStart != CstEnd; ++CstStart) - ValueMap[Values[CstStart].first] = CstStart + 1; -} - /// EnumerateValueSymbolTable - Insert all of the values in the specified symbol /// table into the values table. void ValueEnumerator::EnumerateValueSymbolTable(const ValueSymbolTable &VST) { @@ -1098,9 +1055,6 @@ ValueMap[&BB] = BasicBlocks.size(); } - // Optimize the constant layout. - OptimizeConstants(FirstFuncConstantID, Values.size()); - // Add the function's parameter attributes so they are available for use in // the function's instruction. EnumerateAttributes(F.getAttributes()); diff --git a/llvm/test/tools/dxil-dis/opaque-gep.ll b/llvm/test/tools/dxil-dis/opaque-gep.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/dxil-dis/opaque-gep.ll @@ -0,0 +1,22 @@ +; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s +target triple = "dxil-unknown-unknown" + +define i32 @fn(ptr %0) { + %2 = getelementptr i32, ptr %0, i32 4 + %3 = load i32, ptr %2 + ret i32 %3 +} + +; CHECK: define i32 @fn(i32*) +; CHECK-NEXT: %2 = getelementptr i32, i32* %0, i32 4 +; CHECK-NEXT: %3 = load i32, i32* %2, align 4 + +define i32 @fn2(ptr addrspace(1) %0) { + %2 = getelementptr i32, ptr addrspace(1) %0, i32 4 + %3 = load i32, ptr addrspace(1) %2 + ret i32 %3 +} + +; CHECK: define i32 @fn2(i32 addrspace(1)*) +; CHECK-NEXT: %2 = getelementptr i32, i32 addrspace(1)* %0, i32 4 +; CHECK-NEXT: %3 = load i32, i32 addrspace(1)* %2, align 4 diff --git a/llvm/test/tools/dxil-dis/opaque-pointers.ll b/llvm/test/tools/dxil-dis/opaque-pointers.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/dxil-dis/opaque-pointers.ll @@ -0,0 +1,59 @@ +; RUN: llc --filetype=obj %s -o - | dxil-dis -o - | FileCheck %s +target triple = "dxil-unknown-unknown" + +define i64 @test(ptr %p) { + store i32 0, ptr %p + %v = load i64, ptr %p + ret i64 %v +} + +; CHECK: define i64 @test(i8* %p) { +; CHECK-NEXT: %1 = bitcast i8* %p to i32* +; CHECK-NEXT: store i32 0, i32* %1, align 4 +; CHECK-NEXT: %2 = bitcast i8* %p to i64* +; CHECK-NEXT: %3 = load i64, i64* %2, align 8 + +define i64 @test2(ptr %p) { + store i64 0, ptr %p + %v = load i64, ptr %p + ret i64 %v +} + +; CHECK: define i64 @test2(i64* %p) { +; CHECK-NEXT: store i64 0, i64* %p, align 8 +; CHECK-NEXT: %v = load i64, i64* %p, align 8 + +define i64 @test3(ptr addrspace(1) %p) { + store i32 0, ptr addrspace(1) %p + %v = load i64, ptr addrspace(1) %p + ret i64 %v +} + +; CHECK: define i64 @test3(i8 addrspace(1)* %p) { +; CHECK-NEXT: %1 = bitcast i8 addrspace(1)* %p to i32 addrspace(1)* +; CHECK-NEXT: store i32 0, i32 addrspace(1)* %1, align 4 +; CHECK-NEXT: %2 = bitcast i8 addrspace(1)* %p to i64 addrspace(1)* +; CHECK-NEXT: %3 = load i64, i64 addrspace(1)* %2, align 8 + +define i64 @test4(ptr addrspace(1) %p) { + store i64 0, ptr addrspace(1) %p + %v = load i64, ptr addrspace(1) %p + ret i64 %v +} + +; CHECK: define i64 @test4(i64 addrspace(1)* %p) { +; CHECK-NEXT: store i64 0, i64 addrspace(1)* %p, align 8 +; CHECK-NEXT: %v = load i64, i64 addrspace(1)* %p, align 8 + + +define i64 @test5(ptr %p) { + %casted = addrspacecast ptr %p to ptr addrspace(1) + store i64 0, ptr addrspace(1) %casted + %v = load i64, ptr addrspace(1) %casted + ret i64 %v +} + +; CHECK: define i64 @test5(i8* %p) { +; CHECK-NEXT: %casted = addrspacecast i8* %p to i64 addrspace(1)* +; CHECK-NEXT: store i64 0, i64 addrspace(1)* %casted, align 8 +; CHECK-NEXT: %v = load i64, i64 addrspace(1)* %casted, align 8