Skip to content

Commit 3fb0247

Browse files
bokrzesiigcbot
authored andcommitted
[LLVM16][SinkCommonOffsetFromGEP] Detect type mismatch when grouping GEPs
On opaque pointers we could end up with such group: %C = getelementptr inbounds %class.MC_Vector, %class.MC_Vector* %.privateBuffer, i64 0, i32 1 %C2 = getelementptr inbounds %class.MC_Vector, %class.MC_Vector* %.privateBuffer, i64 0, i32 1 %A = getelementptr inbounds %class.MC_Particle, %class.MC_Particle* %.privateBuffer, i64 0, i32 4 %A2 = getelementptr inbounds %class.MC_Particle, %class.MC_Particle* %.privateBuffer, i64 0, i32 4 The problem is that we have type mismatch here, and later, when such group is being processed it tries to access indices that aren't available in given type e.g 8th index of 3 element struct. Such problematic group should be splitted into two different groups and it solves that problem. %C = getelementptr inbounds %class.MC_Vector, %class.MC_Vector* %.privateBuffer, i64 0, i32 1 %C2 = getelementptr inbounds %class.MC_Vector, %class.MC_Vector* %.privateBuffer, i64 0, i32 1 %A = getelementptr inbounds %class.MC_Particle, %class.MC_Particle* %.privateBuffer, i64 0, i32 4 %A2 = getelementptr inbounds %class.MC_Particle, %class.MC_Particle* %.privateBuffer, i64 0, i32 4 This PR adds check which should result in creation of new group instead of the merge with existing group that'd result in mismatched types.
1 parent edcf21d commit 3fb0247

File tree

2 files changed

+95
-1
lines changed

2 files changed

+95
-1
lines changed

IGC/Compiler/CISACodeGen/SinkCommonOffsetFromGEP.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*========================== begin_copyright_notice ============================
22
3-
Copyright (C) 2022 Intel Corporation
3+
Copyright (C) 2022-2025 Intel Corporation
44
55
SPDX-License-Identifier: MIT
66
@@ -241,6 +241,20 @@ bool DivergentPointersGroups::isBelongedToGroup(const CommonBaseGroup &Group, co
241241
if (CurGroupFactor[BB].second != Indices)
242242
return false;
243243
}
244+
245+
// Check if types are consistent across all group factors
246+
for (auto &GF : Group.GroupFactor) {
247+
auto groupPtrOperandTy = GF.second.first.first;
248+
if (!groupPtrOperandTy)
249+
continue;
250+
251+
for (const auto &Entry : DP.Geps) {
252+
GetElementPtrInst *GEP = Entry.second.GEP;
253+
if (GEP->getSourceElementType() != groupPtrOperandTy)
254+
return false;
255+
}
256+
}
257+
244258
return true;
245259
}
246260

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
;=========================== begin_copyright_notice ============================
2+
;
3+
; Copyright (C) 2025 Intel Corporation
4+
;
5+
; SPDX-License-Identifier: MIT
6+
;
7+
;============================ end_copyright_notice =============================
8+
9+
; RUN: igc_opt --opaque-pointers %s -S -o - -igc-sink-gep-constant | FileCheck %s
10+
; On opaque pointers we could end up with such group:
11+
;
12+
; %C = getelementptr inbounds %class.MC_Vector, %class.MC_Vector* %.privateBuffer, i64 0, i32 1
13+
; %C2 = getelementptr inbounds %class.MC_Vector, %class.MC_Vector* %.privateBuffer, i64 0, i32 1
14+
; %A = getelementptr inbounds %class.MC_Particle, %class.MC_Particle* %.privateBuffer, i64 0, i32 4
15+
; %A2 = getelementptr inbounds %class.MC_Particle, %class.MC_Particle* %.privateBuffer, i64 0, i32 4
16+
;
17+
; The problem is that we have type mismatch here, and later, when such group is being processed it tries
18+
; to access indices that aren't available in given type e.g 8th index of 3 element struct.
19+
; Such problematic group should be splitted into two different groups and it solves that problem.
20+
;
21+
; %C = getelementptr inbounds %class.MC_Vector, %class.MC_Vector* %.privateBuffer, i64 0, i32 1
22+
; %C2 = getelementptr inbounds %class.MC_Vector, %class.MC_Vector* %.privateBuffer, i64 0, i32 1
23+
;
24+
; %A = getelementptr inbounds %class.MC_Particle, %class.MC_Particle* %.privateBuffer, i64 0, i32 4
25+
; %A2 = getelementptr inbounds %class.MC_Particle, %class.MC_Particle* %.privateBuffer, i64 0, i32 4
26+
;
27+
28+
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v24:32:32-v32:32:32-v48:64:64-v64:64:64-v96:128:128-v128:128:128-v192:256:256-v256:256:256-v512:512:512-v1024:1024:1024-n8:16:32"
29+
target triple = "spir64-unknown-unknown"
30+
31+
%class.MC_Particle = type { %class.MC_Vector, %class.MC_Vector, %class.MC_Vector, i64, i64 }
32+
%class.MC_Vector = type { double, double }
33+
34+
; CHECK: if.cond:
35+
; [[GEP0:%.*]] = getelementptr %class.MC_Vector, ptr %.privateBuffer, i64 0
36+
; [[GEP1:%.*]] = getelementptr %class.MC_Particle, ptr %.privateBuffer, i64 0
37+
; [[GEP2:%.*]] = getelementptr %class.MC_Particle, ptr %.privateBuffer, i64 0, i32 1
38+
; CHECK: else.cond:
39+
; [[GEP3:%.*]] = getelementptr %class.MC_Vector, ptr %.privateBuffer, i64 0
40+
; [[GEP4:%.*]] = getelementptr %class.MC_Particle, ptr %.privateBuffer, i64 0
41+
; [[GEP5:%.*]] = getelementptr %class.MC_Particle, ptr %.privateBuffer, i64 0, i32 1
42+
43+
; [[PHI1:%.*]] = phi ptr [ [[GEP0]], %if.cond ], [ [[GEP3]], %else.cond ]
44+
; [[PHI2:%.*]] = phi ptr [ [[GEP1]], %if.cond ], [ [[GEP4]], %else.cond ]
45+
; [[PHI3:%.*]] = phi ptr [ [[GEP2]], %if.cond ], [ [[GEP5]], %else.cond ]
46+
47+
; CHECK-NOT: error
48+
49+
define void @f0(ptr %.privateBuffer, i1 %cond) {
50+
entry:
51+
br i1 %cond, label %if.cond, label %else.cond
52+
if.cond:
53+
%A = getelementptr inbounds %class.MC_Particle, ptr %.privateBuffer, i64 0, i32 4
54+
%B = getelementptr inbounds %class.MC_Particle, ptr %.privateBuffer, i64 0, i32 1, i32 1
55+
%C = getelementptr inbounds %class.MC_Vector, ptr %.privateBuffer, i64 0, i32 1
56+
br label %exit
57+
else.cond:
58+
%A2 = getelementptr inbounds %class.MC_Particle, ptr %.privateBuffer, i64 0, i32 4
59+
%B2 = getelementptr inbounds %class.MC_Particle, ptr %.privateBuffer, i64 0, i32 1, i32 1
60+
%C2 = getelementptr inbounds %class.MC_Vector, ptr %.privateBuffer, i64 0, i32 1
61+
br label %exit
62+
exit:
63+
%PhiA1 = phi i64* [ %A, %if.cond ], [ %A2, %else.cond ]
64+
%PhiA2 = phi i64* [ %A, %if.cond ], [ %A2, %else.cond ]
65+
%PhiB1 = phi i64* [ %B, %if.cond ], [ %B2, %else.cond ]
66+
67+
%PhiB2 = phi i64* [ %B, %if.cond ], [ %B2, %else.cond ]
68+
%PhiC1 = phi i64* [ %C, %if.cond ], [ %C2, %else.cond ]
69+
%PhiC2 = phi i64* [ %C, %if.cond ], [ %C2, %else.cond ]
70+
71+
%LoadC1 = load i64, i64* %PhiC1, align 4
72+
%LoadC2 = load i64, i64* %PhiC2, align 4
73+
74+
%LoadA1 = load i64, i64* %PhiA1, align 4
75+
%LoadA2 = load i64, i64* %PhiA2, align 4
76+
77+
%LoadB1 = load i64, i64* %PhiB1, align 4
78+
%LoadB2 = load i64, i64* %PhiB2, align 4
79+
ret void
80+
}

0 commit comments

Comments
 (0)