@@ -4043,6 +4043,52 @@ InstCombinerImpl::foldExtractOfOverflowIntrinsic(ExtractValueInst &EV) {
40434043 return nullptr ;
40444044}
40454045
4046+ static Value *foldFrexpOfSelect (ExtractValueInst &EV, CallInst *FrexpCall,
4047+ SelectInst *SelectInst,
4048+ InstCombiner::BuilderTy &Builder) {
4049+ // Helper to fold frexp of select to select of frexp.
4050+ Value *Cond = SelectInst->getCondition ();
4051+ Value *TrueVal = SelectInst->getTrueValue ();
4052+ Value *FalseVal = SelectInst->getFalseValue ();
4053+ ConstantFP *ConstOp = nullptr ;
4054+ Value *VarOp = nullptr ;
4055+ bool ConstIsTrue = false ;
4056+
4057+ if (auto *TrueConst = dyn_cast<ConstantFP>(TrueVal)) {
4058+ ConstOp = TrueConst;
4059+ VarOp = FalseVal;
4060+ ConstIsTrue = true ;
4061+ } else if (auto *FalseConst = dyn_cast<ConstantFP>(FalseVal)) {
4062+ ConstOp = FalseConst;
4063+ VarOp = TrueVal;
4064+ ConstIsTrue = false ;
4065+ }
4066+
4067+ if (!ConstOp || !VarOp)
4068+ return nullptr ;
4069+
4070+ CallInst *NewFrexp =
4071+ Builder.CreateCall (FrexpCall->getCalledFunction (), {VarOp}, " frexp" );
4072+
4073+ Value *NewEV = Builder.CreateExtractValue (NewFrexp, 0 , " mantissa" );
4074+
4075+ APFloat ConstVal = ConstOp->getValueAPF ();
4076+ int Exp = 0 ;
4077+ APFloat Mantissa = ConstVal;
4078+
4079+ if (ConstVal.isFiniteNonZero ()) {
4080+ Mantissa = frexp (ConstVal, Exp, APFloat::rmNearestTiesToEven);
4081+ }
4082+
4083+ Constant *ConstantMantissa = ConstantFP::get (ConstOp->getType (), Mantissa);
4084+
4085+ Value *NewSel = Builder.CreateSelect (
4086+ Cond, ConstIsTrue ? ConstantMantissa : NewEV,
4087+ ConstIsTrue ? NewEV : ConstantMantissa, " select.frexp" );
4088+
4089+ return NewSel;
4090+ }
4091+
40464092Instruction *InstCombinerImpl::visitExtractValueInst (ExtractValueInst &EV) {
40474093 Value *Agg = EV.getAggregateOperand ();
40484094
@@ -4052,7 +4098,28 @@ Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) {
40524098 if (Value *V = simplifyExtractValueInst (Agg, EV.getIndices (),
40534099 SQ.getWithInstruction (&EV)))
40544100 return replaceInstUsesWith (EV, V);
4055-
4101+ if (EV.getNumIndices () == 1 && EV.getIndices ()[0 ] == 0 ) {
4102+ if (auto *FrexpCall = dyn_cast<CallInst>(Agg)) {
4103+ if (Function *F = FrexpCall->getCalledFunction ()) {
4104+ if (F->getIntrinsicID () == Intrinsic::frexp) {
4105+ if (auto *SelInst =
4106+ dyn_cast<SelectInst>(FrexpCall->getArgOperand (0 ))) {
4107+ if (!SelInst->hasOneUse ())
4108+ return nullptr ;
4109+ if (isa<ConstantFP>(SelInst->getTrueValue ()) ||
4110+ isa<ConstantFP>(SelInst->getFalseValue ())) {
4111+ Builder.SetInsertPoint (&EV);
4112+
4113+ if (Value *Result =
4114+ foldFrexpOfSelect (EV, FrexpCall, SelInst, Builder)) {
4115+ return replaceInstUsesWith (EV, Result);
4116+ }
4117+ }
4118+ }
4119+ }
4120+ }
4121+ }
4122+ }
40564123 if (InsertValueInst *IV = dyn_cast<InsertValueInst>(Agg)) {
40574124 // We're extracting from an insertvalue instruction, compare the indices
40584125 const unsigned *exti, *exte, *insi, *inse;
0 commit comments