@@ -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."),
@@ -20138,6 +20145,16 @@ void ARMTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
2013820145 }
2013920146}
2014020147
20148+ static bool isLegalLogicalImmediate(unsigned Imm,
20149+ const ARMSubtarget *Subtarget) {
20150+ if (!Subtarget->isThumb())
20151+ return ARM_AM::getSOImmVal(Imm) != -1;
20152+ if (Subtarget->isThumb2())
20153+ return ARM_AM::getT2SOImmVal(Imm) != -1;
20154+ // Thumb1 only has 8-bit unsigned immediate.
20155+ return Imm <= 255;
20156+ }
20157+
2014120158bool ARMTargetLowering::targetShrinkDemandedConstant(
2014220159 SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts,
2014320160 TargetLoweringOpt &TLO) const {
@@ -20146,8 +20163,7 @@ bool ARMTargetLowering::targetShrinkDemandedConstant(
2014620163 if (!TLO.LegalOps)
2014720164 return false;
2014820165
20149- // Only optimize AND for now.
20150- if (Op.getOpcode() != ISD::AND)
20166+ if (!EnableOptimizeLogicalImm)
2015120167 return false;
2015220168
2015320169 EVT VT = Op.getValueType();
@@ -20158,28 +20174,28 @@ bool ARMTargetLowering::targetShrinkDemandedConstant(
2015820174
2015920175 assert(VT == MVT::i32 && "Unexpected integer type");
2016020176
20177+ // Exit early if we demand all bits.
20178+ if (DemandedBits.popcount() == 32)
20179+ return false;
20180+
20181+ // Only optimize AND for now.
20182+ if (Op.getOpcode() != ISD::AND)
20183+ return false;
20184+
2016120185 // Make sure the RHS really is a constant.
2016220186 ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
2016320187 if (!C)
2016420188 return false;
2016520189
2016620190 unsigned Mask = C->getZExtValue();
2016720191
20192+ if (Mask == 0 || Mask == ~0U)
20193+ return false;
20194+
2016820195 unsigned Demanded = DemandedBits.getZExtValue();
2016920196 unsigned ShrunkMask = Mask & Demanded;
2017020197 unsigned ExpandedMask = Mask | ~Demanded;
2017120198
20172- // If the mask is all zeros, let the target-independent code replace the
20173- // result with zero.
20174- if (ShrunkMask == 0)
20175- return false;
20176-
20177- // If the mask is all ones, erase the AND. (Currently, the target-independent
20178- // code won't do this, so we have to do it explicitly to avoid an infinite
20179- // loop in obscure cases.)
20180- if (ExpandedMask == ~0U)
20181- return TLO.CombineTo(Op, Op.getOperand(0));
20182-
2018320199 auto IsLegalMask = [ShrunkMask, ExpandedMask](unsigned Mask) -> bool {
2018420200 return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
2018520201 };
@@ -20192,30 +20208,61 @@ bool ARMTargetLowering::targetShrinkDemandedConstant(
2019220208 return TLO.CombineTo(Op, NewOp);
2019320209 };
2019420210
20195- // Prefer uxtb mask.
20196- if (IsLegalMask(0xFF))
20197- return UseMask(0xFF);
20211+ // If the mask is all zeros, let the target-independent code replace the
20212+ // result with zero.
20213+ if (ShrunkMask == 0) {
20214+ ++NumOptimizedImms;
20215+ return UseMask(ShrunkMask);
20216+ }
2019820217
20199- // Prefer uxth mask.
20200- if (IsLegalMask(0xFFFF))
20201- return UseMask(0xFFFF);
20218+ // If the mask is all ones, erase the AND. (Currently, the target-independent
20219+ // code won't do this, so we have to do it explicitly to avoid an infinite
20220+ // loop in obscure cases.)
20221+ if (ExpandedMask == ~0U) {
20222+ ++NumOptimizedImms;
20223+ return UseMask(ExpandedMask);
20224+ }
2020220225
20203- // [1, 255] is Thumb1 movs+ands, legal immediate for ARM/Thumb2.
20204- // FIXME: Prefer a contiguous sequence of bits for other optimizations.
20205- if (ShrunkMask < 256)
20226+ // If thumb, check for uxth and uxtb masks first and foremost.
20227+ if (Subtarget->isThumb1Only() && Subtarget->hasV6Ops()) {
20228+ if (IsLegalMask(0xFF)) {
20229+ ++NumOptimizedImms;
20230+ return UseMask(0xFF);
20231+ }
20232+
20233+ if (IsLegalMask(0xFFFF)) {
20234+ ++NumOptimizedImms;
20235+ return UseMask(0xFFFF);
20236+ }
20237+ }
20238+
20239+ // Don't optimize if it is legal already.
20240+ if (isLegalLogicalImmediate(Mask, Subtarget))
20241+ return false;
20242+
20243+ if (isLegalLogicalImmediate(ShrunkMask, Subtarget)) {
20244+ ++NumOptimizedImms;
2020620245 return UseMask(ShrunkMask);
20246+ }
2020720247
20208- // [-256, -2] is Thumb1 movs+bics, legal immediate for ARM/Thumb2.
20209- // FIXME: Prefer a contiguous sequence of bits for other optimizations.
20210- if ((int)ExpandedMask <= -2 && (int)ExpandedMask >= -256)
20248+ // FIXME: The check for v6 is because this interferes with some ubfx
20249+ // optimizations
20250+ if (!Subtarget->hasV6Ops() &&
20251+ isLegalLogicalImmediate(~ExpandedMask, Subtarget)) {
20252+ ++NumOptimizedImms;
2021120253 return UseMask(ExpandedMask);
20254+ }
20255+
20256+ if ((~ExpandedMask) < 256) {
20257+ ++NumOptimizedImms;
20258+ return UseMask(ExpandedMask);
20259+ }
2021220260
2021320261 // Potential improvements:
2021420262 //
2021520263 // We could try to recognize lsls+lsrs or lsrs+lsls pairs here.
2021620264 // We could try to prefer Thumb1 immediates which can be lowered to a
2021720265 // two-instruction sequence.
20218- // We could try to recognize more legal ARM/Thumb2 immediates here.
2021920266
2022020267 return false;
2022120268}
0 commit comments