]> granicus.if.org Git - clang/commitdiff
IRgen: Add a -fuse-register-sized-bitfield-access option, for testing.
authorDaniel Dunbar <daniel@zuster.org>
Tue, 21 Jun 2011 18:54:46 +0000 (18:54 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Tue, 21 Jun 2011 18:54:46 +0000 (18:54 +0000)
 - Changes bit-field access policy to try to use (aligned) register sized accesses.

The idea here is that by using larger accesses we expose more coalescing
potential to the backend when we have situations like adjacent bit-fields in the
same structure (which is common), and that the backend should be smart enough to
narrow the accesses down when no coalescing is done or when it is shown not to
be profitable.

--
$ clang -m32 -O3 -S -o - t.c
_f0:                                    ## @f0
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
movb (%eax), %cl
andb $-128, %cl
orb $1, %cl
movb %cl, (%eax)
movb 1(%eax), %cl
andb $-128, %cl
orb $1, %cl
movb %cl, 1(%eax)
movb 2(%eax), %cl
andb $-128, %cl
orb $1, %cl
movb %cl, 2(%eax)
movb 3(%eax), %cl
andb $-128, %cl
orb $1, %cl
movb %cl, 3(%eax)
popl %ebp
ret

$ clang -m32 -O3 -S -o - t.c -Xclang -fuse-register-sized-bitfield-access
_f0:                                    ## @f0
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
movl $-2139062144, %ecx      ## imm = 0xFFFFFFFF80808080
andl (%eax), %ecx
orl $16843009, %ecx         ## imm = 0x1010101
movl %ecx, (%eax)
popl %ebp
ret
--

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133532 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Driver/CC1Options.td
include/clang/Frontend/CodeGenOptions.h
lib/CodeGen/CGRecordLayoutBuilder.cpp
lib/Frontend/CompilerInvocation.cpp

index 442a3edebd68b1173cb46963f2d91e5228d9e772..9d2083258a9fbf8369856fe834d99a09fb4db48f 100644 (file)
@@ -143,6 +143,8 @@ def femit_coverage_data: Flag<"-femit-coverage-data">,
 def coverage_file : Separate<"-coverage-file">,
   HelpText<"Emit coverage data to this filename. The extension will be replaced.">;
 def coverage_file_EQ : Joined<"-coverage-file=">, Alias<coverage_file>;
+def fuse_register_sized_bitfield_access: Flag<"-fuse-register-sized-bitfield-access">,
+  HelpText<"Use register sized accesses to bit-fields, when possible.">;
 def relaxed_aliasing : Flag<"-relaxed-aliasing">,
   HelpText<"Turn off Type Based Alias Analysis">;
 def masm_verbose : Flag<"-masm-verbose">,
index 83be6f770fb0cfd025db1a3b4987a427e20c181f..2191980b955b90e284a3b53b025ce8c03ca05eb8 100644 (file)
@@ -91,6 +91,11 @@ public:
   unsigned UnrollLoops       : 1; /// Control whether loops are unrolled.
   unsigned UnsafeFPMath      : 1; /// Allow unsafe floating point optzns.
   unsigned UnwindTables      : 1; /// Emit unwind tables.
+
+  /// Attempt to use register sized accesses to bit-fields in structures, when
+  /// possible.
+  unsigned UseRegisterSizedBitfieldAccess : 1;
+
   unsigned VerifyModule      : 1; /// Control whether the module should be run
                                   /// through the LLVM Verifier.
 
@@ -176,6 +181,7 @@ public:
     UnrollLoops = 0;
     UnsafeFPMath = 0;
     UnwindTables = 0;
+    UseRegisterSizedBitfieldAccess = 0;
     VerifyModule = 1;
 
     Inlining = NoInlining;
index 0d72f854ba3e0e5e8387c50c014fa13f82047937..6daf2ea371ce6c71ced58fc475530a5ca05bb1d3 100644 (file)
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecordLayout.h"
+#include "clang/Frontend/CodeGenOptions.h"
 #include "CodeGenTypes.h"
 #include "CGCXXABI.h"
 #include "llvm/DerivedTypes.h"
@@ -268,6 +269,18 @@ CGBitFieldInfo CGBitFieldInfo::MakeInfo(CodeGenTypes &Types,
   unsigned AccessedTargetBits = 0;       // The number of target bits accessed.
   unsigned AccessWidth = TypeSizeInBits; // The current access width to attempt.
 
+  // If requested, widen the initial bit-field access to be register sized. The
+  // theory is that this is most likely to allow multiple accesses into the same
+  // structure to be coalesced, and that the backend should be smart enough to
+  // narrow the store if no coalescing is ever done.
+  //
+  // The subsequent code will handle align these access to common boundaries and
+  // guaranteeing that we do not access past the end of the structure.
+  if (Types.getCodeGenOpts().UseRegisterSizedBitfieldAccess) {
+    if (AccessWidth < Types.getTarget().getRegisterWidth())
+      AccessWidth = Types.getTarget().getRegisterWidth();
+  }
+
   // Round down from the field offset to find the first access position that is
   // at an aligned offset of the initial access type.
   uint64_t AccessStart = FieldOffset - (FieldOffset % AccessWidth);
index 977f351e422326a27dc9dfdcb7062c1443d9bf71..61887e8eb2a5cdc83624cfddd828142683248734 100644 (file)
@@ -133,6 +133,8 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts,
     Res.push_back("-fno-common");
   if (Opts.ForbidGuardVariables)
     Res.push_back("-fforbid-guard-variables");
+  if (Opts.UseRegisterSizedBitfieldAccess)
+    Res.push_back("-fuse-register-sized-bitfield-access");
   if (Opts.NoImplicitFloat)
     Res.push_back("-no-implicit-float");
   if (Opts.OmitLeafFramePointer)
@@ -956,6 +958,8 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
   Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns);
   Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
   Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables);
+  Opts.UseRegisterSizedBitfieldAccess = Args.hasArg(
+    OPT_fuse_register_sized_bitfield_access);
   Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing);
   Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
   Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);