Skip to content

Commit 0a9ae5c

Browse files
committed
[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.
1 parent bf4167f commit 0a9ae5c

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

llvm/lib/Transforms/Scalar/LICM.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
#include "llvm/IR/IRBuilder.h"
7171
#include "llvm/IR/LLVMContext.h"
7272
#include "llvm/IR/Metadata.h"
73+
#include "llvm/IR/Module.h"
7374
#include "llvm/IR/PatternMatch.h"
7475
#include "llvm/IR/PredIteratorCache.h"
7576
#include "llvm/InitializePasses.h"
@@ -1328,6 +1329,20 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT,
13281329
}
13291330
}
13301331
return true;
1332+
} else if (auto *PTII = dyn_cast<PtrToIntInst>(&I)) {
1333+
const DataLayout &DL = I.getModule()->getDataLayout();
1334+
// Non-integral pointers may not have a stable bit representation, therefore
1335+
// casting them to an integer is not loop invariant.
1336+
if (DL.isNonIntegralPointerType(PTII->getPointerOperand()->getType())) {
1337+
return false;
1338+
}
1339+
} else if (auto *ITPI = dyn_cast<IntToPtrInst>(&I)) {
1340+
const DataLayout &DL = I.getModule()->getDataLayout();
1341+
// Non-integral pointers may not have a stable bit representation, therefore
1342+
// casting an integer to a non-integral pointer type is not loop invariant.
1343+
if (DL.isNonIntegralPointerType(ITPI->getType())) {
1344+
return false;
1345+
}
13311346
}
13321347

13331348
assert(!I.mayReadOrWriteMemory() && "unhandled aliasing");
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
; RUN: opt -passes=licm -S < %s | FileCheck %s
2+
3+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-ni:1"
4+
5+
declare void @use_i64(i64 %0)
6+
declare void @use_p1(ptr addrspace(1) %0)
7+
declare i1 @cond()
8+
9+
define void @dont_hoist_ptrtoint(ptr addrspace(1) %p) {
10+
; CHECK-LABEL: @dont_hoist_ptrtoint
11+
; CHECK-LABEL: loop
12+
; CHECK: ptrtoint
13+
entry:
14+
br label %loop
15+
16+
loop:
17+
%p.int = ptrtoint ptr addrspace(1) %p to i64
18+
call void @use_i64(i64 %p.int)
19+
br label %loop
20+
}
21+
22+
define void @dont_hoist_inttoptr(i64 %p.int) {
23+
; CHECK-LABEL: @dont_hoist_inttoptr
24+
; CHECK-LABEL: loop
25+
; CHECK: inttoptr
26+
entry:
27+
br label %loop
28+
29+
loop:
30+
%p = inttoptr i64 %p.int to ptr addrspace(1)
31+
call void @use_p1(ptr addrspace(1) %p)
32+
br label %loop
33+
}
34+
35+
define i64 @dont_sink_ptrtoint(ptr addrspace(1) %p) {
36+
; CHECK-LABEL: @dont_sink_ptrtoint
37+
; CHECK-LABEL: loop
38+
; CHECK: ptrtoint
39+
; CHECK-LABEL: exit
40+
entry:
41+
br label %loop
42+
43+
loop:
44+
%p.int = ptrtoint ptr addrspace(1) %p to i64
45+
%c = call i1 @cond()
46+
br i1 %c, label %loop, label %exit
47+
48+
exit:
49+
ret i64 %p.int
50+
}
51+
52+
define ptr addrspace(1) @dont_sink_inttoptr(i64 %p.int) {
53+
; CHECK-LABEL: @dont_sink_inttoptr
54+
; CHECK-LABEL: loop
55+
; CHECK: inttoptr
56+
; CHECK-LABEL: exit
57+
entry:
58+
br label %loop
59+
60+
loop:
61+
%p = inttoptr i64 %p.int to ptr addrspace(1)
62+
%c = call i1 @cond()
63+
br i1 %c, label %loop, label %exit
64+
65+
exit:
66+
ret ptr addrspace(1) %p
67+
}

0 commit comments

Comments
 (0)