Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This occurs in
authorChris Lattner <sabre@nondot.org>
Thu, 13 Jan 2005 22:52:24 +0000 (22:52 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 13 Jan 2005 22:52:24 +0000 (22:52 +0000)
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          ; <bool> [#uses=1]
        %tmp.4 = add double %X, 5.000000e-01            ; <double> [#uses=1]
        %tmp.6 = sub double %X, 5.000000e-01            ; <double> [#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          ; <bool> [#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

lib/Transforms/Scalar/InstructionCombining.cpp

index bb235ca868a4d17e59936560afa6e4ad15458a61..b8ff3d4e7e73c5ff867b49c421ed9cadb01cc627 100644 (file)
@@ -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<Instruction>(TrueVal))
+    if (Instruction *FI = dyn_cast<Instruction>(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<Constant>(SubOp->getOperand(1))) {
+              Value *NegVal;
+              if (Constant *C = dyn_cast<Constant>(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