Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -13630,14 +13630,21 @@ unsigned Mask = C->getZExtValue(); - // If mask is zero, nothing to do. - if (!Mask) - return false; - unsigned Demanded = DemandedAPInt.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; + + // 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)); + auto IsLegalMask = [ShrunkMask, ExpandedMask](unsigned Mask) -> bool { return (ShrunkMask & Mask) == ShrunkMask && (~ExpandedMask & Mask) == 0; }; Index: test/CodeGen/ARM/demanded-bits-and.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/demanded-bits-and.ll @@ -0,0 +1,35 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=arm-eabi < %s | FileCheck %s + +; Make sure this doesn't hang, and there are no unnecessary +; "and" instructions. + +define dso_local void @f(i16* %p) { +; CHECK-LABEL: f: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: .LBB0_1: @ %bb +; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: ldrh r1, [r0] +; CHECK-NEXT: and r2, r1, #255 +; CHECK-NEXT: add r3, r2, r1, lsr #8 +; CHECK-NEXT: add r2, r3, r2 +; CHECK-NEXT: add r1, r2, r1, lsr #8 +; CHECK-NEXT: add r1, r1, #2 +; CHECK-NEXT: lsr r1, r1, #2 +; CHECK-NEXT: strh r1, [r0] +; CHECK-NEXT: b .LBB0_1 +entry: + br label %bb + +bb: + %_p_scalar_ = load i16, i16* %p, align 2 + %p_and = and i16 %_p_scalar_, 255 + %p_ = lshr i16 %_p_scalar_, 8 + %p_add = add nuw nsw i16 %p_, 2 + %p_add14 = add nuw nsw i16 %p_add, %p_and + %p_add18 = add nuw nsw i16 %p_add14, %p_and + %p_add19 = add nuw nsw i16 %p_add18, %p_ + %p_200 = lshr i16 %p_add19, 2 + store i16 %p_200, i16* %p, align 2 + br label %bb +}