mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-01 08:28:19 +00:00
teach zext optimization how to deal with truncs that don't come from
the zext dest type. This allows us to handle test52/53 in cast.ll, and allows llvm-gcc to generate much better code for PR4216 in -m64 mode: _test_bitfield: ## @test_bitfield orl $32962, %edi movl %edi, %eax andl $-25350, %eax ret This also fixes a bug handling vector extends, ensuring that the mask produced is a vector constant, not an integer constant. llvm-svn: 93127
This commit is contained in:
parent
56e327711b
commit
ca53de1ab7
@ -192,7 +192,9 @@ Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty,
|
||||
return I->getOperand(0);
|
||||
|
||||
// Otherwise, must be the same type of cast, so just reinsert a new one.
|
||||
Res = CastInst::Create(cast<CastInst>(I)->getOpcode(), I->getOperand(0),Ty);
|
||||
// This also handles the case of zext(trunc(x)) -> zext(x).
|
||||
Res = CastInst::CreateIntegerCast(I->getOperand(0), Ty,
|
||||
Opc == Instruction::SExt);
|
||||
break;
|
||||
case Instruction::Select: {
|
||||
Value *True = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned);
|
||||
@ -597,6 +599,10 @@ static bool CanEvaluateZExtd(Value *V, const Type *Ty, const TargetData *TD) {
|
||||
|
||||
unsigned Opc = I->getOpcode();
|
||||
switch (Opc) {
|
||||
case Instruction::ZExt: // zext(zext(x)) -> zext(x).
|
||||
case Instruction::SExt: // zext(sext(x)) -> sext(x).
|
||||
case Instruction::Trunc: // zext(trunc(x)) -> trunc(x) or zext(x)
|
||||
return true;
|
||||
case Instruction::And:
|
||||
case Instruction::Or:
|
||||
case Instruction::Xor:
|
||||
@ -608,9 +614,6 @@ static bool CanEvaluateZExtd(Value *V, const Type *Ty, const TargetData *TD) {
|
||||
CanEvaluateZExtd(I->getOperand(1), Ty, TD);
|
||||
|
||||
//case Instruction::LShr:
|
||||
case Instruction::ZExt: // zext(zext(x)) -> zext(x).
|
||||
case Instruction::SExt: // zext(sext(x)) -> sext(x).
|
||||
return true;
|
||||
|
||||
case Instruction::Select:
|
||||
return CanEvaluateZExtd(I->getOperand(1), Ty, TD) &&
|
||||
@ -671,7 +674,7 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) {
|
||||
return ReplaceInstUsesWith(CI, Res);
|
||||
|
||||
// We need to emit an AND to clear the high bits.
|
||||
Constant *C = ConstantInt::get(CI.getContext(),
|
||||
Constant *C = ConstantInt::get(Res->getType(),
|
||||
APInt::getLowBitsSet(DestBitSize, SrcBitSize));
|
||||
return BinaryOperator::CreateAnd(Res, C);
|
||||
}
|
||||
@ -810,23 +813,20 @@ static bool CanEvaluateSExtd(Value *V, const Type *Ty, TargetData *TD) {
|
||||
//case Instruction::LShr: TODO
|
||||
//case Instruction::Trunc: TODO
|
||||
|
||||
case Instruction::SExt:
|
||||
case Instruction::ZExt: {
|
||||
// sext(sext(x)) -> sext(x)
|
||||
// sext(zext(x)) -> zext(x)
|
||||
case Instruction::SExt: // sext(sext(x)) -> sext(x)
|
||||
case Instruction::ZExt: // sext(zext(x)) -> zext(x)
|
||||
return true;
|
||||
}
|
||||
case Instruction::Select:
|
||||
return CanEvaluateSExtd(I->getOperand(1), Ty, TD) &&
|
||||
CanEvaluateSExtd(I->getOperand(2), Ty, TD);
|
||||
|
||||
case Instruction::PHI: {
|
||||
// We can change a phi if we can change all operands. Note that we never
|
||||
// get into trouble with cyclic PHIs here because we only consider
|
||||
// instructions with a single use.
|
||||
PHINode *PN = cast<PHINode>(I);
|
||||
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
|
||||
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
|
||||
if (!CanEvaluateSExtd(PN->getIncomingValue(i), Ty, TD)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
|
@ -496,6 +496,30 @@ define i64 @test51(i64 %A, i1 %cond) {
|
||||
; CHECK-NEXT: %sext = shl i64 %E, 32
|
||||
; CHECK-NEXT: %F = ashr i64 %sext, 32
|
||||
; CHECK-NEXT: ret i64 %F
|
||||
|
||||
}
|
||||
|
||||
define i32 @test52(i64 %A) {
|
||||
%B = trunc i64 %A to i16
|
||||
%C = or i16 %B, -32574
|
||||
%D = and i16 %C, -25350
|
||||
%E = zext i16 %D to i32
|
||||
ret i32 %E
|
||||
; CHECK: @test52
|
||||
; CHECK-NEXT: %B = trunc i64 %A to i32
|
||||
; CHECK-NEXT: %C = or i32 %B, 32962
|
||||
; CHECK-NEXT: %D = and i32 %C, 40186
|
||||
; CHECK-NEXT: ret i32 %D
|
||||
}
|
||||
|
||||
define i64 @test53(i32 %A) {
|
||||
%B = trunc i32 %A to i16
|
||||
%C = or i16 %B, -32574
|
||||
%D = and i16 %C, -25350
|
||||
%E = zext i16 %D to i64
|
||||
ret i64 %E
|
||||
; CHECK: @test53
|
||||
; CHECK-NEXT: %B = zext i32 %A to i64
|
||||
; CHECK-NEXT: %C = or i64 %B, 32962
|
||||
; CHECK-NEXT: %D = and i64 %C, 40186
|
||||
; CHECK-NEXT: ret i64 %D
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user