Index: llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -826,6 +826,20 @@ // do simplifications that apply to *just* the one user if we know that // this instruction has a simpler value in that context. switch (I->getOpcode()) { + case Instruction::Add: { + const APInt *C; + if (match(I->getOperand(1), m_APInt(C))) { + // Right fill the demanded bits for this add to demand the most + // significant demanded bit and all those below it. + unsigned Ctlz = DemandedMask.countLeadingZeros(); + APInt LowMask(APInt::getLowBitsSet(BitWidth, BitWidth - Ctlz)); + // If we are adding zeros to every bit below the highest demanded bit, + // just return the add's variable operand. + if ((*C & LowMask).isNullValue()) + return I->getOperand(0); + } + break; + } case Instruction::And: { // If either the LHS or the RHS are Zero, the result is zero. computeKnownBits(I->getOperand(1), RHSKnown, Depth + 1, CxtI); Index: llvm/test/Transforms/InstCombine/and.ll =================================================================== --- llvm/test/Transforms/InstCombine/and.ll +++ llvm/test/Transforms/InstCombine/and.ll @@ -1049,11 +1049,13 @@ ret <2 x i32> %and } +; Multi-use demanded bits - 'add' doesn't change 'and' + define i8 @lowmask_add(i8 %x) { ; CHECK-LABEL: @lowmask_add( ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -64 ; CHECK-NEXT: call void @use8(i8 [[A]]) -; CHECK-NEXT: [[R:%.*]] = and i8 [[A]], 32 +; CHECK-NEXT: [[R:%.*]] = and i8 [[X]], 32 ; CHECK-NEXT: ret i8 [[R]] ; %a = add i8 %x, -64 ; 0xc0 @@ -1062,6 +1064,8 @@ ret i8 %r } +; Negative test - mask overlaps low bit of add + define i8 @not_lowmask_add(i8 %x) { ; CHECK-LABEL: @not_lowmask_add( ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -64 @@ -1075,6 +1079,8 @@ ret i8 %r } +; Negative test - mask overlaps low bit of add + define i8 @not_lowmask_add2(i8 %x) { ; CHECK-LABEL: @not_lowmask_add2( ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -96 @@ -1088,11 +1094,13 @@ ret i8 %r } +; Multi-use demanded bits - 'add' doesn't change 'and' + define <2 x i8> @lowmask_add_splat(<2 x i8> %x, <2 x i8>* %p) { ; CHECK-LABEL: @lowmask_add_splat( ; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X:%.*]], ; CHECK-NEXT: store <2 x i8> [[A]], <2 x i8>* [[P:%.*]], align 2 -; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[A]], +; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[X]], ; CHECK-NEXT: ret <2 x i8> [[R]] ; %a = add <2 x i8> %x, ; 0xc0 Index: llvm/test/Transforms/LoopVectorize/X86/float-induction-x86.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/X86/float-induction-x86.ll +++ llvm/test/Transforms/LoopVectorize/X86/float-induction-x86.ll @@ -35,7 +35,7 @@ ; AUTO_VEC-NEXT: [[TMP4:%.*]] = icmp ult i64 [[TMP1]], 96 ; AUTO_VEC-NEXT: br i1 [[TMP4]], label [[MIDDLE_BLOCK_UNR_LCSSA:%.*]], label [[VECTOR_PH_NEW:%.*]] ; AUTO_VEC: vector.ph.new: -; AUTO_VEC-NEXT: [[UNROLL_ITER:%.*]] = and i64 [[TMP3]], 1152921504606846972 +; AUTO_VEC-NEXT: [[UNROLL_ITER:%.*]] = and i64 [[TMP3]], -4 ; AUTO_VEC-NEXT: br label [[VECTOR_BODY:%.*]] ; AUTO_VEC: vector.body: ; AUTO_VEC-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH_NEW]] ], [ [[INDEX_NEXT_3:%.*]], [[VECTOR_BODY]] ] @@ -306,7 +306,7 @@ ; AUTO_VEC-NEXT: [[TMP5:%.*]] = icmp ult i64 [[TMP2]], 48 ; AUTO_VEC-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK_UNR_LCSSA:%.*]], label [[VECTOR_PH_NEW:%.*]] ; AUTO_VEC: vector.ph.new: -; AUTO_VEC-NEXT: [[UNROLL_ITER:%.*]] = and i64 [[TMP4]], 2305843009213693948 +; AUTO_VEC-NEXT: [[UNROLL_ITER:%.*]] = and i64 [[TMP4]], -4 ; AUTO_VEC-NEXT: br label [[VECTOR_BODY:%.*]] ; AUTO_VEC: vector.body: ; AUTO_VEC-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH_NEW]] ], [ [[INDEX_NEXT_3:%.*]], [[VECTOR_BODY]] ] Index: llvm/test/Transforms/LoopVectorize/if-conversion-nest.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/if-conversion-nest.ll +++ llvm/test/Transforms/LoopVectorize/if-conversion-nest.ll @@ -25,7 +25,7 @@ ; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]] ; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 8589934588 +; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], -4 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] Index: llvm/test/Transforms/LoopVectorize/runtime-check.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/runtime-check.ll +++ llvm/test/Transforms/LoopVectorize/runtime-check.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function foo ; RUN: opt < %s -loop-vectorize -force-vector-interleave=1 -force-vector-width=4 -dce -instcombine -S | FileCheck %s ; RUN: opt < %s -loop-vectorize -disable-basic-aa -S -pass-remarks-analysis='loop-vectorize' 2>&1 | FileCheck %s -check-prefix=FORCED_OPTSIZE @@ -32,7 +32,7 @@ ; CHECK-NEXT: [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]], [[DBG9]] ; CHECK-NEXT: br i1 [[FOUND_CONFLICT]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]], [[DBG9]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 8589934588, [[DBG9]] +; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], -4, [[DBG9]] ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]], [[DBG9]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ], [[DBG9]] Index: llvm/test/Transforms/PhaseOrdering/X86/vdiv.ll =================================================================== --- llvm/test/Transforms/PhaseOrdering/X86/vdiv.ll +++ llvm/test/Transforms/PhaseOrdering/X86/vdiv.ll @@ -38,7 +38,7 @@ ; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i64 [[TMP0]], 12 ; CHECK-NEXT: br i1 [[TMP3]], label [[MIDDLE_BLOCK_UNR_LCSSA:%.*]], label [[VECTOR_PH_NEW:%.*]] ; CHECK: vector.ph.new: -; CHECK-NEXT: [[UNROLL_ITER:%.*]] = and i64 [[TMP2]], 9223372036854775804 +; CHECK-NEXT: [[UNROLL_ITER:%.*]] = and i64 [[TMP2]], -4 ; CHECK-NEXT: [[TMP4:%.*]] = fdiv fast <4 x double> , [[BROADCAST_SPLAT]] ; CHECK-NEXT: [[TMP5:%.*]] = fdiv fast <4 x double> , [[BROADCAST_SPLAT]] ; CHECK-NEXT: [[TMP6:%.*]] = fdiv fast <4 x double> , [[BROADCAST_SPLAT]]