[llvm] 83ecdb7 - ARM: Support OR and XOR in targetShrinkDemandedConstant (#165106)

via llvm-commits llvm-commits at lists.llvm.org
Fri May 1 07:12:03 PDT 2026


Author: LumioseSil
Date: 2026-05-01T15:11:58+01:00
New Revision: 83ecdb701aecb4d041e86e834ddda2640e5ea374

URL: https://github.com/llvm/llvm-project/commit/83ecdb701aecb4d041e86e834ddda2640e5ea374
DIFF: https://github.com/llvm/llvm-project/commit/83ecdb701aecb4d041e86e834ddda2640e5ea374.diff

LOG: ARM: Support OR and XOR in targetShrinkDemandedConstant (#165106)

Also some changes for AND, OR, and XOR, including not changing if it
is legal. This prevents overcorrection to the mask, especially if it
is valid already.

Added: 
    

Modified: 
    llvm/lib/Target/ARM/ARMISelLowering.cpp
    llvm/test/CodeGen/ARM/dagcombine-ld-op-st.ll
    llvm/test/CodeGen/ARM/fpenv.ll
    llvm/test/CodeGen/ARM/illegal-bitfield-loadstore.ll
    llvm/test/CodeGen/ARM/sdiv-pow2-arm-size.ll
    llvm/test/CodeGen/ARM/sdiv-pow2-thumb-size.ll
    llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll
    llvm/test/CodeGen/ARM/urem-seteq-illegal-types.ll
    llvm/test/CodeGen/Thumb/bic_imm.ll
    llvm/test/CodeGen/Thumb2/active_lane_mask.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 9a7cbd949b1e7..9a83dc82192c2 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -118,6 +118,7 @@ using namespace llvm;
 #define DEBUG_TYPE "arm-isel"
 
 STATISTIC(NumTailCalls, "Number of tail calls");
+STATISTIC(NumOptimizedImms, "Number of times immediates were optimized");
 STATISTIC(NumMovwMovt, "Number of GAs materialized with movw + movt");
 STATISTIC(NumLoopByVals, "Number of loops generated for byval arguments");
 STATISTIC(NumConstpoolPromoted,
@@ -20171,88 +20172,158 @@ 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");
+/// Refine i32 AND/OR/XOR with a constant RHS using demanded bits: replace the
+/// immediate with an equivalent constant that ARM/Thumb can encode as a
+/// logical immediate (or that selects better lowering), without changing the
+/// computed result on those demanded bits.
+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->hasV6Ops()) {
+    if (IsLegalImm(0xFF)) {
+      ++NumOptimizedImms;
+      return UseImm(0xFF);
+    }
+
+    if (IsLegalImm(0xFFFF)) {
+      ++NumOptimizedImms;
+      return UseImm(0xFFFF);
+    }
+  }
+
+  // Don't optimize if it is legal.
+  if (isLegalLogicalImmediate(Imm, Subtarget))
+    return false;
 
-  // Prefer uxth mask.
-  if (IsLegalMask(0xFFFF))
-    return UseMask(0xFFFF);
+  // FIXME: Check for BIC being legal causes infinite loop due to target
+  // independent DAG combine undoing this.
 
-  // [1, 255] is Thumb1 movs+ands, legal immediate for ARM/Thumb2.
-  // FIXME: Prefer a contiguous sequence of bits for other optimizations.
-  if (ShrunkMask < 256)
-    return UseMask(ShrunkMask);
+  // Prefer strict shrink when ShrunkImm encodes for this target, before
+  // complement expansion.
+  if (isLegalLogicalImmediate(ShrunkImm, Subtarget)) {
+    ++NumOptimizedImms;
+    return UseImm(ShrunkImm);
+  }
 
-  // [-256, -2] is Thumb1 movs+bics, legal immediate for ARM/Thumb2.
-  // FIXME: Prefer a contiguous sequence of bits for other optimizations.
-  if ((int)ExpandedMask <= -2 && (int)ExpandedMask >= -256)
-    return UseMask(ExpandedMask);
+  // Complement expansion: if all undemanded bits are already one, ExpandedImm
+  // is Imm with every non-demanded bit set. When (~ExpandedImm) < 256, the
+  // complement fits in an 8-bit unsigned value, i.e. bits 8–31 of ExpandedImm
+  // are all ones; only the low byte may 
diff er from ~0. Use that expanded
+  // constant so isel sees a mask shape that fits logical-immediate patterns.
+  if ((~ExpandedImm) < 256) {
+    ++NumOptimizedImms;
+    return UseImm(ExpandedImm);
+  }
+
+  // FIXME: The check for v6 is because this interferes with some ubfx
+  // optimizations.
+  if (Opc == ISD::AND && isLegalLogicalImmediate(~ExpandedImm, Subtarget) &&
+      !Subtarget->hasV6Ops()) {
+    ++NumOptimizedImms;
+    return UseImm(ExpandedImm);
+  }
 
   // Potential improvements:
   //
   // We could try to recognize lsls+lsrs or lsrs+lsls pairs here.
   // We could try to prefer Thumb1 immediates which can be lowered to a
   // two-instruction sequence.
-  // We could try to recognize more legal ARM/Thumb2 immediates here.
 
   return false;
 }
 
+bool ARMTargetLowering::targetShrinkDemandedConstant(
+    SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts,
+    TargetLoweringOpt &TLO) const {
+  // Delay this optimization to as late as possible.
+  if (!TLO.LegalOps)
+    return false;
+
+  EVT VT = Op.getValueType();
+
+  // Ignore vectors.
+  if (VT.isVector())
+    return false;
+
+  unsigned Size = VT.getSizeInBits();
+
+  if (Size != 32)
+    return false;
+
+  // Exit early if we demand all bits.
+  if (DemandedBits.isAllOnes())
+    return false;
+
+  switch (Op.getOpcode()) {
+  default:
+    return false;
+  case ISD::AND:
+  case ISD::OR:
+  case ISD::XOR:
+    break;
+  }
+  ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
+  if (!C)
+    return false;
+  unsigned Imm = C->getZExtValue();
+  return optimizeLogicalImm(Op, Imm, DemandedBits, Subtarget, TLO);
+}
+
 bool ARMTargetLowering::SimplifyDemandedBitsForTargetNode(
     SDValue Op, const APInt &OriginalDemandedBits,
     const APInt &OriginalDemandedElts, KnownBits &Known, TargetLoweringOpt &TLO,

diff  --git a/llvm/test/CodeGen/ARM/dagcombine-ld-op-st.ll b/llvm/test/CodeGen/ARM/dagcombine-ld-op-st.ll
index 6819af3ba3e26..1700751ac4756 100644
--- a/llvm/test/CodeGen/ARM/dagcombine-ld-op-st.ll
+++ b/llvm/test/CodeGen/ARM/dagcombine-ld-op-st.ll
@@ -24,7 +24,7 @@ define i16 @test(ptr %p1) {
 ; CHECK-LE-NORMAL-LABEL: test:
 ; CHECK-LE-NORMAL:       @ %bb.0: @ %entry
 ; CHECK-LE-NORMAL-NEXT:    ldrh r1, [r0, #8]
-; CHECK-LE-NORMAL-NEXT:    movw r2, #65534
+; CHECK-LE-NORMAL-NEXT:    mvn r2, #1
 ; CHECK-LE-NORMAL-NEXT:    orr r1, r1, r2
 ; CHECK-LE-NORMAL-NEXT:    strh r1, [r0, #8]
 ; CHECK-LE-NORMAL-NEXT:    mov r0, #0
@@ -42,7 +42,7 @@ define i16 @test(ptr %p1) {
 ; CHECK-BE-NORMAL-LABEL: test:
 ; CHECK-BE-NORMAL:       @ %bb.0: @ %entry
 ; CHECK-BE-NORMAL-NEXT:    ldrh r1, [r0]
-; CHECK-BE-NORMAL-NEXT:    movw r2, #65534
+; CHECK-BE-NORMAL-NEXT:    mvn r2, #1
 ; CHECK-BE-NORMAL-NEXT:    orr r1, r1, r2
 ; CHECK-BE-NORMAL-NEXT:    strh r1, [r0]
 ; CHECK-BE-NORMAL-NEXT:    mov r0, #0

diff  --git a/llvm/test/CodeGen/ARM/fpenv.ll b/llvm/test/CodeGen/ARM/fpenv.ll
index f5d87170d9153..57e264d97bc44 100644
--- a/llvm/test/CodeGen/ARM/fpenv.ll
+++ b/llvm/test/CodeGen/ARM/fpenv.ll
@@ -41,8 +41,8 @@ define void @func_05() {
 ; CHECK-LABEL: func_05:
 ; CHECK:       @ %bb.0:
 ; CHECK-NEXT:    vmrs r0, fpscr
-; CHECK-NEXT:    bic r0, r0, #12582912
 ; CHECK-NEXT:    orr r0, r0, #4194304
+; CHECK-NEXT:    bic r0, r0, #8388608
 ; CHECK-NEXT:    vmsr fpscr, r0
 ; CHECK-NEXT:    mov pc, lr
   call void @llvm.set.rounding(i32 2)
@@ -53,8 +53,8 @@ define void @func_06() {
 ; CHECK-LABEL: func_06:
 ; CHECK:       @ %bb.0:
 ; CHECK-NEXT:    vmrs r0, fpscr
-; CHECK-NEXT:    bic r0, r0, #12582912
 ; CHECK-NEXT:    orr r0, r0, #8388608
+; CHECK-NEXT:    bic r0, r0, #4194304
 ; CHECK-NEXT:    vmsr fpscr, r0
 ; CHECK-NEXT:    mov pc, lr
   call void @llvm.set.rounding(i32 3)

diff  --git a/llvm/test/CodeGen/ARM/illegal-bitfield-loadstore.ll b/llvm/test/CodeGen/ARM/illegal-bitfield-loadstore.ll
index 5dbf8dd86b891..822bb89ecf22a 100644
--- a/llvm/test/CodeGen/ARM/illegal-bitfield-loadstore.ll
+++ b/llvm/test/CodeGen/ARM/illegal-bitfield-loadstore.ll
@@ -53,10 +53,8 @@ define void @i24_and_or(ptr %a) {
 define void @i24_insert_bit(ptr %a, i1 zeroext %bit) {
 ; LE-LABEL: i24_insert_bit:
 ; LE:       @ %bb.0:
-; LE-NEXT:    mov r3, #255
 ; LE-NEXT:    ldrh r2, [r0]
-; LE-NEXT:    orr r3, r3, #57088
-; LE-NEXT:    and r2, r2, r3
+; LE-NEXT:    bic r2, r2, #8192
 ; LE-NEXT:    orr r1, r2, r1, lsl #13
 ; LE-NEXT:    strh r1, [r0]
 ; LE-NEXT:    mov pc, lr
@@ -64,8 +62,7 @@ define void @i24_insert_bit(ptr %a, i1 zeroext %bit) {
 ; BE-LABEL: i24_insert_bit:
 ; BE:       @ %bb.0:
 ; BE-NEXT:    ldrh r2, [r0]
-; BE-NEXT:    mov r3, #57088
-; BE-NEXT:    orr r3, r3, #16711680
+; BE-NEXT:    mvn r3, #8192
 ; BE-NEXT:    and r2, r3, r2, lsl #8
 ; BE-NEXT:    orr r1, r2, r1, lsl #13
 ; BE-NEXT:    lsr r1, r1, #8
@@ -144,8 +141,7 @@ define void @i56_insert_bit(ptr %a, i1 zeroext %bit) {
 ; BE-LABEL: i56_insert_bit:
 ; BE:       @ %bb.0:
 ; BE-NEXT:    ldrh r2, [r0, #4]!
-; BE-NEXT:    mov r3, #57088
-; BE-NEXT:    orr r3, r3, #16711680
+; BE-NEXT:    mvn r3, #8192
 ; BE-NEXT:    and r2, r3, r2, lsl #8
 ; BE-NEXT:    orr r1, r2, r1, lsl #13
 ; BE-NEXT:    lsr r1, r1, #8

diff  --git a/llvm/test/CodeGen/ARM/sdiv-pow2-arm-size.ll b/llvm/test/CodeGen/ARM/sdiv-pow2-arm-size.ll
index a9eda31e729e2..53bc7f603bde1 100644
--- a/llvm/test/CodeGen/ARM/sdiv-pow2-arm-size.ll
+++ b/llvm/test/CodeGen/ARM/sdiv-pow2-arm-size.ll
@@ -1,13 +1,16 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc -mtriple=armv7a -mattr=+hwdiv-arm %s -o - | FileCheck %s --check-prefixes=CHECK,DIV
 ; RUN: llc -mtriple=armv7a -mattr=-hwdiv-arm %s -o - | FileCheck %s --check-prefixes=CHECK,NODIV
 
 ; Check SREM
 define dso_local i32 @test_rem(i32 %F) local_unnamed_addr #0 {
-; CHECK-LABEL: test_rem 
-; CHECK:       asr   r1, r0, #31
-; CHECK-NEXT:  add   r1, r0, r1, lsr #30
-; CHECK-NEXT:  bic   r1, r1, #3
-; CHECK-NEXT:  sub   r0, r0, r1
+; CHECK-LABEL: test_rem:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    asr r1, r0, #31
+; CHECK-NEXT:    add r1, r0, r1, lsr #30
+; CHECK-NEXT:    bic r1, r1, #3
+; CHECK-NEXT:    sub r0, r0, r1
+; CHECK-NEXT:    bx lr
 
 entry:
   %div = srem i32 %F, 4
@@ -16,18 +19,22 @@ entry:
 
 ; Try an i16 sdiv, with a small immediate.
 define dso_local signext i16 @f0(i16 signext %F) local_unnamed_addr #0 {
-; CHECK-LABEL: f0
+; DIV-LABEL: f0:
+; DIV:       @ %bb.0: @ %entry
+; DIV-NEXT:    mov r1, #2
+; DIV-NEXT:    sdiv r0, r0, r1
+; DIV-NEXT:    sxth r0, r0
+; DIV-NEXT:    bx lr
+;
+; NODIV-LABEL: f0:
+; NODIV:       @ %bb.0: @ %entry
+; NODIV-NEXT:    uxth r1, r0
+; NODIV-NEXT:    add r0, r0, r1, lsr #15
+; NODIV-NEXT:    sxth r0, r0
+; NODIV-NEXT:    asr r0, r0, #1
+; NODIV-NEXT:    bx lr
 
-; DIV:         mov     r1, #2
-; DIV-NEXT:    sdiv    r0, r0, r1
-; DIV-NEXT:    sxth    r0, r0
-; DIV-NEXT:    bx      lr
 
-; NODIV:       uxth r1, r0
-; NODIV-NEXT:  add  r0, r0, r1, lsr #15
-; NODIV-NEXT:  sxth r0, r0
-; NODIV-NEXT:  asr  r0, r0, #1
-; NODIV-NEXT:  bx   lr
 
 entry:
   %0 = sdiv i16 %F, 2
@@ -36,16 +43,20 @@ entry:
 
 ; Try an i32 sdiv, with a small immediate.
 define dso_local i32 @f1(i32 %F) local_unnamed_addr #0 {
-; CHECK-LABEL: f1
+; DIV-LABEL: f1:
+; DIV:       @ %bb.0: @ %entry
+; DIV-NEXT:    mov r1, #4
+; DIV-NEXT:    sdiv r0, r0, r1
+; DIV-NEXT:    bx lr
+;
+; NODIV-LABEL: f1:
+; NODIV:       @ %bb.0: @ %entry
+; NODIV-NEXT:    asr r1, r0, #31
+; NODIV-NEXT:    add r0, r0, r1, lsr #30
+; NODIV-NEXT:    asr r0, r0, #2
+; NODIV-NEXT:    bx lr
 
-; DIV:       mov     r1, #4
-; DIV-NEXT:  sdiv    r0, r0, r1
-; DIV-NEXT:  bx      lr
 
-; NODIV:       asr  r1, r0, #31
-; NODIV-NEXT:  add  r0, r0, r1, lsr #30
-; NODIV-NEXT:  asr  r0, r0, #2
-; NODIV-NEXT:  bx	  lr
 
 entry:
   %div = sdiv i32 %F, 4
@@ -55,10 +66,18 @@ entry:
 ; Try a large power of 2 immediate, which should also be materialised with 1
 ; move immediate instruction.
 define dso_local i32 @f2(i32 %F) local_unnamed_addr #0 {
-; CHECK-LABEL:  f2
-; DIV:        mov r1, #131072
-; DIV-NEXT:   sdiv  r0, r0, r1
-; DIV-NEXT:   bx  lr
+; DIV-LABEL: f2:
+; DIV:       @ %bb.0: @ %entry
+; DIV-NEXT:    mov r1, #131072
+; DIV-NEXT:    sdiv r0, r0, r1
+; DIV-NEXT:    bx lr
+;
+; NODIV-LABEL: f2:
+; NODIV:       @ %bb.0: @ %entry
+; NODIV-NEXT:    asr r1, r0, #31
+; NODIV-NEXT:    add r0, r0, r1, lsr #15
+; NODIV-NEXT:    asr r0, r0, #17
+; NODIV-NEXT:    bx lr
 entry:
   %div = sdiv i32 %F, 131072
   ret i32 %div
@@ -66,11 +85,12 @@ entry:
 
 ; MinSize not set, so should expand to the faster but longer sequence.
 define dso_local i32 @f3(i32 %F) {
-; CHECK-LABEL: f3
-; CHECK:       asr r1, r0, #31
-; CHECK-NEXT:  add r0, r0, r1, lsr #30
-; CHECK-NEXT:  asr r0, r0, #2
-; CHECK-NEXT:  bx  lr
+; CHECK-LABEL: f3:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    asr r1, r0, #31
+; CHECK-NEXT:    add r0, r0, r1, lsr #30
+; CHECK-NEXT:    asr r0, r0, #2
+; CHECK-NEXT:    bx lr
 entry:
   %div = sdiv i32 %F, 4
   ret i32 %div

diff  --git a/llvm/test/CodeGen/ARM/sdiv-pow2-thumb-size.ll b/llvm/test/CodeGen/ARM/sdiv-pow2-thumb-size.ll
index 4b0419577cdf0..cfd37bd3b86c0 100644
--- a/llvm/test/CodeGen/ARM/sdiv-pow2-thumb-size.ll
+++ b/llvm/test/CodeGen/ARM/sdiv-pow2-thumb-size.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc -mtriple=thumbv8 %s -o -       | FileCheck %s --check-prefixes=CHECK,T2
 ; RUN: llc -mtriple=thumbv8m.main %s -o - | FileCheck %s --check-prefixes=CHECK,T2
 ; RUN: llc -mtriple=thumbv8m.base %s -o - | FileCheck %s --check-prefixes=CHECK,T1
@@ -13,11 +14,21 @@
 
 ; Test sdiv i16
 define dso_local signext i16 @f0(i16 signext %F) local_unnamed_addr #0 {
-; CHECK-LABEL: f0
-; CHECK:       movs    r1, #2
-; CHECK-NEXT:  sdiv    r0, r0, r1
-; CHECK-NEXT:  sxth    r0, r0
-; CHECK-NEXT:  bx      lr
+; CHECK-LABEL: f0:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    movs r1, #2
+; CHECK-NEXT:    sdiv r0, r0, r1
+; CHECK-NEXT:    sxth r0, r0
+; CHECK-NEXT:    bx lr
+;
+; V6M-LABEL: f0:
+; V6M:       @ %bb.0: @ %entry
+; V6M-NEXT:    uxth r1, r0
+; V6M-NEXT:    lsrs r1, r1, #15
+; V6M-NEXT:    adds r0, r0, r1
+; V6M-NEXT:    sxth r0, r0
+; V6M-NEXT:    asrs r0, r0, #1
+; V6M-NEXT:    bx lr
 
 entry:
   %0 = sdiv i16 %F, 2
@@ -26,10 +37,19 @@ entry:
 
 ; Same as above, but now with i32
 define dso_local i32 @f1(i32 %F) local_unnamed_addr #0 {
-; CHECK-LABEL: f1
-; CHECK:       movs    r1, #4
-; CHECK-NEXT:  sdiv    r0, r0, r1
-; CHECK-NEXT:  bx      lr
+; CHECK-LABEL: f1:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    movs r1, #4
+; CHECK-NEXT:    sdiv r0, r0, r1
+; CHECK-NEXT:    bx lr
+;
+; V6M-LABEL: f1:
+; V6M:       @ %bb.0: @ %entry
+; V6M-NEXT:    asrs r1, r0, #31
+; V6M-NEXT:    lsrs r1, r1, #30
+; V6M-NEXT:    adds r0, r0, r1
+; V6M-NEXT:    asrs r0, r0, #2
+; V6M-NEXT:    bx lr
 
 entry:
   %div = sdiv i32 %F, 4
@@ -38,10 +58,18 @@ entry:
 
 ; The immediate is not a power of 2, so we expect a sdiv.
 define dso_local i32 @f2(i32 %F) local_unnamed_addr #0 {
-; CHECK-LABEL: f2
-; CHECK:       movs    r1, #5
-; CHECK-NEXT:  sdiv    r0, r0, r1
-; CHECK-NEXT:  bx      lr
+; CHECK-LABEL: f2:
+; CHECK:       @ %bb.0: @ %entry
+; CHECK-NEXT:    movs r1, #5
+; CHECK-NEXT:    sdiv r0, r0, r1
+; CHECK-NEXT:    bx lr
+;
+; V6M-LABEL: f2:
+; V6M:       @ %bb.0: @ %entry
+; V6M-NEXT:    push {r7, lr}
+; V6M-NEXT:    movs r1, #5
+; V6M-NEXT:    bl __divsi3
+; V6M-NEXT:    pop {r7, pc}
 
 entry:
   %div = sdiv i32 %F, 5
@@ -51,8 +79,28 @@ entry:
 ; Try a larger power of 2 immediate: immediates larger than
 ; 128 don't give any code size savings.
 define dso_local i32 @f3(i32 %F) local_unnamed_addr #0 {
-; CHECK-LABEL:  f3
-; CHECK-NOT:    sdiv
+; T2-LABEL: f3:
+; T2:       @ %bb.0: @ %entry
+; T2-NEXT:    asrs r1, r0, #31
+; T2-NEXT:    add.w r0, r0, r1, lsr #24
+; T2-NEXT:    asrs r0, r0, #8
+; T2-NEXT:    bx lr
+;
+; T1-LABEL: f3:
+; T1:       @ %bb.0: @ %entry
+; T1-NEXT:    asrs r1, r0, #31
+; T1-NEXT:    lsrs r1, r1, #24
+; T1-NEXT:    adds r0, r0, r1
+; T1-NEXT:    asrs r0, r0, #8
+; T1-NEXT:    bx lr
+;
+; V6M-LABEL: f3:
+; V6M:       @ %bb.0: @ %entry
+; V6M-NEXT:    asrs r1, r0, #31
+; V6M-NEXT:    lsrs r1, r1, #24
+; V6M-NEXT:    adds r0, r0, r1
+; V6M-NEXT:    asrs r0, r0, #8
+; V6M-NEXT:    bx lr
 entry:
   %div = sdiv i32 %F, 256
   ret i32 %div
@@ -65,20 +113,32 @@ attributes #0 = { minsize norecurse nounwind optsize readnone }
 ; the sdiv to sdiv, but to the faster instruction sequence.
 
 define dso_local signext i16 @f4(i16 signext %F) {
-; T2-LABEL:  f4
-; T2:        uxth    r1, r0
-; T2-NEXT:   add.w   r0, r0, r1, lsr #15
-; T2-NEXT:   sxth    r0, r0
-; T2-NEXT:   asrs    r0, r0, #1
-; T2-NEXT:   bx      lr
-
-; T1-LABEL: f4
-; T1: 	    uxth  r1, r0
-; T1-NEXT: 	lsrs  r1, r1, #15
-; T1-NEXT: 	adds  r0, r0, r1
-; T1-NEXT: 	sxth  r0, r0
-; T1-NEXT: 	asrs  r0, r0, #1
-; T1-NEXT: 	bx	lr
+; T2-LABEL: f4:
+; T2:       @ %bb.0: @ %entry
+; T2-NEXT:    uxth r1, r0
+; T2-NEXT:    add.w r0, r0, r1, lsr #15
+; T2-NEXT:    sxth r0, r0
+; T2-NEXT:    asrs r0, r0, #1
+; T2-NEXT:    bx lr
+;
+; T1-LABEL: f4:
+; T1:       @ %bb.0: @ %entry
+; T1-NEXT:    uxth r1, r0
+; T1-NEXT:    lsrs r1, r1, #15
+; T1-NEXT:    adds r0, r0, r1
+; T1-NEXT:    sxth r0, r0
+; T1-NEXT:    asrs r0, r0, #1
+; T1-NEXT:    bx lr
+;
+; V6M-LABEL: f4:
+; V6M:       @ %bb.0: @ %entry
+; V6M-NEXT:    uxth r1, r0
+; V6M-NEXT:    lsrs r1, r1, #15
+; V6M-NEXT:    adds r0, r0, r1
+; V6M-NEXT:    sxth r0, r0
+; V6M-NEXT:    asrs r0, r0, #1
+; V6M-NEXT:    bx lr
+
 
 entry:
   %0 = sdiv i16 %F, 2
@@ -86,18 +146,29 @@ entry:
 }
 
 define dso_local i32 @f5(i32 %F) {
-; T2-LABEL: f5
-; T2:       asrs  r1, r0, #31
-; T2-NEXT:  add.w   r0, r0, r1, lsr #30
-; T2-NEXT:  asrs    r0, r0, #2
-; T2-NEXT:  bx      lr
-
-; T1-LABEL: f5
-; T1: 	    asrs r1, r0, #31
-; T1-NEXT:	lsrs  r1, r1, #30
-; T1-NEXT:	adds  r0, r0, r1
-; T1-NEXT:	asrs  r0, r0, #2
-; T1-NEXT:	bx  lr
+; T2-LABEL: f5:
+; T2:       @ %bb.0: @ %entry
+; T2-NEXT:    asrs r1, r0, #31
+; T2-NEXT:    add.w r0, r0, r1, lsr #30
+; T2-NEXT:    asrs r0, r0, #2
+; T2-NEXT:    bx lr
+;
+; T1-LABEL: f5:
+; T1:       @ %bb.0: @ %entry
+; T1-NEXT:    asrs r1, r0, #31
+; T1-NEXT:    lsrs r1, r1, #30
+; T1-NEXT:    adds r0, r0, r1
+; T1-NEXT:    asrs r0, r0, #2
+; T1-NEXT:    bx lr
+;
+; V6M-LABEL: f5:
+; V6M:       @ %bb.0: @ %entry
+; V6M-NEXT:    asrs r1, r0, #31
+; V6M-NEXT:    lsrs r1, r1, #30
+; V6M-NEXT:    adds r0, r0, r1
+; V6M-NEXT:    asrs r0, r0, #2
+; V6M-NEXT:    bx lr
+
 
 entry:
   %div = sdiv i32 %F, 4

diff  --git a/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll b/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll
index 838da59f9e412..a5f3822bfa1ae 100644
--- a/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll
+++ b/llvm/test/CodeGen/ARM/simplifysetcc_narrow_load.ll
@@ -24,9 +24,7 @@ define i1 @test_129_15_0(ptr %y) {
 ; CHECK-LE-LABEL: test_129_15_0:
 ; CHECK-LE:       @ %bb.0:
 ; CHECK-LE-NEXT:    ldrh r0, [r0]
-; CHECK-LE-NEXT:    mov r1, #255
-; CHECK-LE-NEXT:    orr r1, r1, #32512
-; CHECK-LE-NEXT:    ands r0, r0, r1
+; CHECK-LE-NEXT:    bics r0, r0, #32768
 ; CHECK-LE-NEXT:    movne r0, #1
 ; CHECK-LE-NEXT:    mov pc, lr
 ;

diff  --git a/llvm/test/CodeGen/ARM/urem-seteq-illegal-types.ll b/llvm/test/CodeGen/ARM/urem-seteq-illegal-types.ll
index 6fff0d9b155ef..9f703567f122f 100644
--- a/llvm/test/CodeGen/ARM/urem-seteq-illegal-types.ll
+++ b/llvm/test/CodeGen/ARM/urem-seteq-illegal-types.ll
@@ -90,7 +90,7 @@ define i1 @test_urem_even(i27 %X) nounwind {
 ; ARM5:       @ %bb.0:
 ; ARM5-NEXT:    ldr r1, .LCPI1_0
 ; ARM5-NEXT:    mul r2, r0, r1
-; ARM5-NEXT:    bic r0, r2, #-134217727
+; ARM5-NEXT:    bic r0, r2, #134217728
 ; ARM5-NEXT:    lsr r0, r0, #1
 ; ARM5-NEXT:    orr r0, r0, r2, lsl #26
 ; ARM5-NEXT:    ldr r2, .LCPI1_1
@@ -333,11 +333,9 @@ define <3 x i1> @test_urem_vec(<3 x i11> %X) nounwind {
 ; ARM5-NEXT:    mov r3, #171
 ; ARM5-NEXT:    orr r3, r3, #512
 ; ARM5-NEXT:    mul r12, r0, r3
-; ARM5-NEXT:    mov r0, #1020
-; ARM5-NEXT:    orr r0, r0, #1024
 ; ARM5-NEXT:    mov r3, #254
 ; ARM5-NEXT:    orr r3, r3, #1792
-; ARM5-NEXT:    and r0, r12, r0
+; ARM5-NEXT:    bic r0, r12, #2048
 ; ARM5-NEXT:    lsr r0, r0, #1
 ; ARM5-NEXT:    orr r0, r0, r12, lsl #10
 ; ARM5-NEXT:    sub r12, r1, #1

diff  --git a/llvm/test/CodeGen/Thumb/bic_imm.ll b/llvm/test/CodeGen/Thumb/bic_imm.ll
index 741b2cf8db2e3..a2fc448670f0c 100644
--- a/llvm/test/CodeGen/Thumb/bic_imm.ll
+++ b/llvm/test/CodeGen/Thumb/bic_imm.ll
@@ -82,7 +82,7 @@ define void @truncated_neg256(i16 %a, ptr %p) {
 ;
 ; CHECK-T2-LABEL: truncated_neg256:
 ; CHECK-T2:       @ %bb.0:
-; CHECK-T2-NEXT:    bic r0, r0, #255
+; CHECK-T2-NEXT:    and r0, r0, #65280
 ; CHECK-T2-NEXT:    strh r0, [r1]
 ; CHECK-T2-NEXT:    bx lr
   %and = and i16 %a, -256

diff  --git a/llvm/test/CodeGen/Thumb2/active_lane_mask.ll b/llvm/test/CodeGen/Thumb2/active_lane_mask.ll
index bcd92f81911b2..b75f1ff742bee 100644
--- a/llvm/test/CodeGen/Thumb2/active_lane_mask.ll
+++ b/llvm/test/CodeGen/Thumb2/active_lane_mask.ll
@@ -283,7 +283,7 @@ define void @test_width2(ptr nocapture readnone %x, ptr nocapture %y, i8 zeroext
 ; CHECK-NEXT:  @ %bb.1: @ %for.body.preheader
 ; CHECK-NEXT:    adds r0, r2, #1
 ; CHECK-NEXT:    movs r3, #1
-; CHECK-NEXT:    bic r0, r0, #1
+; CHECK-NEXT:    and r0, r0, #510
 ; CHECK-NEXT:    subs r0, #2
 ; CHECK-NEXT:    add.w r0, r3, r0, lsr #1
 ; CHECK-NEXT:    dls lr, r0


        


More information about the llvm-commits mailing list