Skip to content

Commit 4cacb5c

Browse files
committed
[MergeICmps] Don't merge icmps derived from pointers with addressspaces
IIUC we can't emit `memcmp` between pointers in addressspaces, doing so will trigger an assertion since the signature of the memcmp will not match it's arguments (https://bugs.llvm.org/show_bug.cgi?id=48661). This PR disables the attempt to merge icmps, when the pointer is in an addressspace. Reviewed By: #julialang, vtjnash Differential Revision: https://reviews.llvm.org/D94813
1 parent 1b05245 commit 4cacb5c

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

llvm/lib/Transforms/Scalar/MergeICmps.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ BCEAtom visitICmpLoadOperand(Value *const Val, BaseIdentifier &BaseId) {
145145
return {};
146146
}
147147
Value *const Addr = LoadI->getOperand(0);
148+
if (Addr->getType()->getPointerAddressSpace() != 0) {
149+
LLVM_DEBUG(dbgs() << "from non-zero AddressSpace\n");
150+
return {};
151+
}
148152
auto *const GEP = dyn_cast<GetElementPtrInst>(Addr);
149153
if (!GEP)
150154
return {};
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -S -mergeicmps -verify-dom-info | FileCheck %s
3+
target triple = "x86_64"
4+
5+
; First check that we try to from a memcmp.
6+
define void @form_memcmp([2 x i64]* dereferenceable(16) %a, [2 x i64]* dereferenceable(16) %b) {
7+
; CHECK-LABEL: @form_memcmp(
8+
; CHECK-NEXT: bb0:
9+
; CHECK-NEXT: [[PTR_A0:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[A:%.*]], i64 0, i64 0
10+
; CHECK-NEXT: [[PTR_A1:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[A]], i64 0, i64 1
11+
; CHECK-NEXT: [[PTR_B0:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[B:%.*]], i64 0, i64 0
12+
; CHECK-NEXT: [[PTR_B1:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[B]], i64 0, i64 1
13+
; CHECK-NEXT: br label %"bb1+bb2"
14+
; CHECK: "bb1+bb2":
15+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[A]], i64 0, i64 0
16+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [2 x i64], [2 x i64]* [[B]], i64 0, i64 0
17+
; CHECK-NEXT: [[CSTR:%.*]] = bitcast i64* [[TMP0]] to i8*
18+
; CHECK-NEXT: [[CSTR1:%.*]] = bitcast i64* [[TMP1]] to i8*
19+
; CHECK-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(i8* [[CSTR]], i8* [[CSTR1]], i64 16)
20+
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[MEMCMP]], 0
21+
; CHECK-NEXT: br label [[BB3:%.*]]
22+
; CHECK: bb3:
23+
; CHECK-NEXT: ret void
24+
;
25+
bb0:
26+
%ptr_a0 = getelementptr inbounds [2 x i64], [2 x i64]* %a, i64 0, i64 0
27+
%ptr_a1 = getelementptr inbounds [2 x i64], [2 x i64]* %a, i64 0, i64 1
28+
%ptr_b0 = getelementptr inbounds [2 x i64], [2 x i64]* %b, i64 0, i64 0
29+
%ptr_b1 = getelementptr inbounds [2 x i64], [2 x i64]* %b, i64 0, i64 1
30+
br label %bb1
31+
32+
bb1: ; preds = %bb0
33+
%a0 = load i64, i64* %ptr_a0
34+
%b0 = load i64, i64* %ptr_b0
35+
%cond0 = icmp eq i64 %a0, %b0
36+
br i1 %cond0, label %bb2, label %bb3
37+
38+
bb2: ; preds = %bb1
39+
%a1 = load i64, i64* %ptr_a1
40+
%b1 = load i64, i64* %ptr_b1
41+
%cond1 = icmp eq i64 %a1, %b1
42+
br label %bb3
43+
44+
bb3: ; preds = %bb2, %bb1
45+
%necessary = phi i1 [ %cond1, %bb2 ], [ false, %bb1 ]
46+
ret void
47+
}
48+
49+
; We can't use memcmp between arbitrary addressesspaces
50+
define void @no_memcmp([2 x i64] addrspace(11)* dereferenceable(16) %a, [2 x i64] addrspace(11)* dereferenceable(16) %b) {
51+
; CHECK-LABEL: @no_memcmp(
52+
; CHECK-NEXT: bb0:
53+
; CHECK-NEXT: [[PTR_A0:%.*]] = getelementptr inbounds [2 x i64], [2 x i64] addrspace(11)* [[A:%.*]], i64 0, i64 0
54+
; CHECK-NEXT: [[PTR_A1:%.*]] = getelementptr inbounds [2 x i64], [2 x i64] addrspace(11)* [[A]], i64 0, i64 1
55+
; CHECK-NEXT: [[PTR_B0:%.*]] = getelementptr inbounds [2 x i64], [2 x i64] addrspace(11)* [[B:%.*]], i64 0, i64 0
56+
; CHECK-NEXT: [[PTR_B1:%.*]] = getelementptr inbounds [2 x i64], [2 x i64] addrspace(11)* [[B]], i64 0, i64 1
57+
; CHECK-NEXT: br label [[BB1:%.*]]
58+
; CHECK: bb1:
59+
; CHECK-NEXT: [[A0:%.*]] = load i64, i64 addrspace(11)* [[PTR_A0]], align 4
60+
; CHECK-NEXT: [[B0:%.*]] = load i64, i64 addrspace(11)* [[PTR_B0]], align 4
61+
; CHECK-NEXT: [[COND0:%.*]] = icmp eq i64 [[A0]], [[B0]]
62+
; CHECK-NEXT: br i1 [[COND0]], label [[BB2:%.*]], label [[BB3:%.*]]
63+
; CHECK: bb2:
64+
; CHECK-NEXT: [[A1:%.*]] = load i64, i64 addrspace(11)* [[PTR_A1]], align 4
65+
; CHECK-NEXT: [[B1:%.*]] = load i64, i64 addrspace(11)* [[PTR_B1]], align 4
66+
; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[A1]], [[B1]]
67+
; CHECK-NEXT: br label [[BB3]]
68+
; CHECK: bb3:
69+
; CHECK-NEXT: [[NECESSARY:%.*]] = phi i1 [ [[COND1]], [[BB2]] ], [ false, [[BB1]] ]
70+
; CHECK-NEXT: ret void
71+
;
72+
bb0:
73+
%ptr_a0 = getelementptr inbounds [2 x i64], [2 x i64] addrspace(11)* %a, i64 0, i64 0
74+
%ptr_a1 = getelementptr inbounds [2 x i64], [2 x i64] addrspace(11)* %a, i64 0, i64 1
75+
%ptr_b0 = getelementptr inbounds [2 x i64], [2 x i64] addrspace(11)* %b, i64 0, i64 0
76+
%ptr_b1 = getelementptr inbounds [2 x i64], [2 x i64] addrspace(11)* %b, i64 0, i64 1
77+
br label %bb1
78+
79+
bb1: ; preds = %bb0
80+
%a0 = load i64, i64 addrspace(11)* %ptr_a0
81+
%b0 = load i64, i64 addrspace(11)* %ptr_b0
82+
%cond0 = icmp eq i64 %a0, %b0
83+
br i1 %cond0, label %bb2, label %bb3
84+
85+
bb2: ; preds = %bb1
86+
%a1 = load i64, i64 addrspace(11)* %ptr_a1
87+
%b1 = load i64, i64 addrspace(11)* %ptr_b1
88+
%cond1 = icmp eq i64 %a1, %b1
89+
br label %bb3
90+
91+
bb3: ; preds = %bb2, %bb1
92+
%necessary = phi i1 [ %cond1, %bb2 ], [ false, %bb1 ]
93+
ret void
94+
}

0 commit comments

Comments
 (0)