+ if (Constant *SOC = dyn_cast<Constant>(SO)) {
+ if (ConstIsRHS)
+ return ConstantExpr::get(BI.getOpcode(), SOC, ConstOperand);
+ return ConstantExpr::get(BI.getOpcode(), ConstOperand, SOC);
+ }
+
+ Value *Op0 = SO, *Op1 = ConstOperand;
+ if (!ConstIsRHS)
+ std::swap(Op0, Op1);
+ Instruction *New;
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(&BI))
+ New = BinaryOperator::create(BO->getOpcode(), Op0, Op1);
+ else if (ShiftInst *SI = dyn_cast<ShiftInst>(&BI))
+ New = new ShiftInst(SI->getOpcode(), Op0, Op1);
+ else {
+ assert(0 && "Unknown binary instruction type!");
+ abort();
+ }
+ return IC->InsertNewInstBefore(New, BI);
+}
+
+// FoldBinOpIntoSelect - Given an instruction with a select as one operand and a
+// constant as the other operand, try to fold the binary operator into the
+// select arguments.
+static Instruction *FoldBinOpIntoSelect(Instruction &BI, SelectInst *SI,
+ InstCombiner *IC) {
+ // Don't modify shared select instructions
+ if (!SI->hasOneUse()) return 0;
+ Value *TV = SI->getOperand(1);
+ Value *FV = SI->getOperand(2);
+
+ if (isa<Constant>(TV) || isa<Constant>(FV)) {
+ Value *SelectTrueVal = FoldOperationIntoSelectOperand(BI, TV, IC);
+ Value *SelectFalseVal = FoldOperationIntoSelectOperand(BI, FV, IC);
+
+ return new SelectInst(SI->getCondition(), SelectTrueVal,
+ SelectFalseVal);
+ }
+ return 0;
+}