diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 1276807595986..72e628b406a9e 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -5145,7 +5145,7 @@ LLVM_C_ABI LLVMValueRef LLVMBuildInsertValue(LLVMBuilderRef, LLVM_C_ABI LLVMValueRef LLVMBuildFreeze(LLVMBuilderRef, LLVMValueRef Val, const char *Name); LLVM_C_ABI LLVMValueRef LLVMBuildBitExtract(LLVMBuilderRef, - LLVMValueRef Type, + LLVMTypeRef Type, LLVMValueRef Src, LLVMValueRef Offset, const char *Name); diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h index 938a45951e074..0e7c073a47277 100644 --- a/llvm/include/llvm/AsmParser/LLParser.h +++ b/llvm/include/llvm/AsmParser/LLParser.h @@ -684,6 +684,8 @@ namespace llvm { bool parseExtractElement(Instruction *&Inst, PerFunctionState &PFS); bool parseInsertElement(Instruction *&Inst, PerFunctionState &PFS); bool parseShuffleVector(Instruction *&Inst, PerFunctionState &PFS); + bool parseBitExtract(Instruction *&Inst, PerFunctionState &PFS); + bool parseBitInsert(Instruction *&Inst, PerFunctionState &PFS); int parsePHI(Instruction *&Inst, PerFunctionState &PFS); bool parseLandingPad(Instruction *&Inst, PerFunctionState &PFS); bool parseCall(Instruction *&Inst, PerFunctionState &PFS, diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 446026d7f9942..c099f81f59ebe 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -444,6 +444,8 @@ enum ConstantsCodes { // deactivation_symbol] CST_CODE_BYTE = 35, // BYTE: [intval] CST_CODE_WIDE_BYTE = 36, // WIDE_BYTE: [n x intval] + CST_CODE_CE_BITEXTRACT = 37, // BITEXTRACT: [opty, opval, opval] + CST_CODE_CE_BITINSERT = 38, // BITINSERT: [opval, opval, opval] }; /// CastOpcodes - These are values used in the bitcode files to encode which diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h index da49160fe93f0..cad1947d6d990 100644 --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -5459,7 +5459,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BitInsertInst, Value) //===----------------------------------------------------------------------===// class BitExtractInst: public Instruction { - constexpr static IntrusiveOperandsAllocMarker AllocMarker{3}; + constexpr static IntrusiveOperandsAllocMarker AllocMarker{2}; LLVM_ABI BitExtractInst(Type* Ty, Value *Src, Value *Offset, const Twine &NameStr = "", @@ -5497,7 +5497,7 @@ class BitExtractInst: public Instruction { template <> struct OperandTraits : - public FixedNumOperandTraits {}; + public FixedNumOperandTraits {}; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BitExtractInst, Value) } // end namespace llvm diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index dc15ea64e5c08..b8ab35a6ce307 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -4736,6 +4736,12 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) { return true; } + if(Opc == Instruction::BitExtract) { + if (parseType(Ty) || + parseToken(lltok::comma, "expected comma after bitextract's type")) + return true; + } + if (parseGlobalValueVector(Elts) || parseToken(lltok::rparen, "expected ')' in constantexpr")) return true; @@ -4805,14 +4811,26 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) { if (!ExtractElementInst::isValidOperands(Elts[0], Elts[1])) return error(ID.Loc, "invalid extractelement operands"); ID.ConstantVal = ConstantExpr::getExtractElement(Elts[0], Elts[1]); - } else { - assert(Opc == Instruction::InsertElement && "Unknown opcode"); + } else if (Opc == Instruction::InsertElement) { if (Elts.size() != 3) return error(ID.Loc, "expected three operands to insertelement"); if (!InsertElementInst::isValidOperands(Elts[0], Elts[1], Elts[2])) return error(ID.Loc, "invalid insertelement operands"); ID.ConstantVal = ConstantExpr::getInsertElement(Elts[0], Elts[1],Elts[2]); + } else if (Opc == Instruction::BitInsert) { + if (Elts.size() != 3) + return error(ID.Loc, "expected three operands to bitinsert"); + if (!BitInsertInst::isValidOperands(Elts[0], Elts[1], Elts[2])) + return error(ID.Loc, "invalid bitinsert operands"); + ID.ConstantVal = ConstantExpr::getBitInsert(Elts[0], Elts[1], Elts[2]); + } else { + assert(Opc == Instruction::BitExtract && "Unknown opcode"); + if (Elts.size() != 2) + return error(ID.Loc, "expected two operands to bitextract"); + if (!BitExtractInst::isValidOperands(Ty, Elts[0], Elts[1])) + return error(ID.Loc, "invalid bitextract operands"); + ID.ConstantVal = ConstantExpr::getBitExtract(Ty, Elts[0], Elts[1]); } ID.Kind = ValID::t_Constant; @@ -7721,6 +7739,10 @@ int LLParser::parseInstruction(Instruction *&Inst, BasicBlock *BB, return parseLandingPad(Inst, PFS); case lltok::kw_freeze: return parseFreeze(Inst, PFS); + case lltok::kw_bitinsert: + return parseBitInsert(Inst, PFS); + case lltok::kw_bitextract: + return parseBitExtract(Inst, PFS); // Call. case lltok::kw_call: return parseCall(Inst, PFS, CallInst::TCK_None); @@ -8538,6 +8560,45 @@ bool LLParser::parseInsertElement(Instruction *&Inst, PerFunctionState &PFS) { return false; } +// parseBitExtract +// ::= 'bitextract' Type ',' TypeAndValue ',' TypeAndValue +bool LLParser::parseBitExtract(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc = Lex.getLoc(); + Type *Ty = nullptr; + Value *Op0, *Op1; + if (parseType(Ty) || + parseToken(lltok::comma, "expected ',' after bitextract type") || + parseTypeAndValue(Op0, PFS) || + parseToken(lltok::comma, "expected ',' after bitextract source value") || + parseTypeAndValue(Op1, PFS)) + return true; + + if (!BitExtractInst::isValidOperands(Ty, Op0, Op1)) + return error(Loc, "invalid bitextract operands"); + + Inst = BitExtractInst::Create(Ty, Op0, Op1); + return false; +} + +// parseBitInsert +// ::= 'bitinsert' TypeAndValue ',' TypeAndValue ',' TypeAndValue +bool LLParser::parseBitInsert(Instruction *&Inst, PerFunctionState &PFS) { + LocTy Loc = Lex.getLoc(); + Value *Op0, *Op1, *Op2; + if (parseTypeAndValue(Op0, Loc, PFS) || + parseToken(lltok::comma, "expected ',' after bitinsert source value") || + parseTypeAndValue(Op1, PFS) || + parseToken(lltok::comma, "expected ',' after bitinsert insert value") || + parseTypeAndValue(Op2, PFS)) + return true; + + if (!BitInsertInst::isValidOperands(Op0, Op1, Op2)) + return error(Loc, "invalid bitinsert operands"); + + Inst = BitInsertInst::Create(Op0, Op1, Op2); + return false; +} + /// parseShuffleVector /// ::= 'shufflevector' TypeAndValue ',' TypeAndValue ',' TypeAndValue bool LLParser::parseShuffleVector(Instruction *&Inst, PerFunctionState &PFS) { diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index fa7a3b214e463..edbb7f5d3c071 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1835,6 +1835,14 @@ Expected BitcodeReader::materializeValue(unsigned StartValID, I = new ShuffleVectorInst(Ops[0], Ops[1], Ops[2], "constexpr", InsertBB); break; + case Instruction::BitExtract: + I = BitExtractInst::Create(BC->getType(), Ops[0], Ops[1], + "constexpr", InsertBB); + break; + case Instruction::BitInsert: + I = BitInsertInst::Create(Ops[0], Ops[1], Ops[2], "constexpr", + InsertBB); + break; default: llvm_unreachable("Unhandled bitcode constant"); } @@ -3651,6 +3659,24 @@ Error BitcodeReader::parseConstants() { {(unsigned)Record[0], (unsigned)Record[1], IdxRecord}); break; } + case bitc::CST_CODE_CE_BITEXTRACT: { // BITEXTRACT: [opty, opval, opval] + if (Record.size() < 3) + return error("Invalid bitextract constexpr record"); + Type *SrcTy = getTypeByID(Record[0]); + if (!SrcTy) + return error("Invalid bitextract constexpr record"); + V = BitcodeConstant::create(Alloc, CurTy, Instruction::BitExtract, + {(unsigned)Record[1], (unsigned)Record[2]}); + break; + } + case bitc::CST_CODE_CE_BITINSERT: { // BITINSERT: [opval, opval, opval] + if (Record.size() < 3) + return error("Invalid bitinsert constexpr record"); + V = BitcodeConstant::create(Alloc, CurTy, Instruction::BitInsert, + {(unsigned)Record[0], (unsigned)Record[1], + (unsigned)Record[2]}); + break; + } case bitc::CST_CODE_CE_SHUFFLEVEC: { // CE_SHUFFLEVEC: [opval, opval, opval] VectorType *OpTy = dyn_cast(CurTy); if (Record.size() < 3 || !OpTy) @@ -5544,6 +5570,37 @@ Error BitcodeReader::parseFunctionBody(Function *F) { break; } + case bitc::FUNC_CODE_INST_BITINSERT: { // BITINSERT: [ty, opval, opval, opval] + unsigned OpNum = 0; + Value *Base, *Val, *Offset; + unsigned BaseTypeID, ValTypeID, OffsetTypeID; + if (getValueTypePair(Record, OpNum, NextValueNo, Base, BaseTypeID, CurBB) || + getValueTypePair(Record, OpNum, NextValueNo, Val, ValTypeID, CurBB) || + getValueTypePair(Record, OpNum, NextValueNo, Offset, OffsetTypeID, + CurBB)) + return error("Invalid bitinsert record"); + I = BitInsertInst::Create(Base, Val, Offset); + ResTypeID = BaseTypeID; + InstructionList.push_back(I); + break; + } + + case bitc::FUNC_CODE_INST_BITEXTRACT: { // BITEXTRACT: [ty, opval, opval] + unsigned OpNum = 0; + unsigned TypeID = Record[OpNum++]; + Type *ResTy = getTypeByID(TypeID); + Value *Src, *Offset; + unsigned SrcTypeID, OffsetTypeID; + if (getValueTypePair(Record, OpNum, NextValueNo, Src, SrcTypeID, CurBB) || + getValueTypePair(Record, OpNum, NextValueNo, Offset, OffsetTypeID, + CurBB)) + return error("Invalid bitextract record"); + I = BitExtractInst::Create(ResTy, Src, Offset); + ResTypeID = TypeID; + InstructionList.push_back(I); + break; + } + case bitc::FUNC_CODE_INST_SHUFFLEVEC: {// SHUFFLEVEC: [opval,ty,opval,opval] unsigned OpNum = 0; Value *Vec1, *Vec2, *Mask; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 31b8367083087..380e09baa460b 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -3024,6 +3024,18 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal, Record.push_back(VE.getTypeID(C->getOperand(2)->getType())); Record.push_back(VE.getValueID(C->getOperand(2))); break; + case Instruction::BitExtract: + Code = bitc::CST_CODE_CE_BITEXTRACT; + Record.push_back(VE.getTypeID(C->getType())); + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + break; + case Instruction::BitInsert: + Code = bitc::CST_CODE_CE_BITINSERT; + Record.push_back(VE.getValueID(C->getOperand(0))); + Record.push_back(VE.getValueID(C->getOperand(1))); + Record.push_back(VE.getValueID(C->getOperand(2))); + break; case Instruction::ShuffleVector: // If the return type and argument types are the same, this is a // standard shufflevector instruction. If the types are different, @@ -3246,6 +3258,18 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I, pushValue(I.getOperand(1), InstID, Vals); pushValueAndType(I.getOperand(2), InstID, Vals); break; + case Instruction::BitExtract: + Code = bitc::FUNC_CODE_INST_BITEXTRACT; + Vals.push_back(VE.getTypeID(I.getType())); + pushValueAndType(I.getOperand(0), InstID, Vals); + pushValue(I.getOperand(1), InstID, Vals); + break; + case Instruction::BitInsert: + Code = bitc::FUNC_CODE_INST_BITINSERT; + pushValueAndType(I.getOperand(0), InstID, Vals); + pushValueAndType(I.getOperand(1), InstID, Vals); + pushValueAndType(I.getOperand(2), InstID, Vals); + break; case Instruction::ShuffleVector: Code = bitc::FUNC_CODE_INST_SHUFFLEVEC; pushValueAndType(I.getOperand(0), InstID, Vals); @@ -3613,7 +3637,6 @@ void ModuleBitcodeWriter::writeInstruction(const Instruction &I, pushValueAndType(I.getOperand(0), InstID, Vals); break; } - Stream.EmitRecord(Code, Vals, AbbrevToUse); Vals.clear(); } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index 29e253e7c5f97..a62d3ef1e7ee3 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -4802,6 +4802,10 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << ' '; TypePrinter.print(GEP->getSourceElementType(), Out); Out << ','; + } else if (isa(I)) { + Out << ' '; + TypePrinter.print(I.getType(), Out); + Out << ','; } else if (const auto *LI = dyn_cast(&I)) { Out << ' '; TypePrinter.print(LI->getType(), Out); diff --git a/llvm/lib/IR/ConstantsContext.h b/llvm/lib/IR/ConstantsContext.h index 4848c9b5ed9e7..04f438152eb15 100644 --- a/llvm/lib/IR/ConstantsContext.h +++ b/llvm/lib/IR/ConstantsContext.h @@ -562,7 +562,7 @@ struct ConstantExprKeyType { case Instruction::BitInsert: return new BitInsertInstConstantExpr(Ops[0], Ops[1], Ops[2]); case Instruction::BitExtract: - return new BitExtractInstConstantExpr(Ty, Ops[1], Ops[2]); + return new BitExtractInstConstantExpr(Ty, Ops[0], Ops[1]); } } }; diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index 0302f35c85d28..c8ed1c38bcd22 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -2621,7 +2621,7 @@ bool BitInsertInst::isValidOperands(const Value *Base, const Value *Val, if (!Val->getType()->isFirstClassType()) return false;// Second operand of bitinsert must be a first-class type. - if (!Offset->getType()->isIntegerTy()) + if (!Offset->getType()->isIntegerTy(32)) return false; // Third operand of bitinsert must be i32. return true; } @@ -2635,7 +2635,7 @@ BitExtractInst::BitExtractInst(Type *Ty, Value *Src, Value *Offset, InsertPosition InsertBef) : Instruction(Ty, BitExtract, AllocMarker, InsertBef) { assert(isValidOperands(Ty, Src, Offset) && - "Invalid bitinsert instruction operands!"); + "Invalid bitextract instruction operands!"); Op<0>() = Src; Op<1>() = Offset; setName(Name); @@ -2649,7 +2649,7 @@ bool BitExtractInst::isValidOperands(const Type *Ty, const Value *Src, if (!Src->getType()->isByteTy()) return false;// Second operand of bitextract must be a byte type. - if (!Offset->getType()->isIntegerTy()) + if (!Offset->getType()->isIntegerTy(32)) return false; // Third operand of bitextract must be i32. return true; } @@ -4553,7 +4553,7 @@ BitInsertInst *BitInsertInst::cloneImpl() const { } BitExtractInst *BitExtractInst::cloneImpl() const { - return BitExtractInst::Create(getType(), getOperand(1), getOperand(2)); + return BitExtractInst::Create(getType(), getOperand(0), getOperand(1)); } ShuffleVectorInst *ShuffleVectorInst::cloneImpl() const { diff --git a/llvm/test/Assembler/bitextract-invalid-1.ll b/llvm/test/Assembler/bitextract-invalid-1.ll new file mode 100644 index 0000000000000..c746b0d9bafe1 --- /dev/null +++ b/llvm/test/Assembler/bitextract-invalid-1.ll @@ -0,0 +1,6 @@ +; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s +; CHECK: invalid bitextract operands +define i8 @invalid(i32 %src) { + %r = bitextract i8, i32 %src, i32 0 + ret i8 %r +} diff --git a/llvm/test/Assembler/bitinsert-bitextract.ll b/llvm/test/Assembler/bitinsert-bitextract.ll new file mode 100644 index 0000000000000..237a25f0c2744 --- /dev/null +++ b/llvm/test/Assembler/bitinsert-bitextract.ll @@ -0,0 +1,15 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +; CHECK-LABEL: test_bitextract +; CHECK: bitextract i8, b32 %{{.*}}, i32 24 +define i8 @test_bitextract(b32 %src) { + %result = bitextract i8, b32 %src, i32 24 + ret i8 %result +} + +; CHECK-LABEL: test_bitinsert +; CHECK: bitinsert b32 %{{.*}}, i8 %{{.*}}, i32 3 +define b32 @test_bitinsert(b32 %base, i8 %val) { + %result = bitinsert b32 %base, i8 %val, i32 3 + ret b32 %result +} diff --git a/llvm/test/Assembler/bitinsert-invalid-1.ll b/llvm/test/Assembler/bitinsert-invalid-1.ll new file mode 100644 index 0000000000000..acec42649ccda --- /dev/null +++ b/llvm/test/Assembler/bitinsert-invalid-1.ll @@ -0,0 +1,6 @@ +; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s +; CHECK: invalid bitinsert operands +define i32 @invalid(i32 %base, i8 %val) { + %r = bitinsert i32 %base, i8 %val, i32 0 + ret i32 %r +} diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index a913478309b68..c15a013ab80e0 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -1010,9 +1010,9 @@ struct FunCloner { break; } case LLVMBitExtract: { - LLVMValueRef Type = CloneValue(LLVMGetOperand(Src, 0)); - LLVMValueRef SrcV = CloneValue(LLVMGetOperand(Src, 1)); - LLVMValueRef Offset = CloneValue(LLVMGetOperand(Src, 2)); + LLVMTypeRef Type = CloneType(LLVMTypeOf(Src)); + LLVMValueRef SrcV = CloneValue(LLVMGetOperand(Src, 0)); + LLVMValueRef Offset = CloneValue(LLVMGetOperand(Src, 1)); Dst = LLVMBuildBitExtract(Builder, Type, SrcV, Offset, Name); break; }