diff options
| author | Sanjay Patel <spatel@rotateright.com> | 2018-01-21 16:14:51 +0000 |
|---|---|---|
| committer | Sanjay Patel <spatel@rotateright.com> | 2018-01-21 16:14:51 +0000 |
| commit | 9530f1886433d77bc203c366915a9ab3160c7efc (patch) | |
| tree | 7713b04c77141e282a864a0e30e243e64ab4a143 /llvm | |
| parent | 7a44e4d594c98b5998ebffc041490564953a3cb8 (diff) | |
| download | bcm5719-llvm-9530f1886433d77bc203c366915a9ab3160c7efc.tar.gz bcm5719-llvm-9530f1886433d77bc203c366915a9ab3160c7efc.zip | |
[InstCombine] (X << Y) / X -> 1 << Y
...when the shift is known to not overflow with the matching
signed-ness of the division.
This closes an optimization gap caused by canonicalizing mul
by power-of-2 to shl as shown in PR35709:
https://bugs.llvm.org/show_bug.cgi?id=35709
Patch by Anton Bikineev!
Differential Revision: https://reviews.llvm.org/D42032
llvm-svn: 323068
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 19 | ||||
| -rw-r--r-- | llvm/test/Transforms/InstCombine/div-shift.ll | 28 |
2 files changed, 20 insertions, 27 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 899c4dd8fa7..6e7e11a15ae 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -891,6 +891,7 @@ bool InstCombiner::simplifyDivRemOfSelectWithZeroOp(BinaryOperator &I) { /// @brief Common integer divide transforms Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); + bool IsSigned = I.getOpcode() == Instruction::SDiv; // The RHS is known non-zero. if (Value *V = simplifyValueKnownNonZero(I.getOperand(1), *this, I)) { @@ -908,7 +909,6 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { if (match(Op1, m_APInt(C2))) { Value *X; const APInt *C1; - bool IsSigned = I.getOpcode() == Instruction::SDiv; // (X / C1) / C2 -> X / (C1*C2) if ((IsSigned && match(LHS, m_SDiv(m_Value(X), m_APInt(C1)))) || @@ -999,13 +999,18 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { return &I; // (X - (X rem Y)) / Y -> X / Y; usually originates as ((X / Y) * Y) / Y - Value *X = nullptr, *Z = nullptr; - if (match(Op0, m_Sub(m_Value(X), m_Value(Z)))) { // (X - Z) / Y; Y = Op1 - bool isSigned = I.getOpcode() == Instruction::SDiv; - if ((isSigned && match(Z, m_SRem(m_Specific(X), m_Specific(Op1)))) || - (!isSigned && match(Z, m_URem(m_Specific(X), m_Specific(Op1))))) + Value *X, *Z; + if (match(Op0, m_Sub(m_Value(X), m_Value(Z)))) // (X - Z) / Y; Y = Op1 + if ((IsSigned && match(Z, m_SRem(m_Specific(X), m_Specific(Op1)))) || + (!IsSigned && match(Z, m_URem(m_Specific(X), m_Specific(Op1))))) return BinaryOperator::Create(I.getOpcode(), X, Op1); - } + + // (X << Y) / X -> 1 << Y + Value *Y; + if (IsSigned && match(Op0, m_NSWShl(m_Specific(Op1), m_Value(Y)))) + return BinaryOperator::CreateNSWShl(ConstantInt::get(I.getType(), 1), Y); + if (!IsSigned && match(Op0, m_NUWShl(m_Specific(Op1), m_Value(Y)))) + return BinaryOperator::CreateNUWShl(ConstantInt::get(I.getType(), 1), Y); return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/div-shift.ll b/llvm/test/Transforms/InstCombine/div-shift.ll index 6011def38e3..7d84fd6fdd3 100644 --- a/llvm/test/Transforms/InstCombine/div-shift.ll +++ b/llvm/test/Transforms/InstCombine/div-shift.ll @@ -103,9 +103,7 @@ define i32 @t6(i32 %x, i32 %z) { define i32 @t7(i32 %x) { ; CHECK-LABEL: @t7( -; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[X:%.*]], 2 -; CHECK-NEXT: [[R:%.*]] = sdiv i32 [[SHL]], [[X]] -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: ret i32 4 ; %shl = shl nsw i32 %x, 2 %r = sdiv i32 %shl, %x @@ -127,9 +125,7 @@ define i32 @t8(i32 %x) { define <2 x i32> @t9(<2 x i32> %x) { ; CHECK-LABEL: @t9( -; CHECK-NEXT: [[SHL:%.*]] = shl nsw <2 x i32> [[X:%.*]], <i32 2, i32 3> -; CHECK-NEXT: [[R:%.*]] = sdiv <2 x i32> [[SHL]], [[X]] -; CHECK-NEXT: ret <2 x i32> [[R]] +; CHECK-NEXT: ret <2 x i32> <i32 4, i32 8> ; %shl = shl nsw <2 x i32> %x, <i32 2, i32 3> %r = sdiv <2 x i32> %shl, %x @@ -138,8 +134,7 @@ define <2 x i32> @t9(<2 x i32> %x) { define i32 @t10(i32 %x, i32 %y) { ; CHECK-LABEL: @t10( -; CHECK-NEXT: [[SHL:%.*]] = shl nsw i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = sdiv i32 [[SHL]], [[X]] +; CHECK-NEXT: [[R:%.*]] = shl nsw i32 1, [[Y:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %shl = shl nsw i32 %x, %y @@ -149,8 +144,7 @@ define i32 @t10(i32 %x, i32 %y) { define <2 x i32> @t11(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @t11( -; CHECK-NEXT: [[SHL:%.*]] = shl nsw <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = sdiv <2 x i32> [[SHL]], [[X]] +; CHECK-NEXT: [[R:%.*]] = shl nsw <2 x i32> <i32 1, i32 1>, [[Y:%.*]] ; CHECK-NEXT: ret <2 x i32> [[R]] ; %shl = shl nsw <2 x i32> %x, %y @@ -160,9 +154,7 @@ define <2 x i32> @t11(<2 x i32> %x, <2 x i32> %y) { define i32 @t12(i32 %x) { ; CHECK-LABEL: @t12( -; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], 2 -; CHECK-NEXT: [[R:%.*]] = udiv i32 [[SHL]], [[X]] -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: ret i32 4 ; %shl = shl nuw i32 %x, 2 %r = udiv i32 %shl, %x @@ -184,9 +176,7 @@ define i32 @t13(i32 %x) { define <2 x i32> @t14(<2 x i32> %x) { ; CHECK-LABEL: @t14( -; CHECK-NEXT: [[SHL:%.*]] = shl nuw <2 x i32> [[X:%.*]], <i32 2, i32 3> -; CHECK-NEXT: [[R:%.*]] = udiv <2 x i32> [[SHL]], [[X]] -; CHECK-NEXT: ret <2 x i32> [[R]] +; CHECK-NEXT: ret <2 x i32> <i32 4, i32 8> ; %shl = shl nuw <2 x i32> %x, <i32 2, i32 3> %r = udiv <2 x i32> %shl, %x @@ -195,8 +185,7 @@ define <2 x i32> @t14(<2 x i32> %x) { define i32 @t15(i32 %x, i32 %y) { ; CHECK-LABEL: @t15( -; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = udiv i32 [[SHL]], [[X]] +; CHECK-NEXT: [[R:%.*]] = shl nuw i32 1, [[Y:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %shl = shl nuw i32 %x, %y @@ -206,8 +195,7 @@ define i32 @t15(i32 %x, i32 %y) { define <2 x i32> @t16(<2 x i32> %x, <2 x i32> %y) { ; CHECK-LABEL: @t16( -; CHECK-NEXT: [[SHL:%.*]] = shl nuw <2 x i32> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = udiv <2 x i32> [[SHL]], [[X]] +; CHECK-NEXT: [[R:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[Y:%.*]] ; CHECK-NEXT: ret <2 x i32> [[R]] ; %shl = shl nuw <2 x i32> %x, %y |

