[llvm] ARM: Support OR and XOR in targetShrinkDemandedConstant (PR #165106)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 27 05:30:46 PDT 2026
================
@@ -20132,88 +20133,151 @@ void ARMTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
}
}
-bool ARMTargetLowering::targetShrinkDemandedConstant(
- SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts,
- TargetLoweringOpt &TLO) const {
- // Delay optimization, so we don't have to deal with illegal types, or block
- // optimizations.
- if (!TLO.LegalOps)
- return false;
-
- // Only optimize AND for now.
- if (Op.getOpcode() != ISD::AND)
- return false;
-
- EVT VT = Op.getValueType();
-
- // Ignore vectors.
- if (VT.isVector())
- return false;
+static bool isLegalLogicalImmediate(unsigned Imm,
+ const ARMSubtarget *Subtarget) {
+ if (!Subtarget->isThumb())
+ return ARM_AM::getSOImmVal(Imm) != -1;
+ if (Subtarget->isThumb2())
+ return ARM_AM::getT2SOImmVal(Imm) != -1;
+ // Thumb1 only has 8-bit unsigned immediate.
+ return Imm <= 255;
+}
- assert(VT == MVT::i32 && "Unexpected integer type");
+/// Demanded-bits refinements for i32 AND/OR/XOR with a constant RHS (mirrors
+/// AArch64's optimizeLogicalImm helper, but encodes ARM/Thumb immediate rules).
+static bool optimizeLogicalImm(SDValue Op, unsigned Imm,
+ const APInt &DemandedBits,
+ const ARMSubtarget *Subtarget,
+ TargetLowering::TargetLoweringOpt &TLO) {
- // Make sure the RHS really is a constant.
- ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
- if (!C)
+ if (Imm == 0 || Imm == ~0U)
return false;
- unsigned Mask = C->getZExtValue();
-
+ unsigned Opc = Op.getOpcode();
unsigned Demanded = DemandedBits.getZExtValue();
- unsigned ShrunkMask = Mask & Demanded;
- unsigned ExpandedMask = Mask | ~Demanded;
-
- // If the mask is all zeros, let the target-independent code replace the
- // result with zero.
- if (ShrunkMask == 0)
- return false;
+ EVT VT = Op.getValueType();
- // If the mask is all ones, erase the AND. (Currently, the target-independent
- // code won't do this, so we have to do it explicitly to avoid an infinite
- // loop in obscure cases.)
- if (ExpandedMask == ~0U)
- return TLO.CombineTo(Op, Op.getOperand(0));
+ unsigned ShrunkImm = Imm & Demanded;
+ unsigned ExpandedImm = Imm | ~Demanded;
- auto IsLegalMask = [ShrunkMask, ExpandedMask](unsigned Mask) -> bool {
- return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0;
+ auto IsLegalImm = [ShrunkImm, ExpandedImm](unsigned CandidateImm) -> bool {
+ return (ShrunkImm & CandidateImm) == ShrunkImm &&
+ (~ExpandedImm & CandidateImm) == 0;
};
- auto UseMask = [Mask, Op, VT, &TLO](unsigned NewMask) -> bool {
- if (NewMask == Mask)
+ auto UseImm = [Imm, Opc, Op, VT, &TLO](unsigned NewImm) -> bool {
+ if (NewImm == Imm)
return true;
SDLoc DL(Op);
- SDValue NewC = TLO.DAG.getConstant(NewMask, DL, VT);
- SDValue NewOp = TLO.DAG.getNode(ISD::AND, DL, VT, Op.getOperand(0), NewC);
+ SDValue NewC = TLO.DAG.getConstant(NewImm, DL, VT);
+ SDValue NewOp =
+ TLO.DAG.getNode(Opc, DL, VT, Op.getOperand(0), NewC, Op->getFlags());
return TLO.CombineTo(Op, NewOp);
};
- // Prefer uxtb mask.
- if (IsLegalMask(0xFF))
- return UseMask(0xFF);
+ // Shrunk immediate is 0: AND becomes zero; OR/XOR with 0 leaves the other
+ // operand (still valid on demanded bits).
+ if (ShrunkImm == 0) {
+ ++NumOptimizedImms;
+ return UseImm(ShrunkImm);
+ }
+
+ // If the immediate is all ones: for AND this removes the operation; for
+ // OR/XOR it remains a transform valid on demanded bits. (Target-independent
+ // shrink may not fold this, so keep it to avoid obscure combine loops.)
+ if (ExpandedImm == ~0U) {
+ ++NumOptimizedImms;
+ return UseImm(ExpandedImm);
+ }
+
+ // Thumb1: prefer 0xFF / 0xFFFF when they fit the demanded-bit envelope so
+ // lowering can match uxtb / uxth (AND immediates only; OR/XOR do not use
+ // that). Run this before strict ShrunkImm: a tight 8-bit ShrunkImm can be
+ // legal while 0xFF still matches the envelope and yields better isel (uxtb).
+ if (Opc == ISD::AND && Subtarget->isThumb1Only() && Subtarget->hasV6Ops()) {
----------------
LumioseSil wrote:
Tried that. No real benefit.
https://github.com/llvm/llvm-project/pull/165106
More information about the llvm-commits
mailing list