mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-15 07:59:50 +00:00
commit a tweaked version of Daniel's patch for PR3599. We now
eliminate all the extensions and all but the one required truncate from the testcase, but the or/and/shift stuff still isn't zapped. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@64809 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
189c6357a1
commit
a84f47c3e7
@ -8271,32 +8271,35 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) {
|
||||
|
||||
Value *Src = CI.getOperand(0);
|
||||
|
||||
// If this is a cast of a cast
|
||||
if (CastInst *CSrc = dyn_cast<CastInst>(Src)) { // A->B->C cast
|
||||
// If this is a TRUNC followed by a ZEXT then we are dealing with integral
|
||||
// types and if the sizes are just right we can convert this into a logical
|
||||
// 'and' which will be much cheaper than the pair of casts.
|
||||
if (isa<TruncInst>(CSrc)) {
|
||||
// Get the sizes of the types involved
|
||||
Value *A = CSrc->getOperand(0);
|
||||
uint32_t SrcSize = A->getType()->getPrimitiveSizeInBits();
|
||||
uint32_t MidSize = CSrc->getType()->getPrimitiveSizeInBits();
|
||||
uint32_t DstSize = CI.getType()->getPrimitiveSizeInBits();
|
||||
// If we're actually extending zero bits and the trunc is a no-op
|
||||
if (MidSize < DstSize && SrcSize == DstSize) {
|
||||
// Replace both of the casts with an And of the type mask.
|
||||
APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize));
|
||||
Constant *AndConst = ConstantInt::get(AndValue);
|
||||
Instruction *And =
|
||||
BinaryOperator::CreateAnd(CSrc->getOperand(0), AndConst);
|
||||
// Unfortunately, if the type changed, we need to cast it back.
|
||||
if (And->getType() != CI.getType()) {
|
||||
And->setName(CSrc->getName()+".mask");
|
||||
InsertNewInstBefore(And, CI);
|
||||
And = CastInst::CreateIntegerCast(And, CI.getType(), false/*ZExt*/);
|
||||
}
|
||||
return And;
|
||||
}
|
||||
// If this is a TRUNC followed by a ZEXT then we are dealing with integral
|
||||
// types and if the sizes are just right we can convert this into a logical
|
||||
// 'and' which will be much cheaper than the pair of casts.
|
||||
if (TruncInst *CSrc = dyn_cast<TruncInst>(Src)) { // A->B->C cast
|
||||
// Get the sizes of the types involved. We know that the intermediate type
|
||||
// will be smaller than A or C, but don't know the relation between A and C.
|
||||
Value *A = CSrc->getOperand(0);
|
||||
unsigned SrcSize = A->getType()->getPrimitiveSizeInBits();
|
||||
unsigned MidSize = CSrc->getType()->getPrimitiveSizeInBits();
|
||||
unsigned DstSize = CI.getType()->getPrimitiveSizeInBits();
|
||||
// If we're actually extending zero bits, then if
|
||||
// SrcSize < DstSize: zext(a & mask)
|
||||
// SrcSize == DstSize: a & mask
|
||||
// SrcSize > DstSize: trunc(a) & mask
|
||||
if (SrcSize < DstSize) {
|
||||
APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize));
|
||||
Constant *AndConst = ConstantInt::get(AndValue);
|
||||
Instruction *And =
|
||||
BinaryOperator::CreateAnd(A, AndConst, CSrc->getName()+".mask");
|
||||
InsertNewInstBefore(And, CI);
|
||||
return new ZExtInst(And, CI.getType());
|
||||
} else if (SrcSize == DstSize) {
|
||||
APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize));
|
||||
return BinaryOperator::CreateAnd(A, ConstantInt::get(AndValue));
|
||||
} else if (SrcSize > DstSize) {
|
||||
Instruction *Trunc = new TruncInst(A, CI.getType(), "tmp");
|
||||
InsertNewInstBefore(Trunc, CI);
|
||||
APInt AndValue(APInt::getLowBitsSet(DstSize, MidSize));
|
||||
return BinaryOperator::CreateAnd(Trunc, ConstantInt::get(AndValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,3 +8,26 @@ define i64 @test_sext_zext(i16 %A) {
|
||||
ret i64 %c2
|
||||
}
|
||||
|
||||
; PR3599
|
||||
define i32 @test2(i64 %tmp) nounwind readnone {
|
||||
entry:
|
||||
%tmp5 = trunc i64 %tmp to i8 ; <i8> [#uses=1]
|
||||
%tmp7 = lshr i64 %tmp, 8 ; <i64> [#uses=1]
|
||||
%tmp8 = trunc i64 %tmp7 to i8 ; <i8> [#uses=1]
|
||||
%tmp10 = lshr i64 %tmp, 16 ; <i64> [#uses=1]
|
||||
%tmp11 = trunc i64 %tmp10 to i8 ; <i8> [#uses=1]
|
||||
%tmp13 = lshr i64 %tmp, 24 ; <i64> [#uses=1]
|
||||
%tmp14 = trunc i64 %tmp13 to i8 ; <i8> [#uses=1]
|
||||
%tmp1 = zext i8 %tmp5 to i32 ; <i32> [#uses=1]
|
||||
%tmp2 = zext i8 %tmp8 to i32 ; <i32> [#uses=1]
|
||||
%tmp3 = shl i32 %tmp2, 8 ; <i32> [#uses=1]
|
||||
%tmp4 = zext i8 %tmp11 to i32 ; <i32> [#uses=1]
|
||||
%tmp6 = shl i32 %tmp4, 16 ; <i32> [#uses=1]
|
||||
%tmp9 = zext i8 %tmp14 to i32 ; <i32> [#uses=1]
|
||||
%tmp12 = shl i32 %tmp9, 24 ; <i32> [#uses=1]
|
||||
%tmp15 = or i32 %tmp12, %tmp1 ; <i32> [#uses=1]
|
||||
%tmp16 = or i32 %tmp15, %tmp6 ; <i32> [#uses=1]
|
||||
%tmp17 = or i32 %tmp16, %tmp3 ; <i32> [#uses=1]
|
||||
ret i32 %tmp17
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user