diff options
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp | 40 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/shift.ll | 16 |
2 files changed, 29 insertions, 27 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp index edd51baf2a8..61716ca4d7f 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -373,24 +373,6 @@ foldShiftByConstOfShiftByConst(BinaryOperator &I, const APInt *COp1, if (ShiftAmt2 < ShiftAmt1) { uint32_t ShiftDiff = ShiftAmt1 - ShiftAmt2; - // (X << C1) >>u C2 --> X << (C1-C2) & (-1 >> C2) - if (I.getOpcode() == Instruction::LShr && - ShiftOp->getOpcode() == Instruction::Shl) { - ConstantInt *ShiftDiffCst = ConstantInt::get(Ty, ShiftDiff); - if (ShiftOp->hasNoUnsignedWrap()) { - // (X <<nuw C1) >>u C2 --> X <<nuw (C1-C2) - BinaryOperator *NewShl = - BinaryOperator::Create(Instruction::Shl, X, ShiftDiffCst); - NewShl->setHasNoUnsignedWrap(true); - return NewShl; - } - Value *Shift = Builder->CreateShl(X, ShiftDiffCst); - - APInt Mask(APInt::getLowBitsSet(TypeBits, TypeBits - ShiftAmt2)); - return BinaryOperator::CreateAnd(Shift, - ConstantInt::get(I.getContext(), Mask)); - } - // We can't handle (X << C1) >>s C2, it shifts arbitrary bits in. However, // we can handle (X <<nsw C1) >>s C2 since it only shifts in sign bits. if (I.getOpcode() == Instruction::AShr && @@ -740,11 +722,6 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) { const APInt *ShlAmtAPInt; if (match(Op0, m_Shl(m_Value(X), m_APInt(ShlAmtAPInt)))) { unsigned ShlAmt = ShlAmtAPInt->getZExtValue(); - if (ShlAmt == ShAmt) { - // (X << C) >>u C --> X & (-1 >>u C) - APInt Mask(APInt::getLowBitsSet(BitWidth, BitWidth - ShAmt)); - return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask)); - } if (ShlAmt < ShAmt) { Constant *ShiftDiff = ConstantInt::get(Ty, ShAmt - ShlAmt); if (cast<BinaryOperator>(Op0)->hasNoUnsignedWrap()) { @@ -758,6 +735,23 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) { APInt Mask(APInt::getLowBitsSet(BitWidth, BitWidth - ShAmt)); return BinaryOperator::CreateAnd(NewLShr, ConstantInt::get(Ty, Mask)); } + if (ShlAmt > ShAmt) { + Constant *ShiftDiff = ConstantInt::get(Ty, ShlAmt - ShAmt); + if (cast<BinaryOperator>(Op0)->hasNoUnsignedWrap()) { + // (X <<nuw C1) >>u C2 --> X <<nuw (C1 - C2) + auto *NewShl = BinaryOperator::CreateShl(X, ShiftDiff); + NewShl->setHasNoUnsignedWrap(true); + return NewShl; + } + // (X << C1) >>u C2 --> X << (C1 - C2) & (-1 >> C2) + Value *NewShl = Builder->CreateShl(X, ShiftDiff); + APInt Mask(APInt::getLowBitsSet(BitWidth, BitWidth - ShAmt)); + return BinaryOperator::CreateAnd(NewShl, ConstantInt::get(Ty, Mask)); + } + assert(ShlAmt == ShAmt); + // (X << C) >>u C --> X & (-1 >>u C) + APInt Mask(APInt::getLowBitsSet(BitWidth, BitWidth - ShAmt)); + return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask)); } // If the shifted-out value is known-zero, then this is an exact shift. diff --git a/llvm/test/Transforms/InstCombine/shift.ll b/llvm/test/Transforms/InstCombine/shift.ll index 573cb8dfe1d..b105c58201e 100644 --- a/llvm/test/Transforms/InstCombine/shift.ll +++ b/llvm/test/Transforms/InstCombine/shift.ll @@ -997,6 +997,8 @@ define i32 @test52(i32 %x) { ret i32 %B } +; (X <<nuw C1) >>u C2 --> X <<nuw (C1 - C2) + define i32 @test53(i32 %x) { ; CHECK-LABEL: @test53( ; CHECK-NEXT: [[B:%.*]] = shl nuw i32 %x, 2 @@ -1007,10 +1009,11 @@ define i32 @test53(i32 %x) { ret i32 %B } +; (X <<nuw C1) >>u C2 --> X <<nuw (C1 - C2) + define <2 x i32> @test53_splat_vec(<2 x i32> %x) { ; CHECK-LABEL: @test53_splat_vec( -; CHECK-NEXT: [[A:%.*]] = shl nuw <2 x i32> %x, <i32 3, i32 3> -; CHECK-NEXT: [[B:%.*]] = lshr exact <2 x i32> [[A]], <i32 1, i32 1> +; CHECK-NEXT: [[B:%.*]] = shl nuw <2 x i32> %x, <i32 2, i32 2> ; CHECK-NEXT: ret <2 x i32> [[B]] ; %A = shl nuw <2 x i32> %x, <i32 3, i32 3> @@ -1018,6 +1021,8 @@ define <2 x i32> @test53_splat_vec(<2 x i32> %x) { ret <2 x i32> %B } +; (X << C1) >>u C2 --> X << (C1 - C2) & (-1 >> C2) + define i8 @test53_no_nuw(i8 %x) { ; CHECK-LABEL: @test53_no_nuw( ; CHECK-NEXT: [[TMP1:%.*]] = shl i8 %x, 2 @@ -1029,10 +1034,13 @@ define i8 @test53_no_nuw(i8 %x) { ret i8 %B } +; (X << C1) >>u C2 --> X << (C1 - C2) & (-1 >> C2) +; FIXME: Demanded bits should change the mask constant as it does for the scalar case. + define <2 x i8> @test53_no_nuw_splat_vec(<2 x i8> %x) { ; CHECK-LABEL: @test53_no_nuw_splat_vec( -; CHECK-NEXT: [[A:%.*]] = shl <2 x i8> %x, <i8 3, i8 3> -; CHECK-NEXT: [[B:%.*]] = lshr exact <2 x i8> [[A]], <i8 1, i8 1> +; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i8> %x, <i8 2, i8 2> +; CHECK-NEXT: [[B:%.*]] = and <2 x i8> [[TMP1]], <i8 127, i8 127> ; CHECK-NEXT: ret <2 x i8> [[B]] ; %A = shl <2 x i8> %x, <i8 3, i8 3> |