diff --git a/lib/Transforms/InstCombine/InstCombineShifts.cpp b/lib/Transforms/InstCombine/InstCombineShifts.cpp index 404fcecc334..1c75e558a96 100644 --- a/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -414,17 +414,28 @@ Instruction *InstCombiner::visitAShr(BinaryOperator &I) { if (Instruction *R = commonShiftTransforms(I)) return R; - Value *Op0 = I.getOperand(0); + Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); - // ashr int -1, X = -1 (for any arithmetic shift rights of ~0) - if (ConstantInt *CSI = dyn_cast(Op0)) + if (ConstantInt *CSI = dyn_cast(Op0)) { + // ashr int -1, X = -1 (for any arithmetic shift rights of ~0) if (CSI->isAllOnesValue()) return ReplaceInstUsesWith(I, CSI); + } + + if (ConstantInt *Op1C = dyn_cast(Op1)) { + // If the input is a SHL by the same constant (ashr (shl X, C), C), then we + // have a sign-extend idiom. If the input value is known to already be sign + // extended enough, delete the extension. + Value *X; + if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) && + ComputeNumSignBits(X) > Op1C->getZExtValue()) + return ReplaceInstUsesWith(I, X); + } // See if we can turn a signed shr into an unsigned shr. if (MaskedValueIsZero(Op0, APInt::getSignBit(I.getType()->getScalarSizeInBits()))) - return BinaryOperator::CreateLShr(Op0, I.getOperand(1)); + return BinaryOperator::CreateLShr(Op0, Op1); // Arithmetic shifting an all-sign-bit value is a no-op. unsigned NumSignBits = ComputeNumSignBits(Op0); diff --git a/test/Transforms/InstCombine/shift-sra.ll b/test/Transforms/InstCombine/shift-sra.ll index 492c16ac587..58f322635c2 100644 --- a/test/Transforms/InstCombine/shift-sra.ll +++ b/test/Transforms/InstCombine/shift-sra.ll @@ -37,3 +37,22 @@ C: ; CHECK: %P = phi i64 ; CHECK-NEXT: ret i64 %P } + +define i64 @test4(i1 %X, i64 %Y, i1 %Cond) { + br i1 %Cond, label %T, label %F +T: + %X2 = sext i1 %X to i64 + br label %C +F: + %Y2 = ashr i64 %Y, 63 + br label %C +C: + %P = phi i64 [%X2, %T], [%Y2, %F] + %R = shl i64 %P, 12 + %S = ashr i64 %R, 12 + ret i64 %S + +; CHECK: @test4 +; CHECK: %P = phi i64 +; CHECK-NEXT: ret i64 %P +}