diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 0c7279de06cd6..a330b80493032 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2666,8 +2666,8 @@ are grouped into a single :ref:`attribute group `. Operand Bundles --------------- -Operand bundles are tagged sets of SSA values that can be associated -with certain LLVM instructions (currently only ``call`` s and +Operand bundles are tagged sets of SSA values or metadata strings that can be +associated with certain LLVM instructions (currently only ``call`` s and ``invoke`` s). In a way they are like metadata, but dropping them is incorrect and will change program semantics. @@ -2675,7 +2675,7 @@ Syntax:: operand bundle set ::= '[' operand bundle (, operand bundle )* ']' operand bundle ::= tag '(' [ bundle operand ] (, bundle operand )* ')' - bundle operand ::= SSA value + bundle operand ::= SSA value | metadata string tag ::= string constant Operand bundles are **not** part of a function's signature, and a diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md index 8ac5900a7e532..dcdd7a25c7fbe 100644 --- a/llvm/docs/ReleaseNotes.md +++ b/llvm/docs/ReleaseNotes.md @@ -88,6 +88,8 @@ Changes to the LLVM IR * `llvm.nvvm.ptr.shared.to.gen` * `llvm.nvvm.ptr.constant.to.gen` * `llvm.nvvm.ptr.local.to.gen` + +* Operand bundle values can now be metadata strings. Changes to LLVM infrastructure ------------------------------ diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index cbd92fd52fc75..ba2efee941421 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -529,6 +529,9 @@ enum PossiblyExactOperatorOptionalFlags { PEO_EXACT = 0 }; /// PossiblyDisjointInst's SubclassOptionalData contents. enum PossiblyDisjointInstOptionalFlags { PDI_DISJOINT = 0 }; +/// Mark to distinguish metadata from value in an operator bundle. +enum MetadataOperandBundleValueMarker { OB_METADATA = 0x80000000 }; + /// GetElementPtrOptionalFlags - Flags for serializing /// GEPOperator's SubclassOptionalData contents. enum GetElementPtrOptionalFlags { diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 9f2ef2e6a9311..c3b4a8235ce63 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -3202,8 +3202,14 @@ bool LLParser::parseOptionalOperandBundles( Type *Ty = nullptr; Value *Input = nullptr; - if (parseType(Ty) || parseValue(Ty, Input, PFS)) + if (parseType(Ty)) return true; + if (Ty->isMetadataTy()) { + if (parseMetadataAsValue(Input, PFS)) + return true; + } else if (parseValue(Ty, Input, PFS)) { + return true; + } Inputs.push_back(Input); } diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 6f997510b0360..8ee93253bc244 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -792,6 +792,24 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer { return ResVal == nullptr; } + bool getValueOrMetadata(const SmallVectorImpl &Record, + unsigned &Slot, unsigned InstNum, Value *&ResVal, + BasicBlock *ConstExprInsertBB) { + if (Slot == Record.size()) + return true; + unsigned ValID = Record[Slot++]; + if (ValID != bitc::OB_METADATA) { + unsigned TypeId; + return getValueTypePair(Record, --Slot, InstNum, ResVal, TypeId, + ConstExprInsertBB); + } + if (Slot == Record.size()) + return true; + unsigned ValNo = InstNum - (unsigned)Record[Slot++]; + ResVal = MetadataAsValue::get(Context, getFnMetadataByID(ValNo)); + return false; + } + /// Read a value out of the specified record from slot 'Slot'. Increment Slot /// past the number of slots used by the value in the record. Return true if /// there is an error. @@ -6767,8 +6785,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { unsigned OpNum = 1; while (OpNum != Record.size()) { Value *Op; - unsigned OpTypeID; - if (getValueTypePair(Record, OpNum, NextValueNo, Op, OpTypeID, CurBB)) + if (getValueOrMetadata(Record, OpNum, NextValueNo, Op, CurBB)) return error("Invalid record"); Inputs.push_back(Op); } diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index d9086bfebbd2a..bec0caef58afa 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -395,6 +395,8 @@ class ModuleBitcodeWriter : public ModuleBitcodeWriterBase { void writeModuleConstants(); bool pushValueAndType(const Value *V, unsigned InstID, SmallVectorImpl &Vals); + bool pushValueOrMetadata(const Value *V, unsigned InstID, + SmallVectorImpl &Vals); void writeOperandBundles(const CallBase &CB, unsigned InstID); void pushValue(const Value *V, unsigned InstID, SmallVectorImpl &Vals); @@ -2931,6 +2933,19 @@ bool ModuleBitcodeWriter::pushValueAndType(const Value *V, unsigned InstID, return false; } +bool ModuleBitcodeWriter::pushValueOrMetadata(const Value *V, unsigned InstID, + SmallVectorImpl &Vals) { + bool IsMetadata = V->getType()->isMetadataTy(); + if (IsMetadata) { + Vals.push_back(bitc::OB_METADATA); + Metadata *MD = cast(V)->getMetadata(); + unsigned ValID = VE.getMetadataID(MD); + Vals.push_back(InstID - ValID); + return false; + } + return pushValueAndType(V, InstID, Vals); +} + void ModuleBitcodeWriter::writeOperandBundles(const CallBase &CS, unsigned InstID) { SmallVector Record; @@ -2941,7 +2956,7 @@ void ModuleBitcodeWriter::writeOperandBundles(const CallBase &CS, Record.push_back(C.getOperandBundleTagID(Bundle.getTagName())); for (auto &Input : Bundle.Inputs) - pushValueAndType(Input, InstID, Record); + pushValueOrMetadata(Input, InstID, Record); Stream.EmitRecord(bitc::FUNC_CODE_OPERAND_BUNDLE, Record); Record.clear(); diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll index a1b2370a87b82..280c3a99d7535 100644 --- a/llvm/test/Bitcode/compatibility.ll +++ b/llvm/test/Bitcode/compatibility.ll @@ -1327,6 +1327,14 @@ continue: ret i32 0 } +declare void @instructions.bundles.callee(i32) +define void @instructions.bundles.metadata(i32 %x) { +entry: + call void @instructions.bundles.callee(i32 %x) [ "foo"(i32 42, metadata !"abc"), "bar"(metadata !"abcde", metadata !"qwerty") ] +; CHECK: call void @instructions.bundles.callee(i32 %x) [ "foo"(i32 42, metadata !"abc"), "bar"(metadata !"abcde", metadata !"qwerty") ] + ret void +} + ; Instructions -- Unary Operations define void @instructions.unops(double %op1) { fneg double %op1 diff --git a/llvm/test/Bitcode/operand-bundles.ll b/llvm/test/Bitcode/operand-bundles.ll index ab28cffd84aa2..a8e086f784c6c 100644 --- a/llvm/test/Bitcode/operand-bundles.ll +++ b/llvm/test/Bitcode/operand-bundles.ll @@ -56,6 +56,13 @@ define void @f4(i32* %ptr) { ret void } +define void @f5(i32 %x) { +entry: + call void @callee1(i32 10, i32 %x) [ "foo"(i32 42, metadata !"abc"), "bar"(metadata !"abcde", metadata !"qwerty") ] +; CHECK: call void @callee1(i32 10, i32 %x) [ "foo"(i32 42, metadata !"abc"), "bar"(metadata !"abcde", metadata !"qwerty") ] + ret void +} + ; Invoke versions of the above tests: @@ -150,3 +157,20 @@ exception: normal: ret void } + +define void @g5(ptr %ptr) personality i8 3 { +entry: + %l = load i32, ptr %ptr, align 4 + %x = add i32 42, 1 + invoke void @callee1(i32 10, i32 %x) [ "foo"(i32 42, metadata !"abc"), "bar"(metadata !"abcde", metadata !"qwerty") ] + to label %normal unwind label %exception +; CHECK: invoke void @callee1(i32 10, i32 %x) [ "foo"(i32 42, metadata !"abc"), "bar"(metadata !"abcde", metadata !"qwerty") ] + +exception: ; preds = %entry + %cleanup = landingpad i8 + cleanup + br label %normal + +normal: ; preds = %exception, %entry + ret void +}