Skip to content

Commit d1338c2

Browse files
SC llvm teamSC llvm team
SC llvm team
authored and
SC llvm team
committed
Merged main:159614a52f0b into amd-gfx:71bb95469251
Local branch amd-gfx 71bb954 Merged main:2973febe1087 into amd-gfx:4159e61e2644 Remote branch main 159614a [LV] Use variable instead of value number in vplan-dot-printing.ll test.
2 parents 71bb954 + 159614a commit d1338c2

File tree

21 files changed

+252
-393
lines changed

21 files changed

+252
-393
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,24 @@ Attribute Changes in Clang
248248
supports but that are never the result of default argument promotion, such as
249249
``float``. (`#59824: <https://github.com/llvm/llvm-project/issues/59824>`_)
250250

251+
- Clang now supports ``[[clang::preferred_type(type-name)]]`` as an attribute
252+
which can be applied to a bit-field. This attribute helps to map a bit-field
253+
back to a particular type that may be better-suited to representing the bit-
254+
field but cannot be used for other reasons and will impact the debug
255+
information generated for the bit-field. This is most useful when mapping a
256+
bit-field of basic integer type back to a ``bool`` or an enumeration type,
257+
e.g.,
258+
259+
.. code-block:: c++
260+
261+
enum E { Apple, Orange, Pear };
262+
struct S {
263+
[[clang::preferred_type(E)]] unsigned FruitKind : 2;
264+
};
265+
266+
When viewing ``S::FruitKind`` in a debugger, it will behave as if the member
267+
was declared as type ``E`` rather than ``unsigned``.
268+
251269
Improvements to Clang's diagnostics
252270
-----------------------------------
253271
- Clang constexpr evaluator now prints template arguments when displaying

clang/include/clang/Basic/Attr.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ def NonBitField : SubsetSubject<Field,
107107
[{!S->isBitField()}],
108108
"non-bit-field non-static data members">;
109109

110+
def BitField : SubsetSubject<Field,
111+
[{S->isBitField()}],
112+
"bit-field data members">;
113+
110114
def NonStaticCXXMethod : SubsetSubject<CXXMethod,
111115
[{!S->isStatic()}],
112116
"non-static member functions">;
@@ -4269,3 +4273,10 @@ def CountedBy : InheritableAttr {
42694273
void setCountedByFieldLoc(SourceRange Loc) { CountedByFieldLoc = Loc; }
42704274
}];
42714275
}
4276+
4277+
def PreferredType: InheritableAttr {
4278+
let Spellings = [Clang<"preferred_type">];
4279+
let Subjects = SubjectList<[BitField], ErrorDiag>;
4280+
let Args = [TypeArgument<"Type", 1>];
4281+
let Documentation = [PreferredTypeDocumentation];
4282+
}

clang/include/clang/Basic/AttrDocs.td

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7231,6 +7231,69 @@ its underlying representation to be a WebAssembly ``funcref``.
72317231
}];
72327232
}
72337233

7234+
def PreferredTypeDocumentation : Documentation {
7235+
let Category = DocCatField;
7236+
let Content = [{
7237+
This attribute allows adjusting the type of a bit-field in debug information.
7238+
This can be helpful when a bit-field is intended to store an enumeration value,
7239+
but has to be specified as having the enumeration's underlying type in order to
7240+
facilitate compiler optimizations or bit-field packing behavior. Normally, the
7241+
underlying type is what is emitted in debug information, which can make it hard
7242+
for debuggers to know to map a bit-field's value back to a particular enumeration.
7243+
7244+
.. code-block:: c++
7245+
7246+
enum Colors { Red, Green, Blue };
7247+
7248+
struct S {
7249+
[[clang::preferred_type(Colors)]] unsigned ColorVal : 2;
7250+
[[clang::preferred_type(bool)]] unsigned UseAlternateColorSpace : 1;
7251+
} s = { Green, false };
7252+
7253+
Without the attribute, a debugger is likely to display the value ``1`` for ``ColorVal``
7254+
and ``0`` for ``UseAlternateColorSpace``. With the attribute, the debugger may now
7255+
display ``Green`` and ``false`` instead.
7256+
7257+
This can be used to map a bit-field to an arbitrary type that isn't integral
7258+
or an enumeration type. For example:
7259+
7260+
.. code-block:: c++
7261+
7262+
struct A {
7263+
short a1;
7264+
short a2;
7265+
};
7266+
7267+
struct B {
7268+
[[clang::preferred_type(A)]] unsigned b1 : 32 = 0x000F'000C;
7269+
};
7270+
7271+
will associate the type ``A`` with the ``b1`` bit-field and is intended to display
7272+
something like this in the debugger:
7273+
7274+
.. code-block:: text
7275+
7276+
Process 2755547 stopped
7277+
* thread #1, name = 'test-preferred-', stop reason = step in
7278+
frame #0: 0x0000555555555148 test-preferred-type`main at test.cxx:13:14
7279+
10 int main()
7280+
11 {
7281+
12 B b;
7282+
-> 13 return b.b1;
7283+
14 }
7284+
(lldb) v -T
7285+
(B) b = {
7286+
(A:32) b1 = {
7287+
(short) a1 = 12
7288+
(short) a2 = 15
7289+
}
7290+
}
7291+
7292+
Note that debuggers may not be able to handle more complex mappings, and so
7293+
this usage is debugger-dependent.
7294+
}];
7295+
}
7296+
72347297
def CleanupDocs : Documentation {
72357298
let Category = DocCatType;
72367299
let Content = [{

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion",
5454
[SingleBitBitFieldConstantConversion]>;
5555
def BitFieldEnumConversion : DiagGroup<"bitfield-enum-conversion">;
5656
def BitFieldWidth : DiagGroup<"bitfield-width">;
57+
def BitFieldType : DiagGroup<"bitfield-type">;
5758
def CompoundTokenSplitByMacro : DiagGroup<"compound-token-split-by-macro">;
5859
def CompoundTokenSplitBySpace : DiagGroup<"compound-token-split-by-space">;
5960
def CompoundTokenSplit : DiagGroup<"compound-token-split",

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3165,6 +3165,9 @@ def err_invalid_branch_protection_spec : Error<
31653165
"invalid or misplaced branch protection specification '%0'">;
31663166
def warn_unsupported_branch_protection_spec : Warning<
31673167
"unsupported branch protection specification '%0'">, InGroup<BranchProtection>;
3168+
def warn_attribute_underlying_type_mismatch : Warning<
3169+
"underlying type %0 of enumeration %1 doesn't match bit-field type %2">,
3170+
InGroup<BitFieldType>;
31683171

31693172
def warn_unsupported_target_attribute
31703173
: Warning<"%select{unsupported|duplicate|unknown}0%select{| CPU|"

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,8 @@ CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl,
14991499
llvm::DIScope *RecordTy, const RecordDecl *RD) {
15001500
StringRef Name = BitFieldDecl->getName();
15011501
QualType Ty = BitFieldDecl->getType();
1502+
if (BitFieldDecl->hasAttr<PreferredTypeAttr>())
1503+
Ty = BitFieldDecl->getAttr<PreferredTypeAttr>()->getType();
15021504
SourceLocation Loc = BitFieldDecl->getLocation();
15031505
llvm::DIFile *VUnit = getOrCreateFile(Loc);
15041506
llvm::DIType *DebugType = getOrCreateType(Ty, VUnit);

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5916,6 +5916,43 @@ static void handleBuiltinAliasAttr(Sema &S, Decl *D,
59165916
D->addAttr(::new (S.Context) BuiltinAliasAttr(S.Context, AL, Ident));
59175917
}
59185918

5919+
static void handlePreferredTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
5920+
if (!AL.hasParsedType()) {
5921+
S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
5922+
return;
5923+
}
5924+
5925+
TypeSourceInfo *ParmTSI = nullptr;
5926+
QualType QT = S.GetTypeFromParser(AL.getTypeArg(), &ParmTSI);
5927+
assert(ParmTSI && "no type source info for attribute argument");
5928+
S.RequireCompleteType(ParmTSI->getTypeLoc().getBeginLoc(), QT,
5929+
diag::err_incomplete_type);
5930+
5931+
if (QT->isEnumeralType()) {
5932+
auto IsCorrespondingType = [&](QualType LHS, QualType RHS) {
5933+
assert(LHS != RHS);
5934+
if (LHS->isSignedIntegerType())
5935+
return LHS == S.getASTContext().getCorrespondingSignedType(RHS);
5936+
return LHS == S.getASTContext().getCorrespondingUnsignedType(RHS);
5937+
};
5938+
QualType BitfieldType =
5939+
cast<FieldDecl>(D)->getType()->getCanonicalTypeUnqualified();
5940+
QualType EnumUnderlyingType = QT->getAs<EnumType>()
5941+
->getDecl()
5942+
->getIntegerType()
5943+
->getCanonicalTypeUnqualified();
5944+
if (EnumUnderlyingType != BitfieldType &&
5945+
!IsCorrespondingType(EnumUnderlyingType, BitfieldType)) {
5946+
S.Diag(ParmTSI->getTypeLoc().getBeginLoc(),
5947+
diag::warn_attribute_underlying_type_mismatch)
5948+
<< EnumUnderlyingType << QT << BitfieldType;
5949+
return;
5950+
}
5951+
}
5952+
5953+
D->addAttr(::new (S.Context) PreferredTypeAttr(S.Context, AL, ParmTSI));
5954+
}
5955+
59195956
//===----------------------------------------------------------------------===//
59205957
// Checker-specific attribute handlers.
59215958
//===----------------------------------------------------------------------===//
@@ -9636,6 +9673,10 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
96369673
handleBuiltinAliasAttr(S, D, AL);
96379674
break;
96389675

9676+
case ParsedAttr::AT_PreferredType:
9677+
handlePreferredTypeAttr(S, D, AL);
9678+
break;
9679+
96399680
case ParsedAttr::AT_UsingIfExists:
96409681
handleSimpleAttribute<UsingIfExistsAttr>(S, D, AL);
96419682
break;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %clang -target x86_64-linux -g -S -emit-llvm -o - %s | FileCheck %s
2+
3+
struct A {
4+
enum E : unsigned {};
5+
[[clang::preferred_type(E)]] unsigned b : 2;
6+
} a;
7+
8+
// CHECK-DAG: [[ENUM:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "E"{{.*}}
9+
// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "b",{{.*}} baseType: [[ENUM]]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -verify %s
2+
3+
struct A {
4+
enum E : unsigned {};
5+
enum E2 : int {};
6+
[[clang::preferred_type(E)]] unsigned b : 2;
7+
[[clang::preferred_type(E)]] int b2 : 2;
8+
[[clang::preferred_type(E2)]] const unsigned b3 : 2;
9+
[[clang::preferred_type(bool)]] unsigned b4 : 1;
10+
[[clang::preferred_type(bool)]] unsigned b5 : 2;
11+
[[clang::preferred_type()]] unsigned b6 : 2;
12+
// expected-error@-1 {{'preferred_type' attribute takes one argument}}
13+
[[clang::preferred_type]] unsigned b7 : 2;
14+
// expected-error@-1 {{'preferred_type' attribute takes one argument}}
15+
[[clang::preferred_type(E, int)]] unsigned b8 : 2;
16+
// expected-error@-1 {{expected ')'}}
17+
// expected-error@-2 {{expected ','}}
18+
// expected-warning@-3 {{unknown attribute 'int' ignored}}
19+
};

compiler-rt/lib/lsan/lsan_allocator.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,42 @@ using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>;
6868
#else
6969
# if SANITIZER_FUCHSIA || defined(__powerpc64__)
7070
const uptr kAllocatorSpace = ~(uptr)0;
71+
# if SANITIZER_RISCV64
72+
// See the comments in compiler-rt/lib/asan/asan_allocator.h for why these
73+
// values were chosen.
74+
const uptr kAllocatorSize = UINT64_C(1) << 33; // 8GB
75+
using LSanSizeClassMap = SizeClassMap</*kNumBits=*/2,
76+
/*kMinSizeLog=*/5,
77+
/*kMidSizeLog=*/8,
78+
/*kMaxSizeLog=*/18,
79+
/*kNumCachedHintT=*/8,
80+
/*kMaxBytesCachedLog=*/10>;
81+
static_assert(LSanSizeClassMap::kNumClassesRounded <= 32,
82+
"32 size classes is the optimal number to ensure tests run "
83+
"effieciently on Fuchsia.");
84+
# else
7185
const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
86+
using LSanSizeClassMap = DefaultSizeClassMap;
87+
# endif
7288
# elif SANITIZER_RISCV64
7389
const uptr kAllocatorSpace = ~(uptr)0;
7490
const uptr kAllocatorSize = 0x2000000000ULL; // 128G.
91+
using LSanSizeClassMap = DefaultSizeClassMap;
7592
# elif SANITIZER_APPLE
7693
const uptr kAllocatorSpace = 0x600000000000ULL;
7794
const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
95+
using LSanSizeClassMap = DefaultSizeClassMap;
7896
# else
7997
const uptr kAllocatorSpace = 0x500000000000ULL;
8098
const uptr kAllocatorSize = 0x40000000000ULL; // 4T.
99+
using LSanSizeClassMap = DefaultSizeClassMap;
81100
# endif
82101
template <typename AddressSpaceViewTy>
83102
struct AP64 { // Allocator64 parameters. Deliberately using a short name.
84103
static const uptr kSpaceBeg = kAllocatorSpace;
85104
static const uptr kSpaceSize = kAllocatorSize;
86105
static const uptr kMetadataSize = sizeof(ChunkMetadata);
87-
typedef DefaultSizeClassMap SizeClassMap;
106+
using SizeClassMap = LSanSizeClassMap;
88107
typedef NoOpMapUnmapCallback MapUnmapCallback;
89108
static const uptr kFlags = 0;
90109
using AddressSpaceView = AddressSpaceViewTy;

llvm/include/llvm/Config/llvm-config.h.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
/* Indicate that this is LLVM compiled from the amd-gfx branch. */
1818
#define LLVM_HAVE_BRANCH_AMD_GFX
19-
#define LLVM_MAIN_REVISION 478372
19+
#define LLVM_MAIN_REVISION 478378
2020

2121
/* Define if LLVM_ENABLE_DUMP is enabled */
2222
#cmakedefine LLVM_ENABLE_DUMP

llvm/lib/Target/RISCV/RISCVInsertVSETVLI.cpp

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,6 @@ class RISCVInsertVSETVLI : public MachineFunctionPass {
746746
const VSETVLIInfo &CurInfo) const;
747747
bool needVSETVLIPHI(const VSETVLIInfo &Require,
748748
const MachineBasicBlock &MBB) const;
749-
bool mayChangeVL(const VSETVLIInfo &Info, const VSETVLIInfo &PrevInfo) const;
750749
void insertVSETVLI(MachineBasicBlock &MBB, MachineInstr &MI,
751750
const VSETVLIInfo &Info, const VSETVLIInfo &PrevInfo);
752751
void insertVSETVLI(MachineBasicBlock &MBB,
@@ -860,47 +859,41 @@ static VSETVLIInfo getInfoForVSETVLI(const MachineInstr &MI) {
860859
return NewInfo;
861860
}
862861

863-
/// Return true if a vsetvli instruction to change from PrevInfo
864-
/// to Info might change the VL register. If this returns false,
865-
/// the vsetvli can use the X0, X0 form.
866-
bool RISCVInsertVSETVLI::mayChangeVL(const VSETVLIInfo &Info,
867-
const VSETVLIInfo &PrevInfo) const {
868-
if (!PrevInfo.isValid() || PrevInfo.isUnknown())
869-
return true;
870-
871-
// If the AVL is the same and the SEW+LMUL gives the same VLMAX, VL
872-
// can not change.
873-
if (Info.hasSameAVL(PrevInfo) && Info.hasSameVLMAX(PrevInfo))
874-
return false;
875-
876-
// If our AVL is a virtual register, it might be defined by a VSET(I)VLI. If
877-
// it has the same VLMAX we want and the last VL/VTYPE we observed is the
878-
// same, then VL can not change.
879-
if (Info.hasSameVLMAX(PrevInfo) && Info.hasAVLReg() &&
880-
Info.getAVLReg().isVirtual()) {
881-
if (MachineInstr *DefMI = MRI->getVRegDef(Info.getAVLReg());
882-
DefMI && isVectorConfigInstr(*DefMI)) {
883-
VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI);
884-
if (DefInfo.hasSameAVL(PrevInfo) && DefInfo.hasSameVLMAX(PrevInfo))
885-
return false;
886-
}
887-
}
888-
return true;
889-
}
890-
891862
void RISCVInsertVSETVLI::insertVSETVLI(MachineBasicBlock &MBB,
892863
MachineBasicBlock::iterator InsertPt, DebugLoc DL,
893864
const VSETVLIInfo &Info, const VSETVLIInfo &PrevInfo) {
894865

895-
// Use X0, X0 form if VL can't change. Changing only VTYPE is generally
896-
// cheaper than changing VL.
897-
if (!mayChangeVL(Info, PrevInfo)) {
898-
BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0))
899-
.addReg(RISCV::X0, RegState::Define | RegState::Dead)
900-
.addReg(RISCV::X0, RegState::Kill)
901-
.addImm(Info.encodeVTYPE())
902-
.addReg(RISCV::VL, RegState::Implicit);
903-
return;
866+
if (PrevInfo.isValid() && !PrevInfo.isUnknown()) {
867+
// Use X0, X0 form if the AVL is the same and the SEW+LMUL gives the same
868+
// VLMAX.
869+
if (Info.hasSameAVL(PrevInfo) && Info.hasSameVLMAX(PrevInfo)) {
870+
BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0))
871+
.addReg(RISCV::X0, RegState::Define | RegState::Dead)
872+
.addReg(RISCV::X0, RegState::Kill)
873+
.addImm(Info.encodeVTYPE())
874+
.addReg(RISCV::VL, RegState::Implicit);
875+
return;
876+
}
877+
878+
// If our AVL is a virtual register, it might be defined by a VSET(I)VLI. If
879+
// it has the same VLMAX we want and the last VL/VTYPE we observed is the
880+
// same, we can use the X0, X0 form.
881+
if (Info.hasSameVLMAX(PrevInfo) && Info.hasAVLReg() &&
882+
Info.getAVLReg().isVirtual()) {
883+
if (MachineInstr *DefMI = MRI->getVRegDef(Info.getAVLReg())) {
884+
if (isVectorConfigInstr(*DefMI)) {
885+
VSETVLIInfo DefInfo = getInfoForVSETVLI(*DefMI);
886+
if (DefInfo.hasSameAVL(PrevInfo) && DefInfo.hasSameVLMAX(PrevInfo)) {
887+
BuildMI(MBB, InsertPt, DL, TII->get(RISCV::PseudoVSETVLIX0))
888+
.addReg(RISCV::X0, RegState::Define | RegState::Dead)
889+
.addReg(RISCV::X0, RegState::Kill)
890+
.addImm(Info.encodeVTYPE())
891+
.addReg(RISCV::VL, RegState::Implicit);
892+
return;
893+
}
894+
}
895+
}
896+
}
904897
}
905898

906899
if (Info.hasAVLImm()) {

llvm/test/Transforms/LoopVectorize/vplan-dot-printing.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ define void @print_call_and_memory(i64 %n, ptr noalias %y, ptr noalias %x) nounw
2626
; CHECK-NEXT: label="\<x1\> vector loop"
2727
; CHECK-NEXT: N2 [label =
2828
; CHECK-NEXT: "vector.body:\l" +
29-
; CHECK-NEXT: " EMIT vp\<[[CAN_IV:%.+]]\> = CANONICAL-INDUCTION ir\<0\>, vp\<%7\>\l" +
29+
; CHECK-NEXT: " EMIT vp\<[[CAN_IV:%.+]]\> = CANONICAL-INDUCTION ir\<0\>, vp\<[[CAN_IV_NEXT:%.+]]\>\l" +
3030
; CHECK-NEXT: " vp\<[[STEPS:%.+]]\> = SCALAR-STEPS vp\<[[CAN_IV]]\>, ir\<1\>\l" +
3131
; CHECK-NEXT: " CLONE ir\<%arrayidx\> = getelementptr inbounds ir\<%y\>, vp\<[[STEPS]]\>\l" +
3232
; CHECK-NEXT: " WIDEN ir\<%lv\> = load ir\<%arrayidx\>\l" +
3333
; CHECK-NEXT: " WIDEN-CALL ir\<%call\> = call @llvm.sqrt.f32(ir\<%lv\>) (using vector intrinsic)\l" +
3434
; CHECK-NEXT: " CLONE ir\<%arrayidx2\> = getelementptr inbounds ir\<%x\>, vp\<[[STEPS]]\>\l" +
3535
; CHECK-NEXT: " WIDEN store ir\<%arrayidx2\>, ir\<%call\>\l" +
36-
; CHECK-NEXT: " EMIT vp\<[[CAN_IV_NEXT:%.+]]\> = VF * UF + nuw vp\<[[CAN_IV]]\>\l" +
36+
; CHECK-NEXT: " EMIT vp\<[[CAN_IV_NEXT]]\> = VF * UF + nuw vp\<[[CAN_IV]]\>\l" +
3737
; CHECK-NEXT: " EMIT branch-on-count vp\<[[CAN_IV_NEXT]]\>, vp\<{{.+}}\>\l" +
3838
; CHECK-NEXT: "No successors\l"
3939
; CHECK-NEXT: ]

0 commit comments

Comments
 (0)