From: Chris Lattner Date: Sun, 10 Jan 2010 20:25:54 +0000 (+0000) Subject: teach zext optimization how to deal with truncs that don't come from X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=9ee947c224a157a5fb2c921a0e194fddedef2f9f;p=oota-llvm.git 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@93127 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index 771ab23be3a..e2e74c1e5d5 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -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(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(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: diff --git a/test/Transforms/InstCombine/cast.ll b/test/Transforms/InstCombine/cast.ll index 4f0475ac59d..8424967e11a 100644 --- a/test/Transforms/InstCombine/cast.ll +++ b/test/Transforms/InstCombine/cast.ll @@ -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 +}