[llvm] [LICM] Prevent LICM of ptrtoint and inttoptr when using non-integral pointers (PR #97272)

Csanád Hajdú via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 12 02:12:42 PDT 2024


https://github.com/Il-Capitano updated https://github.com/llvm/llvm-project/pull/97272

>From 0a9ae5c3a5e8ce240d1474d14c2b9208782148c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Csan=C3=A1d=20Hajd=C3=BA?= <csanad.hajdu at arm.com>
Date: Thu, 20 Jun 2024 11:45:06 +0200
Subject: [PATCH 1/3] [LICM] Prevent LICM of ptrtoint and inttoptr when using
 non-integral pointers

Non-integral pointers don't have a stable bit representation, i.e.
subsequent executions of `ptrtoint` or `inttoptr` instructions can
create different results, therefore it is invalid to move these
instructions outside of a loop when they use non-integral pointer types.
---
 llvm/lib/Transforms/Scalar/LICM.cpp           | 15 +++++
 .../Transforms/LICM/non-integral-pointers.ll  | 67 +++++++++++++++++++
 2 files changed, 82 insertions(+)
 create mode 100644 llvm/test/Transforms/LICM/non-integral-pointers.ll

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 91ef2b4b7c183..f286d910f932e 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -70,6 +70,7 @@
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/IR/PredIteratorCache.h"
 #include "llvm/InitializePasses.h"
@@ -1328,6 +1329,20 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
           }
       }
     return true;
+  } else if (auto *PTII = dyn_cast<PtrToIntInst>(&I)) {
+    const DataLayout &DL = I.getModule()->getDataLayout();
+    // Non-integral pointers may not have a stable bit representation, therefore
+    // casting them to an integer is not loop invariant.
+    if (DL.isNonIntegralPointerType(PTII->getPointerOperand()->getType())) {
+      return false;
+    }
+  } else if (auto *ITPI = dyn_cast<IntToPtrInst>(&I)) {
+    const DataLayout &DL = I.getModule()->getDataLayout();
+    // Non-integral pointers may not have a stable bit representation, therefore
+    // casting an integer to a non-integral pointer type is not loop invariant.
+    if (DL.isNonIntegralPointerType(ITPI->getType())) {
+      return false;
+    }
   }
 
   assert(!I.mayReadOrWriteMemory() && "unhandled aliasing");
diff --git a/llvm/test/Transforms/LICM/non-integral-pointers.ll b/llvm/test/Transforms/LICM/non-integral-pointers.ll
new file mode 100644
index 0000000000000..01336d7d812b3
--- /dev/null
+++ b/llvm/test/Transforms/LICM/non-integral-pointers.ll
@@ -0,0 +1,67 @@
+; RUN: opt -passes=licm -S < %s | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-ni:1"
+
+declare void @use_i64(i64 %0)
+declare void @use_p1(ptr addrspace(1) %0)
+declare i1 @cond()
+
+define void @dont_hoist_ptrtoint(ptr addrspace(1) %p) {
+; CHECK-LABEL: @dont_hoist_ptrtoint
+; CHECK-LABEL: loop
+; CHECK:         ptrtoint
+entry:
+  br label %loop
+
+loop:
+  %p.int = ptrtoint ptr addrspace(1) %p to i64
+  call void @use_i64(i64 %p.int)
+  br label %loop
+}
+
+define void @dont_hoist_inttoptr(i64 %p.int) {
+; CHECK-LABEL: @dont_hoist_inttoptr
+; CHECK-LABEL: loop
+; CHECK:         inttoptr
+entry:
+  br label %loop
+
+loop:
+  %p = inttoptr i64 %p.int to ptr addrspace(1)
+  call void @use_p1(ptr addrspace(1) %p)
+  br label %loop
+}
+
+define i64 @dont_sink_ptrtoint(ptr addrspace(1) %p) {
+; CHECK-LABEL: @dont_sink_ptrtoint
+; CHECK-LABEL: loop
+; CHECK:         ptrtoint
+; CHECK-LABEL: exit
+entry:
+  br label %loop
+
+loop:
+  %p.int = ptrtoint ptr addrspace(1) %p to i64
+  %c = call i1 @cond()
+  br i1 %c, label %loop, label %exit
+
+exit:
+  ret i64 %p.int
+}
+
+define ptr addrspace(1) @dont_sink_inttoptr(i64 %p.int) {
+; CHECK-LABEL: @dont_sink_inttoptr
+; CHECK-LABEL: loop
+; CHECK:         inttoptr
+; CHECK-LABEL: exit
+entry:
+  br label %loop
+
+loop:
+  %p = inttoptr i64 %p.int to ptr addrspace(1)
+  %c = call i1 @cond()
+  br i1 %c, label %loop, label %exit
+
+exit:
+  ret ptr addrspace(1) %p
+}

>From ffa6cd4efdd7a5286dacaf79afeb89eb359c7dd3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Csan=C3=A1d=20Hajd=C3=BA?= <csanad.hajdu at arm.com>
Date: Fri, 12 Jul 2024 10:39:37 +0200
Subject: [PATCH 2/3] Rerun clang-format

---
 llvm/lib/Transforms/Scalar/LICM.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index f286d910f932e..f360379e9df04 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -65,9 +65,9 @@
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Dominators.h"
+#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
-#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"

>From fac818f70903e73cdf29ab5628087554d990a3d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Csan=C3=A1d=20Hajd=C3=BA?= <csanad.hajdu at arm.com>
Date: Fri, 12 Jul 2024 11:09:55 +0200
Subject: [PATCH 3/3] Run update_test_checks.py on the test file

---
 .../Transforms/LICM/non-integral-pointers.ll  | 57 ++++++++++++++-----
 1 file changed, 43 insertions(+), 14 deletions(-)

diff --git a/llvm/test/Transforms/LICM/non-integral-pointers.ll b/llvm/test/Transforms/LICM/non-integral-pointers.ll
index 01336d7d812b3..683bb03005476 100644
--- a/llvm/test/Transforms/LICM/non-integral-pointers.ll
+++ b/llvm/test/Transforms/LICM/non-integral-pointers.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -passes=licm -S < %s | FileCheck %s
 
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-ni:1"
@@ -7,9 +8,15 @@ declare void @use_p1(ptr addrspace(1) %0)
 declare i1 @cond()
 
 define void @dont_hoist_ptrtoint(ptr addrspace(1) %p) {
-; CHECK-LABEL: @dont_hoist_ptrtoint
-; CHECK-LABEL: loop
-; CHECK:         ptrtoint
+; CHECK-LABEL: define void @dont_hoist_ptrtoint(
+; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[P_INT:%.*]] = ptrtoint ptr addrspace(1) [[P]] to i64
+; CHECK-NEXT:    call void @use_i64(i64 [[P_INT]])
+; CHECK-NEXT:    br label %[[LOOP]]
+;
 entry:
   br label %loop
 
@@ -20,9 +27,15 @@ loop:
 }
 
 define void @dont_hoist_inttoptr(i64 %p.int) {
-; CHECK-LABEL: @dont_hoist_inttoptr
-; CHECK-LABEL: loop
-; CHECK:         inttoptr
+; CHECK-LABEL: define void @dont_hoist_inttoptr(
+; CHECK-SAME: i64 [[P_INT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[P:%.*]] = inttoptr i64 [[P_INT]] to ptr addrspace(1)
+; CHECK-NEXT:    call void @use_p1(ptr addrspace(1) [[P]])
+; CHECK-NEXT:    br label %[[LOOP]]
+;
 entry:
   br label %loop
 
@@ -33,10 +46,18 @@ loop:
 }
 
 define i64 @dont_sink_ptrtoint(ptr addrspace(1) %p) {
-; CHECK-LABEL: @dont_sink_ptrtoint
-; CHECK-LABEL: loop
-; CHECK:         ptrtoint
-; CHECK-LABEL: exit
+; CHECK-LABEL: define i64 @dont_sink_ptrtoint(
+; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[P_INT_LE:%.*]] = ptrtoint ptr addrspace(1) [[P]] to i64
+; CHECK-NEXT:    [[C:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[P_INT_LCSSA:%.*]] = phi i64 [ [[P_INT_LE]], %[[LOOP]] ]
+; CHECK-NEXT:    ret i64 [[P_INT_LCSSA]]
+;
 entry:
   br label %loop
 
@@ -50,10 +71,18 @@ exit:
 }
 
 define ptr addrspace(1) @dont_sink_inttoptr(i64 %p.int) {
-; CHECK-LABEL: @dont_sink_inttoptr
-; CHECK-LABEL: loop
-; CHECK:         inttoptr
-; CHECK-LABEL: exit
+; CHECK-LABEL: define ptr addrspace(1) @dont_sink_inttoptr(
+; CHECK-SAME: i64 [[P_INT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[P_LE:%.*]] = inttoptr i64 [[P_INT]] to ptr addrspace(1)
+; CHECK-NEXT:    [[C:%.*]] = call i1 @cond()
+; CHECK-NEXT:    br i1 [[C]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[P_LCSSA:%.*]] = phi ptr addrspace(1) [ [[P_LE]], %[[LOOP]] ]
+; CHECK-NEXT:    ret ptr addrspace(1) [[P_LCSSA]]
+;
 entry:
   br label %loop
 



More information about the llvm-commits mailing list