You've already forked linux-packaging-mono
acceptance-tests
data
debian
docs
external
Newtonsoft.Json
api-doc-tools
api-snapshot
aspnetwebstack
bdwgc
binary-reference-assemblies
bockbuild
boringssl
cecil
cecil-legacy
corefx
corert
helix-binaries
ikdasm
ikvm
illinker-test-assets
linker
llvm-project
clang
clang-tools-extra
compiler-rt
libcxx
libcxxabi
libunwind
lld
lldb
llvm
bindings
cmake
docs
examples
include
lib
projects
resources
runtimes
scripts
test
Analysis
Assembler
Bindings
Bitcode
BugPoint
CodeGen
AArch64
AMDGPU
ARC
ARM
GlobalISel
Windows
2006-11-10-CycleInDAG.ll
2007-01-19-InfiniteLoop.ll
2007-03-07-CombinerCrash.ll
2007-03-13-InstrSched.ll
2007-03-21-JoinIntervalsCrash.ll
2007-03-27-RegScavengerAssert.ll
2007-03-30-RegScavengerAssert.ll
2007-04-02-RegScavengerAssert.ll
2007-04-03-PEIBug.ll
2007-04-03-UndefinedSymbol.ll
2007-04-30-CombinerCrash.ll
2007-05-03-BadPostIndexedLd.ll
2007-05-07-tailmerge-1.ll
2007-05-09-tailmerge-2.ll
2007-05-14-InlineAsmCstCrash.ll
2007-05-14-RegScavengerAssert.ll
2007-05-22-tailmerge-3.ll
2007-05-23-BadPreIndexedStore.ll
2007-08-15-ReuseBug.ll
2008-02-04-LocalRegAllocBug.ll
2008-02-29-RegAllocLocal.ll
2008-03-05-SxtInRegBug.ll
2008-03-07-RegScavengerAssert.ll
2008-04-04-ScavengerAssert.ll
2008-04-10-ScavengerAssert.ll
2008-04-11-PHIofImpDef.ll.REMOVED.git-id
2008-05-19-LiveIntervalsBug.ll
2008-05-19-ScavengerAssert.ll
2008-07-17-Fdiv.ll
2008-07-24-CodeGenPrepCrash.ll
2008-08-07-AsmPrintBug.ll
2008-09-17-CoalescerBug.ll
2008-11-18-ScavengerAssert.ll
2009-02-16-SpillerBug.ll
2009-02-22-SoftenFloatVaArg.ll
2009-02-27-SpillerBug.ll
2009-03-07-SpillerBug.ll
2009-03-09-AddrModeBug.ll
2009-04-06-AsmModifier.ll
2009-04-08-AggregateAddr.ll
2009-04-08-FREM.ll
2009-04-08-FloatUndef.ll
2009-04-09-RegScavengerAsm.ll
2009-05-05-DAGCombineBug.ll
2009-05-07-RegAllocLocal.ll
2009-05-11-CodePlacementCrash.ll
2009-05-18-InlineAsmMem.ll
2009-06-02-ISelCrash.ll
2009-06-04-MissingLiveIn.ll
2009-06-15-RegScavengerAssert.ll
2009-06-19-RegScavengerAssert.ll
2009-06-22-CoalescerBug.ll
2009-06-30-RegScavengerAssert.ll
2009-06-30-RegScavengerAssert2.ll
2009-06-30-RegScavengerAssert3.ll
2009-06-30-RegScavengerAssert4.ll
2009-06-30-RegScavengerAssert5.ll
2009-07-01-CommuteBug.ll
2009-07-09-asm-p-constraint.ll
2009-07-18-RewriterBug.ll
2009-07-22-ScavengerAssert.ll
2009-07-22-SchedulerAssert.ll
2009-07-29-VFP3Registers.ll
2009-08-02-RegScavengerAssert-Neon.ll
2009-08-04-RegScavengerAssert-2.ll
2009-08-04-RegScavengerAssert.ll
2009-08-15-RegScavenger-EarlyClobber.ll
2009-08-15-RegScavengerAssert.ll
2009-08-21-PostRAKill.ll
2009-08-21-PostRAKill2.ll
2009-08-21-PostRAKill3.ll
2009-08-26-ScalarToVector.ll
2009-08-27-ScalarToVector.ll
2009-08-29-ExtractEltf32.ll
2009-08-29-TooLongSplat.ll
2009-08-31-LSDA-Name.ll
2009-08-31-TwoRegShuffle.ll
2009-09-09-AllOnes.ll
2009-09-09-fpcmp-ole.ll
2009-09-10-postdec.ll
2009-09-13-InvalidSubreg.ll
2009-09-13-InvalidSuperReg.ll
2009-09-20-LiveIntervalsBug.ll
2009-09-21-LiveVariablesBug.ll
2009-09-22-LiveVariablesBug.ll
2009-09-23-LiveVariablesBug.ll
2009-09-24-spill-align.ll
2009-09-27-CoalescerBug.ll
2009-09-28-LdStOptiBug.ll
2009-10-02-NEONSubregsBug.ll
2009-10-16-Scope.ll
2009-10-27-double-align.ll
2009-10-30.ll
2009-11-01-NeonMoves.ll
2009-11-02-NegativeLane.ll
2009-11-07-SubRegAsmPrinting.ll
2009-11-13-CoalescerCrash.ll
2009-11-13-ScavengerAssert.ll
2009-11-13-ScavengerAssert2.ll
2009-11-13-VRRewriterCrash.ll
2009-11-30-LiveVariablesBug.ll
2009-12-02-vtrn-undef.ll
2010-03-04-eabi-fp-spill.ll
2010-03-04-stm-undef-addr.ll
2010-03-18-ldm-rtrn.ll
2010-04-09-NeonSelect.ll
2010-04-13-v2f64SplitArg.ll
2010-04-14-SplitVector.ll
2010-04-15-ScavengerDebugValue.ll
2010-05-14-IllegalType.ll
2010-05-17-FastAllocCrash.ll
2010-05-18-LocalAllocCrash.ll
2010-05-18-PostIndexBug.ll
2010-05-19-Shuffles.ll
2010-05-20-NEONSpillCrash.ll
2010-05-21-BuildVector.ll
2010-06-11-vmovdrr-bitcast.ll
2010-06-21-LdStMultipleBug.ll
2010-06-21-nondarwin-tc.ll
2010-06-25-Thumb2ITInvalidIterator.ll
2010-06-29-PartialRedefFastAlloc.ll
2010-06-29-SubregImpDefs.ll
2010-07-26-GlobalMerge.ll
2010-08-04-EHCrash.ll
2010-08-04-StackVariable.ll
2010-09-21-OptCmpBug.ll
2010-10-25-ifcvt-ldm.ll
2010-11-15-SpillEarlyClobber.ll
2010-11-29-PrologueBug.ll
2010-12-07-PEIBug.ll
2010-12-08-tpsoft.ll
2010-12-15-elf-lcomm.ll
2010-12-17-LocalStackSlotCrash.ll
2011-01-19-MergedGlobalDbg.ll
2011-02-04-AntidepMultidef.ll
2011-02-07-AntidepClobber.ll
2011-03-10-DAGCombineCrash.ll
2011-03-15-LdStMultipleBug.ll
2011-03-23-PeepholeBug.ll
2011-04-07-schediv.ll
2011-04-11-MachineLICMBug.ll
2011-04-12-AlignBug.ll
2011-04-12-FastRegAlloc.ll
2011-04-15-AndVFlagPeepholeBug.ll
2011-04-15-RegisterCmpPeephole.ll
2011-04-26-SchedTweak.ll
2011-04-27-IfCvtBug.ll
2011-05-04-MultipleLandingPadSuccs.ll
2011-06-09-TailCallByVal.ll
2011-06-16-TailCallByVal.ll
2011-06-29-MergeGlobalsAlign.ll
2011-07-10-GlobalMergeBug.ll
2011-08-02-MergedGlobalDbg.ll
2011-08-12-vmovqqqq-pseudo.ll
2011-08-25-ldmia_ret.ll
2011-08-29-SchedCycle.ll
2011-08-29-ldr_pre_imm.ll
2011-09-09-OddVectorDivision.ll
2011-09-19-cpsr.ll
2011-09-28-CMovCombineBug.ll
2011-10-26-ExpandUnalignedLoadCrash.ll
2011-10-26-memset-inline.ll
2011-10-26-memset-with-neon.ll
2011-11-07-PromoteVectorLoadStore.ll
2011-11-09-BitcastVectorDouble.ll
2011-11-09-IllegalVectorFPIntConvert.ll
2011-11-14-EarlyClobber.ll
2011-11-28-DAGCombineBug.ll
2011-11-29-128bitArithmetics.ll
2011-11-30-MergeAlignment.ll
2011-12-14-machine-sink.ll
2011-12-19-sjlj-clobber.ll
2012-01-23-PostRA-LICM.ll
2012-01-24-RegSequenceLiveRange.ll
2012-01-26-CoalescerBug.ll
2012-01-26-CopyPropKills.ll
2012-02-01-CoalescerBug.ll
2012-03-05-FPSCR-bug.ll
2012-03-13-DAGCombineBug.ll
2012-03-26-FoldImmBug.ll
2012-04-02-TwoAddrInstrCrash.ll
2012-04-10-DAGCombine.ll
2012-04-24-SplitEHCriticalEdge.ll
2012-05-04-vmov.ll
2012-05-10-PreferVMOVtoVDUP32.ll
2012-05-29-TailDupBug.ll
2012-06-12-SchedMemLatency.ll
2012-08-04-DtripleSpillReload.ll
2012-08-08-legalize-unaligned.ll
2012-08-09-neon-extload.ll
2012-08-13-bfi.ll
2012-08-23-legalize-vmull.ll
2012-08-27-CopyPhysRegCrash.ll
2012-08-30-select.ll
2012-09-18-ARMv4ISelBug.ll
2012-09-25-InlineAsmScalarToVectorConv.ll
2012-09-25-InlineAsmScalarToVectorConv2.ll
2012-10-04-AAPCS-byval-align8.ll
2012-10-04-FixedFrame-vs-byval.ll
2012-10-04-LDRB_POST_IMM-Crash.ll
2012-10-18-PR14099-ByvalFrameAddress.ll
2012-11-14-subs_carry.ll
2013-01-21-PR14992.ll
2013-02-27-expand-vfma.ll
2013-04-05-Small-ByVal-Structs-PR15293.ll
2013-04-16-AAPCS-C4-vs-VFP.ll
2013-04-16-AAPCS-C5-vs-VFP.ll
2013-04-18-load-overlap-PR14824.ll
2013-04-21-AAPCS-VA-C.1.cp.ll
2013-05-02-AAPCS-ByVal-Structs-C4-C5-VFP.ll
2013-05-02-AAPCS-ByVal-Structs-C4-C5-VFP2.ll
2013-05-05-IfConvertBug.ll
2013-05-07-ByteLoadSameAddress.ll
2013-05-13-AAPCS-byval-padding.ll
2013-05-13-AAPCS-byval-padding2.ll
2013-05-13-DAGCombiner-undef-mask.ll
2013-05-31-char-shift-crash.ll
2013-06-03-ByVal-2Kbytes.ll
2013-07-29-vector-or-combine.ll
2013-10-11-select-stalls.ll
2013-11-08-inline-asm-neon-array.ll
2014-01-09-pseudo_expand_implicit_reg.ll
2014-02-05-vfp-regs-after-stack.ll
2014-02-21-byval-reg-split-alignment.ll
2014-05-14-DwarfEHCrash.ll
2014-07-18-earlyclobber-str-post.ll
2014-08-04-muls-it.ll
2015-01-21-thumbv4t-ldstr-opt.ll
2016-05-01-RegScavengerAssert.ll
2016-08-24-ARM-LDST-dbginfo-bug.ll
ARMLoadStoreDBG.mir
DbgValueOtherTargets.test
MachO-subtypes.ll
MergeConsecutiveStores.ll
PR15053.ll
a15-SD-dep.ll
a15-mla.ll
a15-partial-update.ll
a15.ll
aapcs-hfa-code.ll
aapcs-hfa.ll
acle-intrinsics-v5.ll
acle-intrinsics.ll
addrmode.ll
addrspacecast.ll
addsubcarry-promotion.ll
adv-copy-opt.ll
aeabi-read-tp.ll
aggregate-padding.ll
alias_store.ll
aliases.ll
align-sp-adjustment.ll
align.ll
alloc-no-stack-realign.ll
alloca-align.ll
alloca.ll
and-cmpz.ll
and-load-combine.ll
apcs-vfp.ll
arg-copy-elide.ll
argaddr.ll
arguments-nosplit-double.ll
arguments-nosplit-i64.ll
arguments.ll
arguments2.ll
arguments3.ll
arguments4.ll
arguments5.ll
arguments6.ll
arguments7.ll
arguments8.ll
arguments_f64_backfill.ll
arm-abi-attr.ll
arm-and-tst-peephole.ll
arm-asm.ll
arm-eabi.ll
arm-frame-lowering-no-terminator.ll
arm-frameaddr.ll
arm-insert-subvector.ll
arm-macho-tail.ll
arm-modifier.ll
arm-negative-stride.ll
arm-position-independence-jump-table.ll
arm-position-independence.ll
arm-returnaddr.ll
arm-shrink-wrapping-linux.ll
arm-shrink-wrapping.ll
arm-storebytesmerge.ll
arm-ttype-target2.ll
arm32-round-conv.ll
arm32-rounding.ll
armv4.ll
atomic-64bit.ll
atomic-cmp.ll
atomic-cmpxchg.ll
atomic-load-store.ll
atomic-op.ll
atomic-ops-v8.ll
atomicrmw_minmax.ll
available_externally.ll
avoid-cpsr-rmw.ll
bfc.ll
bfi.ll
bfx.ll
bic.ll
bicZext.ll
big-endian-eh-unwind.ll
big-endian-neon-bitconv.ll
big-endian-neon-extend.ll
big-endian-neon-trunc-store.ll
big-endian-ret-f64.ll
big-endian-vector-callee.ll
big-endian-vector-caller.ll
bit-reverse-to-rbit.ll
bits.ll
bool-ext-inc.ll
bswap-inline-asm.ll
bswap16.ll
build-attributes-encoding.s
build-attributes-fn-attr0.ll
build-attributes-fn-attr1.ll
build-attributes-fn-attr2.ll
build-attributes-fn-attr3.ll
build-attributes-fn-attr4.ll
build-attributes-fn-attr5.ll
build-attributes-fn-attr6.ll
build-attributes-optimization-minsize.ll
build-attributes-optimization-mixed.ll
build-attributes-optimization-optnone.ll
build-attributes-optimization-optsize.ll
build-attributes-optimization.ll
build-attributes.ll
bx_fold.ll
byval-align.ll
byval_load_align.ll
cache-intrinsic.ll
call-noret-minsize.ll
call-noret.ll
call-tc.ll
call.ll
call_nolink.ll
carry.ll
cdp.ll
cdp2.ll
cfi-alignment.ll
clang-section.ll
clz.ll
cmn.ll
cmp.ll
cmp1-peephole-thumb.mir
cmp2-peephole-thumb.mir
cmpxchg-O0-be.ll
cmpxchg-O0.ll
cmpxchg-idioms.ll
cmpxchg-weak.ll
coalesce-dbgvalue.ll
coalesce-subregs.ll
code-placement.ll
combine-movc-sub.ll
combine-vmovdrr.ll
commute-movcc.ll
compare-call.ll
constant-island-crash.ll
constant-islands-cfg.mir
constant-islands.ll
constantfp.ll
constantpool-align.ll
constantpool-promote-dbg.ll
constantpool-promote-duplicate.ll
constantpool-promote-ldrh.ll
constantpool-promote.ll
constants.ll
copy-cpsr.ll
copy-paired-reg.ll
cortex-a57-misched-alu.ll
cortex-a57-misched-basic.ll
cortex-a57-misched-ldm-wrback.ll
cortex-a57-misched-ldm.ll
cortex-a57-misched-stm-wrback.ll
cortex-a57-misched-stm.ll
cortex-a57-misched-vadd.ll
cortex-a57-misched-vfma.ll
cortex-a57-misched-vldm-wrback.ll
cortex-a57-misched-vldm.ll
cortex-a57-misched-vstm-wrback.ll
cortex-a57-misched-vstm.ll
cortex-a57-misched-vsub.ll
cortexr52-misched-basic.ll
crash-O0.ll
crash-greedy-v6.ll
crash-greedy.ll
crash-on-pow2-shufflevector.ll
crash-shufflevector.ll
crash.ll
crc32.ll
cse-call.ll
cse-flags.ll
cse-ldrlit.ll
cse-libcalls.ll
ctor_order.ll
ctors_dtors.ll
cttz.ll
cttz_vector.ll
cxx-tlscc.ll
dag-combine-ldst.ll
dagcombine-anyexttozeroext.ll
dagcombine-concatvector.ll
darwin-eabi.ll
darwin-tls-preserved.ll
darwin-tls.ll
data-in-code-annotations.ll
dbg-range-extension.mir
dbg.ll
debug-frame-large-stack.ll
debug-frame-no-debug.ll
debug-frame-vararg.ll
debug-frame.ll
debug-info-arg.ll
debug-info-blocks.ll
debug-info-branch-folding.ll
debug-info-d16-reg.ll
debug-info-no-frame.ll
debug-info-qreg.ll
debug-info-s16-reg.ll
debug-info-sreg2.ll
debug-segmented-stacks.ll
debugtrap.ll
default-float-abi.ll
default-reloc.ll
deprecated-asm.s
deps-fix.ll
disable-fp-elim.ll
disable-tail-calls.ll
div.ll
divmod-eabi.ll
divmod-hwdiv.ll
divmod.ll
domain-conv-vmovs.ll
dwarf-eh.ll
dwarf-unwind.ll
dyn-stackalloc.ll
early-cfi-sections.ll
eh-dispcont.ll
eh-resume-darwin.ll
ehabi-filters.ll
ehabi-handlerdata-nounwind.ll
ehabi-handlerdata.ll
ehabi-no-landingpad.ll
ehabi-unwind.ll
ehabi.ll
elf-lcomm-align.ll
emit-big-cst.ll
emutls.ll
emutls1.ll
emutls_generic.ll
execute-only-big-stack-frame.ll
execute-only-section.ll
execute-only.ll
expand-pseudos.mir
extload-knownzero.ll
extloadi1.ll
fabs-neon.ll
fabs-to-bfc.ll
fabss.ll
fadds.ll
fast-isel-GEP-coalesce.ll
fast-isel-align.ll
fast-isel-binary.ll
fast-isel-br-const.ll
fast-isel-br-phi.ll
fast-isel-call-multi-reg-return.ll
fast-isel-call.ll
fast-isel-cmp-imm.ll
fast-isel-conversion.ll
fast-isel-crash.ll
fast-isel-crash2.ll
fast-isel-deadcode.ll
fast-isel-ext.ll
fast-isel-fold.ll
fast-isel-frameaddr.ll
fast-isel-icmp.ll
fast-isel-indirectbr.ll
fast-isel-inline-asm.ll
fast-isel-intrinsic.ll
fast-isel-ldr-str-arm.ll
fast-isel-ldr-str-thumb-neg-index.ll
fast-isel-ldrh-strh-arm.ll
fast-isel-load-store-verify.ll
fast-isel-mvn.ll
fast-isel-pic.ll
fast-isel-pie.ll
fast-isel-pred.ll
fast-isel-redefinition.ll
fast-isel-remat-same-constant.ll
fast-isel-ret.ll
fast-isel-select.ll
fast-isel-shift-materialize.ll
fast-isel-shifter.ll
fast-isel-static.ll
fast-isel-update-valuemap-for-extract.ll
fast-isel-vaddd.ll
fast-isel-vararg.ll
fast-isel.ll
fast-tail-call.ll
fastcc-vfp.ll
fastisel-gep-promote-before-add.ll
fastisel-thumb-litpool.ll
fcopysign.ll
fdivs.ll
fence-singlethread.ll
fixunsdfdi.ll
flag-crash.ll
float-helpers.s
floorf.ll
fmacs.ll
fmdrr-fmrrd.ll
fmscs.ll
fmuls.ll
fnattr-trap.ll
fnegs.ll
fnmacs.ll
fnmscs.ll
fnmul.ll
fnmuls.ll
fold-const.ll
fold-stack-adjust.ll
formal.ll
fp-arg-shuffle.ll
fp-fast.ll
fp-only-sp.ll
fp.ll
fp16-args.ll
fp16-promote.ll
fp16-v3.ll
fp16.ll
fp_convert.ll
fparith.ll
fpcmp-f64-neon-opt.ll
fpcmp-opt.ll
fpcmp.ll
fpcmp_ueq.ll
fpconsts.ll
fpconv.ll
fpmem.ll
fpoffset_overflow.mir
fpow.ll
fpowi.ll
fpscr-intrinsics.ll
fptoint.ll
frame-register.ll
fsubs.ll
func-argpassing-endian.ll
fusedMAC.ll
gep-optimization.ll
ghc-tcreturn-lowered.ll
global-merge-1.ll
global-merge-addrspace.ll
global-merge-dllexport.ll
global-merge-external.ll
global-merge.ll
globals.ll
gpr-paired-spill-thumbinst.ll
gpr-paired-spill.ll
gv-stubs-crash.ll
half.ll
hardfloat_neon.ll
hello.ll
hfa-in-contiguous-registers.ll
hidden-vis-2.ll
hidden-vis-3.ll
hidden-vis.ll
hints.ll
i1.ll
iabs.ll
ifconv-kills.ll
ifconv-regmask.ll
ifcvt-branch-weight-bug.ll
ifcvt-branch-weight.ll
ifcvt-callback.ll
ifcvt-dead-def.ll
ifcvt-iter-indbr.ll
ifcvt-regmask-noreturn.ll
ifcvt1.ll
ifcvt10.ll
ifcvt11.ll
ifcvt12.ll
ifcvt2.ll
ifcvt3.ll
ifcvt4.ll
ifcvt5.ll
ifcvt6.ll
ifcvt7.ll
ifcvt8.ll
ifcvt9.ll
illegal-bitfield-loadstore.ll
illegal-vector-bitcast.ll
imm-peephole-arm.mir
imm-peephole-thumb.mir
imm.ll
immcost.ll
indirect-hidden.ll
indirect-reg-input.ll
indirectbr-2.ll
indirectbr-3.ll
indirectbr.ll
inline-diagnostics.ll
inlineasm-64bit.ll
inlineasm-X-allocation.ll
inlineasm-X-constraint.ll
inlineasm-global.ll
inlineasm-imm-arm.ll
inlineasm-imm-thumb.ll
inlineasm-imm-thumb2.ll
inlineasm-ldr-pseudo.ll
inlineasm-switch-mode-oneway-from-arm.ll
inlineasm-switch-mode-oneway-from-thumb.ll
inlineasm-switch-mode.ll
inlineasm.ll
inlineasm2.ll
inlineasm3.ll
inlineasm4.ll
insn-sched1.ll
int-to-fp.ll
integer_insertelement.ll
interrupt-attr.ll
interval-update-remat.ll
interwork.ll
intrinsics-coprocessor.ll
intrinsics-crypto.ll
intrinsics-memory-barrier.ll
intrinsics-overflow.ll
intrinsics-v8.ll
invalid-target.ll
invalidated-save-point.ll
invoke-donothing-assert.ll
isel-v8i32-crash.ll
ispositive.ll
jump-table-islands-split.ll
jump-table-islands.ll
jump-table-tbh.ll
jumptable-label.ll
krait-cpu-div-attribute.ll
large-stack.ll
ldaex-stlex.ll
ldc2l.ll
ldm-base-writeback.ll
ldm-stm-base-materialization.ll
ldm-stm-i256.ll
ldm.ll
ldr.ll
ldr_ext.ll
ldr_frame.ll
ldr_post.ll
ldr_pre.ll
ldrd-memoper.ll
ldrd.ll
ldst-f32-2-i32.ll
ldstrex-m.ll
ldstrex.ll
legalize-unaligned-load.ll
lit.local.cfg
litpool-licm.ll
load-address-masked.ll
load-arm.ll
load-combine-big-endian.ll
load-combine.ll
load-global.ll
load-global2.ll
load-store-flags.ll
load.ll
load_i1_select.ll
load_store_multiple.ll
load_store_opt_kill.mir
local-call.ll
log2_not_readnone.ll
long-setcc.ll
long.ll
longMAC.ll
long_shift.ll
loopvectorize_pr33804.ll
lowerMUL-newload.ll
lsr-code-insertion.ll
lsr-icmp-imm.ll
lsr-scale-addr-mode.ll
lsr-unfolded-offset.ll
machine-copyprop.mir
machine-cse-cmp.ll
machine-licm.ll
macho-extern-hidden.ll
macho-frame-offset.ll
mature-mc-support.ll
mem.ll
memcpy-inline.ll
memcpy-ldm-stm.ll
memcpy-no-inline.ll
memfunc.ll
memset-inline.ll
metadata-default.ll
metadata-short-enums.ll
metadata-short-wchar.ll
minmax.ll
minsize-call-cse.ll
minsize-imms.ll
minsize-litpools.ll
misched-copy-arm.ll
misched-fp-basic.ll
misched-fusion-aes.ll
misched-int-basic-thumb2.mir
misched-int-basic.mir
mls.ll
movcc-double.ll
movt-movw-global.ll
movt.ll
msr-it-block.ll
mul.ll
mul_const.ll
mulhi.ll
mult-alt-generic-arm.ll
mvn.ll
named-reg-alloc.ll
named-reg-notareg.ll
negate-i1.ll
negative-offset.ll
neon-fma.ll
neon-spfp.ll
neon-v8.1a.ll
neon_arith1.ll
neon_cmp.ll
neon_div.ll
neon_fpconv.ll
neon_ld1.ll
neon_ld2.ll
neon_minmax.ll
neon_shift.ll
neon_spill.ll
neon_vabs.ll
neon_vshl_minint.ll
nest-register.ll
no-arm-mode.ll
no-cfi.ll
no-cmov2bfi.ll
no-fpscr-liveness.ll
no-fpu.ll
no-tail-call.ll
no_redundant_trunc_for_cmp.ll
none-macho-v4t.ll
none-macho.ll
noopt-dmb-v7.ll
nop_concat_vectors.ll
noreturn.ll
null-streamer.ll
opt-shuff-tstore.ll
optimize-dmbs-v7.ll
optselect-regclass.ll
out-of-registers.ll
pack.ll
peephole-bitcast.ll
peephole-phi.mir
pei-swiftself.mir
phi.ll
pic.ll
pie.ll
plt-relative-reloc.ll
popcnt.ll
pr13249.ll
pr18364-movw.ll
pr25317.ll
pr25838.ll
pr26669.ll
pr32545.ll
pr32578.ll
pr34045-2.ll
pr34045.ll
pr3502.ll
pr35103.ll
preferred-align.ll
prefetch.ll
prera-ldst-aliasing.mir
prera-ldst-insertpt.mir
print-memb-operand.ll
private.ll
rbit.ll
readcyclecounter.ll
readtp.ll
reg_sequence.ll
regpair_hint_phys.ll
rem_crash.ll
ret0.ll
ret_arg1.ll
ret_arg2.ll
ret_arg3.ll
ret_arg4.ll
ret_arg5.ll
ret_f32_arg2.ll
ret_f32_arg5.ll
ret_f64_arg2.ll
ret_f64_arg_reg_split.ll
ret_f64_arg_split.ll
ret_f64_arg_stack.ll
ret_i128_arg2.ll
ret_i64_arg2.ll
ret_i64_arg3.ll
ret_i64_arg_split.ll
ret_sret_vector.ll
ret_void.ll
returned-ext.ll
returned-trunc-tail-calls.ll
rev.ll
ror.ll
rotate.ll
saxpy10-a9.ll
sbfx.ll
scavenging.mir
sched-it-debug-nodes.mir
section-name.ll
section.ll
segmented-stacks-dynamic.ll
segmented-stacks.ll
select-imm.ll
select-undef.ll
select.ll
select_const.ll
select_xform.ll
setcc-logic.ll
setcc-type-mismatch.ll
setjmp_longjmp.ll
shift-combine.ll
shift-i64.ll
shifter_operand.ll
shuffle.ll
sincos.ll
single-issue-r52.mir
sjlj-prepare-critical-edge.ll
sjljeh-swifterror.ll
sjljehprepare-lower-empty-struct.ll
smml.ll
smul.ll
softfp-fabs-fneg.ll
space-directive.ll
special-reg-acore.ll
special-reg-mcore.ll
special-reg-v8m-base.ll
special-reg-v8m-main.ll
special-reg.ll
spill-q.ll
splitkit.ll
ssat-lower.ll
ssat-upper.ll
ssat-v4t.ll
ssat.ll
ssp-data-layout.ll
stack-alignment.ll
stack-frame.ll
stack-protector-bmovpcb_call.ll
stack_guard_remat.ll
stackpointer.ll
static-addr-hoisting.ll
stc2.ll
stm.ll
str_post.ll
str_pre-2.ll
str_pre.ll
str_trunc.ll
struct-byval-frame-index.ll
struct_byval.ll
struct_byval_arm_t1_t2.ll
su-addsub-overflow.ll
sub-cmp-peephole.ll
sub.ll
subreg-remat.ll
subtarget-features-long-calls.ll
subtarget-no-movt.ll
swift-atomics.ll
swift-ios.ll
swift-return.ll
swift-vldm.ll
swifterror.ll
swiftself.ll
switch-minsize.ll
sxt_rot.ll
t2-imm.ll
t2-shrink-ldrpost.ll
t2abs-killflags.ll
tail-call-builtin.ll
tail-call-float.ll
tail-call-weak.ll
tail-call.ll
tail-dup-bundle.mir
tail-dup-kill-flags.ll
tail-dup.ll
tail-merge-branch-weight.ll
tail-opts.ll
tailcall-mem-intrinsics.ll
taildup-branch-weight.ll
test-sharedidx.ll
this-return.ll
thread_pointer.ll
thumb-alignment.ll
thumb-big-stack.ll.REMOVED.git-id
thumb-litpool.ll
thumb-stub.ll
thumb1-div.ll
thumb1-ldst-opt.ll
thumb1-varalloc.ll
thumb1_return_sequence.ll
thumb2-it-block.ll
thumb2-size-opt.ll
thumb2-size-reduction-internal-flags.ll
thumb_indirect_calls.ll
tls-models.ll
tls1.ll
tls2.ll
tls3.ll
trap.ll
trunc_ldr.ll
truncstore-dag-combine.ll
tst_teq.ll
twoaddrinstr.ll
uint64tof64.ll
umulo-32.ll
unaligned_load_store.ll
unaligned_load_store_vector.ll
unaligned_load_store_vfp.ll
undef-sext.ll
undefined.ll
unfold-shifts.ll
unord.ll
unsafe-fsub.ll
unschedule-first-call.ll
unwind-init.ll
urem-opt-size.ll
usat-lower.ll
usat-upper.ll
usat-v4t.ll
usat.ll
uxt_rot.ll
uxtb.ll
v1-constant-fold.ll
v6-jumptable-clobber.mir
v6m-smul-with-overflow.ll
v6m-umul-with-overflow.ll
v7k-abi-align.ll
v7k-libcalls.ll
v7k-sincos.ll
v8m-tail-call.ll
v8m.base-jumptable_alignment.ll
va_arg.ll
vaba.ll
vabd.ll
vabs.ll
vadd.ll
vararg_no_start.ll
varargs-spill-stack-align-nacl.ll
vargs.ll
vargs_align.ll
vbits.ll
vbsl-constant.ll
vbsl.ll
vceq.ll
vcge.ll
vcgt.ll
vcmp-crash.ll
vcnt.ll
vcombine.ll
vcvt-cost.ll
vcvt-v8.ll
vcvt.ll
vcvt_combine.ll
vdiv_combine.ll
vdup.ll
vector-DAGCombine.ll
vector-extend-narrow.ll
vector-load.ll
vector-promotion.ll
vector-spilling.ll
vector-store.ll
vext.ll
vfcmp.ll
vfloatintrinsics.ll
vfp-libcalls.ll
vfp-reg-stride.ll
vfp-regs-dwarf.ll
vfp.ll
vget_lane.ll
vhadd.ll
vhsub.ll
vicmp-64.ll
vicmp.ll
virtregrewriter-subregliveness.mir
vld-vst-upgrade.ll
vld1.ll
vld2.ll
vld3.ll
vld4.ll
vlddup.ll
vldlane.ll
vldm-liveness.ll
vldm-liveness.mir
vldm-sched-a9.ll
vminmax.ll
vminmaxnm-safe.ll
vminmaxnm.ll
vmla.ll
vmls.ll
vmov.ll
vmul.ll
vneg.ll
vpadal.ll
vpadd.ll
vpminmax.ll
vqadd.ll
vqdmul.ll
vqshl.ll
vqshrn.ll
vqsub.ll
vrec.ll
vrev.ll
vsel.ll
vselect_imax.ll
vshift.ll
vshiftins.ll
vshl.ll
vshll.ll
vshrn.ll
vsra.ll
vst1.ll
vst2.ll
vst3.ll
vst4.ll
vstlane.ll
vsub.ll
vtbl.ll
vtrn.ll
vuzp.ll
vzip.ll
warn-stack.ll
weak.ll
weak2.ll
wide-compares.ll
widen-vmovs.ll
wrong-t2stmia-size-opt.ll
xray-armv6-attribute-instrumentation.ll
xray-armv7-attribute-instrumentation.ll
xray-tail-call-sled.ll
zero-cycle-zero.ll
zextload_demandedbits.ll
AVR
BPF
Generic
Hexagon
Inputs
Lanai
MIR
MSP430
Mips
NVPTX
Nios2
PowerPC
RISCV
SPARC
SystemZ
Thumb
Thumb2
WebAssembly
WinEH
X86
XCore
DebugInfo
Examples
ExecutionEngine
Feature
FileCheck
Instrumentation
Integer
JitListener
LTO
Linker
MC
Object
ObjectYAML
Other
SafepointIRVerifier
SymbolRewriter
TableGen
ThinLTO
Transforms
Unit
Verifier
YAMLParser
tools
.clang-format
CMakeLists.txt
TestRunner.sh
lit.cfg.py
lit.site.cfg.py.in
tools
unittests
utils
.arcconfig
.clang-format
.clang-tidy
.gitattributes
.gitignore
CMakeLists.txt
CODE_OWNERS.TXT
CREDITS.TXT
LICENSE.TXT
LLVMBuild.txt
README.txt
RELEASE_TESTERS.TXT
configure
llvm.spec.in
openmp
polly
nuget-buildtasks
nunit-lite
roslyn-binaries
rx
xunit-binaries
how-to-bump-roslyn-binaries.md
ikvm-native
llvm
m4
man
mcs
mk
mono
msvc
netcore
po
runtime
samples
scripts
support
tools
COPYING.LIB
LICENSE
Makefile.am
Makefile.in
NEWS
README.md
acinclude.m4
aclocal.m4
autogen.sh
code_of_conduct.md
compile
config.guess
config.h.in
config.rpath
config.sub
configure.REMOVED.git-id
configure.ac.REMOVED.git-id
depcomp
install-sh
ltmain.sh.REMOVED.git-id
missing
mkinstalldirs
mono-uninstalled.pc.in
test-driver
winconfig.h
1427 lines
45 KiB
LLVM
1427 lines
45 KiB
LLVM
![]() |
; RUN: llc -mtriple=armv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE --check-prefix=CHECK-ARM --check-prefix=CHECK-ARM-LE
|
||
|
; RUN: llc -mtriple=armebv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE --check-prefix=CHECK-ARM --check-prefix=CHECK-ARM-BE
|
||
|
; RUN: llc -mtriple=thumbv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-LE --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-LE
|
||
|
; RUN: llc -mtriple=thumbebv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BE --check-prefix=CHECK-THUMB --check-prefix=CHECK-THUMB-BE
|
||
|
|
||
|
@var8 = global i8 0
|
||
|
@var16 = global i16 0
|
||
|
@var32 = global i32 0
|
||
|
@var64 = global i64 0
|
||
|
|
||
|
define i8 @test_atomic_load_add_i8(i8 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_add_i8:
|
||
|
%old = atomicrmw add i8* @var8, i8 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i8 %old
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_load_add_i16(i16 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_add_i16:
|
||
|
%old = atomicrmw add i16* @var16, i16 %offset acquire
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var16
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i16 %old
|
||
|
}
|
||
|
|
||
|
define i32 @test_atomic_load_add_i32(i32 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_add_i32:
|
||
|
%old = atomicrmw add i32* @var32, i32 %offset release
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var32
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i32 %old
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_load_add_i64(i64 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_add_i64:
|
||
|
%old = atomicrmw add i64* @var64, i64 %offset monotonic
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-LE-NEXT: adds{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
|
||
|
; CHECK-LE-NEXT: adc{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
|
||
|
; CHECK-BE-NEXT: adds{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
|
||
|
; CHECK-BE-NEXT: adc{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
|
||
|
; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
|
||
|
store i64 %old, i64* @var64
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_sub_i8(i8 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_sub_i8:
|
||
|
%old = atomicrmw sub i8* @var8, i8 %offset monotonic
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i8 %old
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_load_sub_i16(i16 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_sub_i16:
|
||
|
%old = atomicrmw sub i16* @var16, i16 %offset release
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var16
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i16 %old
|
||
|
}
|
||
|
|
||
|
define i32 @test_atomic_load_sub_i32(i32 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_sub_i32:
|
||
|
%old = atomicrmw sub i32* @var32, i32 %offset acquire
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var32
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: strex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i32 %old
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_load_sub_i64(i64 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_sub_i64:
|
||
|
%old = atomicrmw sub i64* @var64, i64 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-LE-NEXT: subs{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
|
||
|
; CHECK-LE-NEXT: sbc{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
|
||
|
; CHECK-BE-NEXT: subs{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
|
||
|
; CHECK-BE-NEXT: sbc{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
|
||
|
; CHECK-NEXT: stlexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
|
||
|
store i64 %old, i64* @var64
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_and_i8(i8 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_and_i8:
|
||
|
%old = atomicrmw and i8* @var8, i8 %offset release
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i8 %old
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_load_and_i16(i16 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_and_i16:
|
||
|
%old = atomicrmw and i16* @var16, i16 %offset monotonic
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var16
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i16 %old
|
||
|
}
|
||
|
|
||
|
define i32 @test_atomic_load_and_i32(i32 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_and_i32:
|
||
|
%old = atomicrmw and i32* @var32, i32 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var32
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i32 %old
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_load_and_i64(i64 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_and_i64:
|
||
|
%old = atomicrmw and i64* @var64, i64 %offset acquire
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-LE-DAG: and{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
|
||
|
; CHECK-LE-DAG: and{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
|
||
|
; CHECK-BE-DAG: and{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
|
||
|
; CHECK-BE-DAG: and{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
|
||
|
; CHECK: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
|
||
|
store i64 %old, i64* @var64
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_or_i8(i8 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_or_i8:
|
||
|
%old = atomicrmw or i8* @var8, i8 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i8 %old
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_load_or_i16(i16 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_or_i16:
|
||
|
%old = atomicrmw or i16* @var16, i16 %offset monotonic
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var16
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i16 %old
|
||
|
}
|
||
|
|
||
|
define i32 @test_atomic_load_or_i32(i32 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_or_i32:
|
||
|
%old = atomicrmw or i32* @var32, i32 %offset acquire
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var32
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: strex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i32 %old
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_load_or_i64(i64 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_or_i64:
|
||
|
%old = atomicrmw or i64* @var64, i64 %offset release
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-LE-DAG: orr{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
|
||
|
; CHECK-LE-DAG: orr{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
|
||
|
; CHECK-BE-DAG: orr{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
|
||
|
; CHECK-BE-DAG: orr{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
|
||
|
; CHECK: stlexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
|
||
|
store i64 %old, i64* @var64
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_xor_i8(i8 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_xor_i8:
|
||
|
%old = atomicrmw xor i8* @var8, i8 %offset acquire
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i8 %old
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_load_xor_i16(i16 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_xor_i16:
|
||
|
%old = atomicrmw xor i16* @var16, i16 %offset release
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var16
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i16 %old
|
||
|
}
|
||
|
|
||
|
define i32 @test_atomic_load_xor_i32(i32 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_xor_i32:
|
||
|
%old = atomicrmw xor i32* @var32, i32 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var32
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
|
||
|
; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i32 %old
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_load_xor_i64(i64 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_xor_i64:
|
||
|
%old = atomicrmw xor i64* @var64, i64 %offset monotonic
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-LE-DAG: eor{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
|
||
|
; CHECK-LE-DAG: eor{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
|
||
|
; CHECK-BE-DAG: eor{{(\.w)?}} [[NEW2:r[0-9]+|lr]], r[[OLD2]], r1
|
||
|
; CHECK-BE-DAG: eor{{(\.w)?}} [[NEW1:r[0-9]+|lr]], r[[OLD1]], r0
|
||
|
; CHECK: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: strd r[[OLD1]], r[[OLD2]], [r[[ADDR]]]
|
||
|
store i64 %old, i64* @var64
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_xchg_i8(i8 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_xchg_i8:
|
||
|
%old = atomicrmw xchg i8* @var8, i8 %offset monotonic
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i8 %old
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_load_xchg_i16(i16 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_xchg_i16:
|
||
|
%old = atomicrmw xchg i16* @var16, i16 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var16
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i16 %old
|
||
|
}
|
||
|
|
||
|
define i32 @test_atomic_load_xchg_i32(i32 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_xchg_i32:
|
||
|
%old = atomicrmw xchg i32* @var32, i32 %offset release
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var32
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i32 %old
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_load_xchg_i64(i64 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_xchg_i64:
|
||
|
%old = atomicrmw xchg i64* @var64, i64 %offset acquire
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexd [[OLD1:r[0-9]+]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], r0, r1, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
|
||
|
store i64 %old, i64* @var64
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_min_i8(i8 signext %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_min_i8:
|
||
|
%old = atomicrmw min i8* @var8, i8 %offset acquire
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK-DAG: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
|
||
|
; CHECK-DAG: movt [[ADDR]], :upper16:var8
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
|
||
|
; CHECK-NEXT: sxtb r[[OLDX:[0-9]+]], r[[OLD]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: cmp r[[OLDX]], r0
|
||
|
; Thumb mode: it le
|
||
|
; CHECK: movle r[[OLDX]], r[[OLD]]
|
||
|
; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i8 %old
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_load_min_i16(i16 signext %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_min_i16:
|
||
|
%old = atomicrmw min i16* @var16, i16 %offset release
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var16
|
||
|
; CHECK: movt [[ADDR]], :upper16:var16
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexh r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
|
||
|
; CHECK-NEXT: sxth r[[OLDX:[0-9]+]], r[[OLD]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: cmp r[[OLDX]], r0
|
||
|
; Thumb mode: it le
|
||
|
; CHECK: movle r[[OLDX]], r[[OLD]]
|
||
|
; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i16 %old
|
||
|
}
|
||
|
|
||
|
define i32 @test_atomic_load_min_i32(i32 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_min_i32:
|
||
|
%old = atomicrmw min i32* @var32, i32 %offset monotonic
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var32
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
|
||
|
; CHECK-NEXT: cmp r[[OLD]], r0
|
||
|
; Thumb mode: it le
|
||
|
; CHECK: movle r[[NEW]], r[[OLD]]
|
||
|
; CHECK-NEXT: strex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i32 %old
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_load_min_i64(i64 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_min_i64:
|
||
|
%old = atomicrmw min i64* @var64, i64 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
|
||
|
; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
|
||
|
; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
|
||
|
; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
|
||
|
; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
|
||
|
; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
|
||
|
; CHECK-ARM: movwge [[CMP:r[0-9]+|lr]], #1
|
||
|
; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
|
||
|
; CHECK-ARM: movne [[MINHI]], [[OLD2]]
|
||
|
; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
|
||
|
; CHECK-ARM: movne [[MINLO]], [[OLD1]]
|
||
|
; CHECK-ARM: stlexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
|
||
|
; CHECK-THUMB: stlexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
|
||
|
store i64 %old, i64* @var64
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_max_i8(i8 signext %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_max_i8:
|
||
|
%old = atomicrmw max i8* @var8, i8 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
|
||
|
; CHECK: movt [[ADDR]], :upper16:var8
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
|
||
|
; CHECK-NEXT: sxtb r[[OLDX:[0-9]+]], r[[OLD]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: cmp r[[OLDX]], r0
|
||
|
; Thumb mode: it gt
|
||
|
; CHECK: movgt r[[OLDX]], r[[OLD]]
|
||
|
; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], r[[OLDX]], {{.*}}[[ADDR]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i8 %old
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_load_max_i16(i16 signext %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_max_i16:
|
||
|
%old = atomicrmw max i16* @var16, i16 %offset acquire
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var16
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: sxth r[[OLDX:[0-9]+]], r[[OLD]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: cmp r[[OLDX]], r0
|
||
|
; Thumb mode: it gt
|
||
|
; CHECK: movgt r[[OLDX]], r[[OLD]]
|
||
|
; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[OLDX]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i16 %old
|
||
|
}
|
||
|
|
||
|
define i32 @test_atomic_load_max_i32(i32 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_max_i32:
|
||
|
%old = atomicrmw max i32* @var32, i32 %offset release
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var32
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
|
||
|
; CHECK-NEXT: cmp r[[OLD]], r0
|
||
|
; Thumb mode: it gt
|
||
|
; CHECK: movgt r[[NEW]], r[[OLD]]
|
||
|
; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i32 %old
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_load_max_i64(i64 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_max_i64:
|
||
|
%old = atomicrmw max i64* @var64, i64 %offset monotonic
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexd [[OLD1:r[0-9]+]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
|
||
|
; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
|
||
|
; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
|
||
|
; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
|
||
|
; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
|
||
|
; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
|
||
|
; CHECK-ARM: movwlt [[CMP:r[0-9]+|lr]], #1
|
||
|
; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
|
||
|
; CHECK-ARM: movne [[MINHI]], [[OLD2]]
|
||
|
; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
|
||
|
; CHECK-ARM: movne [[MINLO]], [[OLD1]]
|
||
|
; CHECK-ARM: strexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
|
||
|
; CHECK-THUMB: strexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
|
||
|
store i64 %old, i64* @var64
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_umin_i8(i8 zeroext %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_umin_i8:
|
||
|
%old = atomicrmw umin i8* @var8, i8 %offset monotonic
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
|
||
|
; CHECK: movt [[ADDR]], :upper16:var8
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
|
||
|
; CHECK-NEXT: cmp r[[OLD]], r0
|
||
|
; Thumb mode: it ls
|
||
|
; CHECK: movls r[[NEW]], r[[OLD]]
|
||
|
; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i8 %old
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_load_umin_i16(i16 zeroext %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_umin_i16:
|
||
|
%old = atomicrmw umin i16* @var16, i16 %offset acquire
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var16
|
||
|
; CHECK: movt [[ADDR]], :upper16:var16
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexh r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
|
||
|
; CHECK-NEXT: cmp r[[OLD]], r0
|
||
|
; Thumb mode: it ls
|
||
|
; CHECK: movls r[[NEW]], r[[OLD]]
|
||
|
; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i16 %old
|
||
|
}
|
||
|
|
||
|
define i32 @test_atomic_load_umin_i32(i32 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_umin_i32:
|
||
|
%old = atomicrmw umin i32* @var32, i32 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var32
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
|
||
|
; CHECK-NEXT: cmp r[[OLD]], r0
|
||
|
; Thumb mode: it ls
|
||
|
; CHECK: movls r[[NEW]], r[[OLD]]
|
||
|
; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i32 %old
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_load_umin_i64(i64 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_umin_i64:
|
||
|
%old = atomicrmw umin i64* @var64, i64 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
|
||
|
; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
|
||
|
; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
|
||
|
; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
|
||
|
; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
|
||
|
; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
|
||
|
; CHECK-ARM: movwhs [[CMP:r[0-9]+|lr]], #1
|
||
|
; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
|
||
|
; CHECK-ARM: movne [[MINHI]], [[OLD2]]
|
||
|
; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
|
||
|
; CHECK-ARM: movne [[MINLO]], [[OLD1]]
|
||
|
; CHECK-ARM: stlexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
|
||
|
; CHECK-THUMB: stlexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
|
||
|
store i64 %old, i64* @var64
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_umax_i8(i8 zeroext %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_umax_i8:
|
||
|
%old = atomicrmw umax i8* @var8, i8 %offset acq_rel
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var8
|
||
|
; CHECK: movt [[ADDR]], :upper16:var8
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexb r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
|
||
|
; CHECK-NEXT: cmp r[[OLD]], r0
|
||
|
; Thumb mode: it hi
|
||
|
; CHECK: movhi r[[NEW]], r[[OLD]]
|
||
|
; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i8 %old
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_load_umax_i16(i16 zeroext %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_umax_i16:
|
||
|
%old = atomicrmw umax i16* @var16, i16 %offset monotonic
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var16
|
||
|
; CHECK: movt [[ADDR]], :upper16:var16
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexh r[[OLD:[0-9]+]], {{.*}}[[ADDR]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
|
||
|
; CHECK-NEXT: cmp r[[OLD]], r0
|
||
|
; Thumb mode: it hi
|
||
|
; CHECK: movhi r[[NEW]], r[[OLD]]
|
||
|
; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[NEW]], {{.*}}[[ADDR]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i16 %old
|
||
|
}
|
||
|
|
||
|
define i32 @test_atomic_load_umax_i32(i32 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_umax_i32:
|
||
|
%old = atomicrmw umax i32* @var32, i32 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var32
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
|
||
|
; CHECK-NEXT: cmp r[[OLD]], r0
|
||
|
; Thumb mode: it hi
|
||
|
; CHECK: movhi r[[NEW]], r[[OLD]]
|
||
|
; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: mov r0, r[[OLD]]
|
||
|
ret i32 %old
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_load_umax_i64(i64 %offset) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_umax_i64:
|
||
|
%old = atomicrmw umax i64* @var64, i64 %offset seq_cst
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-ARM: mov [[MINHI:r[0-9]+]], r1
|
||
|
; CHECK-ARM-LE: subs {{[^,]+}}, r0, [[OLD1]]
|
||
|
; CHECK-ARM-LE: sbcs {{[^,]+}}, r1, [[OLD2]]
|
||
|
; CHECK-ARM-BE: subs {{[^,]+}}, r1, [[OLD2]]
|
||
|
; CHECK-ARM-BE: sbcs {{[^,]+}}, r0, [[OLD1]]
|
||
|
; CHECK-ARM: mov [[CMP:r[0-9]+|lr]], #0
|
||
|
; CHECK-ARM: movwlo [[CMP:r[0-9]+|lr]], #1
|
||
|
; CHECK-ARM: cmp [[CMP:r[0-9]+|lr]], #0
|
||
|
; CHECK-ARM: movne [[MINHI]], [[OLD2]]
|
||
|
; CHECK-ARM: mov [[MINLO:r[0-9]+]], r0
|
||
|
; CHECK-ARM: movne [[MINLO]], [[OLD1]]
|
||
|
; CHECK-ARM: stlexd [[STATUS:r[0-9]+]], [[MINLO]], [[MINHI]], [r[[ADDR]]]
|
||
|
; CHECK-THUMB: stlexd [[STATUS:r[0-9]+]], {{r[0-9]+}}, {{r[0-9]+}}, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
|
||
|
store i64 %old, i64* @var64
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_cmpxchg_i8(i8 zeroext %wanted, i8 zeroext %new) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_cmpxchg_i8:
|
||
|
%pair = cmpxchg i8* @var8, i8 %wanted, i8 %new acquire acquire
|
||
|
%old = extractvalue { i8, i1 } %pair, 0
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK-DAG: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK-DAG: movt r[[ADDR]], :upper16:var8
|
||
|
; CHECK-THUMB-DAG: mov r[[WANTED:[0-9]+]], r0
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-ARM-NEXT: cmp r[[OLD]], r0
|
||
|
; CHECK-THUMB-NEXT: cmp r[[OLD]], r[[WANTED]]
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_4
|
||
|
; CHECK-NEXT: %bb.2:
|
||
|
; As above, r1 is a reasonable guess.
|
||
|
; CHECK: strexb [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-ARM: mov r0, r[[OLD]]
|
||
|
; CHECK: bx lr
|
||
|
; CHECK-NEXT: .LBB{{[0-9]+}}_4:
|
||
|
; CHECK-NEXT: clrex
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK-ARM: mov r0, r[[OLD]]
|
||
|
; CHECK-ARM-NEXT: bx lr
|
||
|
ret i8 %old
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_cmpxchg_i16(i16 zeroext %wanted, i16 zeroext %new) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_cmpxchg_i16:
|
||
|
%pair = cmpxchg i16* @var16, i16 %wanted, i16 %new seq_cst seq_cst
|
||
|
%old = extractvalue { i16, i1 } %pair, 0
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK-DAG: movw r[[ADDR:[0-9]+]], :lower16:var16
|
||
|
; CHECK-DAG: movt r[[ADDR]], :upper16:var16
|
||
|
; CHECK-THUMB-DAG: mov r[[WANTED:[0-9]+]], r0
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-ARM-NEXT: cmp r[[OLD]], r0
|
||
|
; CHECK-THUMB-NEXT: cmp r[[OLD]], r[[WANTED]]
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_4
|
||
|
; CHECK-NEXT: %bb.2:
|
||
|
; As above, r1 is a reasonable guess.
|
||
|
; CHECK: stlexh [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-ARM: mov r0, r[[OLD]]
|
||
|
; CHECK: bx lr
|
||
|
; CHECK-NEXT: .LBB{{[0-9]+}}_4:
|
||
|
; CHECK-NEXT: clrex
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK-ARM: mov r0, r[[OLD]]
|
||
|
; CHECK-ARM-NEXT: bx lr
|
||
|
ret i16 %old
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_cmpxchg_i32(i32 %wanted, i32 %new) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_cmpxchg_i32:
|
||
|
%pair = cmpxchg i32* @var32, i32 %wanted, i32 %new release monotonic
|
||
|
%old = extractvalue { i32, i1 } %pair, 0
|
||
|
store i32 %old, i32* @var32
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var32
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
|
||
|
; r0 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-NEXT: cmp r[[OLD]], r0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_4
|
||
|
; CHECK-NEXT: %bb.2:
|
||
|
; As above, r1 is a reasonable guess.
|
||
|
; CHECK: stlex [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK: str{{(.w)?}} r[[OLD]],
|
||
|
; CHECK-NEXT: bx lr
|
||
|
; CHECK-NEXT: .LBB{{[0-9]+}}_4:
|
||
|
; CHECK-NEXT: clrex
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK: str{{(.w)?}} r[[OLD]],
|
||
|
; CHECK-ARM-NEXT: bx lr
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_cmpxchg_i64(i64 %wanted, i64 %new) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_cmpxchg_i64:
|
||
|
%pair = cmpxchg i64* @var64, i64 %wanted, i64 %new monotonic monotonic
|
||
|
%old = extractvalue { i64, i1 } %pair, 0
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; CHECK: ldrexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK-LE-DAG: eor{{(\.w)?}} [[MISMATCH_LO:r[0-9]+|lr]], [[OLD1]], r0
|
||
|
; CHECK-LE-DAG: eor{{(\.w)?}} [[MISMATCH_HI:r[0-9]+|lr]], [[OLD2]], r1
|
||
|
; CHECK-ARM-LE: orrs{{(\.w)?}} {{r[0-9]+}}, [[MISMATCH_LO]], [[MISMATCH_HI]]
|
||
|
; CHECK-THUMB-LE: orrs{{(\.w)?}} {{(r[0-9]+, )?}}[[MISMATCH_HI]], [[MISMATCH_LO]]
|
||
|
; CHECK-BE-DAG: eor{{(\.w)?}} [[MISMATCH_HI:r[0-9]+|lr]], [[OLD2]], r1
|
||
|
; CHECK-BE-DAG: eor{{(\.w)?}} [[MISMATCH_LO:r[0-9]+|lr]], [[OLD1]], r0
|
||
|
; CHECK-ARM-BE: orrs{{(\.w)?}} {{r[0-9]+}}, [[MISMATCH_HI]], [[MISMATCH_LO]]
|
||
|
; CHECK-THUMB-BE: orrs{{(\.w)?}} {{(r[0-9]+, )?}}[[MISMATCH_LO]], [[MISMATCH_HI]]
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_4
|
||
|
; CHECK-NEXT: %bb.2:
|
||
|
; As above, r2, r3 is a reasonable guess.
|
||
|
; CHECK: strexd [[STATUS:r[0-9]+]], r2, r3, [r[[ADDR]]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
|
||
|
; CHECK-NEXT: pop
|
||
|
; CHECK-NEXT: .LBB{{[0-9]+}}_4:
|
||
|
; CHECK-NEXT: clrex
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
; CHECK-ARM: strd [[OLD1]], [[OLD2]], [r[[ADDR]]]
|
||
|
store i64 %old, i64* @var64
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_monotonic_i8() nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_monotonic_i8:
|
||
|
%val = load atomic i8, i8* @var8 monotonic, align 1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
; CHECK: ldrb r0, [r[[ADDR]]]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
ret i8 %val
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_monotonic_regoff_i8(i64 %base, i64 %off) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_monotonic_regoff_i8:
|
||
|
%addr_int = add i64 %base, %off
|
||
|
%addr = inttoptr i64 %addr_int to i8*
|
||
|
|
||
|
%val = load atomic i8, i8* %addr monotonic, align 1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK-LE: ldrb r0, [r0, r2]
|
||
|
; CHECK-BE: ldrb r0, [r1, r3]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
ret i8 %val
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_acquire_i8() nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_acquire_i8:
|
||
|
%val = load atomic i8, i8* @var8 acquire, align 1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: ldab r0, [r[[ADDR]]]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
ret i8 %val
|
||
|
}
|
||
|
|
||
|
define i8 @test_atomic_load_seq_cst_i8() nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_seq_cst_i8:
|
||
|
%val = load atomic i8, i8* @var8 seq_cst, align 1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: ldab r0, [r[[ADDR]]]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
ret i8 %val
|
||
|
}
|
||
|
|
||
|
define i16 @test_atomic_load_monotonic_i16() nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_monotonic_i16:
|
||
|
%val = load atomic i16, i16* @var16 monotonic, align 2
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var16
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: ldrh r0, [r[[ADDR]]]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
ret i16 %val
|
||
|
}
|
||
|
|
||
|
define i32 @test_atomic_load_monotonic_regoff_i32(i64 %base, i64 %off) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_monotonic_regoff_i32:
|
||
|
%addr_int = add i64 %base, %off
|
||
|
%addr = inttoptr i64 %addr_int to i32*
|
||
|
|
||
|
%val = load atomic i32, i32* %addr monotonic, align 4
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK-LE: ldr r0, [r0, r2]
|
||
|
; CHECK-BE: ldr r0, [r1, r3]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
ret i32 %val
|
||
|
}
|
||
|
|
||
|
define i64 @test_atomic_load_seq_cst_i64() nounwind {
|
||
|
; CHECK-LABEL: test_atomic_load_seq_cst_i64:
|
||
|
%val = load atomic i64, i64* @var64 seq_cst, align 8
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var64
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: ldaexd r0, r1, [r[[ADDR]]]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
ret i64 %val
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_store_monotonic_i8(i8 %val) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_store_monotonic_i8:
|
||
|
store atomic i8 %val, i8* @var8 monotonic, align 1
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
; CHECK: strb r0, [r[[ADDR]]]
|
||
|
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_store_monotonic_regoff_i8(i64 %base, i64 %off, i8 %val) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_store_monotonic_regoff_i8:
|
||
|
|
||
|
%addr_int = add i64 %base, %off
|
||
|
%addr = inttoptr i64 %addr_int to i8*
|
||
|
|
||
|
store atomic i8 %val, i8* %addr monotonic, align 1
|
||
|
; CHECK-LE: ldr{{b?(\.w)?}} [[VAL:r[0-9]+]], [sp]
|
||
|
; CHECK-LE: strb [[VAL]], [r0, r2]
|
||
|
; CHECK-BE: ldrb{{(\.w)?}} [[VAL:r[0-9]+]], [sp, #3]
|
||
|
; CHECK-BE: strb [[VAL]], [r1, r3]
|
||
|
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_store_release_i8(i8 %val) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_store_release_i8:
|
||
|
store atomic i8 %val, i8* @var8 release, align 1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: stlb r0, [r[[ADDR]]]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_store_seq_cst_i8(i8 %val) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_store_seq_cst_i8:
|
||
|
store atomic i8 %val, i8* @var8 seq_cst, align 1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var8
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: stlb r0, [r[[ADDR]]]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_store_monotonic_i16(i16 %val) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_store_monotonic_i16:
|
||
|
store atomic i16 %val, i16* @var16 monotonic, align 2
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movt r[[ADDR]], :upper16:var16
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: strh r0, [r[[ADDR]]]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_store_monotonic_regoff_i32(i64 %base, i64 %off, i32 %val) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_store_monotonic_regoff_i32:
|
||
|
|
||
|
%addr_int = add i64 %base, %off
|
||
|
%addr = inttoptr i64 %addr_int to i32*
|
||
|
|
||
|
store atomic i32 %val, i32* %addr monotonic, align 4
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: ldr [[VAL:r[0-9]+]], [sp]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK-LE: str [[VAL]], [r0, r2]
|
||
|
; CHECK-BE: str [[VAL]], [r1, r3]
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @test_atomic_store_release_i64(i64 %val) nounwind {
|
||
|
; CHECK-LABEL: test_atomic_store_release_i64:
|
||
|
store atomic i64 %val, i64* @var64 release, align 8
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
; CHECK: movw [[ADDR:r[0-9]+|lr]], :lower16:var64
|
||
|
; CHECK: movt [[ADDR]], :upper16:var64
|
||
|
|
||
|
; CHECK: .LBB{{[0-9]+}}_1:
|
||
|
; r0, r1 below is a reasonable guess but could change: it certainly comes into the
|
||
|
; function there.
|
||
|
; CHECK: stlexd [[STATUS:r[0-9]+]], r0, r1, {{.*}}[[ADDR]]
|
||
|
; CHECK-NEXT: cmp [[STATUS]], #0
|
||
|
; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
|
||
|
; CHECK-NOT: dmb
|
||
|
; CHECK-NOT: mcr
|
||
|
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i32 @not.barriers(i32* %var, i1 %cond) {
|
||
|
; CHECK-LABEL: not.barriers:
|
||
|
br i1 %cond, label %atomic_ver, label %simple_ver
|
||
|
simple_ver:
|
||
|
%oldval = load i32, i32* %var
|
||
|
%newval = add nsw i32 %oldval, -1
|
||
|
store i32 %newval, i32* %var
|
||
|
br label %somewhere
|
||
|
atomic_ver:
|
||
|
fence seq_cst
|
||
|
%val = atomicrmw add i32* %var, i32 -1 monotonic
|
||
|
fence seq_cst
|
||
|
br label %somewhere
|
||
|
; CHECK: dmb
|
||
|
; CHECK: ldrex
|
||
|
; CHECK: dmb
|
||
|
; The key point here is that the second dmb isn't immediately followed by the
|
||
|
; simple_ver basic block, which LLVM attempted to do when DMB had been marked
|
||
|
; with isBarrier. For now, look for something that looks like "somewhere".
|
||
|
; CHECK-NEXT: {{mov|bx}}
|
||
|
somewhere:
|
||
|
%combined = phi i32 [ %val, %atomic_ver ], [ %newval, %simple_ver]
|
||
|
ret i32 %combined
|
||
|
}
|