[llvm] [LoongArch] Custom legalizing ConstantFP to avoid float loads (PR #158050)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 12 22:45:43 PDT 2025
================
@@ -549,10 +575,66 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
case ISD::VECREDUCE_UMAX:
case ISD::VECREDUCE_UMIN:
return lowerVECREDUCE(Op, DAG);
+ case ISD::ConstantFP:
+ return lowerConstantFP(Op, DAG);
}
return SDValue();
}
+SDValue LoongArchTargetLowering::lowerConstantFP(SDValue Op,
+ SelectionDAG &DAG) const {
+ EVT VT = Op.getValueType();
+ ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Op);
+ const APFloat &FPVal = CFP->getValueAPF();
+ SDLoc DL(CFP);
+
+ assert((VT == MVT::f32 && Subtarget.hasBasicF()) ||
+ (VT == MVT::f64 && Subtarget.hasBasicD()));
+
+ // If value is 0.0 or -0.0, just ignore it.
+ if (FPVal.isZero())
+ return SDValue();
+
+ // If lsx enabled, use cheaper 'vldi' instruction if possible.
+ if (isFPImmVLDILegal(FPVal, VT))
+ return SDValue();
+
+ // Construct as integer, and move to float register.
+ APInt INTVal = FPVal.bitcastToAPInt();
+ switch (VT.getSimpleVT().SimpleTy) {
+ default:
+ llvm_unreachable("Unexpected floating point type!");
+ break;
+ case MVT::f32: {
+ SDValue NewVal = DAG.getConstant(INTVal, DL, MVT::i32);
+ if (Subtarget.is64Bit())
+ NewVal = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, NewVal);
+ return DAG.getNode(Subtarget.is64Bit() ? LoongArchISD::MOVGR2FR_W_LA64
+ : LoongArchISD::MOVGR2FR_W,
+ DL, VT, NewVal);
+ }
+ case MVT::f64: {
+ // If more than MaterializeFPImmInsNum instructions will be used to
+ // generate the INTVal, fallback to use floating point load from the
+ // constant pool.
+ auto Seq = LoongArchMatInt::generateInstSeq(INTVal.getSExtValue());
+ if (Seq.size() > MaterializeFPImmInsNum && !FPVal.isExactlyValue(+1.0))
----------------
zhaoqi5 wrote:
> Should the maximum instruction threshold also apply to `f32`?
`f32` requires a maximum of two instructions and a `movgr2fr.w`, which maybe always cheaper than loading from constant pool. But if we wish to also control the behavior of dealing with `f32` using this option, it can also be applied. Do you think it is necessary?
> and why is `+1.0` treated as a special case?
`+1.0` only need one `lu52i.d`, so we hope it always entering the following custom processing. The special treatment here is just to prevent it from returning when `MaterializeFPImmInsNum` equals 0. Otherwise, it will match worse code in `.td`.
By the way, `la32` maybe should always load non-zero `f64` from constant pool, because it seems no profit got from customing it. What do you think?
https://github.com/llvm/llvm-project/pull/158050
More information about the llvm-commits
mailing list