[llvm] [GlobalISel] Migrate undef-operand combines to MIR patterns (PR #219449)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 28 05:06:15 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Vikash Gupta (vg0204)

<details>
<summary>Changes</summary>

Part of the ongoing effort to retire `wip_match_opcode` from the generic combiner. A whole class of combines only use it to ask "is operand N of the root undef?", delegating to `matchAnyExplicitUseIsUndef` / `matchOperandIsUndef`. That predicate is purely structural, so it belongs in the MIR pattern itself rather than in C++.

It adds four `GICombinePatFrag` classes parameterized by an opcode list (`unary_undef_frag`, `binop_left_undef_frag`, `binop_right_undef_frag`, `binop_any_undef_frag`). These become the shared vocabulary for undef-operand folds and let each rule express only its match shape. All the undef-to-{zero,-1,undef} / propagate-undef rules and the two extractelement-of-undef rules are re-expressed on top of them, the latter collapsing into a single rule.

It also included the fneg/fneg folds for `fmul/fdiv/fmad/fma` which are partially migrated as MIR-pattern for sub-cases.

Behavioural caveats worth calling out for review:
- Relocating these rules from the opcode-only bucket to the structured bucket can possibly shifts combine application order on the opcodes but it won't effect the semantics equivalence on execution level.

---
Full diff: https://github.com/llvm/llvm-project/pull/219449.diff


5 Files Affected:

- (modified) llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h (-7) 
- (modified) llvm/include/llvm/Target/GlobalISel/Combine.td (+94-48) 
- (modified) llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp (+1-33) 
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-divrem-insertpt-crash.mir (+3-2) 
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/merge-values-s16-true16.ll (+7-4) 


``````````diff
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 28495529ec160..00c7d4808536b 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -496,10 +496,6 @@ class CombinerHelper {
   applyCombineTruncOfShift(MachineInstr &MI,
                            std::pair<MachineInstr *, LLT> &MatchInfo) const;
 
-  /// Return true if any explicit use operand on \p MI is defined by a
-  /// G_IMPLICIT_DEF.
-  LLVM_ABI bool matchAnyExplicitUseIsUndef(MachineInstr &MI) const;
-
   /// Return true if all register explicit use operands on \p MI are defined by
   /// a G_IMPLICIT_DEF.
   LLVM_ABI bool matchAllExplicitUsesAreUndef(MachineInstr &MI) const;
@@ -572,9 +568,6 @@ class CombinerHelper {
   /// Optimize (x op x) -> x
   LLVM_ABI bool matchBinOpSameVal(MachineInstr &MI) const;
 
-  /// Check if operand \p OpIdx is undef.
-  LLVM_ABI bool matchOperandIsUndef(MachineInstr &MI, unsigned OpIdx) const;
-
   /// Check if operand \p MO is known to be a power of 2. When \p OrNegative
   /// is true, also match operands whose negation is a power of 2 (i.e. whose
   /// absolute value is a power of 2).
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index e0f665e85c2cc..4b0a438cd6455 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -470,49 +470,74 @@ def narrow_binop_feeding_and : GICombineRule<
          [{ return Helper.matchNarrowBinopFeedingAnd(*${root}, ${matchinfo}); }]),
   (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
 
+// Reusable match fragments that fire when an operand of the root is undef
+// (i.e. defined by G_IMPLICIT_DEF). Each is a class parameterized by the list
+// of opcodes to match, so any set of opcodes sharing the same "undef operand"
+// shape is expressed once here and combined at the match side; each rule then
+// supplies its own 'apply' (fold to 0, -1, undef, ...). $dst is the root def.
+
+// Unary op ($dst = op $x) with an undef source.
+class unary_undef_frag<list<Instruction> ops> : GICombinePatFrag<
+  (outs root:$dst), (ins),
+  !foreach(op, ops, (pattern (op $dst, $x), (G_IMPLICIT_DEF $x)))>;
+
+// Binary op ($dst = op $x, $y) with an undef left operand ($x).
+class binop_left_undef_frag<list<Instruction> ops> : GICombinePatFrag<
+  (outs root:$dst), (ins),
+  !foreach(op, ops, (pattern (op $dst, $x, $y), (G_IMPLICIT_DEF $x)))>;
+
+// Binary op ($dst = op $x, $y) with an undef right operand ($y).
+class binop_right_undef_frag<list<Instruction> ops> : GICombinePatFrag<
+  (outs root:$dst), (ins),
+  !foreach(op, ops, (pattern (op $dst, $x, $y), (G_IMPLICIT_DEF $y)))>;
+
+// Binary op ($dst = op $x, $y) with either operand undef. Both operand
+// positions are enumerated because match patterns are not auto-commuted.
+class binop_any_undef_frag<list<Instruction> ops> : GICombinePatFrag<
+  (outs root:$dst), (ins),
+  !listconcat(
+    !foreach(op, ops, (pattern (op $dst, $x, $y), (G_IMPLICIT_DEF $x))),
+    !foreach(op, ops, (pattern (op $dst, $x, $y), (G_IMPLICIT_DEF $y))))>;
+
 // [us]itofp(undef) = 0, because the result value is bounded.
+def undef_to_fp_zero_frags : unary_undef_frag<[G_UITOFP, G_SITOFP]>;
 def undef_to_fp_zero : GICombineRule<
-  (defs root:$root),
-  (match (wip_match_opcode G_UITOFP, G_SITOFP):$root,
-         [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
-  (apply [{ Helper.replaceInstWithFConstant(*${root}, 0.0); }])>;
+  (defs root:$dst),
+  (match (undef_to_fp_zero_frags $dst)),
+  (apply [{ Helper.replaceInstWithFConstant(*${dst}.getParent(), 0.0); }])>;
 
+def undef_to_int_zero_frags : binop_any_undef_frag<[G_AND, G_MUL]>;
 def undef_to_int_zero: GICombineRule<
-  (defs root:$root),
-  (match (wip_match_opcode G_AND, G_MUL):$root,
-         [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
-  (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>;
+  (defs root:$dst),
+  (match (undef_to_int_zero_frags $dst)),
+  (apply [{ Helper.replaceInstWithConstant(*${dst}.getParent(), 0); }])>;
 
+def undef_to_negative_one_frags : binop_any_undef_frag<[G_OR]>;
 def undef_to_negative_one: GICombineRule<
-  (defs root:$root),
-  (match (wip_match_opcode G_OR):$root,
-         [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
-  (apply [{ Helper.replaceInstWithConstant(*${root}, -1); }])>;
+  (defs root:$dst),
+  (match (undef_to_negative_one_frags $dst)),
+  (apply [{ Helper.replaceInstWithConstant(*${dst}.getParent(), -1); }])>;
 
+def binop_left_undef_to_zero_frags : binop_left_undef_frag<[G_SHL, G_UDIV, G_UREM]>;
 def binop_left_undef_to_zero: GICombineRule<
-  (defs root:$root),
-  (match (wip_match_opcode G_SHL, G_UDIV, G_UREM):$root,
-         [{ return Helper.matchOperandIsUndef(*${root}, 1); }]),
-  (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>;
+  (defs root:$dst),
+  (match (binop_left_undef_to_zero_frags $dst)),
+  (apply [{ Helper.replaceInstWithConstant(*${dst}.getParent(), 0); }])>;
 
+def binop_right_undef_to_undef_frags : binop_right_undef_frag<[G_SHL, G_ASHR, G_LSHR]>;
 def binop_right_undef_to_undef: GICombineRule<
-  (defs root:$root),
-  (match (wip_match_opcode G_SHL, G_ASHR, G_LSHR):$root,
-         [{ return Helper.matchOperandIsUndef(*${root}, 2); }]),
-  (apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
+  (defs root:$dst),
+  (match (binop_right_undef_to_undef_frags $dst)),
+  (apply [{ Helper.replaceInstWithUndef(*${dst}.getParent()); }])>;
 
+def unary_undef_to_zero_frags : unary_undef_frag<[G_ABS]>;
 def unary_undef_to_zero: GICombineRule<
-  (defs root:$root),
-  (match (wip_match_opcode G_ABS):$root,
-         [{ return Helper.matchOperandIsUndef(*${root}, 1); }]),
-  (apply [{ Helper.replaceInstWithConstant(*${root}, 0); }])>;
+  (defs root:$dst),
+  (match (unary_undef_to_zero_frags $dst)),
+  (apply [{ Helper.replaceInstWithConstant(*${dst}.getParent(), 0); }])>;
 
-def unary_undef_to_undef_frags : GICombinePatFrag<
-  (outs root:$dst), (ins),
-  !foreach(op,
-           [G_TRUNC, G_BITCAST, G_ANYEXT, G_PTRTOINT, G_INTTOPTR, G_FPTOSI,
-            G_FPTOUI],
-           (pattern (op $dst, $x), (G_IMPLICIT_DEF $x)))>;
+def unary_undef_to_undef_frags : unary_undef_frag<
+  [G_TRUNC, G_BITCAST, G_ANYEXT, G_PTRTOINT, G_INTTOPTR, G_FPTOSI, G_FPTOUI]>;
 def unary_undef_to_undef : GICombineRule<
   (defs root:$dst),
   (match (unary_undef_to_undef_frags $dst)),
@@ -520,11 +545,11 @@ def unary_undef_to_undef : GICombineRule<
 
 // Instructions where if any source operand is undef, the instruction can be
 // replaced with undef.
+def propagate_undef_any_op_frags : binop_any_undef_frag<[G_ADD, G_SUB, G_XOR]>;
 def propagate_undef_any_op: GICombineRule<
-  (defs root:$root),
-  (match (wip_match_opcode G_ADD, G_SUB, G_XOR):$root,
-         [{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
-  (apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
+  (defs root:$dst),
+  (match (propagate_undef_any_op_frags $dst)),
+  (apply [{ Helper.replaceInstWithUndef(*${dst}.getParent()); }])>;
 
 // Instructions where if all source operands are undef, the instruction can be
 // replaced with undef.
@@ -1648,12 +1673,39 @@ def truncusatu_to_fptouisat : GICombineRule<
 
 def truncsat_combines : GICombineGroup<[trunc_ssats, trunc_ssatu, trunc_usatu, truncusatu_to_fptouisat]>;
 
-def redundant_neg_operands: GICombineRule<
+// fold (fadd x, fneg(y)) -> (fsub x, y)
+// fold (fsub x, fneg(y)) -> (fadd x, y)
+// These need a legality check on the swapped opcode, so stay in C++.
+def redundant_neg_operands_fadd_fsub: GICombineRule<
   (defs root:$root, build_fn_matchinfo:$matchinfo),
-  (match (wip_match_opcode G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMAD, G_FMA):$root,
+  (match (wip_match_opcode G_FADD, G_FSUB):$root,
     [{ return Helper.matchRedundantNegOperands(*${root}, ${matchinfo}); }]),
   (apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
 
+// fold (fmul (fneg x), (fneg y)) -> (fmul x, y)
+// fold (fdiv (fneg x), (fneg y)) -> (fdiv x, y)
+foreach binop = [G_FMUL, G_FDIV] in {
+  def binop#"_fneg_fneg" : GICombineRule<
+    (defs root:$dst),
+    (match (G_FNEG $nx, $x), (G_FNEG $ny, $y),
+           (binop $dst, $nx, $ny):$root),
+    (apply (binop $dst, $x, $y, (MIFlags $root)))>;
+}
+
+// fold (fmad (fneg x), (fneg y), z) -> (fmad x, y, z)
+// fold (fma (fneg x), (fneg y), z) -> (fma x, y, z)
+foreach fmaop = [G_FMAD, G_FMA] in {
+  def fmaop#"_fneg_fneg" : GICombineRule<
+    (defs root:$dst),
+    (match (G_FNEG $nx, $x), (G_FNEG $ny, $y),
+           (fmaop $dst, $nx, $ny, $z):$root),
+    (apply (fmaop $dst, $x, $y, $z, (MIFlags $root)))>;
+}
+
+def redundant_neg_operands : GICombineGroup<
+  [redundant_neg_operands_fadd_fsub, G_FMUL_fneg_fneg, G_FDIV_fneg_fneg,
+   G_FMAD_fneg_fneg, G_FMA_fneg_fneg]>;
+
 // Transform (fsub +-0.0, X) -> (fneg X)
 def fsub_to_fneg: GICombineRule<
   (defs root:$root, register_matchinfo:$matchinfo),
@@ -1863,17 +1915,12 @@ def match_subo_no_overflow : GICombineRule<
         [{ return Helper.matchSuboCarryOut(*${root}, ${matchinfo}); }]),
   (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
 
-def match_extract_of_element_undef_vector: GICombineRule <
-  (defs root:$root),
-  (match (G_IMPLICIT_DEF $vector),
-         (G_EXTRACT_VECTOR_ELT $root, $vector, $idx)),
-  (apply (G_IMPLICIT_DEF $root))
->;
-
-def match_extract_of_element_undef_index: GICombineRule <
+// extractelement(undef_vector, idx) and extractelement(vector, undef_idx) are
+// both undef. Either undef operand is matched by the shared frag.
+def extract_vector_element_undef_frags : binop_any_undef_frag<[G_EXTRACT_VECTOR_ELT]>;
+def extract_vector_element_undef : GICombineRule <
   (defs root:$root),
-  (match (G_IMPLICIT_DEF $idx),
-         (G_EXTRACT_VECTOR_ELT $root, $vector, $idx)),
+  (match (extract_vector_element_undef_frags $root)),
   (apply (G_IMPLICIT_DEF $root))
 >;
 
@@ -2109,8 +2156,7 @@ def combine_shuffle_disjoint_mask : GICombineRule<
 
 // match_extract_of_element and insert_vector_elt_oob must be the first!
 def vector_ops_combines: GICombineGroup<[
-match_extract_of_element_undef_vector,
-match_extract_of_element_undef_index,
+extract_vector_element_undef,
 insert_vector_element_idx_undef,
 insert_vector_element_elt_undef,
 match_extract_of_element,
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 3f5d9ecfa26fb..102f9e50c34b1 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -2889,13 +2889,6 @@ void CombinerHelper::applyCombineTruncOfShift(
   eraseInst(MI);
 }
 
-bool CombinerHelper::matchAnyExplicitUseIsUndef(MachineInstr &MI) const {
-  return any_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
-    return MO.isReg() &&
-           getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
-  });
-}
-
 bool CombinerHelper::matchAllExplicitUsesAreUndef(MachineInstr &MI) const {
   return all_of(MI.explicit_uses(), [this](const MachineOperand &MO) {
     return !MO.isReg() ||
@@ -3132,19 +3125,6 @@ bool CombinerHelper::matchSelectSameVal(MachineInstr &MI) const {
                        MRI);
 }
 
-bool CombinerHelper::matchBinOpSameVal(MachineInstr &MI) const {
-  return matchEqualDefs(MI.getOperand(1), MI.getOperand(2)) &&
-         canReplaceReg(MI.getOperand(0).getReg(), MI.getOperand(1).getReg(),
-                       MRI);
-}
-
-bool CombinerHelper::matchOperandIsUndef(MachineInstr &MI,
-                                         unsigned OpIdx) const {
-  MachineOperand &MO = MI.getOperand(OpIdx);
-  return MO.isReg() &&
-         getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
-}
-
 bool CombinerHelper::matchOperandIsKnownToBeAPowerOfTwo(
     const MachineOperand &MO, bool OrNegative) const {
   return isKnownToBeAPowerOfTwo(MO.getReg(), MRI, VT, OrNegative);
@@ -6381,9 +6361,7 @@ bool CombinerHelper::matchTruncUSatUToFPTOUISat(MachineInstr &MI,
 bool CombinerHelper::matchRedundantNegOperands(MachineInstr &MI,
                                                BuildFnTy &MatchInfo) const {
   unsigned Opc = MI.getOpcode();
-  assert(Opc == TargetOpcode::G_FADD || Opc == TargetOpcode::G_FSUB ||
-         Opc == TargetOpcode::G_FMUL || Opc == TargetOpcode::G_FDIV ||
-         Opc == TargetOpcode::G_FMAD || Opc == TargetOpcode::G_FMA);
+  assert(Opc == TargetOpcode::G_FADD || Opc == TargetOpcode::G_FSUB);
 
   Register Dst = MI.getOperand(0).getReg();
   Register X = MI.getOperand(1).getReg();
@@ -6401,16 +6379,6 @@ bool CombinerHelper::matchRedundantNegOperands(MachineInstr &MI,
   else if (mi_match(Dst, MRI, m_GFSub(m_Reg(X), m_GFNeg(m_Reg(Y)))) &&
            isLegalOrBeforeLegalizer({TargetOpcode::G_FADD, {Type}})) {
     Opc = TargetOpcode::G_FADD;
-  }
-  // fold (fmul fneg(x), fneg(y)) -> (fmul x, y)
-  // fold (fdiv fneg(x), fneg(y)) -> (fdiv x, y)
-  // fold (fmad fneg(x), fneg(y), z) -> (fmad x, y, z)
-  // fold (fma fneg(x), fneg(y), z) -> (fma x, y, z)
-  else if ((Opc == TargetOpcode::G_FMUL || Opc == TargetOpcode::G_FDIV ||
-            Opc == TargetOpcode::G_FMAD || Opc == TargetOpcode::G_FMA) &&
-           mi_match(X, MRI, m_GFNeg(m_Reg(X))) &&
-           mi_match(Y, MRI, m_GFNeg(m_Reg(Y)))) {
-    // no opcode change
   } else
     return false;
 
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-divrem-insertpt-crash.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-divrem-insertpt-crash.mir
index c9e8adfeaa94a..b66ed3b50feb7 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-divrem-insertpt-crash.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-divrem-insertpt-crash.mir
@@ -16,6 +16,7 @@ body:             |
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT:   [[COPY:%[0-9]+]]:_(p0) = COPY $x0
   ; CHECK-NEXT:   [[DEF:%[0-9]+]]:_(i1) = G_IMPLICIT_DEF
+  ; CHECK-NEXT:   [[DEF1:%[0-9]+]]:_(i64) = G_IMPLICIT_DEF
   ; CHECK-NEXT:   [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 0
   ; CHECK-NEXT:   G_BRCOND [[DEF]](i1), %bb.2
   ; CHECK-NEXT:   G_BR %bb.1
@@ -23,8 +24,8 @@ body:             |
   ; CHECK-NEXT: bb.1:
   ; CHECK-NEXT:   successors: %bb.2(0x80000000)
   ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   [[C1:%[0-9]+]]:_(i64) = G_CONSTANT i64 -1
-  ; CHECK-NEXT:   [[UDIV:%[0-9]+]]:_(i64) = G_UDIV [[C1]], [[C]]
+  ; CHECK-NEXT:   [[FREEZE:%[0-9]+]]:_(i64) = G_FREEZE [[DEF1]]
+  ; CHECK-NEXT:   [[UDIV:%[0-9]+]]:_(i64) = G_UDIV [[FREEZE]], [[C]]
   ; CHECK-NEXT:   G_STORE [[UDIV]](i64), [[COPY]](p0) :: (store (i64))
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.2:
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/merge-values-s16-true16.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/merge-values-s16-true16.ll
index fc1be777b09a3..dfa76d8d0acfa 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/merge-values-s16-true16.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/merge-values-s16-true16.ll
@@ -28,17 +28,20 @@ define amdgpu_kernel void @store_i136_divergent(ptr %p) {
 ; GFX1150-LABEL: store_i136_divergent:
 ; GFX1150:       ; %bb.0:
 ; GFX1150-NEXT:    s_load_b64 s[0:1], s[4:5], 0x0
-; GFX1150-NEXT:    v_dual_mov_b32 v3, 0 :: v_dual_and_b32 v0, 0x3ff, v0
-; GFX1150-NEXT:    v_mov_b32_e32 v2, 0
+; GFX1150-NEXT:    s_pack_ll_b32_b16 s2, 0, 0
 ; GFX1150-NEXT:    v_mov_b32_e32 v6, 0
-; GFX1150-NEXT:    s_delay_alu instid0(VALU_DEP_3) | instskip(SKIP_2) | instid1(VALU_DEP_3)
+; GFX1150-NEXT:    s_mov_b32 s3, s2
+; GFX1150-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; GFX1150-NEXT:    v_dual_mov_b32 v3, s3 :: v_dual_and_b32 v0, 0x3ff, v0
+; GFX1150-NEXT:    v_mov_b32_e32 v2, s2
 ; GFX1150-NEXT:    v_lshrrev_b32_e32 v1, 8, v0
 ; GFX1150-NEXT:    v_mov_b16_e32 v0.h, 0
 ; GFX1150-NEXT:    v_and_b16 v0.l, 0xff, v0.l
+; GFX1150-NEXT:    s_delay_alu instid0(VALU_DEP_3) | instskip(NEXT) | instid1(VALU_DEP_3)
 ; GFX1150-NEXT:    v_lshlrev_b16 v4.l, 8, v1.l
-; GFX1150-NEXT:    s_delay_alu instid0(VALU_DEP_3) | instskip(SKIP_1) | instid1(VALU_DEP_3)
 ; GFX1150-NEXT:    v_mov_b16_e32 v1.l, v0.h
 ; GFX1150-NEXT:    v_mov_b16_e32 v1.h, v0.h
+; GFX1150-NEXT:    s_delay_alu instid0(VALU_DEP_3)
 ; GFX1150-NEXT:    v_or_b16 v0.l, v0.l, v4.l
 ; GFX1150-NEXT:    s_waitcnt lgkmcnt(0)
 ; GFX1150-NEXT:    v_dual_mov_b32 v5, s1 :: v_dual_mov_b32 v4, s0

``````````

</details>


https://github.com/llvm/llvm-project/pull/219449


More information about the llvm-commits mailing list