[llvm] 9fdfd8d - GlobalISel: Add utility function to constant fold FP ops
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 22 11:38:24 PDT 2021
Author: Matt Arsenault
Date: 2021-03-22T14:38:17-04:00
New Revision: 9fdfd8dd52f63d763af11dca3c67fc94f5e5aa46
URL: https://github.com/llvm/llvm-project/commit/9fdfd8dd52f63d763af11dca3c67fc94f5e5aa46
DIFF: https://github.com/llvm/llvm-project/commit/9fdfd8dd52f63d763af11dca3c67fc94f5e5aa46.diff
LOG: GlobalISel: Add utility function to constant fold FP ops
Added:
Modified:
llvm/include/llvm/CodeGen/GlobalISel/Utils.h
llvm/lib/CodeGen/GlobalISel/Utils.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
index 17826cc8d6cb..f74a37e60450 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
@@ -204,6 +204,9 @@ void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU);
Optional<APInt> ConstantFoldBinOp(unsigned Opcode, const Register Op1,
const Register Op2,
const MachineRegisterInfo &MRI);
+Optional<APFloat> ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
+ const Register Op2,
+ const MachineRegisterInfo &MRI);
Optional<APInt> ConstantFoldExtOp(unsigned Opcode, const Register Op1,
uint64_t Imm, const MachineRegisterInfo &MRI);
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index a747fb40d6c6..dcd3e4646f43 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -481,6 +481,60 @@ Optional<APInt> llvm::ConstantFoldBinOp(unsigned Opcode, const Register Op1,
return None;
}
+Optional<APFloat> llvm::ConstantFoldFPBinOp(unsigned Opcode, const Register Op1,
+ const Register Op2,
+ const MachineRegisterInfo &MRI) {
+ const ConstantFP *Op2Cst = getConstantFPVRegVal(Op2, MRI);
+ if (!Op2Cst)
+ return None;
+
+ const ConstantFP *Op1Cst = getConstantFPVRegVal(Op1, MRI);
+ if (!Op1Cst)
+ return None;
+
+ APFloat C1 = Op1Cst->getValueAPF();
+ const APFloat &C2 = Op2Cst->getValueAPF();
+ switch (Opcode) {
+ case TargetOpcode::G_FADD:
+ C1.add(C2, APFloat::rmNearestTiesToEven);
+ return C1;
+ case TargetOpcode::G_FSUB:
+ C1.subtract(C2, APFloat::rmNearestTiesToEven);
+ return C1;
+ case TargetOpcode::G_FMUL:
+ C1.multiply(C2, APFloat::rmNearestTiesToEven);
+ return C1;
+ case TargetOpcode::G_FDIV:
+ C1.divide(C2, APFloat::rmNearestTiesToEven);
+ return C1;
+ case TargetOpcode::G_FREM:
+ C1.mod(C2);
+ return C1;
+ case TargetOpcode::G_FCOPYSIGN:
+ C1.copySign(C2);
+ return C1;
+ case TargetOpcode::G_FMINNUM:
+ return minnum(C1, C2);
+ case TargetOpcode::G_FMAXNUM:
+ return maxnum(C1, C2);
+ case TargetOpcode::G_FMINIMUM:
+ return minimum(C1, C2);
+ case TargetOpcode::G_FMAXIMUM:
+ return maximum(C1, C2);
+ case TargetOpcode::G_FMINNUM_IEEE:
+ case TargetOpcode::G_FMAXNUM_IEEE:
+ // FIXME: These operations were unfortunately named. fminnum/fmaxnum do not
+ // follow the IEEE behavior for signaling nans and follow libm's fmin/fmax,
+ // and currently there isn't a nice wrapper in APFloat for the version with
+ // correct snan handling.
+ break;
+ default:
+ break;
+ }
+
+ return None;
+}
+
bool llvm::isKnownNeverNaN(Register Val, const MachineRegisterInfo &MRI,
bool SNaN) {
const MachineInstr *DefMI = MRI.getVRegDef(Val);
More information about the llvm-commits
mailing list