forked from OSchip/llvm-project
[InstCombine] sub X, sext(bool Y) -> add X, zext(bool Y)
Prefer add/zext because they are better supported in terms of value-tracking. Note that the backend should be prepared for this IR canonicalization (including vector types) after: https://reviews.llvm.org/rL284015 Differential Revision: https://reviews.llvm.org/D25135 llvm-svn: 284241
This commit is contained in:
parent
3155abfb57
commit
c6c5965a42
|
@ -1642,6 +1642,17 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||||
if (Value *XNeg = dyn_castNegVal(X))
|
if (Value *XNeg = dyn_castNegVal(X))
|
||||||
return BinaryOperator::CreateShl(XNeg, Y);
|
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)
|
||||||
|
// 'nuw' is dropped in favor of the canonical form.
|
||||||
|
if (match(Op1, m_SExt(m_Value(Y))) &&
|
||||||
|
Y->getType()->getScalarSizeInBits() == 1) {
|
||||||
|
Value *Zext = Builder->CreateZExt(Y, I.getType());
|
||||||
|
BinaryOperator *Add = BinaryOperator::CreateAdd(Op0, Zext);
|
||||||
|
Add->setHasNoSignedWrap(I.hasNoSignedWrap());
|
||||||
|
return Add;
|
||||||
|
}
|
||||||
|
|
||||||
// X - A*-B -> X + A*B
|
// X - A*-B -> X + A*B
|
||||||
// X - -A*B -> X + A*B
|
// X - -A*B -> X + A*B
|
||||||
Value *A, *B;
|
Value *A, *B;
|
||||||
|
|
|
@ -639,3 +639,56 @@ define i32 @test48(i1 %A, i32 %B, i32 %C, i32 %D) {
|
||||||
%sub = sub i32 %sel0, %sel1
|
%sub = sub i32 %sel0, %sel1
|
||||||
ret i32 %sub
|
ret i32 %sub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Zext+add is more canonical than sext+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
|
||||||
|
}
|
||||||
|
|
||||||
|
; We favor the canonical zext+add over keeping the NUW.
|
||||||
|
|
||||||
|
define i8 @bool_sext_sub_nuw(i8 %x, i1 %y) {
|
||||||
|
; CHECK-LABEL: @bool_sext_sub_nuw(
|
||||||
|
; 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 nuw i8 %x, %sext
|
||||||
|
ret i8 %sub
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,12 +25,11 @@ define i8 @big_divisor(i8 %x) {
|
||||||
ret i8 %rem
|
ret i8 %rem
|
||||||
}
|
}
|
||||||
|
|
||||||
; TODO: Should this be zext+add instead of sext+sub?
|
|
||||||
define i5 @biggest_divisor(i5 %x) {
|
define i5 @biggest_divisor(i5 %x) {
|
||||||
; CHECK-LABEL: @biggest_divisor(
|
; CHECK-LABEL: @biggest_divisor(
|
||||||
; CHECK-NEXT: [[NOT_:%.*]] = icmp eq i5 %x, -1
|
; CHECK-NEXT: [[NOT_:%.*]] = icmp eq i5 %x, -1
|
||||||
; CHECK-NEXT: [[TMP1:%.*]] = sext i1 [[NOT_]] to i5
|
; CHECK-NEXT: [[TMP1:%.*]] = zext i1 [[NOT_]] to i5
|
||||||
; CHECK-NEXT: [[REM:%.*]] = sub i5 %x, [[TMP1]]
|
; CHECK-NEXT: [[REM:%.*]] = add i5 [[TMP1]], %x
|
||||||
; CHECK-NEXT: ret i5 [[REM]]
|
; CHECK-NEXT: ret i5 [[REM]]
|
||||||
;
|
;
|
||||||
%rem = urem i5 %x, -1
|
%rem = urem i5 %x, -1
|
||||||
|
|
Loading…
Reference in New Issue