aboutsummaryrefslogtreecommitdiffstats
path: root/lib/IR/ConstantFold.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/IR/ConstantFold.cpp')
-rw-r--r--lib/IR/ConstantFold.cpp59
1 files changed, 30 insertions, 29 deletions
diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp
index a915d28..d97d2c4 100644
--- a/lib/IR/ConstantFold.cpp
+++ b/lib/IR/ConstantFold.cpp
@@ -1120,27 +1120,18 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode,
return ConstantInt::get(CI1->getContext(), C1V | C2V);
case Instruction::Xor:
return ConstantInt::get(CI1->getContext(), C1V ^ C2V);
- case Instruction::Shl: {
- uint32_t shiftAmt = C2V.getZExtValue();
- if (shiftAmt < C1V.getBitWidth())
- return ConstantInt::get(CI1->getContext(), C1V.shl(shiftAmt));
- else
- return UndefValue::get(C1->getType()); // too big shift is undef
- }
- case Instruction::LShr: {
- uint32_t shiftAmt = C2V.getZExtValue();
- if (shiftAmt < C1V.getBitWidth())
- return ConstantInt::get(CI1->getContext(), C1V.lshr(shiftAmt));
- else
- return UndefValue::get(C1->getType()); // too big shift is undef
- }
- case Instruction::AShr: {
- uint32_t shiftAmt = C2V.getZExtValue();
- if (shiftAmt < C1V.getBitWidth())
- return ConstantInt::get(CI1->getContext(), C1V.ashr(shiftAmt));
- else
- return UndefValue::get(C1->getType()); // too big shift is undef
- }
+ case Instruction::Shl:
+ if (C2V.ult(C1V.getBitWidth()))
+ return ConstantInt::get(CI1->getContext(), C1V.shl(C2V));
+ return UndefValue::get(C1->getType()); // too big shift is undef
+ case Instruction::LShr:
+ if (C2V.ult(C1V.getBitWidth()))
+ return ConstantInt::get(CI1->getContext(), C1V.lshr(C2V));
+ return UndefValue::get(C1->getType()); // too big shift is undef
+ case Instruction::AShr:
+ if (C2V.ult(C1V.getBitWidth()))
+ return ConstantInt::get(CI1->getContext(), C1V.ashr(C2V));
+ return UndefValue::get(C1->getType()); // too big shift is undef
}
}
@@ -1327,7 +1318,7 @@ static FCmpInst::Predicate evaluateFCmpRelation(Constant *V1, Constant *V2) {
if (!isa<ConstantExpr>(V1)) {
if (!isa<ConstantExpr>(V2)) {
- // We distilled thisUse the standard constant folder for a few cases
+ // Simple case, use the standard constant folder.
ConstantInt *R = nullptr;
R = dyn_cast<ConstantInt>(
ConstantExpr::getFCmp(FCmpInst::FCMP_OEQ, V1, V2));
@@ -1665,15 +1656,22 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
// Handle some degenerate cases first
if (isa<UndefValue>(C1) || isa<UndefValue>(C2)) {
+ CmpInst::Predicate Predicate = CmpInst::Predicate(pred);
+ bool isIntegerPredicate = ICmpInst::isIntPredicate(Predicate);
// For EQ and NE, we can always pick a value for the undef to make the
// predicate pass or fail, so we can return undef.
- // Also, if both operands are undef, we can return undef.
- if (ICmpInst::isEquality(ICmpInst::Predicate(pred)) ||
- (isa<UndefValue>(C1) && isa<UndefValue>(C2)))
+ // Also, if both operands are undef, we can return undef for int comparison.
+ if (ICmpInst::isEquality(Predicate) || (isIntegerPredicate && C1 == C2))
return UndefValue::get(ResultTy);
- // Otherwise, pick the same value as the non-undef operand, and fold
- // it to true or false.
- return ConstantInt::get(ResultTy, CmpInst::isTrueWhenEqual(pred));
+
+ // Otherwise, for integer compare, pick the same value as the non-undef
+ // operand, and fold it to true or false.
+ if (isIntegerPredicate)
+ return ConstantInt::get(ResultTy, CmpInst::isTrueWhenEqual(pred));
+
+ // Choosing NaN for the undef will always make unordered comparison succeed
+ // and ordered comparison fails.
+ return ConstantInt::get(ResultTy, CmpInst::isUnordered(Predicate));
}
// icmp eq/ne(null,GV) -> false/true
@@ -1789,7 +1787,10 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred,
return ConstantVector::get(ResElts);
}
- if (C1->getType()->isFloatingPointTy()) {
+ if (C1->getType()->isFloatingPointTy() &&
+ // Only call evaluateFCmpRelation if we have a constant expr to avoid
+ // infinite recursive loop
+ (isa<ConstantExpr>(C1) || isa<ConstantExpr>(C2))) {
int Result = -1; // -1 = unknown, 0 = known false, 1 = known true.
switch (evaluateFCmpRelation(C1, C2)) {
default: llvm_unreachable("Unknown relation!");