summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/ConstantFold.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR/ConstantFold.cpp')
-rw-r--r--llvm/lib/IR/ConstantFold.cpp34
1 files changed, 34 insertions, 0 deletions
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 6a9ef2efa321..c77f47c2ed99 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -126,6 +126,40 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
if (isa<PoisonValue>(V))
return PoisonValue::get(DestTy);
+ if (opc == Instruction::IntToPtr) {
+ // We can't fold inttoptr(0) to ConstantPointerNull without checking the
+ // target data layout. However, since data layout is not available here, we
+ // can't do this.
+ if (V->isZeroValue())
+ return nullptr;
+ // If the input is a ptrtoint(0), we can fold it to the corresponding zero
+ // value pointer.
+ if (auto *CE = dyn_cast<ConstantExpr>(V)) {
+ if (CE->getOpcode() == Instruction::PtrToInt) {
+ if (CE->getOperand(0)->isZeroValue())
+ return Constant::getZeroValue(DestTy);
+ }
+ }
+ }
+ if (opc == Instruction::PtrToInt) {
+ // Similarly, we can't fold ptrtoint(nullptr) to null.
+ if (V->isNullValue())
+ return nullptr;
+ // If the input is a inttoptr(0), we can fold it to the corresponding
+ // zero value.
+ if (auto *CE = dyn_cast<ConstantExpr>(V)) {
+ if (CE->getOpcode() == Instruction::IntToPtr) {
+ if (CE->getOperand(0)->isZeroValue())
+ return Constant::getZeroValue(DestTy);
+ }
+ }
+ }
+ // However, since the recent change of the semantic of `ptr addrspace(N)
+ // null`, we can fold address space cast of a nullptr to the corresponding
+ // nullptr in the destination address space.
+ if (opc == Instruction::AddrSpaceCast && V->isNullValue())
+ return Constant::getNullValue(DestTy);
+
if (isa<UndefValue>(V)) {
// zext(undef) = 0, because the top bits will be zero.
// sext(undef) = 0, because the top bits will all be the same.