Skip to content

Commit 010ef82

Browse files
committed
[InstCombine] InstCombine should fold frexp of select to select of frexp
1 parent a56b52a commit 010ef82

File tree

2 files changed

+75
-9
lines changed

2 files changed

+75
-9
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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+
40464092
Instruction *InstCombinerImpl::visitExtractValueInst(ExtractValueInst &EV) {
40474093
Value *Agg = EV.getAggregateOperand();
40484094

@@ -4052,7 +4098,26 @@ 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 (isa<ConstantFP>(SelInst->getTrueValue()) ||
4108+
isa<ConstantFP>(SelInst->getFalseValue())) {
4109+
Builder.SetInsertPoint(&EV);
4110+
4111+
if (Value *Result =
4112+
foldFrexpOfSelect(EV, FrexpCall, SelInst, Builder)) {
4113+
return replaceInstUsesWith(EV, Result);
4114+
}
4115+
}
4116+
}
4117+
}
4118+
}
4119+
}
4120+
}
40564121
if (InsertValueInst *IV = dyn_cast<InsertValueInst>(Agg)) {
40574122
// We're extracting from an insertvalue instruction, compare the indices
40584123
const unsigned *exti, *exte, *insi, *inse;

llvm/test/Transforms/InstCombine/select_frexp.ll

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ declare void @use(float)
88
define float @test_select_frexp_basic(float %x, i1 %cond) {
99
; CHECK-LABEL: define float @test_select_frexp_basic(
1010
; CHECK-SAME: float [[X:%.*]], i1 [[COND:%.*]]) {
11-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], float 1.000000e+00, float [[X]]
12-
; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[SEL]])
11+
; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
1312
; CHECK-NEXT: [[FREXP_0:%.*]] = extractvalue { float, i32 } [[FREXP]], 0
14-
; CHECK-NEXT: ret float [[FREXP_0]]
13+
; CHECK-NEXT: [[SELECT_FREXP:%.*]] = select i1 [[COND]], float 5.000000e-01, float [[FREXP_0]]
14+
; CHECK-NEXT: ret float [[SELECT_FREXP]]
1515
;
1616
%sel = select i1 %cond, float 1.000000e+00, float %x
1717
%frexp = call { float, i32 } @llvm.frexp.f32.i32(float %sel)
@@ -23,10 +23,10 @@ define float @test_select_frexp_basic(float %x, i1 %cond) {
2323
define float @test_select_frexp_const_false(float %x, i1 %cond) {
2424
; CHECK-LABEL: define float @test_select_frexp_const_false(
2525
; CHECK-SAME: float [[X:%.*]], i1 [[COND:%.*]]) {
26-
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], float [[X]], float 1.000000e+00
27-
; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[SEL]])
26+
; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
2827
; CHECK-NEXT: [[FREXP_0:%.*]] = extractvalue { float, i32 } [[FREXP]], 0
29-
; CHECK-NEXT: ret float [[FREXP_0]]
28+
; CHECK-NEXT: [[SELECT_FREXP:%.*]] = select i1 [[COND]], float [[FREXP_0]], float 5.000000e-01
29+
; CHECK-NEXT: ret float [[SELECT_FREXP]]
3030
;
3131
%sel = select i1 %cond, float %x, float 1.000000e+00
3232
%frexp = call { float, i32 } @llvm.frexp.f32.i32(float %sel)
@@ -40,9 +40,10 @@ define float @test_select_frexp_multi_use(float %x, i1 %cond) {
4040
; CHECK-SAME: float [[X:%.*]], i1 [[COND:%.*]]) {
4141
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND]], float 1.000000e+00, float [[X]]
4242
; CHECK-NEXT: call void @use(float [[SEL]])
43-
; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[SEL]])
43+
; CHECK-NEXT: [[FREXP:%.*]] = call { float, i32 } @llvm.frexp.f32.i32(float [[X]])
4444
; CHECK-NEXT: [[FREXP_0:%.*]] = extractvalue { float, i32 } [[FREXP]], 0
45-
; CHECK-NEXT: ret float [[FREXP_0]]
45+
; CHECK-NEXT: [[SELECT_FREXP:%.*]] = select i1 [[COND]], float 5.000000e-01, float [[FREXP_0]]
46+
; CHECK-NEXT: ret float [[SELECT_FREXP]]
4647
;
4748
%sel = select i1 %cond, float 1.000000e+00, float %x
4849
call void @use(float %sel)

0 commit comments

Comments
 (0)