@@ -4043,6 +4043,52 @@ InstCombinerImpl::foldExtractOfOverflowIntrinsic(ExtractValueInst &EV) {
4043
4043
return nullptr ;
4044
4044
}
4045
4045
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
+
4046
4092
Instruction *InstCombinerImpl::visitExtractValueInst (ExtractValueInst &EV) {
4047
4093
Value *Agg = EV.getAggregateOperand ();
4048
4094
@@ -4052,7 +4098,28 @@ Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) {
4052
4098
if (Value *V = simplifyExtractValueInst (Agg, EV.getIndices (),
4053
4099
SQ.getWithInstruction (&EV)))
4054
4100
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
+ }
4056
4123
if (InsertValueInst *IV = dyn_cast<InsertValueInst>(Agg)) {
4057
4124
// We're extracting from an insertvalue instruction, compare the indices
4058
4125
const unsigned *exti, *exte, *insi, *inse;
0 commit comments