Skip to content

Commit

Permalink
[GISel] Add (fsub +-0.0, X) -> fneg combine
Browse files Browse the repository at this point in the history
Allows for better matching of VOP3 mods.

Reviewed By: arsenm

Differential Revision: https://reviews.llvm.org/D136442
  • Loading branch information
Pierre-vh committed Nov 3, 2022
1 parent e1790c8 commit 020a9d7
Show file tree
Hide file tree
Showing 6 changed files with 468 additions and 45 deletions.
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Expand Up @@ -696,6 +696,9 @@ class CombinerHelper {
/// (fma fneg(x), fneg(y), z) -> (fma x, y, z)
bool matchRedundantNegOperands(MachineInstr &MI, BuildFnTy &MatchInfo);

bool matchFsubToFneg(MachineInstr &MI, Register &MatchInfo);
void applyFsubToFneg(MachineInstr &MI, Register &MatchInfo);

bool canCombineFMadOrFMA(MachineInstr &MI, bool &AllowFusionGlobally,
bool &HasFMAD, bool &Aggressive,
bool CanReassociate = false);
Expand Down
10 changes: 9 additions & 1 deletion llvm/include/llvm/Target/GlobalISel/Combine.td
Expand Up @@ -856,6 +856,13 @@ def redundant_neg_operands: GICombineRule<
[{ return Helper.matchRedundantNegOperands(*${root}, ${matchinfo}); }]),
(apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;

// Transform (fsub +-0.0, X) -> (fneg X)
def fsub_to_fneg: GICombineRule<
(defs root:$root, register_matchinfo:$matchinfo),
(match (wip_match_opcode G_FSUB):$root,
[{ return Helper.matchFsubToFneg(*${root}, ${matchinfo}); }]),
(apply [{ Helper.applyFsubToFneg(*${root}, ${matchinfo}); }])>;

// Transform (fadd x, (fmul y, z)) -> (fma y, z, x)
// (fadd x, (fmul y, z)) -> (fmad y, z, x)
// Transform (fadd (fmul x, y), z) -> (fma x, y, z)
Expand Down Expand Up @@ -1056,7 +1063,8 @@ def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines,
form_bitfield_extract, constant_fold, fabs_fneg_fold,
intdiv_combines, mulh_combines, redundant_neg_operands,
and_or_disjoint_mask, fma_combines, fold_binop_into_select,
sub_add_reg, select_to_minmax, redundant_binop_in_equality]>;
sub_add_reg, select_to_minmax, redundant_binop_in_equality,
fsub_to_fneg]>;

// A combine group used to for prelegalizer combiners at -O0. The combines in
// this group have been selected based on experiments to balance code size and
Expand Down
32 changes: 32 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Expand Up @@ -5190,6 +5190,38 @@ bool CombinerHelper::matchRedundantNegOperands(MachineInstr &MI,
return true;
}

bool CombinerHelper::matchFsubToFneg(MachineInstr &MI, Register &MatchInfo) {
assert(MI.getOpcode() == TargetOpcode::G_FSUB);

Register LHS = MI.getOperand(1).getReg();
MatchInfo = MI.getOperand(2).getReg();
LLT Ty = MRI.getType(MI.getOperand(0).getReg());

const auto LHSCst = Ty.isVector()
? getFConstantSplat(LHS, MRI, /* allowUndef */ true)
: getFConstantVRegValWithLookThrough(LHS, MRI);
if (!LHSCst)
return false;

// -0.0 is always allowed
if (LHSCst->Value.isNegZero())
return true;

// +0.0 is only allowed if nsz is set.
if (LHSCst->Value.isPosZero())
return MI.getFlag(MachineInstr::FmNsz);

return false;
}

void CombinerHelper::applyFsubToFneg(MachineInstr &MI, Register &MatchInfo) {
Builder.setInstrAndDebugLoc(MI);
Register Dst = MI.getOperand(0).getReg();
Builder.buildFNeg(
Dst, Builder.buildFCanonicalize(MRI.getType(Dst), MatchInfo).getReg(0));
eraseInst(MI);
}

/// Checks if \p MI is TargetOpcode::G_FMUL and contractable either
/// due to global flags or MachineInstr flags.
static bool isContractableFMul(MachineInstr &MI, bool AllowFusionGlobally) {
Expand Down

0 comments on commit 020a9d7

Please sign in to comment.