Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -373,6 +373,23 @@ } break; } + case Instruction::AShr: { + // If this is a truncate of an arithmetic shr, we can truncate it to a + // smaller ashr iff we know that all the bits from the sign bit of the + // original type and the sign bit of the truncate type are similar. + // TODO: It is enough to check that the bits we would be shifting in are + // similar to sign bit of the truncate type. + const APInt *Amt; + if (match(I->getOperand(1), m_APInt(Amt))) { + uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits(); + uint32_t BitWidth = Ty->getScalarSizeInBits(); + if (Amt->getLimitedValue(BitWidth) < BitWidth && + OrigBitWidth - BitWidth < + IC.ComputeNumSignBits(I->getOperand(0), 0, CxtI)) + return canEvaluateTruncated(I->getOperand(0), Ty, IC, CxtI); + } + break; + } case Instruction::Trunc: // trunc(trunc(x)) -> trunc(x) return true; Index: llvm/trunk/test/Transforms/InstCombine/trunc.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/trunc.ll +++ llvm/trunk/test/Transforms/InstCombine/trunc.ll @@ -89,6 +89,32 @@ ret i32 %D } +define i32 @trunc_ashr(i32 %X) { +; CHECK-LABEL: @trunc_ashr( +; CHECK-NEXT: [[B:%.*]] = or i32 [[X:%.*]], -2147483648 +; CHECK-NEXT: [[C:%.*]] = ashr i32 [[B]], 8 +; CHECK-NEXT: ret i32 [[C]] +; + %A = zext i32 %X to i36 + %B = or i36 %A, -2147483648 ; 0xF80000000 + %C = ashr i36 %B, 8 + %T = trunc i36 %C to i32 + ret i32 %T +} + +define <2 x i32> @trunc_ashr_vec(<2 x i32> %X) { +; CHECK-LABEL: @trunc_ashr_vec( +; CHECK-NEXT: [[B:%.*]] = or <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[C:%.*]] = ashr <2 x i32> [[B]], +; CHECK-NEXT: ret <2 x i32> [[C]] +; + %A = zext <2 x i32> %X to <2 x i36> + %B = or <2 x i36> %A, ; 0xF80000000 + %C = ashr <2 x i36> %B, + %T = trunc <2 x i36> %C to <2 x i32> + ret <2 x i32> %T +} + define i92 @test7(i64 %A) { ; CHECK-LABEL: @test7( ; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 %A, 32