Skip to content

Commit 9fdfd8d

Browse files
committed
GlobalISel: Add utility function to constant fold FP ops
1 parent 45940db commit 9fdfd8d

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

llvm/include/llvm/CodeGen/GlobalISel/Utils.h

+3
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU);
204204
Optional<APInt> ConstantFoldBinOp(unsigned Opcode, const Register Op1,
205205
const Register Op2,
206206
const MachineRegisterInfo &MRI);
207+
Optional<APFloat> ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
208+
const Register Op2,
209+
const MachineRegisterInfo &MRI);
207210

208211
Optional<APInt> ConstantFoldExtOp(unsigned Opcode, const Register Op1,
209212
uint64_t Imm, const MachineRegisterInfo &MRI);

llvm/lib/CodeGen/GlobalISel/Utils.cpp

+54
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,60 @@ Optional<APInt> llvm::ConstantFoldBinOp(unsigned Opcode, const Register Op1,
481481
return None;
482482
}
483483

484+
Optional<APFloat> llvm::ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
485+
const Register Op2,
486+
const MachineRegisterInfo &MRI) {
487+
const ConstantFP *Op2Cst = getConstantFPVRegVal(Op2, MRI);
488+
if (!Op2Cst)
489+
return None;
490+
491+
const ConstantFP *Op1Cst = getConstantFPVRegVal(Op1, MRI);
492+
if (!Op1Cst)
493+
return None;
494+
495+
APFloat C1 = Op1Cst->getValueAPF();
496+
const APFloat &C2 = Op2Cst->getValueAPF();
497+
switch (Opcode) {
498+
case TargetOpcode::G_FADD:
499+
C1.add(C2, APFloat::rmNearestTiesToEven);
500+
return C1;
501+
case TargetOpcode::G_FSUB:
502+
C1.subtract(C2, APFloat::rmNearestTiesToEven);
503+
return C1;
504+
case TargetOpcode::G_FMUL:
505+
C1.multiply(C2, APFloat::rmNearestTiesToEven);
506+
return C1;
507+
case TargetOpcode::G_FDIV:
508+
C1.divide(C2, APFloat::rmNearestTiesToEven);
509+
return C1;
510+
case TargetOpcode::G_FREM:
511+
C1.mod(C2);
512+
return C1;
513+
case TargetOpcode::G_FCOPYSIGN:
514+
C1.copySign(C2);
515+
return C1;
516+
case TargetOpcode::G_FMINNUM:
517+
return minnum(C1, C2);
518+
case TargetOpcode::G_FMAXNUM:
519+
return maxnum(C1, C2);
520+
case TargetOpcode::G_FMINIMUM:
521+
return minimum(C1, C2);
522+
case TargetOpcode::G_FMAXIMUM:
523+
return maximum(C1, C2);
524+
case TargetOpcode::G_FMINNUM_IEEE:
525+
case TargetOpcode::G_FMAXNUM_IEEE:
526+
// FIXME: These operations were unfortunately named. fminnum/fmaxnum do not
527+
// follow the IEEE behavior for signaling nans and follow libm's fmin/fmax,
528+
// and currently there isn't a nice wrapper in APFloat for the version with
529+
// correct snan handling.
530+
break;
531+
default:
532+
break;
533+
}
534+
535+
return None;
536+
}
537+
484538
bool llvm::isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI,
485539
bool SNaN) {
486540
const MachineInstr *DefMI = MRI.getVRegDef(Val);

0 commit comments

Comments
 (0)