mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Emacs assumes .h files are C files by default which is why the tag "-*- C++ -*-" is needed. .cpp files do not have this problem.
119 lines
4.1 KiB
C++
119 lines
4.1 KiB
C++
//===--- 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<BuiltinIntegerType>()->getGreatestWidth();
|
|
uint32_t DestBitWidth =
|
|
DestTy->castTo<BuiltinIntegerType>()->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);
|
|
}
|
|
}
|