Skip to content

Commit 45e95a1

Browse files
michalpaszkowskiigcbot
authored andcommitted
Migrate ProgramScopeConstantResolution to opaque pointers
The pass resolves references to program-scope consts by replacing their uses with a GEP from an implicit base argument (const or global). The original code used bufArg's pointer element type to create GEP and then cast the GEP to the global variable's type. Hence, GEP's type is irrelevant and can be i8*. The bitcast is still necessary in typed pointer mode to satisfy LLVM IR verification assertions.
1 parent 9e12304 commit 45e95a1

File tree

5 files changed

+202
-31
lines changed

5 files changed

+202
-31
lines changed

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,20 @@ bool ProgramScopeConstantResolution::runOnModule(Module& M)
184184
Instruction* pEntryPoint = &(*userFunc->getEntryBlock().getFirstInsertionPt());
185185

186186
// Create a GEP to get to the right offset in the constant buffer
187-
Type *BaseTy = IGCLLVM::getNonOpaquePtrEltTy((&*bufArg)->getType());
188-
GetElementPtrInst* gep = GetElementPtrInst::Create(BaseTy, &*bufArg, pOffset, "off" + pGlobalVar->getName(), pEntryPoint);
189-
// Cast it back to the correct type.
190-
CastInst* pNewVal = CastInst::CreatePointerCast(gep, pGlobalVar->getType(), "cast" + pGlobalVar->getName(), pEntryPoint);
187+
GetElementPtrInst *gep = GetElementPtrInst::Create(
188+
Type::getInt8Ty(C), &*bufArg, pOffset,
189+
"off" + pGlobalVar->getName(), pEntryPoint);
190+
191+
Value* replacement = gep;
192+
193+
// TODO: Remove when typed pointers are no longer supported.
194+
if (!ptrType->isOpaque())
195+
replacement = CastInst::CreatePointerCast(
196+
gep, pGlobalVar->getType(),
197+
"cast" + pGlobalVar->getName(), pEntryPoint);
191198

192199
// Update the map with the fix new value
193-
funcToVarSet[userFunc][pGlobalVar] = pNewVal;
200+
funcToVarSet[userFunc][pGlobalVar] = replacement;
194201
}
195202

196203
Value* bc = funcToVarSet[userFunc][pGlobalVar];
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
;=========================== begin_copyright_notice ============================
2+
;
3+
; Copyright (C) 2022-2023 Intel Corporation
4+
;
5+
; SPDX-License-Identifier: MIT
6+
;
7+
;============================ end_copyright_notice =============================
8+
; REQUIRES: regkeys
9+
;
10+
; RUN: igc_opt -enable-debugify --igc-programscope-constant-resolve -S < %s 2>&1 | FileCheck %s --check-prefixes=CHECK
11+
; ------------------------------------------------
12+
; ProgramScopeConstantResolution
13+
; ------------------------------------------------
14+
15+
; Debug-info related checks
16+
;
17+
; For llvm 14 check-debugify treats missing debug location on globalbase getter
18+
; at the begining of BB as a warning, while on earlier llvm versions its treated as an error.
19+
;
20+
; CHECK: CheckModuleDebugify: PASS
21+
22+
@a = internal addrspace(2) constant [2 x i32] [i32 0, i32 1], align 4
23+
@d = internal addrspace(1) global i32 addrspace(2)* getelementptr inbounds ([2 x i32], [2 x i32] addrspace(2)* @a, i32 0, i32 0), align 8
24+
@c = internal addrspace(1) global i32 0, align 4
25+
@b = common addrspace(1) global i32 0, align 4
26+
@llvm.used = appending global [3 x i8*] [i8* addrspacecast (i8 addrspace(2)* bitcast ([2 x i32] addrspace(2)* @a to i8 addrspace(2)*) to i8*), i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(1)* @c to i8 addrspace(1)*) to i8*), i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(2)* addrspace(1)* @d to i8 addrspace(1)*) to i8*)], section "llvm.metadata"
27+
28+
; Function Attrs: convergent noinline nounwind optnone
29+
define spir_kernel void @test_program(i32 addrspace(1)* %dst, <8 x i32> %r0, <8 x i32> %payloadHeader, i8 addrspace(2)* %constBase, i8 addrspace(1)* %globalBase, i8* %privateBase, i32 %bufferOffset) {
30+
; CHECK-LABEL: @test_program(
31+
; CHECK: entry:
32+
; CHECK: [[OFFC:%.*]] = getelementptr i8, i8 addrspace(1)* %globalBase, i64 8
33+
; CHECK: [[CASTC:%.*]] = bitcast i8 addrspace(1)* [[OFFC]] to i32 addrspace(1)*
34+
; CHECK: [[OFFD:%.*]] = getelementptr i8, i8 addrspace(1)* %globalBase, i64 0
35+
; CHECK: [[CASTD:%.*]] = bitcast i8 addrspace(1)* [[OFFD]] to i32 addrspace(2)* addrspace(1)*
36+
; CHECK: [[OFFA:%.*]] = getelementptr i8, i8 addrspace(2)* %constBase, i64 0
37+
; CHECK: [[CASTA:%.*]] = bitcast i8 addrspace(2)* [[OFFA]] to [2 x i32] addrspace(2)*
38+
; CHECK: [[DST_ADDR:%.*]] = alloca i32 addrspace(1)*, align 8
39+
; CHECK: [[AA:%.*]] = alloca i32, align 4
40+
; CHECK: store i32 addrspace(1)* [[DST:%.*]], i32 addrspace(1)** [[DST_ADDR]], align 8
41+
; CHECK: [[TMP0:%.*]] = getelementptr inbounds [2 x i32], [2 x i32] addrspace(2)* [[CASTA]], i64 0, i64 1
42+
; CHECK: [[TMP1:%.*]] = load i32, i32 addrspace(2)* [[TMP0]], align 4
43+
; CHECK: store i32 [[TMP1]], i32* [[AA]], align 4
44+
; CHECK: [[TMP2:%.*]] = load i32 addrspace(2)*, i32 addrspace(2)* addrspace(1)* [[CASTD]], align 8
45+
; CHECK: [[TMP3:%.*]] = load i32, i32 addrspace(2)* [[TMP2]], align 4
46+
; CHECK: store i32 [[TMP3]], i32 addrspace(1)* [[CASTC]], align 4
47+
; CHECK: ret void
48+
;
49+
entry:
50+
%dst.addr = alloca i32 addrspace(1)*, align 8
51+
%aa = alloca i32, align 4
52+
store i32 addrspace(1)* %dst, i32 addrspace(1)** %dst.addr, align 8
53+
%0 = getelementptr inbounds [2 x i32], [2 x i32] addrspace(2)* @a, i64 0, i64 1
54+
%1 = load i32, i32 addrspace(2)* %0, align 4
55+
store i32 %1, i32* %aa, align 4
56+
%2 = load i32 addrspace(2)*, i32 addrspace(2)* addrspace(1)* @d, align 8
57+
%3 = load i32, i32 addrspace(2)* %2, align 4
58+
store i32 %3, i32 addrspace(1)* @c, align 4
59+
ret void
60+
}
61+
62+
!IGCMetadata = !{!0}
63+
!igc.functions = !{!20}
64+
65+
!0 = !{!"ModuleMD", !1}
66+
!1 = !{!"inlineProgramScopeOffsets", !2, !3, !4, !5, !6, !7}
67+
!2 = !{!"inlineProgramScopeOffsetsMap[0]", [2 x i32] addrspace(2)* @a}
68+
!3 = !{!"inlineProgramScopeOffsetsValue[0]", i64 0}
69+
!4 = !{!"inlineProgramScopeOffsetsMap[1]", i32 addrspace(1)* @c}
70+
!5 = !{!"inlineProgramScopeOffsetsValue[1]", i64 8}
71+
!6 = !{!"inlineProgramScopeOffsetsMap[2]", i32 addrspace(2)* addrspace(1)* @d}
72+
!7 = !{!"inlineProgramScopeOffsetsValue[2]", i64 0}
73+
74+
!20 = !{void (i32 addrspace(1)*, <8 x i32>, <8 x i32>, i8 addrspace(2)*, i8 addrspace(1)*, i8*, i32)* @test_program, !21}
75+
!21 = !{!22, !23}
76+
!22 = !{!"function_type", i32 0}
77+
!23 = !{!"implicit_arg_desc", !24, !25, !26, !27, !28, !29}
78+
!24 = !{i32 0}
79+
!25 = !{i32 1}
80+
!26 = !{i32 10}
81+
!27 = !{i32 11}
82+
!28 = !{i32 12}
83+
!29 = !{i32 14, !30}
84+
!30 = !{!"explicit_arg_num", i32 0}

IGC/Compiler/tests/ProgramScopeConstantResolution/basic.ll

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
; SPDX-License-Identifier: MIT
66
;
77
;============================ end_copyright_notice =============================
8-
; REQUIRES: regkeys
8+
; REQUIRES: llvm-14-plus, regkeys
99
;
10-
; RUN: igc_opt -enable-debugify --igc-programscope-constant-resolve -S < %s 2>&1 | FileCheck %s --check-prefixes=CHECK
10+
; RUN: igc_opt --opaque-pointers -enable-debugify --igc-programscope-constant-resolve -S < %s 2>&1 | FileCheck %s --check-prefixes=CHECK
1111
; ------------------------------------------------
1212
; ProgramScopeConstantResolution
1313
; ------------------------------------------------
@@ -29,21 +29,18 @@
2929
define spir_kernel void @test_program(i32 addrspace(1)* %dst, <8 x i32> %r0, <8 x i32> %payloadHeader, i8 addrspace(2)* %constBase, i8 addrspace(1)* %globalBase, i8* %privateBase, i32 %bufferOffset) {
3030
; CHECK-LABEL: @test_program(
3131
; CHECK: entry:
32-
; CHECK: [[OFFC:%.*]] = getelementptr i8, i8 addrspace(1)* %globalBase, i64 8
33-
; CHECK: [[CASTC:%.*]] = bitcast i8 addrspace(1)* [[OFFC]] to i32 addrspace(1)*
34-
; CHECK: [[OFFD:%.*]] = getelementptr i8, i8 addrspace(1)* %globalBase, i64 0
35-
; CHECK: [[CASTD:%.*]] = bitcast i8 addrspace(1)* [[OFFD]] to i32 addrspace(2)* addrspace(1)*
36-
; CHECK: [[OFFA:%.*]] = getelementptr i8, i8 addrspace(2)* %constBase, i64 0
37-
; CHECK: [[CASTA:%.*]] = bitcast i8 addrspace(2)* [[OFFA]] to [2 x i32] addrspace(2)*
38-
; CHECK: [[DST_ADDR:%.*]] = alloca i32 addrspace(1)*, align 8
32+
; CHECK: [[OFFC:%.*]] = getelementptr i8, ptr addrspace(1) %globalBase, i64 8
33+
; CHECK: [[OFFD:%.*]] = getelementptr i8, ptr addrspace(1) %globalBase, i64 0
34+
; CHECK: [[OFFA:%.*]] = getelementptr i8, ptr addrspace(2) %constBase, i64 0
35+
; CHECK: [[DST_ADDR:%.*]] = alloca ptr addrspace(1), align 8
3936
; CHECK: [[AA:%.*]] = alloca i32, align 4
40-
; CHECK: store i32 addrspace(1)* [[DST:%.*]], i32 addrspace(1)** [[DST_ADDR]], align 8
41-
; CHECK: [[TMP0:%.*]] = getelementptr inbounds [2 x i32], [2 x i32] addrspace(2)* [[CASTA]], i64 0, i64 1
42-
; CHECK: [[TMP1:%.*]] = load i32, i32 addrspace(2)* [[TMP0]], align 4
43-
; CHECK: store i32 [[TMP1]], i32* [[AA]], align 4
44-
; CHECK: [[TMP2:%.*]] = load i32 addrspace(2)*, i32 addrspace(2)* addrspace(1)* [[CASTD]], align 8
45-
; CHECK: [[TMP3:%.*]] = load i32, i32 addrspace(2)* [[TMP2]], align 4
46-
; CHECK: store i32 [[TMP3]], i32 addrspace(1)* [[CASTC]], align 4
37+
; CHECK: store ptr addrspace(1) [[DST:%.*]], ptr [[DST_ADDR]], align 8
38+
; CHECK: [[TMP0:%.*]] = getelementptr inbounds [2 x i32], ptr addrspace(2) [[OFFA]], i64 0, i64 1
39+
; CHECK: [[TMP1:%.*]] = load i32, ptr addrspace(2) [[TMP0]], align 4
40+
; CHECK: store i32 [[TMP1]], ptr [[AA]], align 4
41+
; CHECK: [[TMP2:%.*]] = load ptr addrspace(2), ptr addrspace(1) [[OFFD]], align 8
42+
; CHECK: [[TMP3:%.*]] = load i32, ptr addrspace(2) [[TMP2]], align 4
43+
; CHECK: store i32 [[TMP3]], ptr addrspace(1) [[OFFC]], align 4
4744
; CHECK: ret void
4845
;
4946
entry:
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
;=========================== begin_copyright_notice ============================
2+
;
3+
; Copyright (C) 2023 Intel Corporation
4+
;
5+
; SPDX-License-Identifier: MIT
6+
;
7+
;============================ end_copyright_notice =============================
8+
; REQUIRES: regkeys
9+
;
10+
; RUN: igc_opt -enable-debugify --igc-programscope-constant-resolve -S < %s 2>&1 | FileCheck %s
11+
; ------------------------------------------------
12+
; ProgramScopeConstantResolution
13+
; ------------------------------------------------
14+
15+
; CHECK: CheckModuleDebugify: PASS
16+
17+
; This test is based on basic.ll but checks that we skip constant resolution when
18+
; inlineProgramScopeOffsetsValue[...] is set to -1.
19+
; There is at least one case in ProgramScopeConstantAnalysis pass where we need to include
20+
; a variable in 'inlineProgramScopeOffsets' for the purposes of codegen emitting a relocation
21+
; at a later point. We do not want to use the offset value itself so we put -1 there.
22+
;
23+
; Here is an example taken from a shader dump:
24+
; !373 = !{!"inlineProgramScopeOffsetsMap[0]", %struct.kmp_program_data addrspace(1)* @__omp_spirv_program_data}
25+
; !374 = !{!"inlineProgramScopeOffsetsValue[0]", i64 -1}
26+
27+
@a = internal addrspace(2) constant [2 x i32] [i32 0, i32 1], align 4
28+
@d = internal addrspace(1) global i32 addrspace(2)* getelementptr inbounds ([2 x i32], [2 x i32] addrspace(2)* @a, i32 0, i32 0), align 8
29+
@c = internal addrspace(1) global i32 0, align 4
30+
@b = common addrspace(1) global i32 0, align 4
31+
@llvm.used = appending global [3 x i8*] [i8* addrspacecast (i8 addrspace(2)* bitcast ([2 x i32] addrspace(2)* @a to i8 addrspace(2)*) to i8*), i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(1)* @c to i8 addrspace(1)*) to i8*), i8* addrspacecast (i8 addrspace(1)* bitcast (i32 addrspace(2)* addrspace(1)* @d to i8 addrspace(1)*) to i8*)], section "llvm.metadata"
32+
33+
; Function Attrs: convergent noinline nounwind optnone
34+
define spir_kernel void @test_program(i32 addrspace(1)* %dst, <8 x i32> %r0, <8 x i32> %payloadHeader, i8 addrspace(2)* %constBase, i8 addrspace(1)* %globalBase, i8* %privateBase, i32 %bufferOffset) {
35+
; CHECK-LABEL: @test_program(
36+
; CHECK: entry:
37+
; CHECK: [[DST_ADDR:%.*]] = alloca i32 addrspace(1)*, align 8
38+
; CHECK: [[AA:%.*]] = alloca i32, align 4
39+
; CHECK: store i32 addrspace(1)* [[DST:%.*]], i32 addrspace(1)** [[DST_ADDR]], align 8
40+
; CHECK: [[TMP0:%.*]] = getelementptr inbounds [2 x i32], [2 x i32] addrspace(2)* @a, i64 0, i64 1
41+
; CHECK: [[TMP1:%.*]] = load i32, i32 addrspace(2)* [[TMP0]], align 4
42+
; CHECK: store i32 [[TMP1]], i32* [[AA]], align 4
43+
; CHECK: [[TMP2:%.*]] = load i32 addrspace(2)*, i32 addrspace(2)* addrspace(1)* @d, align 8
44+
; CHECK: [[TMP3:%.*]] = load i32, i32 addrspace(2)* [[TMP2]], align 4
45+
; CHECK: store i32 [[TMP3]], i32 addrspace(1)* @c, align 4
46+
; CHECK: ret void
47+
;
48+
entry:
49+
%dst.addr = alloca i32 addrspace(1)*, align 8
50+
%aa = alloca i32, align 4
51+
store i32 addrspace(1)* %dst, i32 addrspace(1)** %dst.addr, align 8
52+
%0 = getelementptr inbounds [2 x i32], [2 x i32] addrspace(2)* @a, i64 0, i64 1
53+
%1 = load i32, i32 addrspace(2)* %0, align 4
54+
store i32 %1, i32* %aa, align 4
55+
%2 = load i32 addrspace(2)*, i32 addrspace(2)* addrspace(1)* @d, align 8
56+
%3 = load i32, i32 addrspace(2)* %2, align 4
57+
store i32 %3, i32 addrspace(1)* @c, align 4
58+
ret void
59+
}
60+
61+
!IGCMetadata = !{!0}
62+
!igc.functions = !{!20}
63+
64+
!0 = !{!"ModuleMD", !1}
65+
!1 = !{!"inlineProgramScopeOffsets", !2, !3, !4, !5, !6, !7}
66+
!2 = !{!"inlineProgramScopeOffsetsMap[0]", [2 x i32] addrspace(2)* @a}
67+
!3 = !{!"inlineProgramScopeOffsetsValue[0]", i64 -1}
68+
!4 = !{!"inlineProgramScopeOffsetsMap[1]", i32 addrspace(1)* @c}
69+
!5 = !{!"inlineProgramScopeOffsetsValue[1]", i64 -1}
70+
!6 = !{!"inlineProgramScopeOffsetsMap[2]", i32 addrspace(2)* addrspace(1)* @d}
71+
!7 = !{!"inlineProgramScopeOffsetsValue[2]", i64 -1}
72+
73+
!20 = !{void (i32 addrspace(1)*, <8 x i32>, <8 x i32>, i8 addrspace(2)*, i8 addrspace(1)*, i8*, i32)* @test_program, !21}
74+
!21 = !{!22, !23}
75+
!22 = !{!"function_type", i32 0}
76+
!23 = !{!"implicit_arg_desc", !24, !25, !26, !27, !28, !29}
77+
!24 = !{i32 0}
78+
!25 = !{i32 1}
79+
!26 = !{i32 10}
80+
!27 = !{i32 11}
81+
!28 = !{i32 12}
82+
!29 = !{i32 14, !30}
83+
!30 = !{!"explicit_arg_num", i32 0}

IGC/Compiler/tests/ProgramScopeConstantResolution/offset_minus_one.ll

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
; SPDX-License-Identifier: MIT
66
;
77
;============================ end_copyright_notice =============================
8-
; REQUIRES: regkeys
8+
; REQUIRES: llvm-14-plus, regkeys
99
;
10-
; RUN: igc_opt -enable-debugify --igc-programscope-constant-resolve -S < %s 2>&1 | FileCheck %s
10+
; RUN: igc_opt --opaque-pointers -enable-debugify --igc-programscope-constant-resolve -S < %s 2>&1 | FileCheck %s
1111
; ------------------------------------------------
1212
; ProgramScopeConstantResolution
1313
; ------------------------------------------------
@@ -34,15 +34,15 @@
3434
define spir_kernel void @test_program(i32 addrspace(1)* %dst, <8 x i32> %r0, <8 x i32> %payloadHeader, i8 addrspace(2)* %constBase, i8 addrspace(1)* %globalBase, i8* %privateBase, i32 %bufferOffset) {
3535
; CHECK-LABEL: @test_program(
3636
; CHECK: entry:
37-
; CHECK: [[DST_ADDR:%.*]] = alloca i32 addrspace(1)*, align 8
37+
; CHECK: [[DST_ADDR:%.*]] = alloca ptr addrspace(1), align 8
3838
; CHECK: [[AA:%.*]] = alloca i32, align 4
39-
; CHECK: store i32 addrspace(1)* [[DST:%.*]], i32 addrspace(1)** [[DST_ADDR]], align 8
40-
; CHECK: [[TMP0:%.*]] = getelementptr inbounds [2 x i32], [2 x i32] addrspace(2)* @a, i64 0, i64 1
41-
; CHECK: [[TMP1:%.*]] = load i32, i32 addrspace(2)* [[TMP0]], align 4
42-
; CHECK: store i32 [[TMP1]], i32* [[AA]], align 4
43-
; CHECK: [[TMP2:%.*]] = load i32 addrspace(2)*, i32 addrspace(2)* addrspace(1)* @d, align 8
44-
; CHECK: [[TMP3:%.*]] = load i32, i32 addrspace(2)* [[TMP2]], align 4
45-
; CHECK: store i32 [[TMP3]], i32 addrspace(1)* @c, align 4
39+
; CHECK: store ptr addrspace(1) [[DST:%.*]], ptr [[DST_ADDR]], align 8
40+
; CHECK: [[TMP0:%.*]] = getelementptr inbounds [2 x i32], ptr addrspace(2) @a, i64 0, i64 1
41+
; CHECK: [[TMP1:%.*]] = load i32, ptr addrspace(2) [[TMP0]], align 4
42+
; CHECK: store i32 [[TMP1]], ptr [[AA]], align 4
43+
; CHECK: [[TMP2:%.*]] = load ptr addrspace(2), ptr addrspace(1) @d, align 8
44+
; CHECK: [[TMP3:%.*]] = load i32, ptr addrspace(2) [[TMP2]], align 4
45+
; CHECK: store i32 [[TMP3]], ptr addrspace(1) @c, align 4
4646
; CHECK: ret void
4747
;
4848
entry:

0 commit comments

Comments
 (0)