[CodeGen] Increase applicability of ffine-grained-bitfield-accesses for targets with limited native integer widths

As pointed out in PR45708, -ffine-grained-bitfield-accesses doesn't
trigger in all cases you think it might for RISC-V. The logic in
CGRecordLowering::accumulateBitFields checks OffsetInRecord is a legal
integer according to the datalayout. RISC targets will typically only
have the native width as a legal integer type so this check will fail
for OffsetInRecord of 8 or 16 when you would expect the transformation
is still worthwhile.

This patch changes the logic to check for an OffsetInRecord of a at
least 1 byte, that fits in a legal integer, and is a power of 2. We
would prefer to query whether native load/store operations are
available, but I don't believe that is possible.

Differential Revision: https://reviews.llvm.org/D79155
This commit is contained in:
Alex Bradbury 2020-06-12 10:26:53 +01:00
parent f257c2138f
commit 3dcfd482cb
2 changed files with 15 additions and 6 deletions

View File

@ -406,15 +406,17 @@ CGRecordLowering::accumulateBitFields(RecordDecl::field_iterator Field,
return;
}
// Check if OffsetInRecord is better as a single field run. When OffsetInRecord
// has legal integer width, and its bitfield offset is naturally aligned, it
// is better to make the bitfield a separate storage component so as it can be
// accessed directly with lower cost.
// Check if OffsetInRecord (the size in bits of the current run) is better
// as a single field run. When OffsetInRecord has legal integer width, and
// its bitfield offset is naturally aligned, it is better to make the
// bitfield a separate storage component so as it can be accessed directly
// with lower cost.
auto IsBetterAsSingleFieldRun = [&](uint64_t OffsetInRecord,
uint64_t StartBitOffset) {
if (!Types.getCodeGenOpts().FineGrainedBitfieldAccesses)
return false;
if (!DataLayout.isLegalInteger(OffsetInRecord))
if (OffsetInRecord < 8 || !llvm::isPowerOf2_64(OffsetInRecord) ||
!DataLayout.fitsInLegalInteger(OffsetInRecord))
return false;
// Make sure StartBitOffset is natually aligned if it is treated as an
// IType integer.

View File

@ -1,5 +1,12 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -ffine-grained-bitfield-accesses \
// RUN: -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple riscv64-linux-gnu -ffine-grained-bitfield-accesses \
// RUN: -emit-llvm -o - %s | FileCheck %s
// Note: This test checks the X86-64 and RISC-V targets in order to explore
// behaviour when i8/i16 are native integer widths (X86-64) and when they're
// not (RISC-V).
struct S4 {
unsigned long f1:28;
unsigned long f2:4;