ARMv6m supports dmb etc fench instructions but not ldrex/strex etc. So for some atomic load/store, LLVM should inline instructions instead of lowering to __sync_ calls.
Details
Diff Detail
Event Timeline
Explicitly checking isARMv6m() is wrong... we want to check features, not specific architectures. I think here, we're interested here in the behavior of targets with the following characteristics:
(1) Are in thumb mode (isThumb())
(2) Support a memory barrier instruction (hasAnyDataBarrier())
(3) Don't support ldrex/strex (!hasV8MBaselineOps())
I think ARMv6sm also has these characteristics; checking features makes the code more clear, and avoids mistakes.
It would also be a good idea to add tests to check that this patch doesn't change the generated code for other atomic operations.
Hi Eli,
I think the problem is the feature for armv6m is not well defined.
ARMv6m is mostly Thumb1, but it also supports 5 32-bit instrs: DL, DMB, DSB. ISM. MRS, MSR
In ARM.td, FeatureDB has already been defined for Armv6m.
However, when existing code actually checks for availability of atomic feature (fence + ldrex/strex), if the target is Thumb but not supports ARMv8mBaseline, then it assumes no such feature.
For example: in ARMISelLowering.cpp::1043
if (Subtarget->hasAnyDataBarrier() && (!Subtarget->isThumb() || Subtarget->hasV8MBaselineOps())
bool ARMSubtarget::enableAtomicExpand() const { return hasAnyDataBarrier(); }
TargetLowering::AtomicExpansionKind ARMTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const { unsigned Size = AI->getType()->getPrimitiveSizeInBits(); return ((!isThumb() || hasV8MBaselineOps()) && Size <= (Subtarget->isMClass() ? 32U : 64U)) ? AtomicExpansionKind::LLSC : AtomicExpansionKind::None; }
Is this not sufficient for some reason?
Agree with the change in shouldExpandAtomicRMWInIR but for ARMSubtarget::enableAtomicExpand(),
changing from
return hasAnyDataBarrier() && (!isThumb() || hasV8MBaselineOps()
to
return hasAnyDataBarrier();
Is it too relax? Seems OK but not very sure.
Should be fine; the whole point of this patch is that you want to run atomic expansion for targets which have dmb, but not ldrex/strex.
Looks fine, but someone more familiar with the ARM backend should double-check I didn't miss anything.
lib/Target/ARM/ARMISelLowering.cpp | ||
---|---|---|
12879 | ARMv7-A/R should not be affected because they have V8MBaselineOps() (inherits from v6t2) |
What about ARMv7-A/R here? Previously we'd return LLSC in this case.