diff options
author | Oliver Stannard <oliver.stannard@arm.com> | 2018-02-12 17:03:11 +0000 |
---|---|---|
committer | Oliver Stannard <oliver.stannard@arm.com> | 2018-02-12 17:03:11 +0000 |
commit | 4c334a7e90d67fcf422fb1f462fad3e26720a301 (patch) | |
tree | 521b7661a3d4044e6a9c661b4080b46d7b9f5a0e /lib/Target/AArch64/AArch64InstrAtomics.td | |
parent | ca78a8c1842878c2b5f85c29989fd01d8217ca16 (diff) |
[AArch64] Improve v8.1-A code-gen for atomic load-and
Armv8.1-A added an atomic load-clear instruction (which performs bitwise
and with the complement of it's operand), but not a load-and
instruction. Our current code-generation for atomic load-and always
inserts an MVN instruction to invert its argument, even if it could be
folded into a constant or another instruction.
This adds lowering early in selection DAG to convert a load-and
operation into an xor with -1 and a load-clear, allowing the normal DAG
optimisations to work on it.
To do this, I've had to add a new ISD opcode, ATOMIC_LOAD_CLR. I don't
see any easy way to do this with an AArch64-specific ISD node, because
the code-generation for atomic operations assumes the SDNodes are of
type AtomicSDNode.
I've left the old tablegen patterns in because they are still needed for
global isel.
Differential revision: https://reviews.llvm.org/D42478
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@324908 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/AArch64/AArch64InstrAtomics.td')
-rw-r--r-- | lib/Target/AArch64/AArch64InstrAtomics.td | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/lib/Target/AArch64/AArch64InstrAtomics.td b/lib/Target/AArch64/AArch64InstrAtomics.td index 153bcf75cbc..35cd7735ceb 100644 --- a/lib/Target/AArch64/AArch64InstrAtomics.td +++ b/lib/Target/AArch64/AArch64InstrAtomics.td @@ -409,13 +409,18 @@ let Predicates = [HasLSE] in { defm : LDOPregister_patterns<"LDADD", "atomic_load_add">; defm : LDOPregister_patterns<"LDSET", "atomic_load_or">; defm : LDOPregister_patterns<"LDEOR", "atomic_load_xor">; + defm : LDOPregister_patterns<"LDCLR", "atomic_load_clr">; defm : LDOPregister_patterns<"LDSMAX", "atomic_load_max">; defm : LDOPregister_patterns<"LDSMIN", "atomic_load_min">; defm : LDOPregister_patterns<"LDUMAX", "atomic_load_umax">; defm : LDOPregister_patterns<"LDUMIN", "atomic_load_umin">; defm : LDOPregister_patterns<"SWP", "atomic_swap">; + defm : CASregister_patterns<"CAS", "atomic_cmp_swap">; + + // These two patterns are only needed for global isel, selection dag isel + // converts atomic load-sub into a sub and atomic load-add, and likewise for + // and -> clr. defm : LDOPregister_patterns_mod<"LDADD", "atomic_load_sub", "SUB">; defm : LDOPregister_patterns_mod<"LDCLR", "atomic_load_and", "ORN">; - defm : CASregister_patterns<"CAS", "atomic_cmp_swap">; } |