Skip to content

Commit 77c938c

Browse files
bokrzesiigcbot
authored andcommitted
Backport of "[IR] Unify max alignment for arguments with generic max align."
Recently we've moved to LLVM 15 on production And on LLVM 15 we've found that this check is no longer valid, the ParamMaxAlignment is too small. ``` llvm/lib/IR/Verifier.cpp auto VerifyTypeAlign = [&](Type *Ty, const Twine &Message) { (...) Align MaxAlign(ParamMaxAlignment); Check(ABIAlign <= MaxAlign, ``` This was already adjusted in the upstream, here: * Backport of llvm/llvm-project#99257
1 parent 6e1e358 commit 77c938c

File tree

2 files changed

+301
-0
lines changed

2 files changed

+301
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*========================== begin_copyright_notice ============================
2+
3+
Copyright (C) 2025 Intel Corporation
4+
5+
SPDX-License-Identifier: MIT
6+
7+
============================= end_copyright_notice ===========================*/
8+
9+
/*========================== begin_copyright_notice ============================
10+
11+
Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
12+
See https://llvm.org/LICENSE.txt for license information.
13+
SPDX-License-Identifier: Apache-2.0 with LLVM-exception
14+
15+
============================= end_copyright_notice ===========================*/
16+
17+
This is backport of this fix: https://github.com/llvm/llvm-project/pull/99257
18+
19+
"[IR] Unify max alignment for arguments with generic max align."
20+
21+
22+
From 47f034550a5fb9ef6adee6347cd3c00e70ca663d Mon Sep 17 00:00:00 2001
23+
From: Eli Friedman <[email protected]>
24+
Date: Tue, 16 Jul 2024 16:03:38 -0700
25+
Subject: [PATCH 1/3] Unify max alignment for arguments with generic max align.
26+
27+
The 2^14 limit was completely arbitrary; the generic limit is still
28+
arbitrary, but at least it's the same arbitrary limit as everything
29+
else.
30+
31+
While I'm here, also add a verifier check for the ByValOrByRefSize.
32+
---
33+
llvm/include/llvm/CodeGen/TargetCallingConv.h | 8 ++--
34+
llvm/lib/IR/Verifier.cpp | 38 +++++++++++--------
35+
llvm/test/Verifier/param-align.ll | 14 +++----
36+
llvm/test/Verifier/param-attr-align.ll | 4 +-
37+
llvm/test/Verifier/param-ret-align.ll | 12 +++---
38+
5 files changed, 42 insertions(+), 34 deletions(-)
39+
40+
diff --git a/llvm/include/llvm/CodeGen/TargetCallingConv.h b/llvm/include/llvm/CodeGen/TargetCallingConv.h
41+
index 1333f2d98973..1ae1688c60b7 100644
42+
--- a/llvm/include/llvm/CodeGen/TargetCallingConv.h
43+
+++ b/llvm/include/llvm/CodeGen/TargetCallingConv.h
44+
@@ -45,9 +45,9 @@ namespace ISD {
45+
unsigned IsHva : 1; ///< HVA field for
46+
unsigned IsHvaStart : 1; ///< HVA structure start
47+
unsigned IsSecArgPass : 1; ///< Second argument
48+
- unsigned MemAlign : 4; ///< Log 2 of alignment when arg is passed in memory
49+
- ///< (including byval/byref). The max alignment is
50+
- ///< verified in IR verification.
51+
+ unsigned MemAlign : 6; ///< Log 2 of alignment when arg is passed in memory
52+
+ ///< (including byval/byref). The max alignment is
53+
+ ///< verified in IR verification.
54+
unsigned OrigAlign : 5; ///< Log 2 of original alignment
55+
unsigned IsInConsecutiveRegsLast : 1;
56+
unsigned IsInConsecutiveRegs : 1;
57+
@@ -67,7 +67,7 @@ namespace ISD {
58+
IsSecArgPass(0), MemAlign(0), OrigAlign(0),
59+
IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
60+
IsCopyElisionCandidate(0), IsPointer(0) {
61+
- static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
62+
+ static_assert(sizeof(*this) == 4 * sizeof(unsigned), "flags are too big");
63+
}
64+
65+
bool isZExt() const { return IsZExt; }
66+
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
67+
index e3ea256af16d..02c40e59de05 100644
68+
--- a/llvm/lib/IR/Verifier.cpp
69+
+++ b/llvm/lib/IR/Verifier.cpp
70+
@@ -278,13 +278,6 @@ namespace {
71+
72+
class Verifier : public InstVisitor<Verifier>, VerifierSupport {
73+
friend class InstVisitor<Verifier>;
74+
-
75+
- // ISD::ArgFlagsTy::MemAlign only have 4 bits for alignment, so
76+
- // the alignment size should not exceed 2^15. Since encode(Align)
77+
- // would plus the shift value by 1, the alignment size should
78+
- // not exceed 2^14, otherwise it can NOT be properly lowered
79+
- // in backend.
80+
- static constexpr unsigned ParamMaxAlignment = 1 << 14;
81+
DominatorTree DT;
82+
83+
/// When verifying a basic block, keep track of all of the
84+
@@ -1836,31 +1829,43 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
85+
}
86+
87+
if (PointerType *PTy = dyn_cast<PointerType>(Ty)) {
88+
+ if (Attrs.hasAttribute(Attribute::Alignment)) {
89+
+ Align AttrAlign = Attrs.getAlignment().valueOrOne();
90+
+ Check(AttrAlign.value() <= Value::MaximumAlignment,
91+
+ "huge alignment values are unsupported", V);
92+
+ }
93+
if (Attrs.hasAttribute(Attribute::ByVal)) {
94+
- if (Attrs.hasAttribute(Attribute::Alignment)) {
95+
- Align AttrAlign = Attrs.getAlignment().valueOrOne();
96+
- Align MaxAlign(ParamMaxAlignment);
97+
- Check(AttrAlign <= MaxAlign,
98+
- "Attribute 'align' exceed the max size 2^14", V);
99+
- }
100+
SmallPtrSet<Type *, 4> Visited;
101+
Check(Attrs.getByValType()->isSized(&Visited),
102+
"Attribute 'byval' does not support unsized types!", V);
103+
+ Check(DL.getTypeAllocSize(Attrs.getByValType()).getKnownMinValue() <
104+
+ (1ULL << 32),
105+
+ "huge 'byval' arguments are unsupported", V);
106+
}
107+
if (Attrs.hasAttribute(Attribute::ByRef)) {
108+
SmallPtrSet<Type *, 4> Visited;
109+
Check(Attrs.getByRefType()->isSized(&Visited),
110+
"Attribute 'byref' does not support unsized types!", V);
111+
+ Check(DL.getTypeAllocSize(Attrs.getByRefType()).getKnownMinValue() <
112+
+ (1ULL << 32),
113+
+ "huge 'byref' arguments are unsupported", V);
114+
}
115+
if (Attrs.hasAttribute(Attribute::InAlloca)) {
116+
SmallPtrSet<Type *, 4> Visited;
117+
Check(Attrs.getInAllocaType()->isSized(&Visited),
118+
"Attribute 'inalloca' does not support unsized types!", V);
119+
+ Check(DL.getTypeAllocSize(Attrs.getInAllocaType()).getKnownMinValue() <
120+
+ (1ULL << 32),
121+
+ "huge 'inalloca' arguments are unsupported", V);
122+
}
123+
if (Attrs.hasAttribute(Attribute::Preallocated)) {
124+
SmallPtrSet<Type *, 4> Visited;
125+
Check(Attrs.getPreallocatedType()->isSized(&Visited),
126+
"Attribute 'preallocated' does not support unsized types!", V);
127+
+ Check(
128+
+ DL.getTypeAllocSize(Attrs.getPreallocatedType()).getKnownMinValue() <
129+
+ (1ULL << 32),
130+
+ "huge 'preallocated' arguments are unsupported", V);
131+
}
132+
if (!PTy->isOpaque()) {
133+
if (!isa<PointerType>(PTy->getNonOpaquePointerElementType()))
134+
@@ -3179,12 +3184,15 @@ void Verifier::visitCallBase(CallBase &Call) {
135+
Check(verifyAttributeCount(Attrs, Call.arg_size()),
136+
"Attribute after last parameter!", Call);
137+
138+
+// Disallow passing/returning values with alignment higher than we can
139+
+// represent.
140+
+// FIXME: Consider making DataLayout cap the alignment, so this isn't
141+
+// necessary.
142+
auto VerifyTypeAlign = [&](Type *Ty, const Twine &Message) {
143+
if (!Ty->isSized())
144+
return;
145+
Align ABIAlign = DL.getABITypeAlign(Ty);
146+
- Align MaxAlign(ParamMaxAlignment);
147+
- Check(ABIAlign <= MaxAlign,
148+
+ Check(ABIAlign.value() <= Value::MaximumAlignment,
149+
"Incorrect alignment of " + Message + " to called function!", Call);
150+
};
151+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*========================== begin_copyright_notice ============================
2+
3+
Copyright (C) 2025 Intel Corporation
4+
5+
SPDX-License-Identifier: MIT
6+
7+
============================= end_copyright_notice ===========================*/
8+
9+
/*========================== begin_copyright_notice ============================
10+
11+
Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
12+
See https://llvm.org/LICENSE.txt for license information.
13+
SPDX-License-Identifier: Apache-2.0 with LLVM-exception
14+
15+
============================= end_copyright_notice ===========================*/
16+
17+
This is backport of this fix: https://github.com/llvm/llvm-project/pull/99257
18+
19+
"[IR] Unify max alignment for arguments with generic max align."
20+
21+
From 47f034550a5fb9ef6adee6347cd3c00e70ca663d Mon Sep 17 00:00:00 2001
22+
From: Eli Friedman <[email protected]>
23+
Date: Tue, 16 Jul 2024 16:03:38 -0700
24+
Subject: [PATCH 1/3] Unify max alignment for arguments with generic max align.
25+
26+
The 2^14 limit was completely arbitrary; the generic limit is still
27+
arbitrary, but at least it's the same arbitrary limit as everything
28+
else.
29+
30+
While I'm here, also add a verifier check for the ByValOrByRefSize.
31+
---
32+
llvm/include/llvm/CodeGen/TargetCallingConv.h | 8 ++--
33+
llvm/lib/IR/Verifier.cpp | 38 +++++++++++--------
34+
llvm/test/Verifier/param-align.ll | 14 +++----
35+
llvm/test/Verifier/param-attr-align.ll | 4 +-
36+
llvm/test/Verifier/param-ret-align.ll | 12 +++---
37+
5 files changed, 42 insertions(+), 34 deletions(-)
38+
39+
diff --git a/llvm/include/llvm/CodeGen/TargetCallingConv.h b/llvm/include/llvm/CodeGen/TargetCallingConv.h
40+
index 1333f2d98..1ae1688c6 100644
41+
--- a/llvm/include/llvm/CodeGen/TargetCallingConv.h
42+
+++ b/llvm/include/llvm/CodeGen/TargetCallingConv.h
43+
@@ -45,9 +45,9 @@ namespace ISD {
44+
unsigned IsHva : 1; ///< HVA field for
45+
unsigned IsHvaStart : 1; ///< HVA structure start
46+
unsigned IsSecArgPass : 1; ///< Second argument
47+
- unsigned MemAlign : 4; ///< Log 2 of alignment when arg is passed in memory
48+
- ///< (including byval/byref). The max alignment is
49+
- ///< verified in IR verification.
50+
+ unsigned MemAlign : 6; ///< Log 2 of alignment when arg is passed in memory
51+
+ ///< (including byval/byref). The max alignment is
52+
+ ///< verified in IR verification.
53+
unsigned OrigAlign : 5; ///< Log 2 of original alignment
54+
unsigned IsInConsecutiveRegsLast : 1;
55+
unsigned IsInConsecutiveRegs : 1;
56+
@@ -67,7 +67,7 @@ namespace ISD {
57+
IsSecArgPass(0), MemAlign(0), OrigAlign(0),
58+
IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
59+
IsCopyElisionCandidate(0), IsPointer(0) {
60+
- static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
61+
+ static_assert(sizeof(*this) == 4 * sizeof(unsigned), "flags are too big");
62+
}
63+
64+
bool isZExt() const { return IsZExt; }
65+
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
66+
index 2d62d31cf..5a82f1202 100644
67+
--- a/llvm/lib/IR/Verifier.cpp
68+
+++ b/llvm/lib/IR/Verifier.cpp
69+
@@ -279,13 +279,6 @@ namespace {
70+
71+
class Verifier : public InstVisitor<Verifier>, VerifierSupport {
72+
friend class InstVisitor<Verifier>;
73+
-
74+
- // ISD::ArgFlagsTy::MemAlign only have 4 bits for alignment, so
75+
- // the alignment size should not exceed 2^15. Since encode(Align)
76+
- // would plus the shift value by 1, the alignment size should
77+
- // not exceed 2^14, otherwise it can NOT be properly lowered
78+
- // in backend.
79+
- static constexpr unsigned ParamMaxAlignment = 1 << 14;
80+
DominatorTree DT;
81+
82+
/// When verifying a basic block, keep track of all of the
83+
@@ -1870,31 +1863,43 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
84+
}
85+
86+
if (PointerType *PTy = dyn_cast<PointerType>(Ty)) {
87+
+ if (Attrs.hasAttribute(Attribute::Alignment)) {
88+
+ Align AttrAlign = Attrs.getAlignment().valueOrOne();
89+
+ Check(AttrAlign.value() <= Value::MaximumAlignment,
90+
+ "huge alignment values are unsupported", V);
91+
+ }
92+
if (Attrs.hasAttribute(Attribute::ByVal)) {
93+
- if (Attrs.hasAttribute(Attribute::Alignment)) {
94+
- Align AttrAlign = Attrs.getAlignment().valueOrOne();
95+
- Align MaxAlign(ParamMaxAlignment);
96+
- Check(AttrAlign <= MaxAlign,
97+
- "Attribute 'align' exceed the max size 2^14", V);
98+
- }
99+
SmallPtrSet<Type *, 4> Visited;
100+
Check(Attrs.getByValType()->isSized(&Visited),
101+
"Attribute 'byval' does not support unsized types!", V);
102+
+ Check(DL.getTypeAllocSize(Attrs.getByValType()).getKnownMinValue() <
103+
+ (1ULL << 32),
104+
+ "huge 'byval' arguments are unsupported", V);
105+
}
106+
if (Attrs.hasAttribute(Attribute::ByRef)) {
107+
SmallPtrSet<Type *, 4> Visited;
108+
Check(Attrs.getByRefType()->isSized(&Visited),
109+
"Attribute 'byref' does not support unsized types!", V);
110+
+ Check(DL.getTypeAllocSize(Attrs.getByRefType()).getKnownMinValue() <
111+
+ (1ULL << 32),
112+
+ "huge 'byref' arguments are unsupported", V);
113+
}
114+
if (Attrs.hasAttribute(Attribute::InAlloca)) {
115+
SmallPtrSet<Type *, 4> Visited;
116+
Check(Attrs.getInAllocaType()->isSized(&Visited),
117+
"Attribute 'inalloca' does not support unsized types!", V);
118+
+ Check(DL.getTypeAllocSize(Attrs.getInAllocaType()).getKnownMinValue() <
119+
+ (1ULL << 32),
120+
+ "huge 'inalloca' arguments are unsupported", V);
121+
}
122+
if (Attrs.hasAttribute(Attribute::Preallocated)) {
123+
SmallPtrSet<Type *, 4> Visited;
124+
Check(Attrs.getPreallocatedType()->isSized(&Visited),
125+
"Attribute 'preallocated' does not support unsized types!", V);
126+
+ Check(
127+
+ DL.getTypeAllocSize(Attrs.getPreallocatedType()).getKnownMinValue() <
128+
+ (1ULL << 32),
129+
+ "huge 'preallocated' arguments are unsupported", V);
130+
}
131+
if (!PTy->isOpaque()) {
132+
if (!isa<PointerType>(PTy->getNonOpaquePointerElementType()))
133+
@@ -3237,12 +3242,15 @@ void Verifier::visitCallBase(CallBase &Call) {
134+
Check(Callee->getValueType() == FTy,
135+
"Intrinsic called with incompatible signature", Call);
136+
137+
+ // Disallow passing/returning values with alignment higher than we can
138+
+ // represent.
139+
+ // FIXME: Consider making DataLayout cap the alignment, so this isn't
140+
+ // necessary.
141+
auto VerifyTypeAlign = [&](Type *Ty, const Twine &Message) {
142+
if (!Ty->isSized())
143+
return;
144+
Align ABIAlign = DL.getABITypeAlign(Ty);
145+
- Align MaxAlign(ParamMaxAlignment);
146+
- Check(ABIAlign <= MaxAlign,
147+
+ Check(ABIAlign.value() <= Value::MaximumAlignment,
148+
"Incorrect alignment of " + Message + " to called function!", Call);
149+
};
150+

0 commit comments

Comments
 (0)