diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -1064,6 +1064,27 @@ break; } + case Instruction::Add: { + unsigned NLZ = DemandedMask.countLeadingZeros(); + APInt DemandedFromOps = APInt::getLowBitsSet(BitWidth, BitWidth - NLZ); + + // If an operand adds zeros to every bit below the highest demanded bit, + // that operand doesn't change the result. Return the other side. + computeKnownBits(I->getOperand(1), RHSKnown, Depth + 1, CxtI); + if (DemandedFromOps.isSubsetOf(RHSKnown.Zero)) + return I->getOperand(0); + + computeKnownBits(I->getOperand(0), LHSKnown, Depth + 1, CxtI); + if (DemandedFromOps.isSubsetOf(LHSKnown.Zero)) + return I->getOperand(1); + + bool NSW = cast(I)->hasNoSignedWrap(); + Known = KnownBits::computeForAddSub(true, NSW, LHSKnown, RHSKnown); + if (DemandedMask.isSubsetOf(Known.Zero|Known.One)) + return Constant::getIntegerValue(ITy, Known.One); + + break; + } case Instruction::AShr: { // Compute the Known bits to simplify things downstream. computeKnownBits(I, Known, Depth, CxtI); diff --git a/llvm/test/Transforms/InstCombine/add.ll b/llvm/test/Transforms/InstCombine/add.ll --- a/llvm/test/Transforms/InstCombine/add.ll +++ b/llvm/test/Transforms/InstCombine/add.ll @@ -2183,7 +2183,7 @@ ; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], -32 ; CHECK-NEXT: [[A:%.*]] = add i8 [[M]], [[Y:%.*]] ; CHECK-NEXT: call void @use(i8 [[A]]) -; CHECK-NEXT: [[R:%.*]] = trunc i8 [[A]] to i5 +; CHECK-NEXT: [[R:%.*]] = trunc i8 [[Y]] to i5 ; CHECK-NEXT: ret i5 [[R]] ; %m = mul i8 %x, -32 ; 0xE0 @@ -2193,6 +2193,8 @@ ret i5 %r } +; negative test - demands one more bit + define i6 @demand_low_bits_uses_extra_bit(i8 %x, i8 %y) { ; CHECK-LABEL: @demand_low_bits_uses_extra_bit( ; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], -32 @@ -2214,7 +2216,7 @@ ; CHECK-NEXT: [[M:%.*]] = and i8 [[X:%.*]], -64 ; CHECK-NEXT: [[A:%.*]] = add i8 [[Y]], [[M]] ; CHECK-NEXT: call void @use(i8 [[A]]) -; CHECK-NEXT: [[S:%.*]] = sub i8 [[A]], [[Z:%.*]] +; CHECK-NEXT: [[S:%.*]] = sub i8 [[Y]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = shl i8 [[S]], 2 ; CHECK-NEXT: ret i8 [[R]] ; @@ -2227,8 +2229,10 @@ ret i8 %r } -define i8 @demand_low_bits_uses_commutei_extra_bit(i8 %x, i8 %p, i8 %z) { -; CHECK-LABEL: @demand_low_bits_uses_commutei_extra_bit( +; negative test - demands one more bit + +define i8 @demand_low_bits_uses_commute_extra_bit(i8 %x, i8 %p, i8 %z) { +; CHECK-LABEL: @demand_low_bits_uses_commute_extra_bit( ; CHECK-NEXT: [[Y:%.*]] = mul i8 [[P:%.*]], [[P]] ; CHECK-NEXT: [[M:%.*]] = and i8 [[X:%.*]], -64 ; CHECK-NEXT: [[A:%.*]] = add i8 [[Y]], [[M]] @@ -2257,7 +2261,7 @@ ; CHECK-NEXT: [[XY:%.*]] = or i128 [[SHY]], [[ZX]] ; CHECK-NEXT: [[SUB:%.*]] = sub i128 [[XY]], [[ZZ]] ; CHECK-NEXT: [[ADD:%.*]] = add i128 [[SUB]], [[MW]] -; CHECK-NEXT: [[T:%.*]] = trunc i128 [[ADD]] to i64 +; CHECK-NEXT: [[T:%.*]] = trunc i128 [[SUB]] to i64 ; CHECK-NEXT: [[H:%.*]] = lshr i128 [[ADD]], 64 ; CHECK-NEXT: [[T2:%.*]] = trunc i128 [[H]] to i64 ; CHECK-NEXT: [[R1:%.*]] = insertvalue { i64, i64 } poison, i64 [[T]], 0 diff --git a/llvm/test/Transforms/InstCombine/shift.ll b/llvm/test/Transforms/InstCombine/shift.ll --- a/llvm/test/Transforms/InstCombine/shift.ll +++ b/llvm/test/Transforms/InstCombine/shift.ll @@ -1750,11 +1750,12 @@ define void @ossfuzz_38078(i32 %arg, i32 %arg1, i32* %ptr, i1* %ptr2, i32* %ptr3, i1* %ptr4, i32* %ptr5, i32* %ptr6, i1* %ptr7) { ; CHECK-LABEL: @ossfuzz_38078( ; CHECK-NEXT: bb: +; CHECK-NEXT: [[I2:%.*]] = add nsw i32 [[ARG:%.*]], [[ARG1:%.*]] +; CHECK-NEXT: [[B3:%.*]] = or i32 [[I2]], 2147483647 ; CHECK-NEXT: [[G1:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i64 -1 -; CHECK-NEXT: [[I2:%.*]] = sub i32 0, [[ARG1:%.*]] -; CHECK-NEXT: [[I5:%.*]] = icmp eq i32 [[I2]], [[ARG:%.*]] +; CHECK-NEXT: [[I5:%.*]] = icmp eq i32 [[I2]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[I5]]) -; CHECK-NEXT: store volatile i32 2147483647, i32* [[G1]], align 4 +; CHECK-NEXT: store volatile i32 [[B3]], i32* [[G1]], align 4 ; CHECK-NEXT: br label [[BB:%.*]] ; CHECK: BB: ; CHECK-NEXT: unreachable