diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index bb2a77daa60a7..7a5a811c5e0b2 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -1209,6 +1209,20 @@ static bool combineStoreToValueType(InstCombinerImpl &IC, StoreInst &SI) { return true; } + // Fold away inttoptr/ptrtoint of the stored value by storing the original + // type. + Value *X; + if (match(V, m_IntToPtr(m_Value(X))) || match(V, m_PtrToInt(m_Value(X)))) { + const DataLayout &DL = IC.getDataLayout(); + if (DL.getTypeStoreSize(V->getType()->getScalarType()) != + DL.getTypeStoreSize(X->getType()->getScalarType())) + return false; + if (!SI.isAtomic() || isSupportedAtomicType(X->getType())) { + combineStoreToNewValue(IC, SI, X); + return true; + } + } + // FIXME: We should also canonicalize stores of vectors when their elements // are cast to other types. return false; diff --git a/llvm/test/Transforms/InstCombine/store-inttoptr-ptrtoint.ll b/llvm/test/Transforms/InstCombine/store-inttoptr-ptrtoint.ll new file mode 100644 index 0000000000000..8336f5eccd384 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/store-inttoptr-ptrtoint.ll @@ -0,0 +1,86 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" + +declare void @use64(i64) +declare void @useptr(ptr) +define void @test_inttoptr(ptr %p, i64 %x) { +; CHECK-LABEL: define void @test_inttoptr( +; CHECK-SAME: ptr [[P:%.*]], i64 [[X:%.*]]) { +; CHECK-NEXT: store i64 [[X]], ptr [[P]], align 8 +; CHECK-NEXT: ret void +; + %y = inttoptr i64 %x to ptr + store ptr %y, ptr %p, align 8 + ret void +} +define void @test_inttoptr_multiuse(ptr %p, i64 %x) { +; CHECK-LABEL: define void @test_inttoptr_multiuse( +; CHECK-SAME: ptr [[P:%.*]], i64 [[X:%.*]]) { +; CHECK-NEXT: [[Y:%.*]] = inttoptr i64 [[X]] to ptr +; CHECK-NEXT: call void @useptr(ptr [[Y]]) +; CHECK-NEXT: store i64 [[X]], ptr [[P]], align 8 +; CHECK-NEXT: ret void +; + %y = inttoptr i64 %x to ptr + call void @useptr(ptr %y) + store ptr %y, ptr %p, align 8 + ret void +} +define void @test_inttoptr_constant_expr(ptr %p) { +; CHECK-LABEL: define void @test_inttoptr_constant_expr( +; CHECK-SAME: ptr [[P:%.*]]) { +; CHECK-NEXT: store i64 65, ptr [[P]], align 8 +; CHECK-NEXT: ret void +; + store ptr inttoptr (i64 65 to ptr), ptr %p, align 8 + ret void +} +define void @test_ptrtoint(ptr %p, ptr %x) { +; CHECK-LABEL: define void @test_ptrtoint( +; CHECK-SAME: ptr [[P:%.*]], ptr [[X:%.*]]) { +; CHECK-NEXT: store ptr [[X]], ptr [[P]], align 8 +; CHECK-NEXT: ret void +; + %y = ptrtoint ptr %x to i64 + store i64 %y, ptr %p, align 8 + ret void +} +define void @test_ptrtoint_multiuse(ptr %p, ptr %x) { +; CHECK-LABEL: define void @test_ptrtoint_multiuse( +; CHECK-SAME: ptr [[P:%.*]], ptr [[X:%.*]]) { +; CHECK-NEXT: [[Y:%.*]] = ptrtoint ptr [[X]] to i64 +; CHECK-NEXT: call void @use64(i64 [[Y]]) +; CHECK-NEXT: store ptr [[X]], ptr [[P]], align 8 +; CHECK-NEXT: ret void +; + %y = ptrtoint ptr %x to i64 + call void @use64(i64 %y) + store i64 %y, ptr %p, align 8 + ret void +} +; Negative tests +define void @test_inttoptr_mismatched_size(ptr %p, i32 %x) { +; CHECK-LABEL: define void @test_inttoptr_mismatched_size( +; CHECK-SAME: ptr [[P:%.*]], i32 [[X:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[X]] to i64 +; CHECK-NEXT: store i64 [[TMP1]], ptr [[P]], align 8 +; CHECK-NEXT: ret void +; + %y = inttoptr i32 %x to ptr + store ptr %y, ptr %p, align 8 + ret void +} +define void @test_ptrtoint_mismatched_size(ptr %p, ptr %x) { +; CHECK-LABEL: define void @test_ptrtoint_mismatched_size( +; CHECK-SAME: ptr [[P:%.*]], ptr [[X:%.*]]) { +; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[X]] to i64 +; CHECK-NEXT: [[Y:%.*]] = trunc i64 [[TMP1]] to i32 +; CHECK-NEXT: store i32 [[Y]], ptr [[P]], align 4 +; CHECK-NEXT: ret void +; + %y = ptrtoint ptr %x to i32 + store i32 %y, ptr %p, align 4 + ret void +}