rdar://12329730 (2nd part)

This change tries to simmplify E1 = " X >> C1 << C2" into :
  - E2 = "X << (C2 - C1)" if C2 > C1, or
  - E2 = "X >> (C1 - C2)" if C1 > C2, or
  - E2 = X if C1 == C2.

 Reviewed by Nadav. Thanks!


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169182 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Shuxin Yang 2012-12-04 00:04:54 +00:00
parent fc6374439e
commit c811976b04
5 changed files with 170 additions and 5 deletions

View File

@ -327,6 +327,11 @@ private:
bool SimplifyDemandedBits(Use &U, APInt DemandedMask,
APInt& KnownZero, APInt& KnownOne,
unsigned Depth=0);
/// Helper routine of SimplifyDemandedUseBits. It tries to simplify demanded
/// bit for "r1 = shr x, c1; r2 = shl r1, c2" instruction sequence.
Value *SimplifyShrShlDemandedBits(Instruction *Lsr, Instruction *Sftl,
APInt DemandedMask, APInt &KnownZero,
APInt &KnownOne);
/// SimplifyDemandedInstructionBits - Inst is an integer instruction that
/// SimplifyDemandedBits knows about. See if the instruction has any

View File

@ -16,9 +16,10 @@
#include "InstCombine.h"
#include "llvm/DataLayout.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Support/PatternMatch.h"
using namespace llvm;
using namespace llvm::PatternMatch;
/// ShrinkDemandedConstant - Check to see if the specified operand of the
/// specified instruction is a constant integer. If so, check to see if there
@ -580,6 +581,17 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
break;
case Instruction::Shl:
if (ConstantInt *SA = dyn_cast<ConstantInt>(I->getOperand(1))) {
{
Value *VarX; ConstantInt *C1;
if (match(I->getOperand(0), m_Shr(m_Value(VarX), m_ConstantInt(C1)))) {
Instruction *Shr = cast<Instruction>(I->getOperand(0));
Value *R = SimplifyShrShlDemandedBits(Shr, I, DemandedMask,
KnownZero, KnownOne);
if (R)
return R;
}
}
uint64_t ShiftAmt = SA->getLimitedValue(BitWidth-1);
APInt DemandedMaskIn(DemandedMask.lshr(ShiftAmt));
@ -800,6 +812,78 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
return 0;
}
/// Helper routine of SimplifyDemandedUseBits. It tries to simplify
/// "E1 = (X lsr C1) << C2", where the C1 and C2 are constant, into
/// "E2 = X << (C2 - C1)" or "E2 = X >> (C1 - C2)", depending on the sign
/// of "C2-C1".
///
/// Suppose E1 and E2 are generally different in bits S={bm, bm+1,
/// ..., bn}, without considering the specific value X is holding.
/// This transformation is legal iff one of following conditions is hold:
/// 1) All the bit in S are 0, in this case E1 == E2.
/// 2) We don't care those bits in S, per the input DemandedMask.
/// 3) Combination of 1) and 2). Some bits in S are 0, and we don't care the
/// rest bits.
///
/// Currently we only test condition 2).
///
/// As with SimplifyDemandedUseBits, it returns NULL if the simplification was
/// not successful.
Value *InstCombiner::SimplifyShrShlDemandedBits(Instruction *Shr,
Instruction *Shl, APInt DemandedMask, APInt &KnownZero, APInt &KnownOne) {
unsigned ShlAmt = cast<ConstantInt>(Shl->getOperand(1))->getZExtValue();
unsigned ShrAmt = cast<ConstantInt>(Shr->getOperand(1))->getZExtValue();
KnownOne.clearAllBits();
KnownZero = APInt::getBitsSet(KnownZero.getBitWidth(), 0, ShlAmt-1);
KnownZero &= DemandedMask;
if (ShlAmt == 0 || ShrAmt == 0)
return 0;
Value *VarX = Shr->getOperand(0);
Type *Ty = VarX->getType();
APInt BitMask1(Ty->getIntegerBitWidth(), (uint64_t)-1);
APInt BitMask2(Ty->getIntegerBitWidth(), (uint64_t)-1);
bool isLshr = (Shr->getOpcode() == Instruction::LShr);
BitMask1 = isLshr ? (BitMask1.lshr(ShrAmt) << ShlAmt) :
(BitMask1.ashr(ShrAmt) << ShlAmt);
if (ShrAmt <= ShlAmt) {
BitMask2 <<= (ShlAmt - ShrAmt);
} else {
BitMask2 = isLshr ? BitMask2.lshr(ShrAmt - ShlAmt):
BitMask2.ashr(ShrAmt - ShlAmt);
}
// Check if condition-2 (see the comment to this function) is satified.
if ((BitMask1 & DemandedMask) == (BitMask2 & DemandedMask)) {
if (ShrAmt == ShlAmt)
return VarX;
if (!Shr->hasOneUse())
return 0;
BinaryOperator *New;
if (ShrAmt < ShlAmt) {
Constant *Amt = ConstantInt::get(VarX->getType(), ShlAmt - ShrAmt);
New = BinaryOperator::CreateShl(VarX, Amt);
BinaryOperator *Orig = cast<BinaryOperator>(Shl);
New->setHasNoSignedWrap(Orig->hasNoSignedWrap());
New->setHasNoUnsignedWrap(Orig->hasNoUnsignedWrap());
} else {
Constant *Amt = ConstantInt::get(VarX->getType(), ShrAmt - ShlAmt);
New = BinaryOperator::CreateLShr(VarX, Amt);
}
return InsertNewInstWith(New, *Shl);
}
return 0;
}
/// SimplifyDemandedVectorElts - The specified value produces a vector with
/// any number of elements. DemandedElts contains the set of elements that are

View File

@ -5,8 +5,8 @@
define i32 @main(i32 %argc) nounwind ssp {
entry:
%tmp3151 = trunc i32 %argc to i8
; CHECK: %tmp3163 = shl i8 %tmp3162, 6
; CHECK: and i8 %tmp3163, 64
; CHECK: %tmp3162 = shl i8 %tmp3151, 5
; CHECK: and i8 %tmp3162, 64
; CHECK-NOT: shl
; CHECK-NOT: shr
%tmp3161 = or i8 %tmp3151, -17

View File

@ -659,3 +659,79 @@ define i32 @test53(i32 %x) {
; CHECK-NEXT: %B = shl nuw i32 %x, 2
; CHECK-NEXT: ret i32 %B
}
define i32 @test54(i32 %x) {
%shr2 = lshr i32 %x, 1
%shl = shl i32 %shr2, 4
%and = and i32 %shl, 16
ret i32 %and
; CHECK: @test54
; CHECK: shl i32 %x, 3
}
define i32 @test55(i32 %x) {
%shr2 = lshr i32 %x, 1
%shl = shl i32 %shr2, 4
%or = or i32 %shl, 8
ret i32 %or
; CHECK: @test55
; CHECK: shl i32 %x, 3
}
define i32 @test56(i32 %x) {
%shr2 = lshr i32 %x, 1
%shl = shl i32 %shr2, 4
%or = or i32 %shl, 7
ret i32 %or
; CHECK: @test56
; CHECK: shl i32 %shr2, 4
}
define i32 @test57(i32 %x) {
%shr = lshr i32 %x, 1
%shl = shl i32 %shr, 4
%and = and i32 %shl, 16
ret i32 %and
; CHECK: @test57
; CHECK: shl i32 %x, 3
}
define i32 @test58(i32 %x) {
%shr = lshr i32 %x, 1
%shl = shl i32 %shr, 4
%or = or i32 %shl, 8
ret i32 %or
; CHECK: @test58
; CHECK: shl i32 %x, 3
}
define i32 @test59(i32 %x) {
%shr = ashr i32 %x, 1
%shl = shl i32 %shr, 4
%or = or i32 %shl, 7
ret i32 %or
; CHECK: @test59
; CHECK: %shl = shl i32 %shr1, 4
}
define i32 @test60(i32 %x) {
%shr = ashr i32 %x, 4
%shl = shl i32 %shr, 1
%or = or i32 %shl, 1
ret i32 %or
; CHECK: @test60
; CHECK: lshr i32 %x, 3
}
define i32 @test61(i32 %x) {
%shr = ashr i32 %x, 4
%shl = shl i32 %shr, 1
%or = or i32 %shl, 2
ret i32 %or
; CHECK: @test61
; CHECK: ashr i32 %x, 4
}

View File

@ -82,6 +82,6 @@ entry:
%sub = add i32 %xor, -67108864 ; <i32> [#uses=1]
ret i32 %sub
; CHECK: @test8
; CHECK: %shr = ashr i32 %x, 5
; CHECK: ret i32 %shr
; CHECK: %sub = ashr i32 %x, 5
; CHECK: ret i32 %sub
}