From 56bd02c55c7e512e140003015ab201441ef9eeac Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 18 Jun 2009 16:30:21 +0000 Subject: [PATCH] Generalize the zext(trunc(t) & C) instcombine to work even with C is not a low-bits mask, and add a similar instcombine for zext((trunc(t) & C) ^ C). llvm-svn: 73705 --- .../Scalar/InstructionCombining.cpp | 29 ++++++++++++++----- .../Transforms/InstCombine/trunc-mask-ext.ll | 17 ++++++++++- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp index bf287f2c6808..5bd17e0737b2 100644 --- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp @@ -8564,20 +8564,33 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) { } } - // zext(trunc(t) & C) -> (t & C) if C is a mask. + // zext(trunc(t) & C) -> (t & zext(C)). if (SrcI && SrcI->getOpcode() == Instruction::And && SrcI->hasOneUse()) if (ConstantInt *C = dyn_cast(SrcI->getOperand(1))) if (TruncInst *TI = dyn_cast(SrcI->getOperand(0))) { Value *TI0 = TI->getOperand(0); - if (TI0->getType() == CI.getType()) { - unsigned TO = C->getValue().countTrailingOnes(); - if (APIntOps::isMask(TO, C->getValue())) - return - BinaryOperator::Create(Instruction::And, TI0, - ConstantExpr::getZExt(C, CI.getType())); - } + if (TI0->getType() == CI.getType()) + return + BinaryOperator::CreateAnd(TI0, + ConstantExpr::getZExt(C, CI.getType())); } + // zext((trunc(t) & C) ^ C) -> ((t & zext(C)) ^ zext(C)). + if (SrcI && SrcI->getOpcode() == Instruction::Xor && SrcI->hasOneUse()) + if (ConstantInt *C = dyn_cast(SrcI->getOperand(1))) + if (BinaryOperator *And = dyn_cast(SrcI->getOperand(0))) + if (And->getOpcode() == Instruction::And && And->hasOneUse() && + And->getOperand(1) == C) + if (TruncInst *TI = dyn_cast(And->getOperand(0))) { + Value *TI0 = TI->getOperand(0); + if (TI0->getType() == CI.getType()) { + Constant *ZC = ConstantExpr::getZExt(C, CI.getType()); + Instruction *NewAnd = BinaryOperator::CreateAnd(TI0, ZC, "tmp"); + InsertNewInstBefore(NewAnd, *And); + return BinaryOperator::CreateXor(NewAnd, ZC); + } + } + return 0; } diff --git a/llvm/test/Transforms/InstCombine/trunc-mask-ext.ll b/llvm/test/Transforms/InstCombine/trunc-mask-ext.ll index 1499947cc072..7e3d8446acff 100644 --- a/llvm/test/Transforms/InstCombine/trunc-mask-ext.ll +++ b/llvm/test/Transforms/InstCombine/trunc-mask-ext.ll @@ -2,7 +2,7 @@ ; RUN: not grep zext %t ; RUN: not grep sext %t -; Instcombine should be able to eliminate both ext casts. +; Instcombine should be able to eliminate all of these ext casts. declare void @use(i32) @@ -21,3 +21,18 @@ define i64 @bar(i64 %a) { call void @use(i32 %b) ret i64 %d } +define i64 @goo(i64 %a) { + %b = trunc i64 %a to i32 + %c = and i32 %b, 8 + %d = zext i32 %c to i64 + call void @use(i32 %b) + ret i64 %d +} +define i64 @hoo(i64 %a) { + %b = trunc i64 %a to i32 + %c = and i32 %b, 8 + %x = xor i32 %c, 8 + %d = zext i32 %x to i64 + call void @use(i32 %b) + ret i64 %d +}