Skip to content

Commit eaab324

Browse files
authored
[GlobalISel] Add constant folding support for G_FMA/G_FMAD in the combiner. (#65659)
1 parent 1b78742 commit eaab324

File tree

4 files changed

+86
-1
lines changed

4 files changed

+86
-1
lines changed

llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,9 @@ class CombinerHelper {
657657
/// Do constant FP folding when opportunities are exposed after MIR building.
658658
bool matchConstantFoldFPBinOp(MachineInstr &MI, ConstantFP* &MatchInfo);
659659

660+
/// Constant fold G_FMA/G_FMAD.
661+
bool matchConstantFoldFMA(MachineInstr &MI, ConstantFP *&MatchInfo);
662+
660663
/// \returns true if it is possible to narrow the width of a scalar binop
661664
/// feeding a G_AND instruction \p MI.
662665
bool matchNarrowBinopFeedingAnd(MachineInstr &MI, BuildFnTy &MatchInfo);

llvm/include/llvm/Target/GlobalISel/Combine.td

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,13 @@ def constant_fold_fp_binop : GICombineRule<
985985
[{ return Helper.matchConstantFoldFPBinOp(*${d}, ${matchinfo}); }]),
986986
(apply [{ Helper.replaceInstWithFConstant(*${d}, ${matchinfo}); }])>;
987987

988+
989+
def constant_fold_fma : GICombineRule<
990+
(defs root:$d, constantfp_matchinfo:$matchinfo),
991+
(match (wip_match_opcode G_FMAD, G_FMA):$d,
992+
[{ return Helper.matchConstantFoldFMA(*${d}, ${matchinfo}); }]),
993+
(apply [{ Helper.replaceInstWithFConstant(*${d}, ${matchinfo}); }])>;
994+
988995
def constant_fold_cast_op : GICombineRule<
989996
(defs root:$d, apint_matchinfo:$matchinfo),
990997
(match (wip_match_opcode G_ZEXT, G_SEXT, G_ANYEXT):$d,
@@ -1253,7 +1260,8 @@ def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines,
12531260
const_combines, xor_of_and_with_same_reg, ptr_add_with_zero,
12541261
shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine,
12551262
div_rem_to_divrem, funnel_shift_combines, commute_shift,
1256-
form_bitfield_extract, constant_fold_binops, constant_fold_cast_op, fabs_fneg_fold,
1263+
form_bitfield_extract, constant_fold_binops, constant_fold_fma,
1264+
constant_fold_cast_op, fabs_fneg_fold,
12571265
intdiv_combines, mulh_combines, redundant_neg_operands,
12581266
and_or_disjoint_mask, fma_combines, fold_binop_into_select,
12591267
sub_add_reg, select_to_minmax, redundant_binop_in_equality,

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88
#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
9+
#include "llvm/ADT/APFloat.h"
910
#include "llvm/ADT/SetVector.h"
1011
#include "llvm/ADT/SmallBitVector.h"
1112
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
@@ -4621,6 +4622,31 @@ bool CombinerHelper::matchConstantFoldFPBinOp(MachineInstr &MI, ConstantFP* &Mat
46214622
return true;
46224623
}
46234624

4625+
bool CombinerHelper::matchConstantFoldFMA(MachineInstr &MI,
4626+
ConstantFP *&MatchInfo) {
4627+
assert(MI.getOpcode() == TargetOpcode::G_FMA ||
4628+
MI.getOpcode() == TargetOpcode::G_FMAD);
4629+
auto [_, Op1, Op2, Op3] = MI.getFirst4Regs();
4630+
4631+
const ConstantFP *Op3Cst = getConstantFPVRegVal(Op3, MRI);
4632+
if (!Op3Cst)
4633+
return false;
4634+
4635+
const ConstantFP *Op2Cst = getConstantFPVRegVal(Op2, MRI);
4636+
if (!Op2Cst)
4637+
return false;
4638+
4639+
const ConstantFP *Op1Cst = getConstantFPVRegVal(Op1, MRI);
4640+
if (!Op1Cst)
4641+
return false;
4642+
4643+
APFloat Op1F = Op1Cst->getValueAPF();
4644+
Op1F.fusedMultiplyAdd(Op2Cst->getValueAPF(), Op3Cst->getValueAPF(),
4645+
APFloat::rmNearestTiesToEven);
4646+
MatchInfo = ConstantFP::get(MI.getMF()->getFunction().getContext(), Op1F);
4647+
return true;
4648+
}
4649+
46244650
bool CombinerHelper::matchNarrowBinopFeedingAnd(
46254651
MachineInstr &MI, std::function<void(MachineIRBuilder &)> &MatchInfo) {
46264652
// Look for a binop feeding into an AND with a mask:
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2+
# RUN: llc -mtriple aarch64 -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
3+
4+
---
5+
name: fma
6+
liveins:
7+
- { reg: '$d0' }
8+
body: |
9+
bb.1.entry:
10+
liveins: $d0
11+
12+
; CHECK-LABEL: name: fma
13+
; CHECK: liveins: $d0
14+
; CHECK-NEXT: {{ $}}
15+
; CHECK-NEXT: %res:_(s64) = G_FCONSTANT double 8.100000e+01
16+
; CHECK-NEXT: $d0 = COPY %res(s64)
17+
; CHECK-NEXT: RET_ReallyLR implicit $d0
18+
%a:_(s64) = G_FCONSTANT double 40.0
19+
%b:_(s64) = G_FCONSTANT double 2.0
20+
%c:_(s64) = G_FCONSTANT double 1.0
21+
%res:_(s64) = G_FMA %a, %b, %c
22+
$d0 = COPY %res(s64)
23+
RET_ReallyLR implicit $d0
24+
25+
...
26+
27+
---
28+
name: fmad
29+
liveins:
30+
- { reg: '$d0' }
31+
body: |
32+
bb.1.entry:
33+
liveins: $d0
34+
35+
; CHECK-LABEL: name: fmad
36+
; CHECK: liveins: $d0
37+
; CHECK-NEXT: {{ $}}
38+
; CHECK-NEXT: %res:_(s64) = G_FCONSTANT double 8.100000e+01
39+
; CHECK-NEXT: $d0 = COPY %res(s64)
40+
; CHECK-NEXT: RET_ReallyLR implicit $d0
41+
%a:_(s64) = G_FCONSTANT double 40.0
42+
%b:_(s64) = G_FCONSTANT double 2.0
43+
%c:_(s64) = G_FCONSTANT double 1.0
44+
%res:_(s64) = G_FMAD %a, %b, %c
45+
$d0 = COPY %res(s64)
46+
RET_ReallyLR implicit $d0
47+
48+
...

0 commit comments

Comments
 (0)