diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/AsmParser/LLLexer.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.cpp | 73 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLParser.h | 2 | ||||
-rw-r--r-- | llvm/lib/AsmParser/LLToken.h | 1 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 47 | ||||
-rw-r--r-- | llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 52 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/TargetLoweringBase.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/IR/Constants.cpp | 30 | ||||
-rw-r--r-- | llvm/lib/IR/ConstantsContext.h | 4 | ||||
-rw-r--r-- | llvm/lib/IR/Instruction.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/IR/Instructions.cpp | 57 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 23 |
15 files changed, 311 insertions, 3 deletions
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp index af4f43986ef..4f8ce3ddc7b 100644 --- a/llvm/lib/AsmParser/LLLexer.cpp +++ b/llvm/lib/AsmParser/LLLexer.cpp @@ -823,6 +823,8 @@ lltok::Kind LLLexer::LexIdentifier() { } \ } while (false) + INSTKEYWORD(fneg, FNeg); + INSTKEYWORD(add, Add); INSTKEYWORD(fadd, FAdd); INSTKEYWORD(sub, Sub); INSTKEYWORD(fsub, FSub); INSTKEYWORD(mul, Mul); INSTKEYWORD(fmul, FMul); diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 5fe1e125d48..856be2fb64a 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -3295,7 +3295,31 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { ID.Kind = ValID::t_Constant; return false; } - + + // Unary Operators. + case lltok::kw_fneg: { + unsigned Opc = Lex.getUIntVal(); + Constant *Val; + Lex.Lex(); + if (ParseToken(lltok::lparen, "expected '(' in unary constantexpr") || + ParseGlobalTypeAndValue(Val) || + ParseToken(lltok::rparen, "expected ')' in unary constantexpr")) + return true; + + // Check that the type is valid for the operator. + switch (Opc) { + case Instruction::FNeg: + if (!Val->getType()->isFPOrFPVectorTy()) + return Error(ID.Loc, "constexpr requires fp operands"); + break; + default: llvm_unreachable("Unknown unary operator!"); + } + unsigned Flags = 0; + Constant *C = ConstantExpr::get(Opc, Val, Flags); + ID.ConstantVal = C; + ID.Kind = ValID::t_Constant; + return false; + } // Binary Operators. case lltok::kw_add: case lltok::kw_fadd: @@ -5492,6 +5516,16 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, case lltok::kw_catchswitch: return ParseCatchSwitch(Inst, PFS); case lltok::kw_catchpad: return ParseCatchPad(Inst, PFS); case lltok::kw_cleanuppad: return ParseCleanupPad(Inst, PFS); + // Unary Operators. + case lltok::kw_fneg: { + FastMathFlags FMF = EatFastMathFlagsIfPresent(); + int Res = ParseUnaryOp(Inst, PFS, KeywordVal, 2); + if (Res != 0) + return Res; + if (FMF.any()) + Inst->setFastMathFlags(FMF); + return false; + } // Binary Operators. case lltok::kw_add: case lltok::kw_sub: @@ -6064,6 +6098,43 @@ bool LLParser::ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS) { } //===----------------------------------------------------------------------===// +// Unary Operators. +//===----------------------------------------------------------------------===// + +/// ParseUnaryOp +/// ::= UnaryOp TypeAndValue ',' Value +/// +/// If OperandType is 0, then any FP or integer operand is allowed. If it is 1, +/// then any integer operand is allowed, if it is 2, any fp operand is allowed. +bool LLParser::ParseUnaryOp(Instruction *&Inst, PerFunctionState &PFS, + unsigned Opc, unsigned OperandType) { + LocTy Loc; Value *LHS; + if (ParseTypeAndValue(LHS, Loc, PFS)) + return true; + + bool Valid; + switch (OperandType) { + default: llvm_unreachable("Unknown operand type!"); + case 0: // int or FP. + Valid = LHS->getType()->isIntOrIntVectorTy() || + LHS->getType()->isFPOrFPVectorTy(); + break; + case 1: + Valid = LHS->getType()->isIntOrIntVectorTy(); + break; + case 2: + Valid = LHS->getType()->isFPOrFPVectorTy(); + break; + } + + if (!Valid) + return Error(Loc, "invalid operand type for instruction"); + + Inst = UnaryOperator::Create((Instruction::UnaryOps)Opc, LHS); + return false; +} + +//===----------------------------------------------------------------------===// // Binary Operators. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/AsmParser/LLParser.h b/llvm/lib/AsmParser/LLParser.h index cec1a8e8f7e..6f8962b6d4e 100644 --- a/llvm/lib/AsmParser/LLParser.h +++ b/llvm/lib/AsmParser/LLParser.h @@ -571,6 +571,8 @@ namespace llvm { bool ParseCatchPad(Instruction *&Inst, PerFunctionState &PFS); bool ParseCleanupPad(Instruction *&Inst, PerFunctionState &PFS); + bool ParseUnaryOp(Instruction *&Inst, PerFunctionState &PFS, unsigned Opc, + unsigned OperandType); bool ParseArithmetic(Instruction *&Inst, PerFunctionState &PFS, unsigned Opc, unsigned OperandType); bool ParseLogical(Instruction *&Inst, PerFunctionState &PFS, unsigned Opc); diff --git a/llvm/lib/AsmParser/LLToken.h b/llvm/lib/AsmParser/LLToken.h index f8f5955a16c..dae1d41fd8c 100644 --- a/llvm/lib/AsmParser/LLToken.h +++ b/llvm/lib/AsmParser/LLToken.h @@ -270,6 +270,7 @@ enum Kind { kw_umin, // Instruction Opcodes (Opcode in UIntVal). + kw_fneg, kw_add, kw_fadd, kw_sub, diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 56e05f8f085..3b1d54f82cb 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -964,6 +964,20 @@ 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_NEG: + return IsFP ? Instruction::FNeg : -1; + } +} + static int getDecodedBinaryOpcode(unsigned Val, Type *Ty) { bool IsFP = Ty->isFPOrFPVectorTy(); // BinOps are only valid for int/fp or vector of int/fp types @@ -2317,6 +2331,19 @@ Error BitcodeReader::parseConstants() { } break; } + case bitc::CST_CODE_CE_UNOP: { // CE_UNOP: [opcode, opval] + if (Record.size() < 2) + return error("Invalid record"); + int Opc = getDecodedUnaryOpcode(Record[0], CurTy); + if (Opc < 0) { + V = UndefValue::get(CurTy); // Unknown unop. + } else { + Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy); + unsigned Flags = 0; + V = ConstantExpr::get(Opc, LHS, Flags); + } + break; + } case bitc::CST_CODE_CE_BINOP: { // CE_BINOP: [opcode, opval, opval] if (Record.size() < 3) return error("Invalid record"); @@ -3535,7 +3562,27 @@ Error BitcodeReader::parseFunctionBody(Function *F) { I = nullptr; continue; } + case bitc::FUNC_CODE_INST_UNOP: { // UNOP: [opval, ty, opcode] + unsigned OpNum = 0; + Value *LHS; + if (getValueTypePair(Record, OpNum, NextValueNo, LHS) || + OpNum+1 > Record.size()) + return error("Invalid record"); + int Opc = getDecodedUnaryOpcode(Record[OpNum++], LHS->getType()); + if (Opc == -1) + return error("Invalid record"); + I = UnaryOperator::Create((Instruction::UnaryOps)Opc, LHS); + InstructionList.push_back(I); + if (OpNum < Record.size()) { + if (isa<FPMathOperator>(I)) { + FastMathFlags FMF = getDecodedFastMathFlags(Record[OpNum]); + if (FMF.any()) + I->setFastMathFlags(FMF); + } + } + break; + } case bitc::FUNC_CODE_INST_BINOP: { // BINOP: [opval, ty, opval, opcode] unsigned OpNum = 0; Value *LHS, *RHS; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index f4634c9d3f4..06eb0f76254 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -112,6 +112,8 @@ enum { // FUNCTION_BLOCK abbrev id's. FUNCTION_INST_LOAD_ABBREV = bitc::FIRST_APPLICATION_ABBREV, + FUNCTION_INST_UNOP_ABBREV, + FUNCTION_INST_UNOP_FLAGS_ABBREV, FUNCTION_INST_BINOP_ABBREV, FUNCTION_INST_BINOP_FLAGS_ABBREV, FUNCTION_INST_CAST_ABBREV, @@ -513,6 +515,13 @@ static unsigned getEncodedCastOpcode(unsigned Opcode) { } } +static unsigned getEncodedUnaryOpcode(unsigned Opcode) { + switch (Opcode) { + default: llvm_unreachable("Unknown binary instruction!"); + case Instruction::FNeg: return bitc::UNOP_NEG; + } +} + static unsigned getEncodedBinaryOpcode(unsigned Opcode) { switch (Opcode) { default: llvm_unreachable("Unknown binary instruction!"); @@ -2384,6 +2393,16 @@ 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); @@ -2556,7 +2575,19 @@ 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; @@ -3217,6 +3248,25 @@ void ModuleBitcodeWriter::writeBlockInfo() { FUNCTION_INST_LOAD_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } + { // INST_UNOP abbrev for FUNCTION_BLOCK. + auto Abbv = std::make_shared<BitCodeAbbrev>(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_UNOP)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_INST_UNOP_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } + { // INST_UNOP_FLAGS abbrev for FUNCTION_BLOCK. + auto Abbv = std::make_shared<BitCodeAbbrev>(); + Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_UNOP)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); // flags + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + FUNCTION_INST_UNOP_FLAGS_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } { // INST_BINOP abbrev for FUNCTION_BLOCK. auto Abbv = std::make_shared<BitCodeAbbrev>(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP)); diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index ef090777726..0a41877839a 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -330,6 +330,13 @@ bool IRTranslator::translateFSub(const User &U, MachineIRBuilder &MIRBuilder) { return translateBinaryOp(TargetOpcode::G_FSUB, U, MIRBuilder); } +bool IRTranslator::translateFNeg(const User &U, MachineIRBuilder &MIRBuilder) { + MIRBuilder.buildInstr(TargetOpcode::G_FNEG) + .addDef(getOrCreateVReg(U)) + .addUse(getOrCreateVReg(*U.getOperand(1))); + return true; +} + bool IRTranslator::translateCompare(const User &U, MachineIRBuilder &MIRBuilder) { const CmpInst *CI = dyn_cast<CmpInst>(&U); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index bf24d7f7562..ebe172548e3 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2801,6 +2801,15 @@ static bool isVectorReductionOp(const User *I) { return ReduxExtracted; } +void SelectionDAGBuilder::visitUnary(const User &I, unsigned Opcode) { + SDNodeFlags Flags; + + SDValue Op = getValue(I.getOperand(0)); + SDValue UnNodeValue = DAG.getNode(Opcode, getCurSDLoc(), Op.getValueType(), + Op, Flags); + setValue(&I, UnNodeValue); +} + void SelectionDAGBuilder::visitBinary(const User &I, unsigned Opcode) { SDNodeFlags Flags; if (auto *OFBinOp = dyn_cast<OverflowingBinaryOperator>(&I)) { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index 4b5dda982f1..5f9cdb69daf 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -854,6 +854,9 @@ private: void visitInvoke(const InvokeInst &I); void visitResume(const ResumeInst &I); + void visitUnary(const User &I, unsigned Opcode); + void visitFNeg(const User &I) { visitUnary(I, ISD::FNEG); } + void visitBinary(const User &I, unsigned Opcode); void visitShift(const User &I, unsigned Opcode); void visitAdd(const User &I) { visitBinary(I, ISD::ADD); } diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp index 166ff18e775..44afbef946f 100644 --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -1451,6 +1451,7 @@ int TargetLoweringBase::InstructionOpcodeToISD(unsigned Opcode) const { case CatchPad: return 0; case CatchSwitch: return 0; case CleanupPad: return 0; + case FNeg: return ISD::FNEG; case Add: return ISD::ADD; case FAdd: return ISD::FADD; case Sub: return ISD::SUB; diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index 2351e7e4a38..7368a4c8571 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -1780,6 +1780,36 @@ Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy, return getFoldedCast(Instruction::AddrSpaceCast, C, DstTy, OnlyIfReduced); } +Constant *ConstantExpr::get(unsigned Opcode, Constant *C, unsigned Flags, + Type *OnlyIfReducedTy) { + // Check the operands for consistency first. + assert(Instruction::isUnaryOp(Opcode) && + "Invalid opcode in unary constant expression"); + +#ifndef NDEBUG + switch (Opcode) { + case Instruction::FNeg: + assert(C->getType()->isFPOrFPVectorTy() && + "Tried to create a floating-point operation on a " + "non-floating-point type!"); + break; + default: + break; + } +#endif + + // TODO: Try to constant fold operation. + + if (OnlyIfReducedTy == C->getType()) + return nullptr; + + Constant *ArgVec[] = { C }; + ConstantExprKeyType Key(Opcode, ArgVec, 0, Flags); + + LLVMContextImpl *pImpl = C->getContext().pImpl; + return pImpl->ExprConstants.getOrCreate(C->getType(), Key); +} + Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, unsigned Flags, Type *OnlyIfReducedTy) { // Check the operands for consistency first. diff --git a/llvm/lib/IR/ConstantsContext.h b/llvm/lib/IR/ConstantsContext.h index e9f31e4ded6..eac17139708 100644 --- a/llvm/lib/IR/ConstantsContext.h +++ b/llvm/lib/IR/ConstantsContext.h @@ -529,7 +529,9 @@ struct ConstantExprKeyType { ConstantExpr *create(TypeClass *Ty) const { switch (Opcode) { default: - if (Instruction::isCast(Opcode)) + if (Instruction::isCast(Opcode) || + (Opcode >= Instruction::UnaryOpsBegin && + Opcode < Instruction::UnaryOpsEnd)) return new UnaryConstantExpr(Opcode, Ops[0], Ty); if ((Opcode >= Instruction::BinaryOpsBegin && Opcode < Instruction::BinaryOpsEnd)) diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index 1e326370318..f077957969f 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -303,6 +303,9 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case CatchPad: return "catchpad"; case CatchSwitch: return "catchswitch"; + // Standard unary operators... + case FNeg: return "fneg"; + // Standard binary operators... case Add: return "add"; case FAdd: return "fadd"; diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index 0295da95a3a..7d159039c27 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -1957,6 +1957,59 @@ Type *ExtractValueInst::getIndexedType(Type *Agg, } //===----------------------------------------------------------------------===// +// UnaryOperator Class +//===----------------------------------------------------------------------===// + +UnaryOperator::UnaryOperator(UnaryOps iType, Value *S, + Type *Ty, const Twine &Name, + Instruction *InsertBefore) + : UnaryInstruction(Ty, iType, S, InsertBefore) { + Op<0>() = S; + setName(Name); + AssertOK(); +} + +UnaryOperator::UnaryOperator(UnaryOps iType, Value *S, + Type *Ty, const Twine &Name, + BasicBlock *InsertAtEnd) + : UnaryInstruction(Ty, iType, S, InsertAtEnd) { + Op<0>() = S; + setName(Name); + AssertOK(); +} + +UnaryOperator *UnaryOperator::Create(UnaryOps Op, Value *S, + const Twine &Name, + Instruction *InsertBefore) { + return new UnaryOperator(Op, S, S->getType(), Name, InsertBefore); +} + +UnaryOperator *UnaryOperator::Create(UnaryOps Op, Value *S, + const Twine &Name, + BasicBlock *InsertAtEnd) { + UnaryOperator *Res = Create(Op, S, Name); + InsertAtEnd->getInstList().push_back(Res); + return Res; +} + +void UnaryOperator::AssertOK() { + Value *LHS = getOperand(0); + (void)LHS; // Silence warnings. +#ifndef NDEBUG + switch (getOpcode()) { + case FNeg: + assert(getType() == LHS->getType() && + "Unary operation should return same type as operand!"); + assert(getType()->isFPOrFPVectorTy() && + "Tried to create a floating-point operation on a " + "non-floating-point type!"); + break; + default: llvm_unreachable("Invalid opcode provided"); + } +#endif +} + +//===----------------------------------------------------------------------===// // BinaryOperator Class //===----------------------------------------------------------------------===// @@ -3697,6 +3750,10 @@ GetElementPtrInst *GetElementPtrInst::cloneImpl() const { return new (getNumOperands()) GetElementPtrInst(*this); } +UnaryOperator *UnaryOperator::cloneImpl() const { + return Create(getOpcode(), Op<0>()); +} + BinaryOperator *BinaryOperator::cloneImpl() const { return Create(getOpcode(), Op<0>(), Op<1>()); } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 4d0135d8338..899534dd10f 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -443,6 +443,7 @@ private: void visitBitCastInst(BitCastInst &I); void visitAddrSpaceCastInst(AddrSpaceCastInst &I); void visitPHINode(PHINode &PN); + void visitUnaryOperator(UnaryOperator &U); void visitBinaryOperator(BinaryOperator &B); void visitICmpInst(ICmpInst &IC); void visitFCmpInst(FCmpInst &FC); @@ -2990,6 +2991,28 @@ void Verifier::visitInvokeInst(InvokeInst &II) { visitTerminator(II); } +/// visitUnaryOperator - Check the argument to the unary operator. +/// +void Verifier::visitUnaryOperator(UnaryOperator &U) { + Assert(U.getType() == U.getOperand(0)->getType(), + "Unary operators must have same type for" + "operands and result!", + &U); + + switch (U.getOpcode()) { + // Check that floating-point arithmetic operators are only used with + // floating-point operands. + case Instruction::FNeg: + Assert(U.getType()->isFPOrFPVectorTy(), + "FNeg operator only works with float types!", &U); + break; + default: + llvm_unreachable("Unknown UnaryOperator opcode!"); + } + + visitInstruction(U); +} + /// visitBinaryOperator - Check that both arguments to the binary operator are /// of the same type! /// |