[llvm] [AMDGPU] Adjust amdgpu fmax/fmin legalization (PR #202917)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 10 05:06:41 PDT 2026
================
@@ -10322,6 +10324,121 @@ void SIInstrInfo::fixImplicitOperands(MachineInstr &MI) const {
}
}
+// fcanonicalize is selected as a self-max (SelectCanonicalizeAsMax), i.e.
+// V_MAX_F{16,32} src, src, so only these max opcodes can define a canonicalize.
+static bool isFPSelfMaxCanonicalizeOpc(unsigned Opc) {
+ switch (Opc) {
+ case AMDGPU::V_MAX_F16_e32:
+ case AMDGPU::V_MAX_F16_e64:
+ case AMDGPU::V_MAX_F16_t16_e32:
+ case AMDGPU::V_MAX_F16_t16_e64:
+ case AMDGPU::V_MAX_F16_fake16_e32:
+ case AMDGPU::V_MAX_F16_fake16_e64:
+ case AMDGPU::V_MAX_F32_e32:
+ case AMDGPU::V_MAX_F32_e64:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// VALU FP min/max (f16/f32). On FeatureIEEEMinimumMaximumInsts targets these
+// print as v_{min,max}_num_f*, which canonicalize their inputs internally.
+static bool isFPMinMaxNumOpc(unsigned Opc) {
+ switch (Opc) {
+ case AMDGPU::V_MIN_F16_e32:
+ case AMDGPU::V_MIN_F16_e64:
+ case AMDGPU::V_MIN_F16_t16_e32:
+ case AMDGPU::V_MIN_F16_t16_e64:
+ case AMDGPU::V_MIN_F16_fake16_e32:
+ case AMDGPU::V_MIN_F16_fake16_e64:
+ case AMDGPU::V_MIN_F32_e32:
+ case AMDGPU::V_MIN_F32_e64:
+ return true;
+ default:
+ return isFPSelfMaxCanonicalizeOpc(Opc);
+ }
+}
+
+static bool isFPCanonicalizeSrcModifier(unsigned Mod) {
+ return !(Mod & ~(SISrcMods::NEG | SISrcMods::ABS));
+}
+
+/// On FeatureIEEEMinimumMaximumInsts targets a VALU FP min/max is printed as
+/// v_{min,max}_num_f*, which already canonicalizes its inputs, so feeding it an
+/// explicitly canonicalized operand is redundant.
+///
+/// A uniform llvm.minnum/maxnum on a target without scalar _num_ min/max is
+/// lowered to fcanonicalize(x)/fcanonicalize(y) feeding S_{MIN,MAX}_F*, where
+/// each fcanonicalize is selected as a self-max V_MAX_F*_e64 src_mods:src,
+/// src_mods:src. When SIFixSGPRCopies later moves that scalar op back to a
+/// VALU min/max, e.g.:
+///
+/// %10 = V_MAX_F32_e64 0, %9, 0, %9, 0, 0 ; fcanonicalize %9
+/// %11 = V_MAX_F32_e64 1, %8, 1, %8, 0, 0 ; fcanonicalize -%8
+/// %13 = COPY %11
+/// %14 = COPY %10
+/// %12 = S_MAX_F32 %13, %14 --> V_MAX_F32_e64 %10, %11
+///
+/// the self-max inputs become redundant once the user is a v_max_num, so fold
+/// them back to %9/-%8 and drop the now-dead canonicalizes.
+void SIInstrInfo::removeFcanonicalize(MachineInstr &MI) const {
----------------
arsenm wrote:
This shouldn't be here. The current optimization strategy for eliminating canonicalizes is dodgy, but replacing it shouldn't be in this PR. If we want to move this into MI folding, this should *repalce* the existing DAG fold, but this isn't doing that. This is also too narrowly targeted on lowered canonicalizes, instead of against all canonicalizing operations
https://github.com/llvm/llvm-project/pull/202917
More information about the llvm-commits
mailing list