Skip to content

Commit aafcb46

Browse files
admitricigcbot
authored andcommitted
Fix GEP addrspace mismatch in ProgramScopeConstantResolution
When BreakConstantExpr expands constant GEP expressions into instructions before ProgramScopeConstantResolution runs, replaceUsesOfWith on a GEP changes its pointer operand address space without updating the result type, producing invalid IR. Create a new GEP with the correct base pointer instead of in-place operand replacement.
1 parent c595ec5 commit aafcb46

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

IGC/Compiler/Optimizer/OpenCLPasses/ProgramScopeConstants/ProgramScopeConstantResolution.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,26 @@ bool ProgramScopeConstantResolution::runOnModule(Module &M) {
190190
Value *bc = funcToVarSet[userFunc][pGlobalVar];
191191
IGC_ASSERT_MESSAGE(bc != nullptr, "Program Scope buffer handling is broken!");
192192

193+
// Create a new GEP with the correct base pointer and
194+
// propagate the address space to all users.
195+
if (auto *GEP = dyn_cast<GetElementPtrInst>(user)) {
196+
if (GEP->getPointerOperand() == pGlobalVar) {
197+
SmallVector<Value *, 4> Indices(GEP->indices());
198+
auto *NewGEP = GetElementPtrInst::Create(GEP->getSourceElementType(), bc, Indices, GEP->getName(), GEP);
199+
NewGEP->setIsInBounds(GEP->isInBounds());
200+
NewGEP->setDebugLoc(GEP->getDebugLoc());
201+
// Cannot use replaceAllUsesWith because the old GEP result type
202+
// (ptr addrspace(0)) differs from the new one (ptr addrspace(2)).
203+
// Update each user individually.
204+
while (!GEP->use_empty()) {
205+
Use &U = *GEP->use_begin();
206+
U.set(NewGEP);
207+
}
208+
GEP->eraseFromParent();
209+
continue;
210+
}
211+
}
212+
193213
// And actually use the bitcast.
194214
user->replaceUsesOfWith(pGlobalVar, bc);
195215
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
;=========================== begin_copyright_notice ============================
2+
;
3+
; Copyright (C) 2026 Intel Corporation
4+
;
5+
; SPDX-License-Identifier: MIT
6+
;
7+
;============================ end_copyright_notice =============================
8+
;
9+
; REQUIRES: llvm-14-plus, regkeys
10+
;
11+
; RUN: igc_opt --verify --opaque-pointers --igc-break-const-expr --igc-programscope-constant-resolve -S < %s 2>&1 | FileCheck %s
12+
; ------------------------------------------------
13+
; ProgramScopeConstantResolution: GEP address space mismatch
14+
; ------------------------------------------------
15+
;
16+
; @gVar is in addrspace(0) and SROA loads use constant GEP expressions
17+
; (ptr getelementptr(@gVar, offset)). Check that the new GEP has the correct result type
18+
;
19+
; CHECK-LABEL: @test_kernel
20+
; CHECK: %offgVar = getelementptr i8, ptr addrspace(2) %constBase, i64 0
21+
;
22+
; All loads must use ptr addrspace(2), not bare ptr:
23+
; CHECK: load <8 x float>, ptr addrspace(2) %offgVar
24+
; CHECK: load <8 x float>, ptr addrspace(2)
25+
; CHECK: load <8 x float>, ptr addrspace(2)
26+
; CHECK-NOT: load <8 x float>, ptr %
27+
28+
@gVar = internal global [128 x i8] zeroinitializer, align 32, !spirv.Decorations !0
29+
30+
define spir_kernel void @test_kernel(
31+
ptr addrspace(1) %dst,
32+
<8 x i32> %r0,
33+
<8 x i32> %payloadHeader,
34+
ptr addrspace(2) %constBase,
35+
ptr addrspace(1) %globalBase,
36+
ptr %privateBase,
37+
i32 %bufferOffset) {
38+
entry:
39+
%.load0 = load <8 x float>, ptr @gVar, align 32
40+
41+
%.load1 = load <8 x float>, ptr getelementptr inbounds ([128 x i8], ptr @gVar, i64 0, i64 32), align 32
42+
%.load2 = load <8 x float>, ptr getelementptr inbounds ([128 x i8], ptr @gVar, i64 0, i64 64), align 32
43+
44+
%sum01 = fadd <8 x float> %.load0, %.load1
45+
%sum012 = fadd <8 x float> %sum01, %.load2
46+
store <8 x float> %sum012, ptr addrspace(1) %dst, align 32
47+
ret void
48+
}
49+
50+
!IGCMetadata = !{!10}
51+
!igc.functions = !{!20}
52+
53+
!0 = !{!1}
54+
!1 = !{i32 44, i32 16}
55+
56+
!10 = !{!"ModuleMD", !11}
57+
!11 = !{!"inlineProgramScopeOffsets", !12, !13}
58+
!12 = !{!"inlineProgramScopeOffsetsMap[0]", ptr @gVar}
59+
!13 = !{!"inlineProgramScopeOffsetsValue[0]", i64 0}
60+
61+
!20 = !{ptr @test_kernel, !21}
62+
!21 = !{!22, !23}
63+
!22 = !{!"function_type", i32 0}
64+
!23 = !{!"implicit_arg_desc", !24, !25, !26, !27, !28, !29}
65+
!24 = !{i32 0}
66+
!25 = !{i32 1}
67+
!26 = !{i32 11}
68+
!27 = !{i32 12}
69+
!28 = !{i32 13}
70+
!29 = !{i32 15, !30}
71+
!30 = !{!"explicit_arg_num", i32 0}

0 commit comments

Comments
 (0)