diff options
author | JF Bastien <jfb@google.com> | 2013-05-17 23:49:01 +0000 |
---|---|---|
committer | JF Bastien <jfb@google.com> | 2013-05-17 23:49:01 +0000 |
commit | bab06ba696694e7f62f964af7ee5290a13f78340 (patch) | |
tree | 5e253bd087fd639188bf69b6b15a9cc9604c88d7 /lib/Target/ARM | |
parent | 637cb17a3d65b46f48ae8dfd012057e6c9d00c2b (diff) | |
download | llvm-bab06ba696694e7f62f964af7ee5290a13f78340.tar.gz llvm-bab06ba696694e7f62f964af7ee5290a13f78340.tar.bz2 llvm-bab06ba696694e7f62f964af7ee5290a13f78340.tar.xz |
Support unaligned load/store on more ARM targets
This patch matches GCC behavior: the code used to only allow unaligned
load/store on ARM for v6+ Darwin, it will now allow unaligned load/store
for v6+ Darwin as well as for v7+ on Linux and NaCl.
The distinction is made because v6 doesn't guarantee support (but LLVM
assumes that Apple controls hardware+kernel and therefore have
conformant v6 CPUs), whereas v7 does provide this guarantee (and
Linux/NaCl behave sanely).
The patch keeps the -arm-strict-align command line option, and adds
-arm-no-strict-align. They behave similarly to GCC's -mstrict-align and
-mnostrict-align.
I originally encountered this discrepancy in FastIsel tests which expect
unaligned load/store generation. Overall this should slightly improve
performance in most cases because of reduced I$ pressure.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182175 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM')
-rw-r--r-- | lib/Target/ARM/ARMSubtarget.cpp | 51 | ||||
-rw-r--r-- | lib/Target/ARM/ARMSubtarget.h | 5 |
2 files changed, 46 insertions, 10 deletions
diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index 8653c462f0..c7d9743790 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -38,9 +38,24 @@ static cl::opt<bool> UseFusedMulOps("arm-use-mulops", cl::init(true), cl::Hidden); -static cl::opt<bool> -StrictAlign("arm-strict-align", cl::Hidden, - cl::desc("Disallow all unaligned memory accesses")); +enum AlignMode { + DefaultAlign, + StrictAlign, + NoStrictAlign +}; + +static cl::opt<AlignMode> +Align(cl::desc("Load/store alignment support"), + cl::Hidden, cl::init(DefaultAlign), + cl::values( + clEnumValN(DefaultAlign, "arm-default-align", + "Generate unaligned accesses only on hardware/OS " + "combinations that are known to support them"), + clEnumValN(StrictAlign, "arm-strict-align", + "Disallow all unaligned memory accesses"), + clEnumValN(NoStrictAlign, "arm-no-strict-align", + "Allow unaligned memory accesses"), + clEnumValEnd)); ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, const TargetOptions &Options) @@ -162,10 +177,32 @@ void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) { if (!isThumb() || hasThumb2()) PostRAScheduler = true; - // v6+ may or may not support unaligned mem access depending on the system - // configuration. - if (!StrictAlign && hasV6Ops() && isTargetDarwin()) - AllowsUnalignedMem = true; + switch (Align) { + case DefaultAlign: + // Assume pre-ARMv6 doesn't support unaligned accesses. + // + // ARMv6 may or may not support unaligned accesses depending on the + // SCTLR.U bit, which is architecture-specific. We assume ARMv6 + // Darwin targets support unaligned accesses, and others don't. + // + // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit + // which raises an alignment fault on unaligned accesses. Linux + // defaults this bit to 0 and handles it as a system-wide (not + // per-process) setting. It is therefore safe to assume that ARMv7+ + // Linux targets support unaligned accesses. The same goes for NaCl. + // + // The above behavior is consistent with GCC. + AllowsUnalignedMem = ( + (hasV7Ops() && (isTargetLinux() || isTargetNaCl())) || + (hasV6Ops() && isTargetDarwin())); + break; + case StrictAlign: + AllowsUnalignedMem = false; + break; + case NoStrictAlign: + AllowsUnalignedMem = true; + break; + } // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. uint64_t Bits = getFeatureBits(); diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h index 038eb76ae1..d01316511c 100644 --- a/lib/Target/ARM/ARMSubtarget.h +++ b/lib/Target/ARM/ARMSubtarget.h @@ -270,9 +270,8 @@ public: bool isTargetIOS() const { return TargetTriple.getOS() == Triple::IOS; } bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); } - bool isTargetNaCl() const { - return TargetTriple.getOS() == Triple::NaCl; - } + bool isTargetNaCl() const { return TargetTriple.getOS() == Triple::NaCl; } + bool isTargetLinux() const { return TargetTriple.getOS() == Triple::Linux; } bool isTargetELF() const { return !isTargetDarwin(); } bool isAPCS_ABI() const { return TargetABI == ARM_ABI_APCS; } |