Skip to content

Commit 2460786

Browse files
committed
[InstCombine] fold inc-of-signbit-splat to not+lshr
(iN X s>> (N - 1)) + 1 --> (~X) u>> (N - 1) https://alive2.llvm.org/ce/z/wzS474
1 parent ac4c46d commit 2460786

File tree

3 files changed

+20
-7
lines changed

3 files changed

+20
-7
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,7 @@ static Instruction *foldNoWrapAdd(BinaryOperator &Add,
849849

850850
Instruction *InstCombinerImpl::foldAddWithConstant(BinaryOperator &Add) {
851851
Value *Op0 = Add.getOperand(0), *Op1 = Add.getOperand(1);
852+
Type *Ty = Add.getType();
852853
Constant *Op1C;
853854
if (!match(Op1, m_ImmConstant(Op1C)))
854855
return nullptr;
@@ -883,7 +884,14 @@ Instruction *InstCombinerImpl::foldAddWithConstant(BinaryOperator &Add) {
883884
if (match(Op0, m_Not(m_Value(X))))
884885
return BinaryOperator::CreateSub(InstCombiner::SubOne(Op1C), X);
885886

887+
// (iN X s>> (N - 1)) + 1 --> (~X) u>> (N - 1)
886888
const APInt *C;
889+
if (match(Op0, m_OneUse(m_AShr(m_Value(X), m_APIntAllowUndef(C)))) &&
890+
*C == (Ty->getScalarSizeInBits() - 1) && match(Op1, m_One())) {
891+
Value *NotX = Builder.CreateNot(X, X->getName() + ".not");
892+
return BinaryOperator::CreateLShr(NotX, ConstantInt::get(Ty, *C));
893+
}
894+
887895
if (!match(Op1, m_APInt(C)))
888896
return nullptr;
889897

@@ -911,7 +919,6 @@ Instruction *InstCombinerImpl::foldAddWithConstant(BinaryOperator &Add) {
911919

912920
// Is this add the last step in a convoluted sext?
913921
// add(zext(xor i16 X, -32768), -32768) --> sext X
914-
Type *Ty = Add.getType();
915922
if (match(Op0, m_ZExt(m_Xor(m_Value(X), m_APInt(C2)))) &&
916923
C2->isMinSignedValue() && C2->sext(Ty->getScalarSizeInBits()) == *C)
917924
return CastInst::Create(Instruction::SExt, X, Ty);

llvm/test/Transforms/InstCombine/add.ll

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,8 +1900,8 @@ define i8 @not_mul_use2(i8 %x) {
19001900

19011901
define i8 @full_ashr_inc(i8 %x) {
19021902
; CHECK-LABEL: @full_ashr_inc(
1903-
; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 7
1904-
; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[A]], 1
1903+
; CHECK-NEXT: [[X_NOT:%.*]] = xor i8 [[X:%.*]], -1
1904+
; CHECK-NEXT: [[R:%.*]] = lshr i8 [[X_NOT]], 7
19051905
; CHECK-NEXT: ret i8 [[R]]
19061906
;
19071907
%a = ashr i8 %x, 7
@@ -1911,15 +1911,17 @@ define i8 @full_ashr_inc(i8 %x) {
19111911

19121912
define <2 x i6> @full_ashr_inc_vec(<2 x i6> %x) {
19131913
; CHECK-LABEL: @full_ashr_inc_vec(
1914-
; CHECK-NEXT: [[A:%.*]] = ashr <2 x i6> [[X:%.*]], <i6 5, i6 poison>
1915-
; CHECK-NEXT: [[R:%.*]] = add <2 x i6> [[A]], <i6 1, i6 1>
1914+
; CHECK-NEXT: [[X_NOT:%.*]] = xor <2 x i6> [[X:%.*]], <i6 -1, i6 -1>
1915+
; CHECK-NEXT: [[R:%.*]] = lshr <2 x i6> [[X_NOT]], <i6 5, i6 5>
19161916
; CHECK-NEXT: ret <2 x i6> [[R]]
19171917
;
19181918
%a = ashr <2 x i6> %x, <i6 5, i6 poison>
19191919
%r = add <2 x i6> %a, <i6 1, i6 1>
19201920
ret <2 x i6> %r
19211921
}
19221922

1923+
; negative test - extra use
1924+
19231925
define i8 @full_ashr_inc_use(i8 %x) {
19241926
; CHECK-LABEL: @full_ashr_inc_use(
19251927
; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 7
@@ -1933,6 +1935,8 @@ define i8 @full_ashr_inc_use(i8 %x) {
19331935
ret i8 %r
19341936
}
19351937

1938+
; negative test - wrong shift amount
1939+
19361940
define i8 @not_full_ashr_inc(i8 %x) {
19371941
; CHECK-LABEL: @not_full_ashr_inc(
19381942
; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 6
@@ -1944,6 +1948,8 @@ define i8 @not_full_ashr_inc(i8 %x) {
19441948
ret i8 %r
19451949
}
19461950

1951+
; negative test - wrong add amount
1952+
19471953
define i8 @full_ashr_not_inc(i8 %x) {
19481954
; CHECK-LABEL: @full_ashr_not_inc(
19491955
; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 7

llvm/test/Transforms/InstCombine/high-bit-signmask.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ define i64 @n9(i64 %x) {
116116

117117
define i64 @n10(i64 %x) {
118118
; CHECK-LABEL: @n10(
119-
; CHECK-NEXT: [[T0_NEG:%.*]] = ashr i64 [[X:%.*]], 63
120-
; CHECK-NEXT: [[R:%.*]] = add nsw i64 [[T0_NEG]], 1
119+
; CHECK-NEXT: [[X_NOT:%.*]] = xor i64 [[X:%.*]], -1
120+
; CHECK-NEXT: [[R:%.*]] = lshr i64 [[X_NOT]], 63
121121
; CHECK-NEXT: ret i64 [[R]]
122122
;
123123
%t0 = lshr i64 %x, 63

0 commit comments

Comments
 (0)