mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-12 22:30:12 +00:00
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@323068 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
424be7676e
commit
00352310aa
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user