Skip to content

Commit 286198f

Browse files
committed
[InstCombine] Optimize lshr+shl+and conversion pattern
if `C1` and `C3` are pow2 and `Log2(C3) >= C2`: ((C1 >> X) << C2) & C3 -> X == (Log2(C1)+C2-Log2(C3)) ? C3 : 0 https://alive2.llvm.org/ce/z/zvrkKF Reviewed By: spatel Differential Revision: https://reviews.llvm.org/D127469
1 parent e99c07a commit 286198f

File tree

2 files changed

+40
-29
lines changed

2 files changed

+40
-29
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1917,25 +1917,40 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
19171917
Constant *C1, *C2;
19181918
const APInt *C3 = C;
19191919
Value *X;
1920-
if (C3->isPowerOf2() &&
1921-
match(Op0, m_OneUse(m_LShr(m_Shl(m_ImmConstant(C1), m_Value(X)),
1922-
m_ImmConstant(C2)))) &&
1923-
match(C1, m_Power2())) {
1924-
Constant *Log2C1 = ConstantExpr::getExactLogBase2(C1);
1920+
if (C3->isPowerOf2()) {
19251921
Constant *Log2C3 = ConstantInt::get(Ty, C3->countTrailingZeros());
1926-
Constant *LshrC = ConstantExpr::getAdd(C2, Log2C3);
1927-
KnownBits KnownLShrc = computeKnownBits(LshrC, 0, nullptr);
1928-
if (KnownLShrc.getMaxValue().ult(Width)) {
1929-
// iff C1,C3 is pow2 and C2 + cttz(C3) < BitWidth:
1930-
// ((C1 << X) >> C2) & C3 -> X == (cttz(C3)+C2-cttz(C1)) ? C3 : 0
1931-
Constant *CmpC = ConstantExpr::getSub(LshrC, Log2C1);
1932-
Value *Cmp = Builder.CreateICmpEQ(X, CmpC);
1933-
return SelectInst::Create(Cmp, ConstantInt::get(Ty, *C3),
1934-
ConstantInt::getNullValue(Ty));
1922+
if (match(Op0, m_OneUse(m_LShr(m_Shl(m_ImmConstant(C1), m_Value(X)),
1923+
m_ImmConstant(C2)))) &&
1924+
match(C1, m_Power2())) {
1925+
Constant *Log2C1 = ConstantExpr::getExactLogBase2(C1);
1926+
Constant *LshrC = ConstantExpr::getAdd(C2, Log2C3);
1927+
KnownBits KnownLShrc = computeKnownBits(LshrC, 0, nullptr);
1928+
if (KnownLShrc.getMaxValue().ult(Width)) {
1929+
// iff C1,C3 is pow2 and C2 + cttz(C3) < BitWidth:
1930+
// ((C1 << X) >> C2) & C3 -> X == (cttz(C3)+C2-cttz(C1)) ? C3 : 0
1931+
Constant *CmpC = ConstantExpr::getSub(LshrC, Log2C1);
1932+
Value *Cmp = Builder.CreateICmpEQ(X, CmpC);
1933+
return SelectInst::Create(Cmp, ConstantInt::get(Ty, *C3),
1934+
ConstantInt::getNullValue(Ty));
1935+
}
1936+
}
1937+
1938+
if (match(Op0, m_OneUse(m_Shl(m_LShr(m_ImmConstant(C1), m_Value(X)),
1939+
m_ImmConstant(C2)))) &&
1940+
match(C1, m_Power2())) {
1941+
Constant *Log2C1 = ConstantExpr::getExactLogBase2(C1);
1942+
Constant *Cmp =
1943+
ConstantExpr::getCompare(ICmpInst::ICMP_ULT, Log2C3, C2);
1944+
if (Cmp->isZeroValue()) {
1945+
// iff C1,C3 is pow2 and Log2(C3) >= C2:
1946+
// ((C1 >> X) << C2) & C3 -> X == (cttz(C1)+C2-cttz(C3)) ? C3 : 0
1947+
Constant *ShlC = ConstantExpr::getAdd(C2, Log2C1);
1948+
Constant *CmpC = ConstantExpr::getSub(ShlC, Log2C3);
1949+
Value *Cmp = Builder.CreateICmpEQ(X, CmpC);
1950+
return SelectInst::Create(Cmp, ConstantInt::get(Ty, *C3),
1951+
ConstantInt::getNullValue(Ty));
1952+
}
19351953
}
1936-
// TODO: Symmetrical case
1937-
// iff C1,C3 is pow2 and Log2(C3) >= C2:
1938-
// ((C1 >> X) << C2) & C3 -> X == (cttz(C1)+C2-cttz(C3)) ? C3 : 0
19391954
}
19401955
}
19411956

llvm/test/Transforms/InstCombine/and.ll

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,9 +2062,8 @@ define i16 @lshr_shl_pow2_const_xor(i16 %x) {
20622062

20632063
define i16 @lshr_shl_pow2_const_case2(i16 %x) {
20642064
; CHECK-LABEL: @lshr_shl_pow2_const_case2(
2065-
; CHECK-NEXT: [[LSHR1:%.*]] = lshr i16 8192, [[X:%.*]]
2066-
; CHECK-NEXT: [[SHL:%.*]] = shl i16 [[LSHR1]], 4
2067-
; CHECK-NEXT: [[R:%.*]] = and i16 [[SHL]], 32
2065+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[X:%.*]], 12
2066+
; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i16 32, i16 0
20682067
; CHECK-NEXT: ret i16 [[R]]
20692068
;
20702069
%lshr1 = lshr i16 8192, %x
@@ -2102,9 +2101,8 @@ define i16 @lshr_shl_pow2_const_negative_oneuse(i16 %x) {
21022101

21032102
define <3 x i16> @lshr_shl_pow2_const_case1_uniform_vec(<3 x i16> %x) {
21042103
; CHECK-LABEL: @lshr_shl_pow2_const_case1_uniform_vec(
2105-
; CHECK-NEXT: [[LSHR:%.*]] = lshr <3 x i16> <i16 8192, i16 8192, i16 8192>, [[X:%.*]]
2106-
; CHECK-NEXT: [[SHL:%.*]] = shl <3 x i16> [[LSHR]], <i16 6, i16 6, i16 6>
2107-
; CHECK-NEXT: [[R:%.*]] = and <3 x i16> [[SHL]], <i16 128, i16 128, i16 128>
2104+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <3 x i16> [[X:%.*]], <i16 12, i16 12, i16 12>
2105+
; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i16> <i16 128, i16 128, i16 128>, <3 x i16> zeroinitializer
21082106
; CHECK-NEXT: ret <3 x i16> [[R]]
21092107
;
21102108
%lshr = lshr <3 x i16> <i16 8192, i16 8192, i16 8192>, %x
@@ -2141,9 +2139,8 @@ define <3 x i16> @lshr_shl_pow2_const_case1_non_uniform_vec_negative(<3 x i16> %
21412139

21422140
define <3 x i16> @lshr_shl_pow2_const_case1_undef1_vec(<3 x i16> %x) {
21432141
; CHECK-LABEL: @lshr_shl_pow2_const_case1_undef1_vec(
2144-
; CHECK-NEXT: [[LSHR:%.*]] = lshr <3 x i16> <i16 undef, i16 8192, i16 8192>, [[X:%.*]]
2145-
; CHECK-NEXT: [[SHL:%.*]] = shl <3 x i16> [[LSHR]], <i16 6, i16 6, i16 6>
2146-
; CHECK-NEXT: [[R:%.*]] = and <3 x i16> [[SHL]], <i16 128, i16 128, i16 128>
2142+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <3 x i16> [[X:%.*]], <i16 -1, i16 12, i16 12>
2143+
; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i16> <i16 128, i16 128, i16 128>, <3 x i16> zeroinitializer
21472144
; CHECK-NEXT: ret <3 x i16> [[R]]
21482145
;
21492146
%lshr = lshr <3 x i16> <i16 undef, i16 8192, i16 8192>, %x
@@ -2154,9 +2151,8 @@ define <3 x i16> @lshr_shl_pow2_const_case1_undef1_vec(<3 x i16> %x) {
21542151

21552152
define <3 x i16> @lshr_shl_pow2_const_case1_undef2_vec(<3 x i16> %x) {
21562153
; CHECK-LABEL: @lshr_shl_pow2_const_case1_undef2_vec(
2157-
; CHECK-NEXT: [[LSHR:%.*]] = lshr <3 x i16> <i16 8192, i16 8192, i16 8192>, [[X:%.*]]
2158-
; CHECK-NEXT: [[SHL:%.*]] = shl <3 x i16> [[LSHR]], <i16 undef, i16 6, i16 6>
2159-
; CHECK-NEXT: [[R:%.*]] = and <3 x i16> [[SHL]], <i16 128, i16 128, i16 128>
2154+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <3 x i16> [[X:%.*]], <i16 undef, i16 12, i16 12>
2155+
; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i16> <i16 128, i16 128, i16 128>, <3 x i16> zeroinitializer
21602156
; CHECK-NEXT: ret <3 x i16> [[R]]
21612157
;
21622158
%lshr = lshr <3 x i16> <i16 8192, i16 8192, i16 8192>, %x

0 commit comments

Comments
 (0)