[llvm] [AMDGPU] Eliminate redundant s_round_mode writes (PR #216305)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 14 04:16:54 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: Barbara Mitic (barbara-amd)
<details>
<summary>Changes</summary>
Add a block local peephole that drops writes to the FP round mode which cannot be observed. A write is removed when a later s_round_mode replaces the whole round mode field before any instruction reads MODE, or when the value it writes is already live in MODE.
The analysis is intra-block only: the round mode on entry to a block is treated as unknown, and a write still live at the end of a block is kept for its successors.
---
Full diff: https://github.com/llvm/llvm-project/pull/216305.diff
2 Files Affected:
- (modified) llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp (+73)
- (added) llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-redundant-round-mode.mir (+317)
``````````diff
diff --git a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
index 7f87fbc0448b3..3cb75e88f42c7 100644
--- a/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
+++ b/llvm/lib/Target/AMDGPU/SIPreEmitPeephole.cpp
@@ -22,16 +22,22 @@
#include "GCNSubtarget.h"
#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachinePostDominators.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/Support/BranchProbability.h"
+#include <cstdint>
+#include <optional>
using namespace llvm;
#define DEBUG_TYPE "si-pre-emit-peephole"
+STATISTIC(NumRoundModeWritesRemoved,
+ "Number of redundant s_round_mode writes removed");
+
namespace {
class SIPreEmitPeephole {
@@ -52,6 +58,7 @@ class SIPreEmitPeephole {
const MachineBasicBlock &From,
const MachineBasicBlock &To) const;
bool removeExeczBranch(MachineInstr &MI, MachineBasicBlock &SrcMBB);
+ bool removeRedundantRoundMode(MachineBasicBlock &SrcMBB) const;
// Creates a list of packed instructions following an MFMA that are suitable
// for unpacking.
void collectUnpackingCandidates(MachineInstr &BeginMI,
@@ -514,6 +521,68 @@ bool SIPreEmitPeephole::removeExeczBranch(MachineInstr &MI,
return true;
}
+/// Remove writes to the FP round mode that can never be observed: either the
+/// value written is already live in MODE, or a later s_round_mode overwrites
+/// the whole round mode field before anything reads it.
+///
+/// This is a purely intra-block analysis: the round mode on entry to \p MBB is
+/// unknown, and a write that is still live at the end of the block is kept for
+/// the benefit of the successors.
+bool SIPreEmitPeephole::removeRedundantRoundMode(
+ MachineBasicBlock &SrcMBB) const {
+ MachineInstr *PendingWrite = nullptr;
+ std::optional<int64_t> CurrentRoundMode;
+ std::optional<int64_t> RoundModeBeforePendingWrite;
+ bool Changed = false;
+
+ for (MachineInstr &MI : make_early_inc_range(SrcMBB.instrs())) {
+ if (MI.isDebugInstr())
+ continue;
+
+ if (MI.getOpcode() == AMDGPU::S_ROUND_MODE) {
+ int64_t NewRoundMode = MI.getOperand(0).getImm();
+
+ if (PendingWrite && CurrentRoundMode != NewRoundMode) {
+ LLVM_DEBUG(dbgs() << "Removing dead round mode write: "
+ << *PendingWrite);
+ PendingWrite->eraseFromParent();
+ ++NumRoundModeWritesRemoved;
+ Changed = true;
+ PendingWrite = nullptr;
+ CurrentRoundMode = RoundModeBeforePendingWrite;
+ }
+
+ if (CurrentRoundMode == NewRoundMode) {
+ LLVM_DEBUG(dbgs() << "Removing redundant round mode write: " << MI);
+ MI.eraseFromParent();
+ ++NumRoundModeWritesRemoved;
+ Changed = true;
+ continue;
+ }
+
+ RoundModeBeforePendingWrite = CurrentRoundMode;
+ PendingWrite = &MI;
+ CurrentRoundMode = NewRoundMode;
+ continue;
+ }
+
+ if (!PendingWrite && !CurrentRoundMode)
+ continue;
+
+ if (MI.isCall() || MI.isInlineAsm() ||
+ MI.modifiesRegister(AMDGPU::MODE, TRI)) {
+ PendingWrite = nullptr;
+ CurrentRoundMode.reset();
+ continue;
+ }
+
+ if (MI.readsRegister(AMDGPU::MODE, TRI) || MI.hasUnmodeledSideEffects()) {
+ PendingWrite = nullptr;
+ }
+ }
+ return Changed;
+}
+
bool SIPreEmitPeephole::canUnpackingClobberRegister(const MachineInstr &MI) {
unsigned OpCode = MI.getOpcode();
Register DstReg = MI.getOperand(0).getReg();
@@ -792,6 +861,10 @@ bool SIPreEmitPeephole::run(MachineFunction &MF, MachineLoopInfo *LoopInfo) {
MF.RenumberBlocks();
+ for (MachineBasicBlock &MBB : MF) {
+ Changed |= removeRedundantRoundMode(MBB);
+ }
+
for (MachineBasicBlock &MBB : MF) {
MachineBasicBlock::iterator TermI = MBB.getFirstTerminator();
// Check first terminator for branches to optimize
diff --git a/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-redundant-round-mode.mir b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-redundant-round-mode.mir
new file mode 100644
index 0000000000000..e678714815021
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/si-pre-emit-peephole-redundant-round-mode.mir
@@ -0,0 +1,317 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc --mtriple=amdgpu12.01 -run-pass=si-pre-emit-peephole -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc --mtriple=amdgpu12.01 -passes=si-pre-emit-peephole %s -o - | FileCheck %s
+
+---
+name: dead_write_pair
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: dead_write_pair
+ ; CHECK: $sgpr2 = S_MOV_B32 0
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ $sgpr2 = S_MOV_B32 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: dead_write_run_of_three
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: dead_write_run_of_three
+ ; CHECK: $sgpr2 = S_MOV_B32 0
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ $sgpr2 = S_MOV_B32 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ S_ROUND_MODE 10, implicit-def $mode, implicit $mode
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: dead_write_across_non_mode_instr
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: dead_write_across_non_mode_instr
+ ; CHECK: $sgpr2 = S_MOV_B32 0
+ ; CHECK-NEXT: $vgpr3 = V_ADD_U32_e32 $vgpr1, $vgpr2, implicit $exec
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ $sgpr2 = S_MOV_B32 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ $vgpr3 = V_ADD_U32_e32 $vgpr1, $vgpr2, implicit $exec
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: dead_write_across_fp_instr_not_reading_mode
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: dead_write_across_fp_instr_not_reading_mode
+ ; CHECK: $sgpr2 = S_MOV_B32 0
+ ; CHECK-NEXT: $vgpr3 = V_CVT_F32_UBYTE0_e32 $vgpr1, implicit $exec
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ $sgpr2 = S_MOV_B32 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ $vgpr3 = V_CVT_F32_UBYTE0_e32 $vgpr1, implicit $exec
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: redundant_write_after_reader
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: redundant_write_after_reader
+ ; CHECK: S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: $vgpr3 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ $vgpr3 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: duplicate_adjacent_writes
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: duplicate_adjacent_writes
+ ; CHECK: S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: redundant_write_across_side_effecting_instr
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: redundant_write_across_side_effecting_instr
+ ; CHECK: S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_NOP 0
+ ; CHECK-NEXT: $vgpr3 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_NOP 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ $vgpr3 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: unknown_mode_on_entry
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: unknown_mode_on_entry
+ ; CHECK: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: fp_reader_between
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: fp_reader_between
+ ; CHECK: S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr3 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr3 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: getreg_reader_between
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: getreg_reader_between
+ ; CHECK: S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $sgpr0 = S_GETREG_B32 1, implicit $mode
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ $sgpr0 = S_GETREG_B32 1, implicit $mode
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: write_kept_across_side_effecting_instr
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: write_kept_across_side_effecting_instr
+ ; CHECK: S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: S_NOP 0
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ S_NOP 0
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: partial_setreg_between
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: partial_setreg_between
+ ; CHECK: S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: S_SETREG_IMM32_B32_mode 1, 1, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ S_SETREG_IMM32_B32_mode 1, 1, implicit-def $mode, implicit $mode
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: denorm_mode_between
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: denorm_mode_between
+ ; CHECK: S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: S_DENORM_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ S_DENORM_MODE 0, implicit-def $mode, implicit $mode
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: call_between
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: call_between
+ ; CHECK: S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $sgpr30_sgpr31 = SI_CALL killed $sgpr0_sgpr1, 0, csr_amdgpu
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ $sgpr30_sgpr31 = SI_CALL killed $sgpr0_sgpr1, 0, csr_amdgpu
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: inline_asm_between
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: inline_asm_between
+ ; CHECK: S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: INLINEASM &"s_nop 0", attdialect
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ INLINEASM &"s_nop 0", 0
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: write_live_out_of_block
+body: |
+ ; CHECK-LABEL: name: write_live_out_of_block
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ bb.0:
+ successors: %bb.1
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+
+ bb.1:
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: same_value_in_predecessor
+body: |
+ ; CHECK-LABEL: name: same_value_in_predecessor
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr3 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ bb.0:
+ successors: %bb.1
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+
+ bb.1:
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr3 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
+
+---
+name: dead_write_then_restore_makes_redundant
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: dead_write_then_restore_makes_redundant
+ ; CHECK: S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ ; CHECK-NEXT: $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: $vgpr3 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ ; CHECK-NEXT: S_ENDPGM 0
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr0 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ROUND_MODE 5, implicit-def $mode, implicit $mode
+ S_ROUND_MODE 0, implicit-def $mode, implicit $mode
+ $vgpr3 = V_ADD_F32_e32 $vgpr1, $vgpr2, implicit $mode, implicit $exec
+ S_ENDPGM 0
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/216305
More information about the llvm-commits
mailing list