From ea340054040583f9e7c6395fa288b8d341c94650 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 10 Mar 2003 19:16:08 +0000 Subject: [PATCH] Fix bug: (x << 100) wasn't folded to 0, but (x >> 100) was (when x is unsigned) Implement new shift optimizations for shifting the result of a shift. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5729 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 55 ++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 0dfb235d892..041122401ce 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -73,7 +73,7 @@ namespace { Instruction *visitOr (BinaryOperator &I); Instruction *visitXor(BinaryOperator &I); Instruction *visitSetCondInst(BinaryOperator &I); - Instruction *visitShiftInst(Instruction &I); + Instruction *visitShiftInst(ShiftInst &I); Instruction *visitCastInst(CastInst &CI); Instruction *visitPHINode(PHINode &PN); Instruction *visitGetElementPtrInst(GetElementPtrInst &GEP); @@ -637,7 +637,7 @@ Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) { -Instruction *InstCombiner::visitShiftInst(Instruction &I) { +Instruction *InstCombiner::visitShiftInst(ShiftInst &I) { assert(I.getOperand(1)->getType() == Type::UByteTy); Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); @@ -647,15 +647,56 @@ Instruction *InstCombiner::visitShiftInst(Instruction &I) { Op0 == Constant::getNullValue(Op0->getType())) return ReplaceInstUsesWith(I, Op0); + // If this is a shift of a shift, see if we can fold the two together... + if (ShiftInst *Op0SI = dyn_cast(Op0)) { + if (isa(Op1) && isa(Op0SI->getOperand(1))) { + ConstantUInt *ShiftAmt1C = cast(Op0SI->getOperand(1)); + unsigned ShiftAmt1 = ShiftAmt1C->getValue(); + unsigned ShiftAmt2 = cast(Op1)->getValue(); + + // Check for (A << c1) << c2 and (A >> c1) >> c2 + if (I.getOpcode() == Op0SI->getOpcode()) { + unsigned Amt = ShiftAmt1+ShiftAmt2; // Fold into one big shift... + return new ShiftInst(I.getOpcode(), Op0SI->getOperand(0), + ConstantUInt::get(Type::UByteTy, Amt)); + } + + if (I.getType()->isUnsigned()) { // Check for (A << c1) >> c2 or visaversa + // Calculate bitmask for what gets shifted off the edge... + Constant *C = ConstantIntegral::getAllOnesValue(I.getType()); + if (I.getOpcode() == Instruction::Shr) + C = *C >> *ShiftAmt1C; + else + C = *C << *ShiftAmt1C; + assert(C && "Couldn't constant fold shift expression?"); + + Instruction *Mask = + BinaryOperator::create(Instruction::And, Op0SI->getOperand(0), + C, Op0SI->getOperand(0)->getName()+".mask",&I); + WorkList.push_back(Mask); + + // Figure out what flavor of shift we should use... + if (ShiftAmt1 == ShiftAmt2) + return ReplaceInstUsesWith(I, Mask); // (A << c) >> c === A & c2 + else if (ShiftAmt1 < ShiftAmt2) { + return new ShiftInst(I.getOpcode(), Mask, + ConstantUInt::get(Type::UByteTy, ShiftAmt2-ShiftAmt1)); + } else { + return new ShiftInst(Op0SI->getOpcode(), Mask, + ConstantUInt::get(Type::UByteTy, ShiftAmt1-ShiftAmt2)); + } + } + } + } + // shl uint X, 32 = 0 and shr ubyte Y, 9 = 0, ... just don't eliminate shr of // a signed value. // if (ConstantUInt *CUI = dyn_cast(Op1)) { - if (I.getOpcode() == Instruction::Shr) { - unsigned TypeBits = Op0->getType()->getPrimitiveSize()*8; - if (CUI->getValue() >= TypeBits && !(Op0->getType()->isSigned())) - return ReplaceInstUsesWith(I, Constant::getNullValue(Op0->getType())); - } + unsigned TypeBits = Op0->getType()->getPrimitiveSize()*8; + if (CUI->getValue() >= TypeBits && + (!Op0->getType()->isSigned() || I.getOpcode() == Instruction::Shl)) + return ReplaceInstUsesWith(I, Constant::getNullValue(Op0->getType())); // Check to see if we are shifting left by 1. If so, turn it into an add // instruction.