Skip to content

Commit

Permalink
Merge pull request #170 from RossBrunton/fix_align
Browse files Browse the repository at this point in the history
[passes] Handle alignments of structs correctly with local memory
  • Loading branch information
RossBrunton authored Oct 20, 2023
2 parents e22d0c6 + 43e099a commit a09e2ac
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
; Copyright (C) Codeplay Software Limited
;
; Licensed under the Apache License, Version 2.0 (the "License") with LLVM
; Exceptions; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; https://github.com/codeplaysoftware/oneapi-construction-kit/blob/main/LICENSE.txt
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
; WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
; License for the specific language governing permissions and limitations
; under the License.
;
; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

; RUN: muxc --passes replace-module-scope-vars,verify -S %s | FileCheck %s

target triple = "spir64-unknown-unknown"
target datalayout = "e-p:64:64:64-m:e-i64:64-f80:128-n8:16:32:64-S128"

; CHECK: %localVarTypes = type { %triplet, [8 x i8], %triplet, %triplet, [16 x i8], [5 x %triplet], [8 x i8], i64, i20, [4 x i8], i64 }
%triplet = type { i64, i64, i64 }

@a = internal addrspace(3) global %triplet undef, align 16
@b = internal addrspace(3) global %triplet undef, align 16
@c = internal addrspace(3) global %triplet undef, align 8
@d = internal addrspace(3) global [5 x %triplet] undef, align 32
@e = internal addrspace(3) global i64 0, align 16
@f = internal addrspace(3) global i20 0, align 1
@g = internal addrspace(3) global i64 100

define spir_kernel void @foo() {
; CHECK: getelementptr {{.*}}, i32 0, i32 0
%a1 = load i64, ptr addrspace(3) @a, align 8
; CHECK: getelementptr {{.*}}, i32 0, i32 0
; CHECK: getelementptr {{.*}}, i64 0, i32 1
%a2p = getelementptr inbounds %triplet, ptr addrspace(3) @a, i64 0, i32 1
%a2 = load i64, ptr addrspace(3) %a2p, align 8

; CHECK: getelementptr {{.*}}, i32 0, i32 2
%b1 = load i64, ptr addrspace(3) @b, align 8
; CHECK: getelementptr {{.*}}, i32 0, i32 2
; CHECK: getelementptr {{.*}}, i64 0, i32 1
%b2p = getelementptr inbounds %triplet, ptr addrspace(3) @b, i64 0, i32 1
%b2 = load i64, ptr addrspace(3) %b2p, align 8

; CHECK: getelementptr {{.*}}, i32 0, i32 3
%c1 = load i64, ptr addrspace(3) @c, align 8
; CHECK: getelementptr {{.*}}, i32 0, i32 3
; CHECK: getelementptr {{.*}}, i64 0, i32 1
%c2p = getelementptr inbounds %triplet, ptr addrspace(3) @c, i64 0, i32 1
%c2 = load i64, ptr addrspace(3) %c2p, align 8

; CHECK: getelementptr {{.*}}, i32 0, i32 5
%d1 = load i64, ptr addrspace(3) @d, align 8
; CHECK: getelementptr {{.*}}, i32 0, i32 5
; CHECK: getelementptr {{.*}}, i64 0, i32 3, i32 1
%d2p = getelementptr inbounds [5 x %triplet], ptr addrspace(3) @d, i64 0, i32 3, i32 1
%d2 = load i64, ptr addrspace(3) %d2p, align 8

; CHECK: getelementptr {{.*}}, i32 0, i32 7
%e = load i64, ptr addrspace(3) @e, align 8

; CHECK: getelementptr {{.*}}, i32 0, i32 8
%f = load i20, ptr addrspace(3) @f

; CHECK: getelementptr {{.*}}, i32 0, i32 10
%g = load i1, ptr addrspace(3) @g

ret void
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ PreservedAnalyses compiler::utils::ReplaceLocalModuleScopeVariablesPass::run(
unsigned int maxAlignment = 0;
// byte offset in struct of current member
unsigned int offset = 0;
const auto &dl = M.getDataLayout();
for (auto &global : globals) {
auto memberType = global->getValueType();

Expand All @@ -202,8 +203,7 @@ PreservedAnalyses compiler::utils::ReplaceLocalModuleScopeVariablesPass::run(
// global. This is also needed if '__attribute__(aligned)' was used to
// set a specific alignment.
const unsigned int alignment =
std::max(global->getAlignment(),
calculateTypeAlign(memberType, M.getDataLayout()));
std::max(global->getAlignment(), calculateTypeAlign(memberType, dl));
assert(alignment > 0 && "'0' is an impossible alignment");

// check if this is the largest alignment seen so far
Expand Down Expand Up @@ -236,12 +236,13 @@ PreservedAnalyses compiler::utils::ReplaceLocalModuleScopeVariablesPass::run(
// then add our element type to the struct
structElementTypes.push_back(memberType);

// update the offset, taking into account any array length
unsigned int totalSize = alignment;
while (memberType->isArrayTy()) {
totalSize *= memberType->getArrayNumElements();
memberType = memberType->getArrayElementType();
// update the offset based on the type's size
auto allocSize = dl.getTypeAllocSize(memberType);
if (dl.getTypeAllocSize(memberType).isScalable()) {
// Not an assert because this can happen in user-supplied IR
report_fatal_error("Scalable types in local memory are not supported");
}
unsigned int totalSize = allocSize.getFixedValue();
offset += totalSize;
}

Expand Down

0 comments on commit a09e2ac

Please sign in to comment.