Skip to content

Commit 82cca0c

Browse files
[IR] Unify max alignment for arguments with generic max align. (#99257)
The 2^14 limit was completely arbitrary; the generic limit is still arbitrary, but at least it's the same arbitrary limit as everything else. While I'm here, also add a verifier check for the ByValOrByRefSize.
1 parent e2c3cd7 commit 82cca0c

File tree

6 files changed

+46
-34
lines changed

6 files changed

+46
-34
lines changed

llvm/include/llvm/CodeGen/TargetCallingConv.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ namespace ISD {
4545
unsigned IsHva : 1; ///< HVA field for
4646
unsigned IsHvaStart : 1; ///< HVA structure start
4747
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.
48+
unsigned MemAlign : 6; ///< Log 2 of alignment when arg is passed in memory
49+
///< (including byval/byref). The max alignment is
50+
///< verified in IR verification.
5151
unsigned OrigAlign : 5; ///< Log 2 of original alignment
5252
unsigned IsInConsecutiveRegsLast : 1;
5353
unsigned IsInConsecutiveRegs : 1;
@@ -67,7 +67,7 @@ namespace ISD {
6767
IsSecArgPass(0), MemAlign(0), OrigAlign(0),
6868
IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
6969
IsCopyElisionCandidate(0), IsPointer(0) {
70-
static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
70+
static_assert(sizeof(*this) == 4 * sizeof(unsigned), "flags are too big");
7171
}
7272

7373
bool isZExt() const { return IsZExt; }

llvm/lib/IR/Verifier.cpp

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -324,13 +324,6 @@ namespace {
324324

325325
class Verifier : public InstVisitor<Verifier>, VerifierSupport {
326326
friend class InstVisitor<Verifier>;
327-
328-
// ISD::ArgFlagsTy::MemAlign only have 4 bits for alignment, so
329-
// the alignment size should not exceed 2^15. Since encode(Align)
330-
// would plus the shift value by 1, the alignment size should
331-
// not exceed 2^14, otherwise it can NOT be properly lowered
332-
// in backend.
333-
static constexpr unsigned ParamMaxAlignment = 1 << 14;
334327
DominatorTree DT;
335328

336329
/// When verifying a basic block, keep track of all of the
@@ -2021,31 +2014,43 @@ void Verifier::verifyParameterAttrs(AttributeSet Attrs, Type *Ty,
20212014
}
20222015

20232016
if (isa<PointerType>(Ty)) {
2017+
if (Attrs.hasAttribute(Attribute::Alignment)) {
2018+
Align AttrAlign = Attrs.getAlignment().valueOrOne();
2019+
Check(AttrAlign.value() <= Value::MaximumAlignment,
2020+
"huge alignment values are unsupported", V);
2021+
}
20242022
if (Attrs.hasAttribute(Attribute::ByVal)) {
2025-
if (Attrs.hasAttribute(Attribute::Alignment)) {
2026-
Align AttrAlign = Attrs.getAlignment().valueOrOne();
2027-
Align MaxAlign(ParamMaxAlignment);
2028-
Check(AttrAlign <= MaxAlign,
2029-
"Attribute 'align' exceed the max size 2^14", V);
2030-
}
20312023
SmallPtrSet<Type *, 4> Visited;
20322024
Check(Attrs.getByValType()->isSized(&Visited),
20332025
"Attribute 'byval' does not support unsized types!", V);
2026+
Check(DL.getTypeAllocSize(Attrs.getByValType()).getKnownMinValue() <
2027+
(1ULL << 32),
2028+
"huge 'byval' arguments are unsupported", V);
20342029
}
20352030
if (Attrs.hasAttribute(Attribute::ByRef)) {
20362031
SmallPtrSet<Type *, 4> Visited;
20372032
Check(Attrs.getByRefType()->isSized(&Visited),
20382033
"Attribute 'byref' does not support unsized types!", V);
2034+
Check(DL.getTypeAllocSize(Attrs.getByRefType()).getKnownMinValue() <
2035+
(1ULL << 32),
2036+
"huge 'byref' arguments are unsupported", V);
20392037
}
20402038
if (Attrs.hasAttribute(Attribute::InAlloca)) {
20412039
SmallPtrSet<Type *, 4> Visited;
20422040
Check(Attrs.getInAllocaType()->isSized(&Visited),
20432041
"Attribute 'inalloca' does not support unsized types!", V);
2042+
Check(DL.getTypeAllocSize(Attrs.getInAllocaType()).getKnownMinValue() <
2043+
(1ULL << 32),
2044+
"huge 'inalloca' arguments are unsupported", V);
20442045
}
20452046
if (Attrs.hasAttribute(Attribute::Preallocated)) {
20462047
SmallPtrSet<Type *, 4> Visited;
20472048
Check(Attrs.getPreallocatedType()->isSized(&Visited),
20482049
"Attribute 'preallocated' does not support unsized types!", V);
2050+
Check(
2051+
DL.getTypeAllocSize(Attrs.getPreallocatedType()).getKnownMinValue() <
2052+
(1ULL << 32),
2053+
"huge 'preallocated' arguments are unsupported", V);
20492054
}
20502055
}
20512056

@@ -3511,12 +3516,15 @@ void Verifier::visitCallBase(CallBase &Call) {
35113516
"not allowed. Please use the @llvm.amdgpu.cs.chain intrinsic instead.",
35123517
Call);
35133518

3519+
// Disallow passing/returning values with alignment higher than we can
3520+
// represent.
3521+
// FIXME: Consider making DataLayout cap the alignment, so this isn't
3522+
// necessary.
35143523
auto VerifyTypeAlign = [&](Type *Ty, const Twine &Message) {
35153524
if (!Ty->isSized())
35163525
return;
35173526
Align ABIAlign = DL.getABITypeAlign(Ty);
3518-
Align MaxAlign(ParamMaxAlignment);
3519-
Check(ABIAlign <= MaxAlign,
3527+
Check(ABIAlign.value() <= Value::MaximumAlignment,
35203528
"Incorrect alignment of " + Message + " to called function!", Call);
35213529
};
35223530

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
; RUN: not llvm-as < %s 2>&1 | FileCheck %s
2+
3+
; CHECK: huge 'byval' arguments are unsupported
4+
define void @f(ptr byval([2147483648 x i16])) { ret void }

llvm/test/Verifier/param-align.ll

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
; Large vector for intrinsics is valid
44
; CHECK-NOT: llvm.fshr
5-
define dso_local <8192 x i32> @test_intrin(<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt) {
5+
define dso_local <2147483648 x i32> @test_intrin(<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt) {
66
entry:
7-
%b = call <8192 x i32> @llvm.fshr.v8192i32(<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt)
8-
ret <8192 x i32> %b
7+
%b = call <2147483648 x i32> @llvm.fshr.v8192i32(<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt)
8+
ret <2147483648 x i32> %b
99
}
10-
declare <8192 x i32> @llvm.fshr.v8192i32 (<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt)
10+
declare <2147483648 x i32> @llvm.fshr.v8192i32 (<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt)
1111

1212
; CHECK: Incorrect alignment of argument passed to called function!
1313
; CHECK: bar
14-
define dso_local void @foo(<8192 x float> noundef %vec) {
14+
define dso_local void @foo(<2147483648 x float> noundef %vec) {
1515
entry:
16-
call void @bar(<8192 x float> %vec)
16+
call void @bar(<2147483648 x float> %vec)
1717
ret void
1818
}
1919

20-
declare dso_local void @bar(<8192 x float>)
20+
declare dso_local void @bar(<2147483648 x float>)

llvm/test/Verifier/param-attr-align.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
; RUN: not llvm-as < %s 2>&1 | FileCheck %s
22

3-
; CHECK: Attribute 'align' exceed the max size 2^14
3+
; CHECK: huge alignments are not supported yet
44
define dso_local void @foo(ptr %p) {
55
entry:
6-
call void @bar(ptr noundef byval(<8 x float>) align 32768 %p)
6+
call void @bar(ptr noundef byval(<8 x float>) align 8589934592 %p)
77
ret void
88
}
99

llvm/test/Verifier/param-ret-align.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
; Large vector for intrinsics is valid
44
; CHECK-NOT: llvm.fshr
5-
define dso_local <8192 x i32> @test_intrin(<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt) {
5+
define dso_local <2147483648 x i32> @test_intrin(<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt) {
66
entry:
7-
%b = call <8192 x i32> @llvm.fshr.v8192i32(<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt)
8-
ret <8192 x i32> %b
7+
%b = call <2147483648 x i32> @llvm.fshr.v8192i32(<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt)
8+
ret <2147483648 x i32> %b
99
}
10-
declare <8192 x i32> @llvm.fshr.v8192i32 (<8192 x i32> %l, <8192 x i32> %r, <8192 x i32> %amt)
10+
declare <2147483648 x i32> @llvm.fshr.v2147483648i32 (<2147483648 x i32> %l, <2147483648 x i32> %r, <2147483648 x i32> %amt)
1111

1212
; CHECK: Incorrect alignment of return type to called function!
1313
; CHECK: bar
1414
define dso_local void @foo() {
1515
entry:
16-
call <8192 x float> @bar()
16+
call <2147483648 x float> @bar()
1717
ret void
1818
}
1919

20-
declare dso_local <8192 x float> @bar()
20+
declare dso_local <2147483648 x float> @bar()

0 commit comments

Comments
 (0)