Skip to content

Commit

Permalink
[LoongArch] Load floating-point immediate using VLDI (#101923)
Browse files Browse the repository at this point in the history
This commit uses the VLDI instruction to load some common floating-point
constants when the LSX feature is enabled.
  • Loading branch information
heiher authored Aug 9, 2024
1 parent e1a16cd commit dbae30d
Show file tree
Hide file tree
Showing 4 changed files with 1,334 additions and 3,845 deletions.
20 changes: 19 additions & 1 deletion llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5573,14 +5573,32 @@ SDValue LoongArchTargetLowering::LowerReturn(
return DAG.getNode(LoongArchISD::RET, DL, MVT::Other, RetOps);
}

bool LoongArchTargetLowering::isFPImmVLDILegal(const APFloat &Imm,
EVT VT) const {
if (!Subtarget.hasExtLSX())
return false;

if (VT == MVT::f32) {
uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7e07ffff;
return (masked == 0x3e000000 || masked == 0x40000000);
}

if (VT == MVT::f64) {
uint64_t masked = Imm.bitcastToAPInt().getZExtValue() & 0x7fc0ffffffffffff;
return (masked == 0x3fc0000000000000 || masked == 0x4000000000000000);
}

return false;
}

bool LoongArchTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
bool ForCodeSize) const {
// TODO: Maybe need more checks here after vector extension is supported.
if (VT == MVT::f32 && !Subtarget.hasBasicF())
return false;
if (VT == MVT::f64 && !Subtarget.hasBasicD())
return false;
return (Imm.isZero() || Imm.isExactlyValue(+1.0));
return (Imm.isZero() || Imm.isExactlyValue(1.0) || isFPImmVLDILegal(Imm, VT));
}

bool LoongArchTargetLowering::isCheapToSpeculateCttz(Type *) const {
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,8 @@ class LoongArchTargetLowering : public TargetLowering {
bool shouldAlignPointerArgs(CallInst *CI, unsigned &MinSize,
Align &PrefAlign) const override;

bool isFPImmVLDILegal(const APFloat &Imm, EVT VT) const;

private:
/// Target-specific function used to lower LoongArch calling conventions.
typedef bool LoongArchCCAssignFn(const DataLayout &DL, LoongArchABI::ABI ABI,
Expand Down
31 changes: 31 additions & 0 deletions llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,29 @@ def to_valid_timm : SDNodeXForm<timm, [{
return CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(N), Subtarget->getGRLenVT());
}]>;

// FP immediate of VLDI patterns.
def f32imm_vldi : PatLeaf<(fpimm), [{
const auto &TLI =
*static_cast<const LoongArchTargetLowering*>(getTargetLowering());
return TLI.isFPImmVLDILegal(N->getValueAPF(), MVT::f32);
}]>;
def f64imm_vldi : PatLeaf<(fpimm), [{
const auto &TLI =
*static_cast<const LoongArchTargetLowering*>(getTargetLowering());
return TLI.isFPImmVLDILegal(N->getValueAPF(), MVT::f64);
}]>;

def to_f32imm_vldi : SDNodeXForm<fpimm, [{
uint64_t x = N->getValueAPF().bitcastToAPInt().getZExtValue();
x = (0b11011 << 8) | (((x >> 24) & 0xc0) ^ 0x40) | ((x >> 19) & 0x3f);
return CurDAG->getTargetConstant(SignExtend32<13>(x), SDLoc(N), MVT::i32);
}]>;
def to_f64imm_vldi : SDNodeXForm<fpimm, [{
uint64_t x = N->getValueAPF().bitcastToAPInt().getZExtValue();
x = (0b11100 << 8) | (((x >> 56) & 0xc0) ^ 0x40) | ((x >> 48) & 0x3f);
return CurDAG->getTargetConstant(SignExtend32<13>(x), SDLoc(N), MVT::i32);
}]>;

//===----------------------------------------------------------------------===//
// Instruction class templates
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -663,7 +686,9 @@ def VMSKGEZ_B : LSX2R_VV<0x729c5000>;

def VMSKNZ_B : LSX2R_VV<0x729c6000>;

let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
def VLDI : LSX1RI13_VI<0x73e00000>;
}

def VAND_V : LSX3R_VVV<0x71260000>;
def VOR_V : LSX3R_VVV<0x71268000>;
Expand Down Expand Up @@ -1910,6 +1935,12 @@ def : Pat<(v2i64 (fp_to_sint v2f64:$vj)), (VFTINTRZ_L_D v2f64:$vj)>;
def : Pat<(v4i32 (fp_to_uint v4f32:$vj)), (VFTINTRZ_WU_S v4f32:$vj)>;
def : Pat<(v2i64 (fp_to_uint v2f64:$vj)), (VFTINTRZ_LU_D v2f64:$vj)>;

// Vector loads floating-point constants
def : Pat<(f32 f32imm_vldi:$in),
(f32 (EXTRACT_SUBREG (VLDI (to_f32imm_vldi f32imm_vldi:$in)), sub_32))>;
def : Pat<(f64 f64imm_vldi:$in),
(f64 (EXTRACT_SUBREG (VLDI (to_f64imm_vldi f64imm_vldi:$in)), sub_64))>;

} // Predicates = [HasExtLSX]

/// Intrinsic pattern
Expand Down
Loading

0 comments on commit dbae30d

Please sign in to comment.