summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/AsmParser/LLLexer.cpp1
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp12
-rw-r--r--llvm/lib/AsmParser/LLToken.h1
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp11
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp46
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp5
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h1
-rw-r--r--llvm/lib/CodeGen/TargetLoweringBase.cpp1
-rw-r--r--llvm/lib/IR/ConstantFold.cpp67
-rw-r--r--llvm/lib/IR/Core.cpp5
-rw-r--r--llvm/lib/IR/Instruction.cpp1
-rw-r--r--llvm/lib/IR/Instructions.cpp3
-rw-r--r--llvm/lib/IR/Verifier.cpp3
13 files changed, 93 insertions, 64 deletions
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 819f8a0712d..c6df821a22c 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 042f324249f..c204a9448ce 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 2ebfb9da257..e418f7cbfb4 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 ed736298dfa..71166ba337e 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 deb4019ea8b..86d20e920fe 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 0e6e7027e0c..914edad0b8b 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 bfcf30b430b..c288a4f6908 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -668,6 +668,7 @@ private:
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 cb95d47e598..c5b12902949 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 a6cd8331008..218a25fdfff 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 03bff7e5fde..78ae36c9018 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 b157c7bb34b..2e9310c1173 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 f62ec8fbec1..95521ad9121 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 e89d8b0a9b5..91026c3b1b2 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!");
}
OpenPOWER on IntegriCloud