From: Chris Lattner Date: Thu, 13 Jan 2005 22:52:24 +0000 (+0000) Subject: Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This occurs in X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=87875dac899f9316b6b02585196cce2f077c08bc;p=oota-llvm.git Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This occurs in the 'sim' program and probably elsewhere. In sim, it comes up for cases like this: #define round(x) ((x)>0.0 ? (x)+0.5 : (x)-0.5) double G; void T(double X) { G = round(X); } (it uses the round macro a lot). This changes the LLVM code from: %tmp.1 = setgt double %X, 0.000000e+00 ; [#uses=1] %tmp.4 = add double %X, 5.000000e-01 ; [#uses=1] %tmp.6 = sub double %X, 5.000000e-01 ; [#uses=1] %mem_tmp.0 = select bool %tmp.1, double %tmp.4, double %tmp.6 store double %mem_tmp.0, double* %G to: %tmp.1 = setgt double %X, 0.000000e+00 ; [#uses=1] %mem_tmp.0.p = select bool %tmp.1, double 5.000000e-01, double -5.000000e-01 %mem_tmp.0 = add double %mem_tmp.0.p, %X store double %mem_tmp.0, double* %G ret void git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19537 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index bb235ca868a..b8ff3d4e7e7 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -3588,6 +3588,59 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { } } + // Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This is legal for + // FP as well. + if (Instruction *TI = dyn_cast(TrueVal)) + if (Instruction *FI = dyn_cast(FalseVal)) + if (TI->hasOneUse() && FI->hasOneUse()) { + bool isInverse = false; + Instruction *AddOp = 0, *SubOp = 0; + + if (TI->getOpcode() == Instruction::Sub && + FI->getOpcode() == Instruction::Add) { + AddOp = FI; SubOp = TI; + } else if (FI->getOpcode() == Instruction::Sub && + TI->getOpcode() == Instruction::Add) { + AddOp = TI; SubOp = FI; + } + + if (AddOp) { + Value *OtherAddOp = 0; + if (SubOp->getOperand(0) == AddOp->getOperand(0)) { + OtherAddOp = AddOp->getOperand(1); + } else if (SubOp->getOperand(0) == AddOp->getOperand(1)) { + OtherAddOp = AddOp->getOperand(0); + } + + if (OtherAddOp) { + // So at this point we know we have: + // select C, (add X, Y), (sub X, ?) + // We can do the transform profitably if either 'Y' = '?' or '?' is + // a constant. + if (SubOp->getOperand(1) == AddOp || + isa(SubOp->getOperand(1))) { + Value *NegVal; + if (Constant *C = dyn_cast(SubOp->getOperand(1))) { + NegVal = ConstantExpr::getNeg(C); + } else { + NegVal = InsertNewInstBefore( + BinaryOperator::createNeg(SubOp->getOperand(1)), SI); + } + + Value *NewTrueOp = AddOp->getOperand(1); + Value *NewFalseOp = NegVal; + if (AddOp != TI) + std::swap(NewTrueOp, NewFalseOp); + Instruction *NewSel = + new SelectInst(CondVal, NewTrueOp,NewFalseOp,SI.getName()+".p"); + + NewSel = InsertNewInstBefore(NewSel, SI); + return BinaryOperator::createAdd(AddOp->getOperand(0), NewSel); + } + } + } + } + // See if we can fold the select into one of our operands. if (SI.getType()->isInteger()) { // See the comment above GetSelectFoldableOperands for a description of the