[llvm] 58acbce - [IR] Add Freeze instruction
Mikael Holmén via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 4 23:21:08 PST 2019
Hi,
At least clang 8 warns on this code with
../lib/IR/ConstantFold.cpp:945:3: error: default label in switch which
covers all enumeration values [-Werror,-Wcovered-switch-default]
default:
^
1 error generated.
Regards,
Mikael
On Mon, 2019-11-04 at 22:55 -0800, via llvm-commits wrote:
> Author: aqjune
> Date: 2019-11-05T15:54:56+09:00
> New Revision: 58acbce3def63a207b8f5a69318a99666a4aac53
>
> URL:
> https://protect2.fireeye.com/v1/url?k=21beda83-7d6ad672-21be9a18-864685b2085c-83d404229ba80e73&q=1&e=a3825398-25c9-4e53-af5e-4bbfdd19ce24&u=https%3A%2F%2Fgithub.com%2Fllvm%2Fllvm-project%2Fcommit%2F58acbce3def63a207b8f5a69318a99666a4aac53
> DIFF:
> https://protect2.fireeye.com/v1/url?k=4bccce7a-1718c28b-4bcc8ee1-864685b2085c-51cdda5e387d9758&q=1&e=a3825398-25c9-4e53-af5e-4bbfdd19ce24&u=https%3A%2F%2Fgithub.com%2Fllvm%2Fllvm-project%2Fcommit%2F58acbce3def63a207b8f5a69318a99666a4aac53.diff
>
> LOG: [IR] Add Freeze instruction
>
> Summary:
> - Define Instruction::Freeze, let it be UnaryOperator
> - Add support for freeze to
> LLLexer/LLParser/BitcodeReader/BitcodeWriter
> The format is `%x = freeze <ty> %v`
> - Add support for freeze instruction to llvm-c interface.
> - Add m_Freeze in PatternMatch.
> - Erase freeze when lowering IR to SelDag.
>
> Reviewers: deadalnix, hfinkel, efriedma, lebedev.ri, nlopes,
> jdoerfert, regehr, filcab, delcypher, whitequark
>
> Reviewed By: lebedev.ri, jdoerfert
>
> Subscribers: jfb, kristof.beyls, hiraditya, lebedev.ri, steven_wu,
> dexonsmith, xbolva00, delcypher, spatel, regehr, trentxintong, vsk,
> filcab, nlopes, mehdi_amini, deadalnix, llvm-commits
>
> Differential Revision:
> https://protect2.fireeye.com/v1/url?k=e867703f-b4b37cce-e86730a4-864685b2085c-71ac7740de2666ce&q=1&e=a3825398-25c9-4e53-af5e-4bbfdd19ce24&u=https%3A%2F%2Freviews.llvm.org%2FD29011
>
> Added:
> llvm/test/Bindings/llvm-c/freeze.ll
>
> Modified:
> llvm/include/llvm-c/Core.h
> llvm/include/llvm/Bitcode/LLVMBitCodes.h
> llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
> llvm/include/llvm/IR/IRBuilder.h
> llvm/include/llvm/IR/Instruction.def
> llvm/include/llvm/IR/Operator.h
> llvm/include/llvm/IR/PatternMatch.h
> llvm/lib/AsmParser/LLLexer.cpp
> llvm/lib/AsmParser/LLParser.cpp
> llvm/lib/AsmParser/LLToken.h
> llvm/lib/Bitcode/Reader/BitcodeReader.cpp
> llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
> llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
> llvm/lib/CodeGen/TargetLoweringBase.cpp
> llvm/lib/IR/ConstantFold.cpp
> llvm/lib/IR/Core.cpp
> llvm/lib/IR/Instruction.cpp
> llvm/lib/IR/Instructions.cpp
> llvm/lib/IR/Verifier.cpp
> llvm/test/Bindings/OCaml/core.ml
> llvm/test/Bitcode/compatibility.ll
> llvm/test/Transforms/MergeFunc/inline-asm.ll
> llvm/tools/llvm-c-test/echo.cpp
>
> Removed:
>
>
>
> #####################################################################
> ###########
> diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
> index b84970956666..23e855148bb5 100644
> --- a/llvm/include/llvm-c/Core.h
> +++ b/llvm/include/llvm-c/Core.h
> @@ -69,6 +69,7 @@ typedef enum {
>
> /* Standard Unary Operators */
> LLVMFNeg = 66,
> + LLVMFreeze = 68,
>
> /* Standard Binary Operators */
> LLVMAdd = 8,
> @@ -3747,6 +3748,7 @@ LLVMValueRef LLVMBuildNUWNeg(LLVMBuilderRef B,
> LLVMValueRef V,
> const char *Name);
> LLVMValueRef LLVMBuildFNeg(LLVMBuilderRef, LLVMValueRef V, const
> char *Name);
> LLVMValueRef LLVMBuildNot(LLVMBuilderRef, LLVMValueRef V, const char
> *Name);
> +LLVMValueRef LLVMBuildFreeze(LLVMBuilderRef, LLVMValueRef V, const
> char *Name);
>
> /* Memory */
> LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef, LLVMTypeRef Ty, const
> char *Name);
>
> diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
> b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
> index 1a397068caf0..b97abc4f0612 100644
> --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
> +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
> @@ -391,7 +391,8 @@ enum CastOpcodes {
> /// have no fixed relation to the LLVM IR enum values. Changing
> these will
> /// break compatibility with old files.
> enum UnaryOpcodes {
> - UNOP_FNEG = 0
> + UNOP_FNEG = 0,
> + UNOP_FREEZE = 1
> };
>
> /// BinaryOpcodes - These are values used in the bitcode files to
> encode which
>
> diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
> b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
> index bdb92aa4689d..6a2ea05f1b08 100644
> --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
> +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
> @@ -483,6 +483,9 @@ class IRTranslator : public MachineFunctionPass {
> bool translateUserOp2(const User &U, MachineIRBuilder &MIRBuilder)
> {
> return false;
> }
> + bool translateFreeze(const User &U, MachineIRBuilder &MIRBuilder)
> {
> + return false;
> + }
>
> /// @}
>
>
> diff --git a/llvm/include/llvm/IR/IRBuilder.h
> b/llvm/include/llvm/IR/IRBuilder.h
> index f556db7893c4..970fca6e1ebb 100644
> --- a/llvm/include/llvm/IR/IRBuilder.h
> +++ b/llvm/include/llvm/IR/IRBuilder.h
> @@ -2392,6 +2392,10 @@ class IRBuilder : public IRBuilderBase, public
> Inserter {
> return Insert(LandingPadInst::Create(Ty, NumClauses), Name);
> }
>
> + Value *CreateFreeze(Value *V, const Twine &Name = "") {
> + return Insert(UnaryOperator::CreateFreeze(V, Name));
> + }
> +
> //===-------------------------------------------------------------
> -------===//
> // Utility creation methods
> //===-------------------------------------------------------------
> -------===//
>
> diff --git a/llvm/include/llvm/IR/Instruction.def
> b/llvm/include/llvm/IR/Instruction.def
> index 41cdf613ad64..3f698f93b2b2 100644
> --- a/llvm/include/llvm/IR/Instruction.def
> +++ b/llvm/include/llvm/IR/Instruction.def
> @@ -140,84 +140,85 @@ HANDLE_TERM_INST (11, CallBr ,
> CallBrInst) // A call-site terminator
> // Standard unary operators...
> FIRST_UNARY_INST(12)
> HANDLE_UNARY_INST(12, FNeg , UnaryOperator)
> - LAST_UNARY_INST(12)
> +HANDLE_UNARY_INST(13, Freeze, UnaryOperator)
> + LAST_UNARY_INST(13)
>
> // Standard binary operators...
> - FIRST_BINARY_INST(13)
> -HANDLE_BINARY_INST(13, Add , BinaryOperator)
> -HANDLE_BINARY_INST(14, FAdd , BinaryOperator)
> -HANDLE_BINARY_INST(15, Sub , BinaryOperator)
> -HANDLE_BINARY_INST(16, FSub , BinaryOperator)
> -HANDLE_BINARY_INST(17, Mul , BinaryOperator)
> -HANDLE_BINARY_INST(18, FMul , BinaryOperator)
> -HANDLE_BINARY_INST(19, UDiv , BinaryOperator)
> -HANDLE_BINARY_INST(20, SDiv , BinaryOperator)
> -HANDLE_BINARY_INST(21, FDiv , BinaryOperator)
> -HANDLE_BINARY_INST(22, URem , BinaryOperator)
> -HANDLE_BINARY_INST(23, SRem , BinaryOperator)
> -HANDLE_BINARY_INST(24, FRem , BinaryOperator)
> + FIRST_BINARY_INST(14)
> +HANDLE_BINARY_INST(14, Add , BinaryOperator)
> +HANDLE_BINARY_INST(15, FAdd , BinaryOperator)
> +HANDLE_BINARY_INST(16, Sub , BinaryOperator)
> +HANDLE_BINARY_INST(17, FSub , BinaryOperator)
> +HANDLE_BINARY_INST(18, Mul , BinaryOperator)
> +HANDLE_BINARY_INST(19, FMul , BinaryOperator)
> +HANDLE_BINARY_INST(20, UDiv , BinaryOperator)
> +HANDLE_BINARY_INST(21, SDiv , BinaryOperator)
> +HANDLE_BINARY_INST(22, FDiv , BinaryOperator)
> +HANDLE_BINARY_INST(23, URem , BinaryOperator)
> +HANDLE_BINARY_INST(24, SRem , BinaryOperator)
> +HANDLE_BINARY_INST(25, FRem , BinaryOperator)
>
> // Logical operators (integer operands)
> -HANDLE_BINARY_INST(25, Shl , BinaryOperator) // Shift
> left (logical)
> -HANDLE_BINARY_INST(26, LShr , BinaryOperator) // Shift right
> (logical)
> -HANDLE_BINARY_INST(27, AShr , BinaryOperator) // Shift right
> (arithmetic)
> -HANDLE_BINARY_INST(28, And , BinaryOperator)
> -HANDLE_BINARY_INST(29, Or , BinaryOperator)
> -HANDLE_BINARY_INST(30, Xor , BinaryOperator)
> - LAST_BINARY_INST(30)
> +HANDLE_BINARY_INST(26, Shl , BinaryOperator) // Shift
> left (logical)
> +HANDLE_BINARY_INST(27, LShr , BinaryOperator) // Shift right
> (logical)
> +HANDLE_BINARY_INST(28, AShr , BinaryOperator) // Shift right
> (arithmetic)
> +HANDLE_BINARY_INST(29, And , BinaryOperator)
> +HANDLE_BINARY_INST(30, Or , BinaryOperator)
> +HANDLE_BINARY_INST(31, Xor , BinaryOperator)
> + LAST_BINARY_INST(31)
>
> // Memory operators...
> - FIRST_MEMORY_INST(31)
> -HANDLE_MEMORY_INST(31, Alloca, AllocaInst) // Stack management
> -HANDLE_MEMORY_INST(32, Load , LoadInst ) // Memory manipulation
> instrs
> -HANDLE_MEMORY_INST(33, Store , StoreInst )
> -HANDLE_MEMORY_INST(34, GetElementPtr, GetElementPtrInst)
> -HANDLE_MEMORY_INST(35, Fence , FenceInst )
> -HANDLE_MEMORY_INST(36, AtomicCmpXchg , AtomicCmpXchgInst )
> -HANDLE_MEMORY_INST(37, AtomicRMW , AtomicRMWInst )
> - LAST_MEMORY_INST(37)
> + FIRST_MEMORY_INST(32)
> +HANDLE_MEMORY_INST(32, Alloca, AllocaInst) // Stack management
> +HANDLE_MEMORY_INST(33, Load , LoadInst ) // Memory manipulation
> instrs
> +HANDLE_MEMORY_INST(34, Store , StoreInst )
> +HANDLE_MEMORY_INST(35, GetElementPtr, GetElementPtrInst)
> +HANDLE_MEMORY_INST(36, Fence , FenceInst )
> +HANDLE_MEMORY_INST(37, AtomicCmpXchg , AtomicCmpXchgInst )
> +HANDLE_MEMORY_INST(38, AtomicRMW , AtomicRMWInst )
> + LAST_MEMORY_INST(38)
>
> // Cast operators ...
> // NOTE: The order matters here because
> CastInst::isEliminableCastPair
> // NOTE: (see Instructions.cpp) encodes a table based on this
> ordering.
> - FIRST_CAST_INST(38)
> -HANDLE_CAST_INST(38, Trunc , TruncInst ) // Truncate integers
> -HANDLE_CAST_INST(39, ZExt , ZExtInst ) // Zero extend
> integers
> -HANDLE_CAST_INST(40, SExt , SExtInst ) // Sign extend
> integers
> -HANDLE_CAST_INST(41, FPToUI , FPToUIInst ) // floating point ->
> UInt
> -HANDLE_CAST_INST(42, FPToSI , FPToSIInst ) // floating point ->
> SInt
> -HANDLE_CAST_INST(43, UIToFP , UIToFPInst ) // UInt -> floating
> point
> -HANDLE_CAST_INST(44, SIToFP , SIToFPInst ) // SInt -> floating
> point
> -HANDLE_CAST_INST(45, FPTrunc , FPTruncInst ) // Truncate floating
> point
> -HANDLE_CAST_INST(46, FPExt , FPExtInst ) // Extend floating
> point
> -HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer
> -HANDLE_CAST_INST(48, IntToPtr, IntToPtrInst) // Integer -> Pointer
> -HANDLE_CAST_INST(49, BitCast , BitCastInst ) // Type cast
> -HANDLE_CAST_INST(50, AddrSpaceCast, AddrSpaceCastInst) // addrspace
> cast
> - LAST_CAST_INST(50)
> -
> - FIRST_FUNCLETPAD_INST(51)
> -HANDLE_FUNCLETPAD_INST(51, CleanupPad, CleanupPadInst)
> -HANDLE_FUNCLETPAD_INST(52, CatchPad , CatchPadInst)
> - LAST_FUNCLETPAD_INST(52)
> + FIRST_CAST_INST(39)
> +HANDLE_CAST_INST(39, Trunc , TruncInst ) // Truncate integers
> +HANDLE_CAST_INST(40, ZExt , ZExtInst ) // Zero extend
> integers
> +HANDLE_CAST_INST(41, SExt , SExtInst ) // Sign extend
> integers
> +HANDLE_CAST_INST(42, FPToUI , FPToUIInst ) // floating point ->
> UInt
> +HANDLE_CAST_INST(43, FPToSI , FPToSIInst ) // floating point ->
> SInt
> +HANDLE_CAST_INST(44, UIToFP , UIToFPInst ) // UInt -> floating
> point
> +HANDLE_CAST_INST(45, SIToFP , SIToFPInst ) // SInt -> floating
> point
> +HANDLE_CAST_INST(46, FPTrunc , FPTruncInst ) // Truncate floating
> point
> +HANDLE_CAST_INST(47, FPExt , FPExtInst ) // Extend floating
> point
> +HANDLE_CAST_INST(48, PtrToInt, PtrToIntInst) // Pointer -> Integer
> +HANDLE_CAST_INST(49, IntToPtr, IntToPtrInst) // Integer -> Pointer
> +HANDLE_CAST_INST(50, BitCast , BitCastInst ) // Type cast
> +HANDLE_CAST_INST(51, AddrSpaceCast, AddrSpaceCastInst) // addrspace
> cast
> + LAST_CAST_INST(51)
> +
> + FIRST_FUNCLETPAD_INST(52)
> +HANDLE_FUNCLETPAD_INST(52, CleanupPad, CleanupPadInst)
> +HANDLE_FUNCLETPAD_INST(53, CatchPad , CatchPadInst)
> + LAST_FUNCLETPAD_INST(53)
>
> // Other operators...
> - FIRST_OTHER_INST(53)
> -HANDLE_OTHER_INST(53, ICmp , ICmpInst ) // Integer comparison
> instruction
> -HANDLE_OTHER_INST(54, FCmp , FCmpInst ) // Floating point
> comparison instr.
> -HANDLE_OTHER_INST(55, PHI , PHINode ) // PHI node instruction
> -HANDLE_OTHER_INST(56, Call , CallInst ) // Call a function
> -HANDLE_OTHER_INST(57, Select , SelectInst ) // select instruction
> -HANDLE_USER_INST (58, UserOp1, Instruction) // May be used
> internally in a pass
> -HANDLE_USER_INST (59, UserOp2, Instruction) // Internal to passes
> only
> -HANDLE_OTHER_INST(60, VAArg , VAArgInst ) // vaarg instruction
> -HANDLE_OTHER_INST(61, ExtractElement, ExtractElementInst)// extract
> from vector
> -HANDLE_OTHER_INST(62, InsertElement, InsertElementInst) // insert
> into vector
> -HANDLE_OTHER_INST(63, ShuffleVector, ShuffleVectorInst) // shuffle
> two vectors.
> -HANDLE_OTHER_INST(64, ExtractValue, ExtractValueInst)// extract from
> aggregate
> -HANDLE_OTHER_INST(65, InsertValue, InsertValueInst) // insert into
> aggregate
> -HANDLE_OTHER_INST(66, LandingPad, LandingPadInst) // Landing pad
> instruction.
> - LAST_OTHER_INST(66)
> + FIRST_OTHER_INST(54)
> +HANDLE_OTHER_INST(54, ICmp , ICmpInst ) // Integer comparison
> instruction
> +HANDLE_OTHER_INST(55, FCmp , FCmpInst ) // Floating point
> comparison instr.
> +HANDLE_OTHER_INST(56, PHI , PHINode ) // PHI node instruction
> +HANDLE_OTHER_INST(57, Call , CallInst ) // Call a function
> +HANDLE_OTHER_INST(58, Select , SelectInst ) // select instruction
> +HANDLE_USER_INST (59, UserOp1, Instruction) // May be used
> internally in a pass
> +HANDLE_USER_INST (60, UserOp2, Instruction) // Internal to passes
> only
> +HANDLE_OTHER_INST(61, VAArg , VAArgInst ) // vaarg instruction
> +HANDLE_OTHER_INST(62, ExtractElement, ExtractElementInst)// extract
> from vector
> +HANDLE_OTHER_INST(63, InsertElement, InsertElementInst) // insert
> into vector
> +HANDLE_OTHER_INST(64, ShuffleVector, ShuffleVectorInst) // shuffle
> two vectors.
> +HANDLE_OTHER_INST(65, ExtractValue, ExtractValueInst)// extract from
> aggregate
> +HANDLE_OTHER_INST(66, InsertValue, InsertValueInst) // insert into
> aggregate
> +HANDLE_OTHER_INST(67, LandingPad, LandingPadInst) // Landing pad
> instruction.
> + LAST_OTHER_INST(67)
>
> #undef FIRST_TERM_INST
> #undef HANDLE_TERM_INST
>
> diff --git a/llvm/include/llvm/IR/Operator.h
> b/llvm/include/llvm/IR/Operator.h
> index c8ca7e9a00e8..7d0b739000c6 100644
> --- a/llvm/include/llvm/IR/Operator.h
> +++ b/llvm/include/llvm/IR/Operator.h
> @@ -598,6 +598,9 @@ class BitCastOperator
> }
> };
>
> +class FreezeOperator : public ConcreteOperator<Operator,
> Instruction::Freeze>
> +{};
> +
> } // end namespace llvm
>
> #endif // LLVM_IR_OPERATOR_H
>
> diff --git a/llvm/include/llvm/IR/PatternMatch.h
> b/llvm/include/llvm/IR/PatternMatch.h
> index 37a2fe52ec11..173b664028f7 100644
> --- a/llvm/include/llvm/IR/PatternMatch.h
> +++ b/llvm/include/llvm/IR/PatternMatch.h
> @@ -825,6 +825,28 @@ m_FNegNSZ(const RHS &X) {
> return m_FSub(m_AnyZeroFP(), X);
> }
>
> +template <typename Op_t> struct Freeze_match {
> + Op_t X;
> +
> + Freeze_match(const Op_t &Op) : X(Op) {}
> + template <typename OpTy> bool match(OpTy *V) {
> + auto *I = dyn_cast<UnaryOperator>(V);
> + if (!I) return false;
> +
> + if (isa<FreezeOperator>(I))
> + return X.match(I->getOperand(0));
> +
> + return false;
> + }
> +};
> +
> +/// Matches freeze.
> +template <typename OpTy>
> +inline Freeze_match<OpTy>
> +m_Freeze(const OpTy &X) {
> + return Freeze_match<OpTy>(X);
> +}
> +
> template <typename LHS, typename RHS>
> inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS
> &L,
> const RHS
> &R) {
>
> diff --git a/llvm/lib/AsmParser/LLLexer.cpp
> b/llvm/lib/AsmParser/LLLexer.cpp
> index 819f8a0712db..c6df821a22cd 100644
> --- a/llvm/lib/AsmParser/LLLexer.cpp
> +++ b/llvm/lib/AsmParser/LLLexer.cpp
> @@ -837,6 +837,7 @@ lltok::Kind LLLexer::LexIdentifier() {
> } while (false)
>
> INSTKEYWORD(fneg, FNeg);
> + INSTKEYWORD(freeze, Freeze);
>
> INSTKEYWORD(add, Add); INSTKEYWORD(fadd, FAdd);
> INSTKEYWORD(sub, Sub); INSTKEYWORD(fsub, FSub);
>
> diff --git a/llvm/lib/AsmParser/LLParser.cpp
> b/llvm/lib/AsmParser/LLParser.cpp
> index 042f324249f6..c204a9448ce0 100644
> --- a/llvm/lib/AsmParser/LLParser.cpp
> +++ b/llvm/lib/AsmParser/LLParser.cpp
> @@ -3414,7 +3414,8 @@ bool LLParser::ParseValID(ValID &ID,
> PerFunctionState *PFS) {
> }
>
> // Unary Operators.
> - case lltok::kw_fneg: {
> + case lltok::kw_fneg:
> + case lltok::kw_freeze: {
> unsigned Opc = Lex.getUIntVal();
> Constant *Val;
> Lex.Lex();
> @@ -3429,6 +3430,8 @@ bool LLParser::ParseValID(ValID &ID,
> PerFunctionState *PFS) {
> if (!Val->getType()->isFPOrFPVectorTy())
> return Error(ID.Loc, "constexpr requires fp operands");
> break;
> + case Instruction::Freeze:
> + break;
> default: llvm_unreachable("Unknown unary operator!");
> }
> unsigned Flags = 0;
> @@ -5722,6 +5725,7 @@ int LLParser::ParseInstruction(Instruction
> *&Inst, BasicBlock *BB,
> Inst->setFastMathFlags(FMF);
> return false;
> }
> + case lltok::kw_freeze: return ParseUnaryOp(Inst, PFS, KeywordVal,
> false);
> // Binary Operators.
> case lltok::kw_add:
> case lltok::kw_sub:
> @@ -6325,16 +6329,14 @@ bool LLParser::ParseCleanupPad(Instruction
> *&Inst, PerFunctionState &PFS) {
> /// ParseUnaryOp
> /// ::= UnaryOp TypeAndValue ',' Value
> ///
> -/// If IsFP is false, then any integer operand is allowed, if it is
> true, any fp
> -/// operand is allowed.
> +/// If IsFP is true, then fp operand is only allowed.
> bool LLParser::ParseUnaryOp(Instruction *&Inst, PerFunctionState
> &PFS,
> unsigned Opc, bool IsFP) {
> LocTy Loc; Value *LHS;
> if (ParseTypeAndValue(LHS, Loc, PFS))
> return true;
>
> - bool Valid = IsFP ? LHS->getType()->isFPOrFPVectorTy()
> - : LHS->getType()->isIntOrIntVectorTy();
> + bool Valid = !IsFP || LHS->getType()->isFPOrFPVectorTy();
>
> if (!Valid)
> return Error(Loc, "invalid operand type for instruction");
>
> diff --git a/llvm/lib/AsmParser/LLToken.h
> b/llvm/lib/AsmParser/LLToken.h
> index 2ebfb9da2579..e418f7cbfb49 100644
> --- a/llvm/lib/AsmParser/LLToken.h
> +++ b/llvm/lib/AsmParser/LLToken.h
> @@ -279,6 +279,7 @@ enum Kind {
>
> // Instruction Opcodes (Opcode in UIntVal).
> kw_fneg,
> + kw_freeze,
> kw_add,
> kw_fadd,
> kw_sub,
>
> diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
> b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
> index ed736298dfa0..71166ba337e6 100644
> --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
> +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
> @@ -1055,16 +1055,13 @@ static int getDecodedCastOpcode(unsigned Val)
> {
> }
>
> static int getDecodedUnaryOpcode(unsigned Val, Type *Ty) {
> - bool IsFP = Ty->isFPOrFPVectorTy();
> - // UnOps are only valid for int/fp or vector of int/fp types
> - if (!IsFP && !Ty->isIntOrIntVectorTy())
> - return -1;
> -
> switch (Val) {
> default:
> return -1;
> case bitc::UNOP_FNEG:
> - return IsFP ? Instruction::FNeg : -1;
> + return Ty->isFPOrFPVectorTy() ? Instruction::FNeg : -1;
> + case bitc::UNOP_FREEZE:
> + return Instruction::Freeze;
> }
> }
>
> @@ -3865,7 +3862,7 @@ Error BitcodeReader::parseFunctionBody(Function
> *F) {
> case bitc::FUNC_CODE_INST_UNOP: { // UNOP: [opval, ty,
> opcode]
> unsigned OpNum = 0;
> Value *LHS;
> - if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
> + if (getValueTypePair(Record, OpNum, NextValueNo, LHS, &FullTy)
> ||
> OpNum+1 > Record.size())
> return error("Invalid record");
>
>
> diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
> b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
> index deb4019ea8ba..86d20e920fe2 100644
> --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
> +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
> @@ -521,6 +521,7 @@ static unsigned getEncodedUnaryOpcode(unsigned
> Opcode) {
> switch (Opcode) {
> default: llvm_unreachable("Unknown binary instruction!");
> case Instruction::FNeg: return bitc::UNOP_FNEG;
> + case Instruction::Freeze: return bitc::UNOP_FREEZE;
> }
> }
>
> @@ -2433,6 +2434,17 @@ void
> ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned
> LastVal,
> Record.push_back(VE.getTypeID(C->getOperand(0)-
> >getType()));
> Record.push_back(VE.getValueID(C->getOperand(0)));
> AbbrevToUse = CONSTANTS_CE_CAST_Abbrev;
> + } else if (Instruction::isUnaryOp(CE->getOpcode())) {
> + assert(CE->getNumOperands() == 1 && "Unknown constant
> expr!");
> + Code = bitc::CST_CODE_CE_UNOP;
> + Record.push_back(getEncodedUnaryOpcode(CE->getOpcode()));
> + Record.push_back(VE.getValueID(C->getOperand(0)));
> + uint64_t Flags = getOptimizationFlags(CE);
> + if (Flags != 0) {
> + assert(CE->getOpcode() == Instruction::FNeg);
> + Record.push_back(Flags);
> + }
> + break;
> } else {
> assert(CE->getNumOperands() == 2 && "Unknown constant
> expr!");
> Code = bitc::CST_CODE_CE_BINOP;
> @@ -2444,16 +2456,6 @@ void
> ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned
> LastVal,
> Record.push_back(Flags);
> }
> break;
> - case Instruction::FNeg: {
> - assert(CE->getNumOperands() == 1 && "Unknown constant
> expr!");
> - Code = bitc::CST_CODE_CE_UNOP;
> - Record.push_back(getEncodedUnaryOpcode(CE->getOpcode()));
> - Record.push_back(VE.getValueID(C->getOperand(0)));
> - uint64_t Flags = getOptimizationFlags(CE);
> - if (Flags != 0)
> - Record.push_back(Flags);
> - break;
> - }
> case Instruction::GetElementPtr: {
> Code = bitc::CST_CODE_CE_GEP;
> const auto *GO = cast<GEPOperator>(C);
> @@ -2611,6 +2613,17 @@ void
> ModuleBitcodeWriter::writeInstruction(const Instruction &I,
> AbbrevToUse = FUNCTION_INST_CAST_ABBREV;
> Vals.push_back(VE.getTypeID(I.getType()));
> Vals.push_back(getEncodedCastOpcode(I.getOpcode()));
> + } else if (isa<UnaryOperator>(I)) {
> + Code = bitc::FUNC_CODE_INST_UNOP;
> + if (!pushValueAndType(I.getOperand(0), InstID, Vals))
> + AbbrevToUse = FUNCTION_INST_UNOP_ABBREV;
> + Vals.push_back(getEncodedUnaryOpcode(I.getOpcode()));
> + uint64_t Flags = getOptimizationFlags(&I);
> + if (Flags != 0) {
> + if (AbbrevToUse == FUNCTION_INST_UNOP_ABBREV)
> + AbbrevToUse = FUNCTION_INST_UNOP_FLAGS_ABBREV;
> + Vals.push_back(Flags);
> + }
> } else {
> assert(isa<BinaryOperator>(I) && "Unknown instruction!");
> Code = bitc::FUNC_CODE_INST_BINOP;
> @@ -2626,19 +2639,6 @@ void
> ModuleBitcodeWriter::writeInstruction(const Instruction &I,
> }
> }
> break;
> - case Instruction::FNeg: {
> - Code = bitc::FUNC_CODE_INST_UNOP;
> - if (!pushValueAndType(I.getOperand(0), InstID, Vals))
> - AbbrevToUse = FUNCTION_INST_UNOP_ABBREV;
> - Vals.push_back(getEncodedUnaryOpcode(I.getOpcode()));
> - uint64_t Flags = getOptimizationFlags(&I);
> - if (Flags != 0) {
> - if (AbbrevToUse == FUNCTION_INST_UNOP_ABBREV)
> - AbbrevToUse = FUNCTION_INST_UNOP_FLAGS_ABBREV;
> - Vals.push_back(Flags);
> - }
> - break;
> - }
> case Instruction::GetElementPtr: {
> Code = bitc::FUNC_CODE_INST_GEP;
> AbbrevToUse = FUNCTION_INST_GEP_ABBREV;
>
> diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> index 0e6e7027e0cd..914edad0b8b9 100644
> --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> @@ -10592,3 +10592,8 @@ void SelectionDAGBuilder::visitSwitch(const
> SwitchInst &SI) {
> lowerWorkItem(W, SI.getCondition(), SwitchMBB, DefaultMBB);
> }
> }
> +
> +void SelectionDAGBuilder::visitFreeze(const User &I) {
> + SDValue N = getValue(I.getOperand(0));
> + setValue(&I, N);
> +}
>
> diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
> b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
> index bfcf30b430b6..c288a4f69084 100644
> --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
> +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
> @@ -668,6 +668,7 @@ class SelectionDAGBuilder {
>
> void visitUnary(const User &I, unsigned Opcode);
> void visitFNeg(const User &I) { visitUnary(I, ISD::FNEG); }
> + void visitFreeze(const User &I);
>
> void visitBinary(const User &I, unsigned Opcode);
> void visitShift(const User &I, unsigned Opcode);
>
> diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp
> b/llvm/lib/CodeGen/TargetLoweringBase.cpp
> index cb95d47e598f..c5b129029493 100644
> --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
> +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
> @@ -1663,6 +1663,7 @@ int
> TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const {
> case ExtractValue: return ISD::MERGE_VALUES;
> case InsertValue: return ISD::MERGE_VALUES;
> case LandingPad: return 0;
> + case Freeze: return 0;
> }
>
> llvm_unreachable("Unknown instruction type encountered!");
>
> diff --git a/llvm/lib/IR/ConstantFold.cpp
> b/llvm/lib/IR/ConstantFold.cpp
> index a6cd83310088..218a25fdfff6 100644
> --- a/llvm/lib/IR/ConstantFold.cpp
> +++ b/llvm/lib/IR/ConstantFold.cpp
> @@ -941,43 +941,52 @@ Constant
> *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
> Constant *llvm::ConstantFoldUnaryInstruction(unsigned Opcode,
> Constant *C) {
> assert(Instruction::isUnaryOp(Opcode) && "Non-unary instruction
> detected");
>
> - // Handle scalar UndefValue. Vectors are always evaluated per
> element.
> - bool HasScalarUndef = !C->getType()->isVectorTy() &&
> isa<UndefValue>(C);
> + switch (static_cast<Instruction::UnaryOps>(Opcode)) {
> + default:
> + break;
> + case Instruction::FNeg: {
> + // Handle scalar UndefValue. Vectors are always evaluated per
> element.
> + bool HasScalarUndef = !C->getType()->isVectorTy() &&
> isa<UndefValue>(C);
>
> - if (HasScalarUndef) {
> - switch (static_cast<Instruction::UnaryOps>(Opcode)) {
> - case Instruction::FNeg:
> + if (HasScalarUndef) {
> return C; // -undef -> undef
> - case Instruction::UnaryOpsEnd:
> - llvm_unreachable("Invalid UnaryOp");
> }
> - }
>
> - // Constant should not be UndefValue, unless these are vector
> constants.
> - assert(!HasScalarUndef && "Unexpected UndefValue");
> - // We only have FP UnaryOps right now.
> - assert(!isa<ConstantInt>(C) && "Unexpected Integer UnaryOp");
> + // Constant should not be UndefValue, unless these are vector
> constants.
> + assert(!HasScalarUndef && "Unexpected UndefValue");
> + assert(!isa<ConstantInt>(C) && "Unexpected Integer UnaryOp");
>
> - if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
> - const APFloat &CV = CFP->getValueAPF();
> - switch (Opcode) {
> - default:
> - break;
> - case Instruction::FNeg:
> + if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
> + const APFloat &CV = CFP->getValueAPF();
> return ConstantFP::get(C->getContext(), neg(CV));
> - }
> - } else if (VectorType *VTy = dyn_cast<VectorType>(C->getType())) {
> - // Fold each element and create a vector constant from those
> constants.
> - SmallVector<Constant*, 16> Result;
> - Type *Ty = IntegerType::get(VTy->getContext(), 32);
> - for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) {
> - Constant *ExtractIdx = ConstantInt::get(Ty, i);
> - Constant *Elt = ConstantExpr::getExtractElement(C,
> ExtractIdx);
> + } else if (VectorType *VTy = dyn_cast<VectorType>(C->getType()))
> {
> + // Fold each element and create a vector constant from those
> constants.
> + SmallVector<Constant*, 16> Result;
> + Type *Ty = IntegerType::get(VTy->getContext(), 32);
> + for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) {
> + Constant *ExtractIdx = ConstantInt::get(Ty, i);
> + Constant *Elt = ConstantExpr::getExtractElement(C,
> ExtractIdx);
> +
> + Result.push_back(ConstantExpr::get(Opcode, Elt));
> + }
>
> - Result.push_back(ConstantExpr::get(Opcode, Elt));
> + return ConstantVector::get(Result);
> }
> -
> - return ConstantVector::get(Result);
> + break;
> + }
> + case Instruction::Freeze: {
> + if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
> + return CFP;
> + } else if (ConstantInt *CINT = dyn_cast<ConstantInt>(C)) {
> + return CINT;
> + } else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
> + // A global variable is neither undef nor poison.
> + return GV;
> + }
> + break;
> + }
> + case Instruction::UnaryOpsEnd:
> + llvm_unreachable("Invalid UnaryOp");
> }
>
> // We don't know how to fold this.
>
> diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
> index 03bff7e5fde0..78ae36c9018f 100644
> --- a/llvm/lib/IR/Core.cpp
> +++ b/llvm/lib/IR/Core.cpp
> @@ -3410,6 +3410,11 @@ LLVMValueRef LLVMBuildFNeg(LLVMBuilderRef B,
> LLVMValueRef V, const char *Name) {
> return wrap(unwrap(B)->CreateFNeg(unwrap(V), Name));
> }
>
> +LLVMValueRef LLVMBuildFreeze(LLVMBuilderRef B, LLVMValueRef V,
> + const char *Name) {
> + return wrap(unwrap(B)->CreateFreeze(unwrap(V), Name));
> +}
> +
> LLVMValueRef LLVMBuildNot(LLVMBuilderRef B, LLVMValueRef V, const
> char *Name) {
> return wrap(unwrap(B)->CreateNot(unwrap(V), Name));
> }
>
> diff --git a/llvm/lib/IR/Instruction.cpp
> b/llvm/lib/IR/Instruction.cpp
> index b157c7bb34bf..2e9310c11738 100644
> --- a/llvm/lib/IR/Instruction.cpp
> +++ b/llvm/lib/IR/Instruction.cpp
> @@ -307,6 +307,7 @@ const char *Instruction::getOpcodeName(unsigned
> OpCode) {
>
> // Standard unary operators...
> case FNeg: return "fneg";
> + case Freeze: return "freeze";
>
> // Standard binary operators...
> case Add: return "add";
>
> diff --git a/llvm/lib/IR/Instructions.cpp
> b/llvm/lib/IR/Instructions.cpp
> index f62ec8fbec17..95521ad91210 100644
> --- a/llvm/lib/IR/Instructions.cpp
> +++ b/llvm/lib/IR/Instructions.cpp
> @@ -2232,6 +2232,9 @@ void UnaryOperator::AssertOK() {
> "Tried to create a floating-point operation on a "
> "non-floating-point type!");
> break;
> + case Freeze:
> + // Freeze can take any type as an argument.
> + break;
> default: llvm_unreachable("Invalid opcode provided");
> }
> #endif
>
> diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
> index e89d8b0a9b58..91026c3b1b28 100644
> --- a/llvm/lib/IR/Verifier.cpp
> +++ b/llvm/lib/IR/Verifier.cpp
> @@ -3145,6 +3145,9 @@ void Verifier::visitUnaryOperator(UnaryOperator
> &U) {
> Assert(U.getType()->isFPOrFPVectorTy(),
> "FNeg operator only works with float types!", &U);
> break;
> + case Instruction::Freeze:
> + // Freeze can take all kinds of types.
> + break;
> default:
> llvm_unreachable("Unknown UnaryOperator opcode!");
> }
>
> diff --git a/llvm/test/Bindings/OCaml/core.ml
> b/llvm/test/Bindings/OCaml/core.ml
> index f649dbdb8fa2..185a286fcb27 100644
> --- a/llvm/test/Bindings/OCaml/core.ml
> +++ b/llvm/test/Bindings/OCaml/core.ml
> @@ -267,6 +267,7 @@ let test_constants () =
> * CHECK: @const_nsw_neg = global i64 sub nsw
> * CHECK: @const_nuw_neg = global i64 sub nuw
> * CHECK: @const_fneg = global double fneg
> + * CHECK: @const_freeze = global i64 freeze
> * CHECK: @const_not = global i64 xor
> * CHECK: @const_add = global i64 add
> * CHECK: @const_nsw_add = global i64 add nsw
> @@ -303,6 +304,7 @@ let test_constants () =
> ignore (define_global "const_nsw_neg" (const_nsw_neg foldbomb) m);
> ignore (define_global "const_nuw_neg" (const_nuw_neg foldbomb) m);
> ignore (define_global "const_fneg" (const_fneg ffoldbomb) m);
> + ignore (define_global "const_freeze" (const_freeze foldbomb) m);
> ignore (define_global "const_not" (const_not foldbomb) m);
> ignore (define_global "const_add" (const_add foldbomb five) m);
> ignore (define_global "const_nsw_add" (const_nsw_add foldbomb
> five) m);
> @@ -1400,6 +1402,7 @@ let test_builder () =
> ignore (build_nsw_neg p1 "build_nsw_neg" b);
> ignore (build_nuw_neg p1 "build_nuw_neg" b);
> ignore (build_fneg f1 "build_fneg" b);
> + ignore (build_freeze f1 "build_freeze" b);
> ignore (build_not p1 "build_not" b);
> ignore (build_unreachable b)
> end;
>
> diff --git a/llvm/test/Bindings/llvm-c/freeze.ll
> b/llvm/test/Bindings/llvm-c/freeze.ll
> new file mode 100644
> index 000000000000..eb842c03b788
> --- /dev/null
> +++ b/llvm/test/Bindings/llvm-c/freeze.ll
> @@ -0,0 +1,22 @@
> +; RUN: llvm-as < %s | llvm-dis > %t.orig
> +; RUN: llvm-as < %s | llvm-c-test --echo > %t.echo
> +; RUN:
> diff -w %t.orig %t.echo
> +
> +%struct.T = type { i32, i32 }
> +
> +define i32 @f(i32 %arg, <2 x i32> %arg2, float %arg3, <2 x float>
> %arg4,
> + i8* %arg5, %struct.T %arg6, [2 x i32] %arg7, { i32,
> i32 } %arg8) {
> + %1 = freeze i32 %arg
> + %2 = freeze i32 10
> + %3 = freeze i32 %1
> + %4 = freeze i32 undef
> + %5 = freeze i666 11
> + %6 = freeze <2 x i32> %arg2
> + %7 = freeze float %arg3
> + %8 = freeze <2 x float> %arg4
> + %9 = freeze i8* %arg5
> + %10 = freeze %struct.T %arg6
> + %11 = freeze [2 x i32] %arg7
> + %12 = freeze { i32, i32 } %arg8
> + ret i32 %1
> +}
>
> diff --git a/llvm/test/Bitcode/compatibility.ll
> b/llvm/test/Bitcode/compatibility.ll
> index 8269a90e1460..c7b22c7999dd 100644
> --- a/llvm/test/Bitcode/compatibility.ll
> +++ b/llvm/test/Bitcode/compatibility.ll
> @@ -1172,9 +1172,17 @@ continue:
> }
>
> ; Instructions -- Unary Operations
> -define void @instructions.unops(double %op1) {
> +define void @instructions.unops(double %op1, i32 %op2, <2 x i32>
> %op3, i8* %op4) {
> fneg double %op1
> ; CHECK: fneg double %op1
> + freeze i32 %op2
> + ; CHECK: freeze i32 %op2
> + freeze double %op1
> + ; CHECK: freeze double %op1
> + freeze <2 x i32> %op3
> + ; CHECK: freeze <2 x i32> %op3
> + freeze i8* %op4
> + ; CHECK: freeze i8* %op4
> ret void
> }
>
> @@ -1826,6 +1834,10 @@ define void @instructions.strictfp() strictfp
> {
> ret void
> }
>
> +define i64 @constexpr_freeze() {
> + ret i64 freeze (i64 32)
> +}
> +
> ; immarg attribute
> declare void @llvm.test.immarg.intrinsic(i32 immarg)
> ; CHECK: declare void @llvm.test.immarg.intrinsic(i32 immarg)
>
> diff --git a/llvm/test/Transforms/MergeFunc/inline-asm.ll
> b/llvm/test/Transforms/MergeFunc/inline-asm.ll
> index 15760242cf69..370d3c56f060 100644
> --- a/llvm/test/Transforms/MergeFunc/inline-asm.ll
> +++ b/llvm/test/Transforms/MergeFunc/inline-asm.ll
> @@ -3,13 +3,13 @@
> ; CHECK-LABEL: @int_ptr_arg_
> diff erent
> ; CHECK-NEXT: call void asm
>
> -; CHECK-LABEL: @int_ptr_null
> -; CHECK-NEXT: tail call void @float_ptr_null()
> -
> ; CHECK-LABEL: @int_ptr_arg_same
> ; CHECK-NEXT: %2 = bitcast i32* %0 to float*
> ; CHECK-NEXT: tail call void @float_ptr_arg_same(float* %2)
>
> +; CHECK-LABEL: @int_ptr_null
> +; CHECK-NEXT: tail call void @float_ptr_null()
> +
> ; Used to satisfy minimum size limit
> declare void @stuff()
>
>
> diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-
> test/echo.cpp
> index 8abbfb3fb0c0..7fca8ada5145 100644
> --- a/llvm/tools/llvm-c-test/echo.cpp
> +++ b/llvm/tools/llvm-c-test/echo.cpp
> @@ -755,6 +755,11 @@ struct FunCloner {
> Dst = LLVMBuildInsertValue(Builder, Agg, V, I, Name);
> break;
> }
> + case LLVMFreeze: {
> + LLVMValueRef Arg = CloneValue(LLVMGetOperand(Src, 0));
> + Dst = LLVMBuildFreeze(Builder, Arg, Name);
> + break;
> + }
> default:
> break;
> }
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
>
https://protect2.fireeye.com/v1/url?k=66003b1f-3ad437ee-66007b84-864685b2085c-567d08e7191d5925&q=1&e=a3825398-25c9-4e53-af5e-4bbfdd19ce24&u=https%3A%2F%2Flists.llvm.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fllvm-commits
More information about the llvm-commits
mailing list