summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/AsmParser/LLLexer.cpp2
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp73
-rw-r--r--llvm/lib/AsmParser/LLParser.h2
-rw-r--r--llvm/lib/AsmParser/LLToken.h1
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp47
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp52
-rw-r--r--llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp7
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp9
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h3
-rw-r--r--llvm/lib/CodeGen/TargetLoweringBase.cpp1
-rw-r--r--llvm/lib/IR/Constants.cpp30
-rw-r--r--llvm/lib/IR/ConstantsContext.h4
-rw-r--r--llvm/lib/IR/Instruction.cpp3
-rw-r--r--llvm/lib/IR/Instructions.cpp57
-rw-r--r--llvm/lib/IR/Verifier.cpp23
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!
///
OpenPOWER on IntegriCloud