Skip to content

Commit 9ad72df

Browse files
Fznamznonrjmccall
andauthored
[clang] Use different memory layout type for _BitInt(N) in LLVM IR (#91364)
There are two problems with _BitInt prior to this patch: 1. For at least some values of N, we cannot use LLVM's iN for the type of struct elements, array elements, allocas, global variables, and so on, because the LLVM layout for that type does not match the high-level layout of _BitInt(N). Example: Currently for i128:128 targets correct implementation is possible either for __int128 or for _BitInt(129+) with lowering to iN, but not both, since we have now correct implementation of __int128 in place after a21abc7. When this happens, opaque [M x i8] types used, where M = sizeof(_BitInt(N)). 2. LLVM doesn't guarantee any particular extension behavior for integer types that aren't a multiple of 8. For this reason, all _BitInt types are now have in-memory representation that is a whole number of bytes. I.e. for example _BitInt(17) now will have memory layout type i32. This patch also introduces concept of load/store type and adds an API to CodeGenTypes that returns the IR type that should be used for load and store operations. This is particularly useful for the case when a _BitInt ends up having array of bytes as memory layout type. For _BitInt(N), let M = sizeof(_BitInt(N)), and let BITS = M * 8. Loads and stores of iM would both (1) produce far better code from the backends and (2) be far more optimizable by IR passes than loads and stores of [M x i8]. Fixes #85139 Fixes #83419 --------- Co-authored-by: John McCall <[email protected]>
1 parent 9ac2b89 commit 9ad72df

33 files changed

+2579
-2188
lines changed

clang/lib/CodeGen/CGCall.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3863,7 +3863,8 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
38633863
LValue ArgVal =
38643864
LValue::MakeAddr(ArgAddr, RetTy, getContext(), BaseInfo, TBAAInfo);
38653865
EmitStoreOfScalar(
3866-
Builder.CreateLoad(ReturnValue), ArgVal, /*isInit*/ true);
3866+
EmitLoadOfScalar(MakeAddrLValue(ReturnValue, RetTy), EndLoc), ArgVal,
3867+
/*isInit*/ true);
38673868
break;
38683869
}
38693870
}

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "clang/Basic/TargetInfo.h"
3434
#include "clang/CodeGen/CGFunctionInfo.h"
3535
#include "clang/Sema/Sema.h"
36+
#include "llvm/Analysis/ConstantFolding.h"
3637
#include "llvm/Analysis/ValueTracking.h"
3738
#include "llvm/IR/DataLayout.h"
3839
#include "llvm/IR/GlobalVariable.h"
@@ -1969,6 +1970,17 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
19691970
constant = constWithPadding(CGM, IsPattern::No,
19701971
replaceUndef(CGM, isPattern, constant));
19711972
}
1973+
1974+
if (D.getType()->isBitIntType() &&
1975+
CGM.getTypes().typeRequiresSplitIntoByteArray(D.getType())) {
1976+
// Constants for long _BitInt types are split into individual bytes.
1977+
// Try to fold these back into an integer constant so it can be stored
1978+
// properly.
1979+
llvm::Type *LoadType = CGM.getTypes().convertTypeForLoadStore(
1980+
D.getType(), constant->getType());
1981+
constant = llvm::ConstantFoldLoadFromConst(
1982+
constant, LoadType, llvm::APInt::getZero(32), CGM.getDataLayout());
1983+
}
19721984
}
19731985

19741986
if (!constant) {

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,6 +1986,9 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
19861986
return EmitAtomicLoad(AtomicLValue, Loc).getScalarVal();
19871987
}
19881988

1989+
Addr =
1990+
Addr.withElementType(convertTypeForLoadStore(Ty, Addr.getElementType()));
1991+
19891992
llvm::LoadInst *Load = Builder.CreateLoad(Addr, Volatile);
19901993
if (isNontemporal) {
19911994
llvm::MDNode *Node = llvm::MDNode::get(
@@ -2008,27 +2011,33 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(Address Addr, bool Volatile,
20082011
return EmitFromMemory(Load, Ty);
20092012
}
20102013

2014+
/// Converts a scalar value from its primary IR type (as returned
2015+
/// by ConvertType) to its load/store type (as returned by
2016+
/// convertTypeForLoadStore).
20112017
llvm::Value *CodeGenFunction::EmitToMemory(llvm::Value *Value, QualType Ty) {
2012-
// Bool has a different representation in memory than in registers.
2013-
if (hasBooleanRepresentation(Ty)) {
2014-
// This should really always be an i1, but sometimes it's already
2015-
// an i8, and it's awkward to track those cases down.
2016-
if (Value->getType()->isIntegerTy(1))
2017-
return Builder.CreateZExt(Value, ConvertTypeForMem(Ty), "frombool");
2018-
assert(Value->getType()->isIntegerTy(getContext().getTypeSize(Ty)) &&
2019-
"wrong value rep of bool");
2018+
if (hasBooleanRepresentation(Ty) || Ty->isBitIntType()) {
2019+
llvm::Type *StoreTy = convertTypeForLoadStore(Ty, Value->getType());
2020+
bool Signed = Ty->isSignedIntegerOrEnumerationType();
2021+
return Builder.CreateIntCast(Value, StoreTy, Signed, "storedv");
2022+
}
2023+
2024+
if (Ty->isExtVectorBoolType()) {
2025+
llvm::Type *StoreTy = convertTypeForLoadStore(Ty, Value->getType());
2026+
// Expand to the memory bit width.
2027+
unsigned MemNumElems = StoreTy->getPrimitiveSizeInBits();
2028+
// <N x i1> --> <P x i1>.
2029+
Value = emitBoolVecConversion(Value, MemNumElems, "insertvec");
2030+
// <P x i1> --> iP.
2031+
Value = Builder.CreateBitCast(Value, StoreTy);
20202032
}
20212033

20222034
return Value;
20232035
}
20242036

2037+
/// Converts a scalar value from its load/store type (as returned
2038+
/// by convertTypeForLoadStore) to its primary IR type (as returned
2039+
/// by ConvertType).
20252040
llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
2026-
// Bool has a different representation in memory than in registers.
2027-
if (hasBooleanRepresentation(Ty)) {
2028-
assert(Value->getType()->isIntegerTy(getContext().getTypeSize(Ty)) &&
2029-
"wrong value rep of bool");
2030-
return Builder.CreateTrunc(Value, Builder.getInt1Ty(), "tobool");
2031-
}
20322041
if (Ty->isExtVectorBoolType()) {
20332042
const auto *RawIntTy = Value->getType();
20342043
// Bitcast iP --> <P x i1>.
@@ -2041,6 +2050,11 @@ llvm::Value *CodeGenFunction::EmitFromMemory(llvm::Value *Value, QualType Ty) {
20412050
return emitBoolVecConversion(V, ValNumElems, "extractvec");
20422051
}
20432052

2053+
if (hasBooleanRepresentation(Ty) || Ty->isBitIntType()) {
2054+
llvm::Type *ResTy = ConvertType(Ty);
2055+
return Builder.CreateTrunc(Value, ResTy, "loadedv");
2056+
}
2057+
20442058
return Value;
20452059
}
20462060

@@ -2093,17 +2107,10 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, Address Addr,
20932107
llvm::Type *SrcTy = Value->getType();
20942108
if (const auto *ClangVecTy = Ty->getAs<VectorType>()) {
20952109
auto *VecTy = dyn_cast<llvm::FixedVectorType>(SrcTy);
2096-
if (VecTy && ClangVecTy->isExtVectorBoolType()) {
2097-
auto *MemIntTy = cast<llvm::IntegerType>(Addr.getElementType());
2098-
// Expand to the memory bit width.
2099-
unsigned MemNumElems = MemIntTy->getPrimitiveSizeInBits();
2100-
// <N x i1> --> <P x i1>.
2101-
Value = emitBoolVecConversion(Value, MemNumElems, "insertvec");
2102-
// <P x i1> --> iP.
2103-
Value = Builder.CreateBitCast(Value, MemIntTy);
2104-
} else if (!CGM.getCodeGenOpts().PreserveVec3Type) {
2110+
if (!CGM.getCodeGenOpts().PreserveVec3Type) {
21052111
// Handle vec3 special.
2106-
if (VecTy && cast<llvm::FixedVectorType>(VecTy)->getNumElements() == 3) {
2112+
if (VecTy && !ClangVecTy->isExtVectorBoolType() &&
2113+
cast<llvm::FixedVectorType>(VecTy)->getNumElements() == 3) {
21072114
// Our source is a vec3, do a shuffle vector to make it a vec4.
21082115
Value = Builder.CreateShuffleVector(Value, ArrayRef<int>{0, 1, 2, -1},
21092116
"extractVec");
@@ -2477,7 +2484,7 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
24772484
void CodeGenFunction::EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst,
24782485
llvm::Value **Result) {
24792486
const CGBitFieldInfo &Info = Dst.getBitFieldInfo();
2480-
llvm::Type *ResLTy = ConvertTypeForMem(Dst.getType());
2487+
llvm::Type *ResLTy = convertTypeForLoadStore(Dst.getType());
24812488
Address Ptr = Dst.getBitFieldAddress();
24822489

24832490
// Get the source value, truncated to the width of the bit-field.

clang/lib/CodeGen/CGExprConstant.cpp

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ class ConstStructBuilder {
585585
bool AllowOverwrite = false);
586586

587587
bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
588-
llvm::ConstantInt *InitExpr, bool AllowOverwrite = false);
588+
llvm::Constant *InitExpr, bool AllowOverwrite = false);
589589

590590
bool Build(const InitListExpr *ILE, bool AllowOverwrite);
591591
bool Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,
@@ -609,9 +609,25 @@ bool ConstStructBuilder::AppendBytes(CharUnits FieldOffsetInChars,
609609
return Builder.add(InitCst, StartOffset + FieldOffsetInChars, AllowOverwrite);
610610
}
611611

612-
bool ConstStructBuilder::AppendBitField(
613-
const FieldDecl *Field, uint64_t FieldOffset, llvm::ConstantInt *CI,
614-
bool AllowOverwrite) {
612+
bool ConstStructBuilder::AppendBitField(const FieldDecl *Field,
613+
uint64_t FieldOffset, llvm::Constant *C,
614+
bool AllowOverwrite) {
615+
616+
llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C);
617+
if (!CI) {
618+
// Constants for long _BitInt types are sometimes split into individual
619+
// bytes. Try to fold these back into an integer constant. If that doesn't
620+
// work out, then we are trying to initialize a bitfield with a non-trivial
621+
// constant, this must require run-time code.
622+
llvm::Type *LoadType =
623+
CGM.getTypes().convertTypeForLoadStore(Field->getType(), C->getType());
624+
llvm::Constant *FoldedConstant = llvm::ConstantFoldLoadFromConst(
625+
C, LoadType, llvm::APInt::getZero(32), CGM.getDataLayout());
626+
CI = dyn_cast_if_present<llvm::ConstantInt>(FoldedConstant);
627+
if (!CI)
628+
return false;
629+
}
630+
615631
const CGRecordLayout &RL =
616632
CGM.getTypes().getCGRecordLayout(Field->getParent());
617633
const CGBitFieldInfo &Info = RL.getBitFieldInfo(Field);
@@ -762,15 +778,9 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
762778
AllowOverwrite = true;
763779
} else {
764780
// Otherwise we have a bitfield.
765-
if (auto *CI = dyn_cast<llvm::ConstantInt>(EltInit)) {
766-
if (!AppendBitField(Field, Layout.getFieldOffset(FieldNo), CI,
767-
AllowOverwrite))
768-
return false;
769-
} else {
770-
// We are trying to initialize a bitfield with a non-trivial constant,
771-
// this must require run-time code.
781+
if (!AppendBitField(Field, Layout.getFieldOffset(FieldNo), EltInit,
782+
AllowOverwrite))
772783
return false;
773-
}
774784
}
775785
}
776786

@@ -871,7 +881,7 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
871881
} else {
872882
// Otherwise we have a bitfield.
873883
if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo) + OffsetBits,
874-
cast<llvm::ConstantInt>(EltInit), AllowOverwrite))
884+
EltInit, AllowOverwrite))
875885
return false;
876886
}
877887
}
@@ -1888,6 +1898,27 @@ llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM,
18881898
return Res;
18891899
}
18901900

1901+
if (destType->isBitIntType()) {
1902+
ConstantAggregateBuilder Builder(CGM);
1903+
llvm::Type *LoadStoreTy = CGM.getTypes().convertTypeForLoadStore(destType);
1904+
// ptrtoint/inttoptr should not involve _BitInt in constant expressions, so
1905+
// casting to ConstantInt is safe here.
1906+
auto *CI = cast<llvm::ConstantInt>(C);
1907+
llvm::Constant *Res = llvm::ConstantFoldCastOperand(
1908+
destType->isSignedIntegerOrEnumerationType() ? llvm::Instruction::SExt
1909+
: llvm::Instruction::ZExt,
1910+
CI, LoadStoreTy, CGM.getDataLayout());
1911+
if (CGM.getTypes().typeRequiresSplitIntoByteArray(destType, C->getType())) {
1912+
// Long _BitInt has array of bytes as in-memory type.
1913+
// So, split constant into individual bytes.
1914+
llvm::Type *DesiredTy = CGM.getTypes().ConvertTypeForMem(destType);
1915+
llvm::APInt Value = cast<llvm::ConstantInt>(Res)->getValue();
1916+
Builder.addBits(Value, /*OffsetInBits=*/0, /*AllowOverwrite=*/false);
1917+
return Builder.build(DesiredTy, /*AllowOversized*/ false);
1918+
}
1919+
return Res;
1920+
}
1921+
18911922
return C;
18921923
}
18931924

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,9 +436,10 @@ class ScalarExprEmitter
436436

437437
if (Value *Result = ConstantEmitter(CGF).tryEmitConstantExpr(E)) {
438438
if (E->isGLValue())
439-
return CGF.Builder.CreateLoad(Address(
440-
Result, CGF.ConvertTypeForMem(E->getType()),
441-
CGF.getContext().getTypeAlignInChars(E->getType())));
439+
return CGF.EmitLoadOfScalar(
440+
Address(Result, CGF.convertTypeForLoadStore(E->getType()),
441+
CGF.getContext().getTypeAlignInChars(E->getType())),
442+
/*Volatile*/ false, E->getType(), E->getExprLoc());
442443
return Result;
443444
}
444445
return Visit(E->getSubExpr());

clang/lib/CodeGen/CGRecordLayoutBuilder.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,8 +427,7 @@ CGRecordLowering::accumulateBitFields(bool isNonVirtualBaseType,
427427
continue;
428428
}
429429
uint64_t BitOffset = getFieldBitOffset(*Field);
430-
llvm::Type *Type =
431-
Types.ConvertTypeForMem(Field->getType(), /*ForBitField=*/true);
430+
llvm::Type *Type = Types.ConvertTypeForMem(Field->getType());
432431
// If we don't have a run yet, or don't live within the previous run's
433432
// allocated storage then we allocate some storage and start a new run.
434433
if (Run == FieldEnd || BitOffset >= Tail) {

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,9 +1537,15 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
15371537
Builder.CreateStore(Result.getScalarVal(), ReturnValue);
15381538
} else {
15391539
switch (getEvaluationKind(RV->getType())) {
1540-
case TEK_Scalar:
1541-
Builder.CreateStore(EmitScalarExpr(RV), ReturnValue);
1540+
case TEK_Scalar: {
1541+
llvm::Value *Ret = EmitScalarExpr(RV);
1542+
if (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect)
1543+
EmitStoreOfScalar(Ret, MakeAddrLValue(ReturnValue, RV->getType()),
1544+
/*isInit*/ true);
1545+
else
1546+
Builder.CreateStore(Ret, ReturnValue);
15421547
break;
1548+
}
15431549
case TEK_Complex:
15441550
EmitComplexExprIntoLValue(RV, MakeAddrLValue(ReturnValue, RV->getType()),
15451551
/*isInit*/ true);

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,11 @@ llvm::Type *CodeGenFunction::ConvertType(QualType T) {
233233
return CGM.getTypes().ConvertType(T);
234234
}
235235

236+
llvm::Type *CodeGenFunction::convertTypeForLoadStore(QualType ASTTy,
237+
llvm::Type *LLVMTy) {
238+
return CGM.getTypes().convertTypeForLoadStore(ASTTy, LLVMTy);
239+
}
240+
236241
TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) {
237242
type = type.getCanonicalType();
238243
while (true) {

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2576,6 +2576,8 @@ class CodeGenFunction : public CodeGenTypeCache {
25762576

25772577
llvm::Type *ConvertTypeForMem(QualType T);
25782578
llvm::Type *ConvertType(QualType T);
2579+
llvm::Type *convertTypeForLoadStore(QualType ASTTy,
2580+
llvm::Type *LLVMTy = nullptr);
25792581
llvm::Type *ConvertType(const TypeDecl *T) {
25802582
return ConvertType(getContext().getTypeDeclType(T));
25812583
}

clang/lib/CodeGen/CodeGenTypes.cpp

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,14 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD,
8989
/// ConvertType in that it is used to convert to the memory representation for
9090
/// a type. For example, the scalar representation for _Bool is i1, but the
9191
/// memory representation is usually i8 or i32, depending on the target.
92-
llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T, bool ForBitField) {
92+
///
93+
/// We generally assume that the alloc size of this type under the LLVM
94+
/// data layout is the same as the size of the AST type. The alignment
95+
/// does not have to match: Clang should always use explicit alignments
96+
/// and packed structs as necessary to produce the layout it needs.
97+
/// But the size does need to be exactly right or else things like struct
98+
/// layout will break.
99+
llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) {
93100
if (T->isConstantMatrixType()) {
94101
const Type *Ty = Context.getCanonicalType(T).getTypePtr();
95102
const ConstantMatrixType *MT = cast<ConstantMatrixType>(Ty);
@@ -107,17 +114,65 @@ llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T, bool ForBitField) {
107114
return llvm::IntegerType::get(FixedVT->getContext(), BytePadded);
108115
}
109116

110-
// If this is a bool type, or a bit-precise integer type in a bitfield
111-
// representation, map this integer to the target-specified size.
112-
if ((ForBitField && T->isBitIntType()) ||
113-
(!T->isBitIntType() && R->isIntegerTy(1)))
117+
// If T is _Bool or a _BitInt type, ConvertType will produce an IR type
118+
// with the exact semantic bit-width of the AST type; for example,
119+
// _BitInt(17) will turn into i17. In memory, however, we need to store
120+
// such values extended to their full storage size as decided by AST
121+
// layout; this is an ABI requirement. Ideally, we would always use an
122+
// integer type that's just the bit-size of the AST type; for example, if
123+
// sizeof(_BitInt(17)) == 4, _BitInt(17) would turn into i32. That is what's
124+
// returned by convertTypeForLoadStore. However, that type does not
125+
// always satisfy the size requirement on memory representation types
126+
// describe above. For example, a 32-bit platform might reasonably set
127+
// sizeof(_BitInt(65)) == 12, but i96 is likely to have to have an alloc size
128+
// of 16 bytes in the LLVM data layout. In these cases, we simply return
129+
// a byte array of the appropriate size.
130+
if (T->isBitIntType()) {
131+
if (typeRequiresSplitIntoByteArray(T, R))
132+
return llvm::ArrayType::get(CGM.Int8Ty,
133+
Context.getTypeSizeInChars(T).getQuantity());
134+
return llvm::IntegerType::get(getLLVMContext(),
135+
(unsigned)Context.getTypeSize(T));
136+
}
137+
138+
if (R->isIntegerTy(1))
114139
return llvm::IntegerType::get(getLLVMContext(),
115140
(unsigned)Context.getTypeSize(T));
116141

117142
// Else, don't map it.
118143
return R;
119144
}
120145

146+
bool CodeGenTypes::typeRequiresSplitIntoByteArray(QualType ASTTy,
147+
llvm::Type *LLVMTy) {
148+
if (!LLVMTy)
149+
LLVMTy = ConvertType(ASTTy);
150+
151+
CharUnits ASTSize = Context.getTypeSizeInChars(ASTTy);
152+
CharUnits LLVMSize =
153+
CharUnits::fromQuantity(getDataLayout().getTypeAllocSize(LLVMTy));
154+
return ASTSize != LLVMSize;
155+
}
156+
157+
llvm::Type *CodeGenTypes::convertTypeForLoadStore(QualType T,
158+
llvm::Type *LLVMTy) {
159+
if (!LLVMTy)
160+
LLVMTy = ConvertType(T);
161+
162+
if (T->isBitIntType())
163+
return llvm::Type::getIntNTy(
164+
getLLVMContext(), Context.getTypeSizeInChars(T).getQuantity() * 8);
165+
166+
if (LLVMTy->isIntegerTy(1))
167+
return llvm::IntegerType::get(getLLVMContext(),
168+
(unsigned)Context.getTypeSize(T));
169+
170+
if (T->isExtVectorBoolType())
171+
return ConvertTypeForMem(T);
172+
173+
return LLVMTy;
174+
}
175+
121176
/// isRecordLayoutComplete - Return true if the specified type is already
122177
/// completely laid out.
123178
bool CodeGenTypes::isRecordLayoutComplete(const Type *Ty) const {

0 commit comments

Comments
 (0)