Index: lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1642,6 +1642,17 @@ if (Value *XNeg = dyn_castNegVal(X)) return BinaryOperator::CreateShl(XNeg, Y); + // Subtracting -1/0 is the same as adding 1/0: + // sub [nsw] Op0, sext(bool Y) -> add [nsw] Op0, zext(bool Y) + // But ignore a 'sub nuw' because we can't transfer nuw to the add. + if (!I.hasNoUnsignedWrap() && match(Op1, m_SExt(m_Value(Y))) && + Y->getType()->getScalarSizeInBits() == 1) { + Value *Zext = Builder->CreateZExt(Y, I.getType()); + auto *Add = BinaryOperator::CreateAdd(Op0, Zext); + Add->setHasNoSignedWrap(I.hasNoSignedWrap()); + return Add; + } + // X - A*-B -> X + A*B // X - -A*B -> X + A*B Value *A, *B; Index: test/Transforms/InstCombine/sub.ll =================================================================== --- test/Transforms/InstCombine/sub.ll +++ test/Transforms/InstCombine/sub.ll @@ -639,3 +639,54 @@ %sub = sub i32 %sel0, %sel1 ret i32 %sub } + +define i8 @bool_sext_sub(i8 %x, i1 %y) { +; CHECK-LABEL: @bool_sext_sub( +; CHECK-NEXT: [[TMP1:%.*]] = zext i1 %y to i8 +; CHECK-NEXT: [[SUB:%.*]] = add i8 [[TMP1]], %x +; CHECK-NEXT: ret i8 [[SUB]] +; + %sext = sext i1 %y to i8 + %sub = sub i8 %x, %sext + ret i8 %sub +} + +; Vectors get the same transform. + +define <2 x i8> @bool_sext_sub_vec(<2 x i8> %x, <2 x i1> %y) { +; CHECK-LABEL: @bool_sext_sub_vec( +; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i1> %y to <2 x i8> +; CHECK-NEXT: [[SUB:%.*]] = add <2 x i8> [[TMP1]], %x +; CHECK-NEXT: ret <2 x i8> [[SUB]] +; + %sext = sext <2 x i1> %y to <2 x i8> + %sub = sub <2 x i8> %x, %sext + ret <2 x i8> %sub +} + +; NSW is preserved. + +define <2 x i8> @bool_sext_sub_vec_nsw(<2 x i8> %x, <2 x i1> %y) { +; CHECK-LABEL: @bool_sext_sub_vec_nsw( +; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i1> %y to <2 x i8> +; CHECK-NEXT: [[SUB:%.*]] = add nsw <2 x i8> [[TMP1]], %x +; CHECK-NEXT: ret <2 x i8> [[SUB]] +; + %sext = sext <2 x i1> %y to <2 x i8> + %sub = sub nsw <2 x i8> %x, %sext + ret <2 x i8> %sub +} + +; Don't lose the information provided by NUW. If y is true, then x can only be 0xff. + +define i8 @bool_sext_sub_vec_nuw(i8 %x, i1 %y) { +; CHECK-LABEL: @bool_sext_sub_vec_nuw( +; CHECK-NEXT: [[SEXT:%.*]] = sext i1 %y to i8 +; CHECK-NEXT: [[SUB:%.*]] = sub nuw i8 %x, [[SEXT]] +; CHECK-NEXT: ret i8 [[SUB]] +; + %sext = sext i1 %y to i8 + %sub = sub nuw i8 %x, %sext + ret i8 %sub +} + Index: test/Transforms/InstCombine/urem.ll =================================================================== --- test/Transforms/InstCombine/urem.ll +++ test/Transforms/InstCombine/urem.ll @@ -25,12 +25,11 @@ ret i8 %rem } -; TODO: Should this be zext+add instead of sext+sub? define i5 @biggest_divisor(i5 %x) { ; CHECK-LABEL: @biggest_divisor( ; CHECK-NEXT: [[NOT_:%.*]] = icmp eq i5 %x, -1 -; CHECK-NEXT: [[TMP1:%.*]] = sext i1 [[NOT_]] to i5 -; CHECK-NEXT: [[REM:%.*]] = sub i5 %x, [[TMP1]] +; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[NOT_]] to i5 +; CHECK-NEXT: [[REM:%.*]] = add i5 [[TMP1]], %x ; CHECK-NEXT: ret i5 [[REM]] ; %rem = urem i5 %x, -1