simplify a transformation by making it more general.

llvm-svn: 83792
This commit is contained in:
Chris Lattner 2009-10-11 21:22:21 +00:00
parent f39f4f928a
commit 406cb75c6b
3 changed files with 34 additions and 33 deletions

View File

@ -2783,39 +2783,21 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
// we know the bool is either zero or one, so this is a 'masking' multiply. // we know the bool is either zero or one, so this is a 'masking' multiply.
// See if we can simplify things based on how the boolean was originally // See if we can simplify things based on how the boolean was originally
// formed. // formed.
CastInst *BoolCast = 0; {
if (ZExtInst *CI = dyn_cast<ZExtInst>(Op0)) Value *BoolCast = 0, *OtherOp = 0;
if (CI->getOperand(0)->getType() == Type::getInt1Ty(*Context)) if (ZExtInst *CI = dyn_cast<ZExtInst>(Op0))
BoolCast = CI;
if (!BoolCast)
if (ZExtInst *CI = dyn_cast<ZExtInst>(I.getOperand(1)))
if (CI->getOperand(0)->getType() == Type::getInt1Ty(*Context)) if (CI->getOperand(0)->getType() == Type::getInt1Ty(*Context))
BoolCast = CI; BoolCast = CI, OtherOp = I.getOperand(1);
if (BoolCast) { if (!BoolCast)
if (ICmpInst *SCI = dyn_cast<ICmpInst>(BoolCast->getOperand(0))) { if (ZExtInst *CI = dyn_cast<ZExtInst>(I.getOperand(1)))
Value *SCIOp0 = SCI->getOperand(0), *SCIOp1 = SCI->getOperand(1); if (CI->getOperand(0)->getType() == Type::getInt1Ty(*Context))
const Type *SCOpTy = SCIOp0->getType(); BoolCast = CI, OtherOp = Op0;
bool TIS = false;
if (BoolCast) {
// If the icmp is true iff the sign bit of X is set, then convert this // X * Y (where Y is 0 or 1) -> X & (0-Y)
// multiply into a shift/and combination. Value *V = Builder->CreateSub(Constant::getNullValue(I.getType()),
if (isa<ConstantInt>(SCIOp1) && BoolCast, "tmp");
isSignBitCheck(SCI->getPredicate(), cast<ConstantInt>(SCIOp1), TIS) && return BinaryOperator::CreateAnd(V, OtherOp);
TIS) {
// Shift the X value right to turn it into "all signbits".
Constant *Amt = ConstantInt::get(SCIOp0->getType(),
SCOpTy->getPrimitiveSizeInBits()-1);
Value *V = Builder->CreateAShr(SCIOp0, Amt,
BoolCast->getOperand(0)->getName()+".mask");
// If the multiply type is not the same as the source type, sign extend
// or truncate to the multiply type.
if (I.getType() != V->getType())
V = Builder->CreateIntCast(V, I.getType(), true);
Value *OtherOp = Op0 == BoolCast ? I.getOperand(1) : Op0;
return BinaryOperator::CreateAnd(V, OtherOp);
}
} }
} }

View File

@ -33,4 +33,12 @@ define <2 x i1> @test5(<2 x i64> %x) {
entry: entry:
%V = icmp eq <2 x i64> %x, undef %V = icmp eq <2 x i64> %x, undef
ret <2 x i1> %V ret <2 x i1> %V
} }
define i32 @test6(i32 %a, i32 %b) {
%c = icmp sle i32 %a, -1
%d = zext i1 %c to i32
%e = sub i32 0, %d
%f = and i32 %e, %b
ret i32 %f
}

View File

@ -96,3 +96,14 @@ entry:
%m = mul i32 %shl, %A %m = mul i32 %shl, %A
ret i32 %m ret i32 %m
} }
; X * Y (when Y is 0 or 1) --> x & (0-Y)
define i32 @test16(i32 %b, i1 %c) {
%d = zext i1 %c to i32 ; <i32> [#uses=1]
; e = b & (a >> 31)
%e = mul i32 %d, %b ; <i32> [#uses=1]
ret i32 %e
}