@@ -118,6 +118,7 @@ using namespace llvm;
118118#define DEBUG_TYPE "arm-isel"
119119
120120STATISTIC(NumTailCalls, "Number of tail calls");
121+ STATISTIC(NumOptimizedImms, "Number of times immediates were optimized");
121122STATISTIC(NumMovwMovt, "Number of GAs materialized with movw + movt");
122123STATISTIC(NumLoopByVals, "Number of loops generated for byval arguments");
123124STATISTIC(NumConstpoolPromoted,
@@ -142,6 +143,12 @@ static cl::opt<unsigned> ConstpoolPromotionMaxTotal(
142143 cl::desc("Maximum size of ALL constants to promote into a constant pool"),
143144 cl::init(128));
144145
146+ static cl::opt<bool>
147+ EnableOptimizeLogicalImm("arm-enable-logical-imm", cl::Hidden,
148+ cl::desc("Enable ARM logical imm instruction "
149+ "optimization"),
150+ cl::init(true));
151+
145152cl::opt<unsigned>
146153MVEMaxSupportedInterleaveFactor("mve-max-interleave-factor", cl::Hidden,
147154 cl::desc("Maximum interleave factor for MVE VLDn to generate."),
@@ -20105,6 +20112,16 @@ void ARMTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
2010520112 }
2010620113}
2010720114
20115+ static bool isLegalLogicalImmediate(unsigned Imm,
20116+ const ARMSubtarget *Subtarget) {
20117+ if (!Subtarget->isThumb())
20118+ return ARM_AM::getSOImmVal(Imm) != -1;
20119+ if (Subtarget->isThumb2())
20120+ return ARM_AM::getT2SOImmVal(Imm) != -1;
20121+ // Thumb1 only has 8-bit unsigned immediate.
20122+ return Imm <= 255;
20123+ }
20124+
2010820125bool ARMTargetLowering::targetShrinkDemandedConstant(
2010920126 SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts,
2011020127 TargetLoweringOpt &TLO) const {
@@ -20113,8 +20130,7 @@ bool ARMTargetLowering::targetShrinkDemandedConstant(
2011320130 if (!TLO.LegalOps)
2011420131 return false;
2011520132
20116- // Only optimize AND for now.
20117- if (Op.getOpcode() != ISD::AND)
20133+ if (!EnableOptimizeLogicalImm)
2011820134 return false;
2011920135
2012020136 EVT VT = Op.getValueType();
@@ -20125,28 +20141,28 @@ bool ARMTargetLowering::targetShrinkDemandedConstant(
2012520141
2012620142 assert(VT == MVT::i32 && "Unexpected integer type");
2012720143
20144+ // Exit early if we demand all bits.
20145+ if (DemandedBits.popcount() == 32)
20146+ return false;
20147+
20148+ // Only optimize AND for now.
20149+ if (Op.getOpcode() != ISD::AND)
20150+ return false;
20151+
2012820152 // Make sure the RHS really is a constant.
2012920153 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
2013020154 if (!C)
2013120155 return false;
2013220156
2013320157 unsigned Mask = C->getZExtValue();
2013420158
20159+ if (Mask == 0 || Mask == ~0U)
20160+ return false;
20161+
2013520162 unsigned Demanded = DemandedBits.getZExtValue();
2013620163 unsigned ShrunkMask = Mask & Demanded;
2013720164 unsigned ExpandedMask = Mask | ~Demanded;
2013820165
20139- // If the mask is all zeros, let the target-independent code replace the
20140- // result with zero.
20141- if (ShrunkMask == 0)
20142- return false;
20143-
20144- // If the mask is all ones, erase the AND. (Currently, the target-independent
20145- // code won't do this, so we have to do it explicitly to avoid an infinite
20146- // loop in obscure cases.)
20147- if (ExpandedMask == ~0U)
20148- return TLO.CombineTo(Op, Op.getOperand(0));
20149-
2015020166 auto IsLegalMask = [ShrunkMask, ExpandedMask](unsigned Mask) -> bool {
2015120167 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
2015220168 };
@@ -20159,30 +20175,61 @@ bool ARMTargetLowering::targetShrinkDemandedConstant(
2015920175 return TLO.CombineTo(Op, NewOp);
2016020176 };
2016120177
20162- // Prefer uxtb mask.
20163- if (IsLegalMask(0xFF))
20164- return UseMask(0xFF);
20178+ // If the mask is all zeros, let the target-independent code replace the
20179+ // result with zero.
20180+ if (ShrunkMask == 0) {
20181+ ++NumOptimizedImms;
20182+ return UseMask(ShrunkMask);
20183+ }
2016520184
20166- // Prefer uxth mask.
20167- if (IsLegalMask(0xFFFF))
20168- return UseMask(0xFFFF);
20185+ // If the mask is all ones, erase the AND. (Currently, the target-independent
20186+ // code won't do this, so we have to do it explicitly to avoid an infinite
20187+ // loop in obscure cases.)
20188+ if (ExpandedMask == ~0U) {
20189+ ++NumOptimizedImms;
20190+ return UseMask(ExpandedMask);
20191+ }
2016920192
20170- // [1, 255] is Thumb1 movs+ands, legal immediate for ARM/Thumb2.
20171- // FIXME: Prefer a contiguous sequence of bits for other optimizations.
20172- if (ShrunkMask < 256)
20193+ // If thumb, check for uxth and uxtb masks first and foremost.
20194+ if (Subtarget->isThumb1Only() && Subtarget->hasV6Ops()) {
20195+ if (IsLegalMask(0xFF)) {
20196+ ++NumOptimizedImms;
20197+ return UseMask(0xFF);
20198+ }
20199+
20200+ if (IsLegalMask(0xFFFF)) {
20201+ ++NumOptimizedImms;
20202+ return UseMask(0xFFFF);
20203+ }
20204+ }
20205+
20206+ // Don't optimize if it is legal already.
20207+ if (isLegalLogicalImmediate(Mask, Subtarget))
20208+ return false;
20209+
20210+ if (isLegalLogicalImmediate(ShrunkMask, Subtarget)) {
20211+ ++NumOptimizedImms;
2017320212 return UseMask(ShrunkMask);
20213+ }
2017420214
20175- // [-256, -2] is Thumb1 movs+bics, legal immediate for ARM/Thumb2.
20176- // FIXME: Prefer a contiguous sequence of bits for other optimizations.
20177- if ((int)ExpandedMask <= -2 && (int)ExpandedMask >= -256)
20215+ // FIXME: The check for v6 is because this interferes with some ubfx
20216+ // optimizations
20217+ if (!Subtarget->hasV6Ops() &&
20218+ isLegalLogicalImmediate(~ExpandedMask, Subtarget)) {
20219+ ++NumOptimizedImms;
2017820220 return UseMask(ExpandedMask);
20221+ }
20222+
20223+ if ((~ExpandedMask) < 256) {
20224+ ++NumOptimizedImms;
20225+ return UseMask(ExpandedMask);
20226+ }
2017920227
2018020228 // Potential improvements:
2018120229 //
2018220230 // We could try to recognize lsls+lsrs or lsrs+lsls pairs here.
2018320231 // We could try to prefer Thumb1 immediates which can be lowered to a
2018420232 // two-instruction sequence.
20185- // We could try to recognize more legal ARM/Thumb2 immediates here.
2018620233
2018720234 return false;
2018820235}
0 commit comments