//===--- ConstantFolding.cpp - Utils for SIL constant folding -------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "swift/SILOptimizer/Utils/ConstantFolding.h" using namespace swift; APInt swift::constantFoldBitOperation(APInt lhs, APInt rhs, BuiltinValueKind ID) { switch (ID) { default: llvm_unreachable("Not all cases are covered!"); case BuiltinValueKind::And: return lhs.And(rhs); case BuiltinValueKind::AShr: return lhs.ashr(rhs); case BuiltinValueKind::LShr: return lhs.lshr(rhs); case BuiltinValueKind::Or: return lhs.Or(rhs); case BuiltinValueKind::Shl: return lhs.shl(rhs); case BuiltinValueKind::Xor: return lhs.Xor(rhs); } } APInt swift::constantFoldComparison(APInt lhs, APInt rhs, BuiltinValueKind ID) { bool result; switch (ID) { default: llvm_unreachable("Invalid integer compare kind"); case BuiltinValueKind::ICMP_EQ: result = lhs == rhs; break; case BuiltinValueKind::ICMP_NE: result = lhs != rhs; break; case BuiltinValueKind::ICMP_SLT: result = lhs.slt(rhs); break; case BuiltinValueKind::ICMP_SGT: result = lhs.sgt(rhs); break; case BuiltinValueKind::ICMP_SLE: result = lhs.sle(rhs); break; case BuiltinValueKind::ICMP_SGE: result = lhs.sge(rhs); break; case BuiltinValueKind::ICMP_ULT: result = lhs.ult(rhs); break; case BuiltinValueKind::ICMP_UGT: result = lhs.ugt(rhs); break; case BuiltinValueKind::ICMP_ULE: result = lhs.ule(rhs); break; case BuiltinValueKind::ICMP_UGE: result = lhs.uge(rhs); break; } return APInt(1, result); } APInt swift::constantFoldBinaryWithOverflow(APInt lhs, APInt rhs, bool &Overflow, llvm::Intrinsic::ID ID) { switch (ID) { default: llvm_unreachable("Invalid case"); case llvm::Intrinsic::sadd_with_overflow: return lhs.sadd_ov(rhs, Overflow); case llvm::Intrinsic::uadd_with_overflow: return lhs.uadd_ov(rhs, Overflow); case llvm::Intrinsic::ssub_with_overflow: return lhs.ssub_ov(rhs, Overflow); case llvm::Intrinsic::usub_with_overflow: return lhs.usub_ov(rhs, Overflow); case llvm::Intrinsic::smul_with_overflow: return lhs.smul_ov(rhs, Overflow); case llvm::Intrinsic::umul_with_overflow: return lhs.umul_ov(rhs, Overflow); } } APInt swift::constantFoldDiv(APInt lhs, APInt rhs, bool &Overflow, BuiltinValueKind ID) { assert(rhs != 0 && "division by zero"); switch (ID) { default : llvm_unreachable("Invalid case"); case BuiltinValueKind::SDiv: return lhs.sdiv_ov(rhs, Overflow); case BuiltinValueKind::SRem: // Check for overflow lhs.sdiv_ov(rhs, Overflow); return lhs.srem(rhs); case BuiltinValueKind::UDiv: Overflow = false; return lhs.udiv(rhs); case BuiltinValueKind::URem: Overflow = false; return lhs.urem(rhs); } } APInt swift::constantFoldCast(APInt val, const BuiltinInfo &BI) { // Get the cast result. Type SrcTy = BI.Types[0]; Type DestTy = BI.Types.size() == 2 ? BI.Types[1] : Type(); uint32_t SrcBitWidth = SrcTy->castTo()->getGreatestWidth(); uint32_t DestBitWidth = DestTy->castTo()->getGreatestWidth(); APInt CastResV; if (SrcBitWidth == DestBitWidth) { return val; } else switch (BI.ID) { default : llvm_unreachable("Invalid case."); case BuiltinValueKind::Trunc: case BuiltinValueKind::TruncOrBitCast: return val.trunc(DestBitWidth); case BuiltinValueKind::ZExt: case BuiltinValueKind::ZExtOrBitCast: return val.zext(DestBitWidth); break; case BuiltinValueKind::SExt: case BuiltinValueKind::SExtOrBitCast: return val.sext(DestBitWidth); } }