summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r--llvm/lib/IR/ConstantFold.cpp46
-rw-r--r--llvm/lib/IR/ConstantFold.h1
-rw-r--r--llvm/lib/IR/Constants.cpp10
3 files changed, 53 insertions, 4 deletions
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 1dfd5284a97..835fbb3443b 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -918,6 +918,52 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
return ConstantVector::get(Result);
}
+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);
+
+ if (HasScalarUndef) {
+ switch (static_cast<Instruction::UnaryOps>(Opcode)) {
+ case Instruction::FNeg:
+ 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");
+
+ if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
+ const APFloat &CV = CFP->getValueAPF();
+ switch (Opcode) {
+ default:
+ break;
+ case Instruction::FNeg:
+ 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);
+
+ Result.push_back(ConstantExpr::get(Opcode, Elt));
+ }
+
+ return ConstantVector::get(Result);
+ }
+
+ // We don't know how to fold this.
+ return nullptr;
+}
+
Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
Constant *C2) {
assert(Instruction::isBinaryOp(Opcode) && "Non-binary instruction detected");
diff --git a/llvm/lib/IR/ConstantFold.h b/llvm/lib/IR/ConstantFold.h
index b57153bf00b..9ad6e14e9e4 100644
--- a/llvm/lib/IR/ConstantFold.h
+++ b/llvm/lib/IR/ConstantFold.h
@@ -43,6 +43,7 @@ template <typename T> class ArrayRef;
ArrayRef<unsigned> Idxs);
Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
ArrayRef<unsigned> Idxs);
+ Constant *ConstantFoldUnaryInstruction(unsigned Opcode, Constant *V);
Constant *ConstantFoldBinaryInstruction(unsigned Opcode, Constant *V1,
Constant *V2);
Constant *ConstantFoldCompareInstruction(unsigned short predicate,
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 00c722651ed..5545eb46686 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -1830,7 +1830,8 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C, unsigned Flags,
}
#endif
- // TODO: Try to constant fold operation.
+ if (Constant *FC = ConstantFoldUnaryInstruction(Opcode, C))
+ return FC;
if (OnlyIfReducedTy == C->getType())
return nullptr;
@@ -1909,7 +1910,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
#endif
if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2))
- return FC; // Fold a few common cases.
+ return FC;
if (OnlyIfReducedTy == C1->getType())
return nullptr;
@@ -2235,7 +2236,7 @@ Constant *ConstantExpr::getNeg(Constant *C, bool HasNUW, bool HasNSW) {
Constant *ConstantExpr::getFNeg(Constant *C) {
assert(C->getType()->isFPOrFPVectorTy() &&
"Cannot FNEG a non-floating-point value!");
- return getFSub(ConstantFP::getZeroValueForNegation(C->getType()), C);
+ return get(Instruction::FNeg, C);
}
Constant *ConstantExpr::getNot(Constant *C) {
@@ -3024,7 +3025,8 @@ Instruction *ConstantExpr::getAsInstruction() {
case Instruction::FCmp:
return CmpInst::Create((Instruction::OtherOps)getOpcode(),
(CmpInst::Predicate)getPredicate(), Ops[0], Ops[1]);
-
+ case Instruction::FNeg:
+ return UnaryOperator::Create((Instruction::UnaryOps)getOpcode(), Ops[0]);
default:
assert(getNumOperands() == 2 && "Must be binary operator?");
BinaryOperator *BO =
OpenPOWER on IntegriCloud