[llvm] [InstCombine] Canonicalize the stored value type with inttoptr/ptrtoint (PR #76339)

via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 24 12:25:59 PST 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Yingwei Zheng (dtcxzyw)

<details>
<summary>Changes</summary>

This patch folds away the `inttoptr/ptrtoint` of the stored value by storing the original type. It will enable more optimizations.
An example in [z3/src/smt/smt_enode.h](https://github.com/Z3Prover/z3/blob/ebe5ebf0ae63bf520839b4d34d7b19e0af87fe36/src/smt/smt_enode.h#L41):
```
diff --git a/bench/z3/optimized/smt_enode.cpp.ll b/bench/z3/optimized/smt_enode.cpp.ll
index 6f42a9f4..91bc9b0e 100644
--- a/bench/z3/optimized/smt_enode.cpp.ll
+++ b/bench/z3/optimized/smt_enode.cpp.ll
@@ -4,12 +4,12 @@ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:
 target triple = "x86_64-unknown-linux-gnu"
 
 %"class.std::ios_base::Init" = type { i8 }
-%"class.smt::eq_justification" = type { ptr }
 %"class.smt::enode" = type { ptr, ptr, ptr, ptr, i32, i32, i32, i16, i32, i8, i8, %class.ptr_vector, %class.id_var_list, %"struct.smt::trans_justification", %class.approx_set, %class.approx_set, [0 x ptr] }
 %class.ptr_vector = type { %class.vector }
 %class.vector = type { ptr }
 %class.id_var_list = type { i32, ptr }
 %"struct.smt::trans_justification" = type { ptr, %"class.smt::eq_justification" }
+%"class.smt::eq_justification" = type { ptr }
 %class.approx_set = type { %class.approx_set_tpl }
 %class.approx_set_tpl = type { i64 }
 %class.ast = type { i32, i24, i32, i32 }
@@ -454,7 +454,7 @@ $_ZTI11value_trailI10approx_setE = comdat any
 
 @<!-- -->_ZStL8__ioinit = internal global %"class.std::ios_base::Init" zeroinitializer, align 1
 @<!-- -->__dso_handle = external hidden global i8
-@<!-- -->_ZN3smtL21null_eq_justificationE = internal unnamed_addr global %"class.smt::eq_justification" zeroinitializer, align 8
+@<!-- -->_ZN3smtL21null_eq_justificationE.0 = internal unnamed_addr global i1 false, align 8
 @.str = private unnamed_addr constant [2 x i8] c"#\00", align 1
 @.str.7 = private unnamed_addr constant [8 x i8] c"  ->  #\00", align 1
 @.str.8 = private unnamed_addr constant [9 x i8] c", lbls: \00", align 1
@@ -504,7 +504,8 @@ entry:
   %m_next.i.i = getelementptr inbounds %"class.smt::enode", ptr %mem, i64 0, i32 12, i32 1
   %m_justification.i.i = getelementptr inbounds %"class.smt::enode", ptr %mem, i64 0, i32 13, i32 1
   tail call void @<!-- -->llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %m_next.i.i, i8 0, i64 16, i1 false)
-  %0 = load i64, ptr @<!-- -->_ZN3smtL21null_eq_justificationE, align 8
+  %.b = load i1, ptr @<!-- -->_ZN3smtL21null_eq_justificationE.0, align 8
+  %0 = select i1 %.b, i64 3, i64 0
   store i64 %0, ptr %m_justification.i.i, align 8
   %m_lbls.i = getelementptr inbounds %"class.smt::enode", ptr %mem, i64 0, i32 14
   tail call void @<!-- -->llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %m_lbls.i, i8 0, i64 16, i1 false)
@@ -2125,7 +2126,7 @@ define internal void @<!-- -->_GLOBAL__sub_I_smt_enode.cpp() #<!-- -->17 section ".text.startup"
 entry:
   tail call void @<!-- -->_ZNSt8ios_base4InitC1Ev(ptr noundef nonnull align 1 dereferenceable(1) @<!-- -->_ZStL8__ioinit)
   %0 = tail call i32 @<!-- -->__cxa_atexit(ptr nonnull @<!-- -->_ZNSt8ios_base4InitD1Ev, ptr nonnull @<!-- -->_ZStL8__ioinit, ptr nonnull @<!-- -->__dso_handle) #<!-- -->20
-  store ptr inttoptr (i64 3 to ptr), ptr @<!-- -->_ZN3smtL21null_eq_justificationE, align 8
+  store i1 true, ptr @<!-- -->_ZN3smtL21null_eq_justificationE.0, align 8
   ret void
 }
```


---
Full diff: https://github.com/llvm/llvm-project/pull/76339.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp (+14) 
- (added) llvm/test/Transforms/InstCombine/store-inttoptr-ptrtoint.ll (+86) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index bb2a77daa60a76..7a5a811c5e0b2e 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 00000000000000..8336f5eccd3841
--- /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
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/76339


More information about the llvm-commits mailing list