[llvm] [AMDGPU] Fix BITOP3 matcher for op(X, X) operands (PR #198373)
Arseniy Obolenskiy via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 10 08:27:46 PDT 2026
https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/198373
>From 64932c25e0ea06a881779cd0a95a149aa9d49c21 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 18 May 2026 20:38:30 +0200
Subject: [PATCH 1/4] [AMDGPU] Fix BITOP3 matcher for op(X, X) operands
Both operands share a Src slot, and recursing into X may replace that slot via the "replace parent operator" path, invalidating the truth-table bits cached for the other use. Handle AND/OR/XOR(X, X) directly: AND(X, X) = OR(X, X) = X, XOR(X, X) = 0
---
llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp | 11 +++
.../AMDGPU/AMDGPUInstructionSelector.cpp | 11 +++
llvm/test/CodeGen/AMDGPU/bitop3-op-self.ll | 71 +++++++++++++++++++
3 files changed, 93 insertions(+)
create mode 100644 llvm/test/CodeGen/AMDGPU/bitop3-op-self.ll
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
index ecf8d957fc80f..4a74b037cef08 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
@@ -4393,6 +4393,17 @@ static std::pair<unsigned, uint8_t> BitOp3_Op(SDValue In,
SDValue LHS = In.getOperand(0);
SDValue RHS = In.getOperand(1);
+ // op(X, X): both sides would share a Src slot, and recursing into X may
+ // replace that slot via the "replace parent operator" path, invalidating
+ // the truth-table bits cached for the other use.
+ if (LHS == RHS) {
+ uint8_t Bits;
+ if (!getOperandBits(LHS, Bits))
+ return std::make_pair(0, 0);
+ uint8_t TTbl = In.getOpcode() == ISD::XOR ? 0 : Bits;
+ return std::make_pair(1, TTbl);
+ }
+
SmallVector<SDValue, 3> Backup(Src.begin(), Src.end());
if (!getOperandBits(LHS, LHSBits) ||
!getOperandBits(RHS, RHSBits)) {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
index 4bfd56c0c4007..43b2b31ff5d0b 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
@@ -4225,6 +4225,17 @@ static std::pair<unsigned, uint8_t> BitOp3_Op(Register R,
Register LHS = getSrcRegIgnoringCopies(MI->getOperand(1).getReg(), MRI);
Register RHS = getSrcRegIgnoringCopies(MI->getOperand(2).getReg(), MRI);
+ // op(X, X): both sides would share a Src slot, and recursing into X may
+ // replace that slot via the "replace parent operator" path, invalidating
+ // the truth-table bits cached for the other use.
+ if (LHS == RHS) {
+ uint8_t Bits;
+ if (!getOperandBits(LHS, Bits))
+ return std::make_pair(0, 0);
+ uint8_t TTbl = MI->getOpcode() == TargetOpcode::G_XOR ? 0 : Bits;
+ return std::make_pair(1, TTbl);
+ }
+
SmallVector<Register, 3> Backup(Src.begin(), Src.end());
if (!getOperandBits(LHS, LHSBits) ||
!getOperandBits(RHS, RHSBits)) {
diff --git a/llvm/test/CodeGen/AMDGPU/bitop3-op-self.ll b/llvm/test/CodeGen/AMDGPU/bitop3-op-self.ll
new file mode 100644
index 0000000000000..32a3e665e5ff2
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/bitop3-op-self.ll
@@ -0,0 +1,71 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -O0 -global-isel=0 -mtriple=amdgcn-- -mcpu=gfx950 < %s | FileCheck -enable-var-scope -check-prefixes=GFX950-SDAG %s
+; RUN: llc -O0 -global-isel -new-reg-bank-select -mtriple=amdgcn-- -mcpu=gfx950 < %s | FileCheck -enable-var-scope -check-prefixes=GFX950-GISEL %s
+
+; Verify the BITOP3 matcher handles op(X, X) where both operands share a
+; Src slot: AND(X, X) = OR(X, X) = X, XOR(X, X) = 0. Run at -O0 so
+; DAGCombiner does not fold the self-op before selection.
+
+define amdgpu_ps i32 @xor_self_complex(i32 %a, i32 %b, i32 %c) {
+; GFX950-SDAG-LABEL: xor_self_complex:
+; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-SDAG-NEXT: v_xor_b32_e64 v0, v0, v0
+; GFX950-SDAG-NEXT: s_nop 0
+; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX950-GISEL-LABEL: xor_self_complex:
+; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: s_mov_b32 s0, 0
+; GFX950-GISEL-NEXT: v_mov_b32_e32 v0, s0
+; GFX950-GISEL-NEXT: s_nop 0
+; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-GISEL-NEXT: ; return to shader part epilog
+ %t1 = and i32 %a, %b
+ %xor1 = xor i32 %t1, %c
+ %res = xor i32 %xor1, %xor1
+ ret i32 %res
+}
+
+define amdgpu_ps i32 @and_self_complex(i32 %a, i32 %b, i32 %c) {
+; GFX950-SDAG-LABEL: and_self_complex:
+; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-SDAG-NEXT: v_and_b32_e64 v0, v0, v0
+; GFX950-SDAG-NEXT: s_nop 0
+; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX950-GISEL-LABEL: and_self_complex:
+; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-GISEL-NEXT: s_nop 0
+; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-GISEL-NEXT: ; return to shader part epilog
+ %t1 = and i32 %a, %b
+ %xor1 = xor i32 %t1, %c
+ %res = and i32 %xor1, %xor1
+ ret i32 %res
+}
+
+define amdgpu_ps i32 @or_self_complex(i32 %a, i32 %b, i32 %c) {
+; GFX950-SDAG-LABEL: or_self_complex:
+; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-SDAG-NEXT: v_or_b32_e64 v0, v0, v0
+; GFX950-SDAG-NEXT: s_nop 0
+; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX950-GISEL-LABEL: or_self_complex:
+; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-GISEL-NEXT: s_nop 0
+; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-GISEL-NEXT: ; return to shader part epilog
+ %t1 = and i32 %a, %b
+ %xor1 = xor i32 %t1, %c
+ %res = or i32 %xor1, %xor1
+ ret i32 %res
+}
>From a3d3744a2c8e1089f367e3432968b5330e17e3e5 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 18 May 2026 21:10:18 +0200
Subject: [PATCH 2/4] Address review comments
---
llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp | 16 ++-
.../AMDGPU/AMDGPUInstructionSelector.cpp | 7 ++
llvm/test/CodeGen/AMDGPU/bitop3-op-self.ll | 71 -----------
llvm/test/CodeGen/AMDGPU/bitop3.ll | 117 ++++++++++++++++++
4 files changed, 135 insertions(+), 76 deletions(-)
delete mode 100644 llvm/test/CodeGen/AMDGPU/bitop3-op-self.ll
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
index 4a74b037cef08..b0023cadc9603 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
@@ -4318,8 +4318,8 @@ bool AMDGPUDAGToDAGISel::SelectVOP3PMadMixBF16Mods(SDValue In, SDValue &Src,
// Match BITOP3 operation and return a number of matched instructions plus
// truth table.
-static std::pair<unsigned, uint8_t> BitOp3_Op(SDValue In,
- SmallVectorImpl<SDValue> &Src) {
+static std::pair<unsigned, uint8_t>
+BitOp3_Op(SDValue In, SmallVectorImpl<SDValue> &Src, SelectionDAG &DAG) {
unsigned NumOpcodes = 0;
uint8_t LHSBits, RHSBits;
@@ -4397,6 +4397,12 @@ static std::pair<unsigned, uint8_t> BitOp3_Op(SDValue In,
// replace that slot via the "replace parent operator" path, invalidating
// the truth-table bits cached for the other use.
if (LHS == RHS) {
+ // XOR(X, X) folds to 0 only when X is well-defined; XOR(undef, undef)
+ // is undef, not 0. AND/OR(X, X) folds to X and propagates undef
+ // correctly.
+ if (In.getOpcode() == ISD::XOR &&
+ !DAG.isGuaranteedNotToBeUndefOrPoison(LHS))
+ return std::make_pair(0, 0);
uint8_t Bits;
if (!getOperandBits(LHS, Bits))
return std::make_pair(0, 0);
@@ -4412,13 +4418,13 @@ static std::pair<unsigned, uint8_t> BitOp3_Op(SDValue In,
}
// Recursion is naturally limited by the size of the operand vector.
- auto Op = BitOp3_Op(LHS, Src);
+ auto Op = BitOp3_Op(LHS, Src, DAG);
if (Op.first) {
NumOpcodes += Op.first;
LHSBits = Op.second;
}
- Op = BitOp3_Op(RHS, Src);
+ Op = BitOp3_Op(RHS, Src, DAG);
if (Op.first) {
NumOpcodes += Op.first;
RHSBits = Op.second;
@@ -4453,7 +4459,7 @@ bool AMDGPUDAGToDAGISel::SelectBITOP3(SDValue In, SDValue &Src0, SDValue &Src1,
uint8_t TTbl;
unsigned NumOpcodes;
- std::tie(NumOpcodes, TTbl) = BitOp3_Op(In, Src);
+ std::tie(NumOpcodes, TTbl) = BitOp3_Op(In, Src, *CurDAG);
// Src.empty() case can happen if all operands are all zero or all ones.
// Normally it shall be optimized out before reaching this.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
index 43b2b31ff5d0b..23deeedcc0b9b 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
@@ -24,6 +24,7 @@
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/IntrinsicsAMDGPU.h"
@@ -4229,6 +4230,12 @@ static std::pair<unsigned, uint8_t> BitOp3_Op(Register R,
// replace that slot via the "replace parent operator" path, invalidating
// the truth-table bits cached for the other use.
if (LHS == RHS) {
+ // XOR(X, X) folds to 0 only when X is well-defined; XOR(undef, undef)
+ // is undef, not 0. AND/OR(X, X) folds to X and propagates undef
+ // correctly.
+ if (MI->getOpcode() == TargetOpcode::G_XOR &&
+ !isGuaranteedNotToBeUndef(LHS, MRI))
+ return std::make_pair(0, 0);
uint8_t Bits;
if (!getOperandBits(LHS, Bits))
return std::make_pair(0, 0);
diff --git a/llvm/test/CodeGen/AMDGPU/bitop3-op-self.ll b/llvm/test/CodeGen/AMDGPU/bitop3-op-self.ll
deleted file mode 100644
index 32a3e665e5ff2..0000000000000
--- a/llvm/test/CodeGen/AMDGPU/bitop3-op-self.ll
+++ /dev/null
@@ -1,71 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc -O0 -global-isel=0 -mtriple=amdgcn-- -mcpu=gfx950 < %s | FileCheck -enable-var-scope -check-prefixes=GFX950-SDAG %s
-; RUN: llc -O0 -global-isel -new-reg-bank-select -mtriple=amdgcn-- -mcpu=gfx950 < %s | FileCheck -enable-var-scope -check-prefixes=GFX950-GISEL %s
-
-; Verify the BITOP3 matcher handles op(X, X) where both operands share a
-; Src slot: AND(X, X) = OR(X, X) = X, XOR(X, X) = 0. Run at -O0 so
-; DAGCombiner does not fold the self-op before selection.
-
-define amdgpu_ps i32 @xor_self_complex(i32 %a, i32 %b, i32 %c) {
-; GFX950-SDAG-LABEL: xor_self_complex:
-; GFX950-SDAG: ; %bb.0:
-; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX950-SDAG-NEXT: v_xor_b32_e64 v0, v0, v0
-; GFX950-SDAG-NEXT: s_nop 0
-; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-SDAG-NEXT: ; return to shader part epilog
-;
-; GFX950-GISEL-LABEL: xor_self_complex:
-; GFX950-GISEL: ; %bb.0:
-; GFX950-GISEL-NEXT: s_mov_b32 s0, 0
-; GFX950-GISEL-NEXT: v_mov_b32_e32 v0, s0
-; GFX950-GISEL-NEXT: s_nop 0
-; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-GISEL-NEXT: ; return to shader part epilog
- %t1 = and i32 %a, %b
- %xor1 = xor i32 %t1, %c
- %res = xor i32 %xor1, %xor1
- ret i32 %res
-}
-
-define amdgpu_ps i32 @and_self_complex(i32 %a, i32 %b, i32 %c) {
-; GFX950-SDAG-LABEL: and_self_complex:
-; GFX950-SDAG: ; %bb.0:
-; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX950-SDAG-NEXT: v_and_b32_e64 v0, v0, v0
-; GFX950-SDAG-NEXT: s_nop 0
-; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-SDAG-NEXT: ; return to shader part epilog
-;
-; GFX950-GISEL-LABEL: and_self_complex:
-; GFX950-GISEL: ; %bb.0:
-; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX950-GISEL-NEXT: s_nop 0
-; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-GISEL-NEXT: ; return to shader part epilog
- %t1 = and i32 %a, %b
- %xor1 = xor i32 %t1, %c
- %res = and i32 %xor1, %xor1
- ret i32 %res
-}
-
-define amdgpu_ps i32 @or_self_complex(i32 %a, i32 %b, i32 %c) {
-; GFX950-SDAG-LABEL: or_self_complex:
-; GFX950-SDAG: ; %bb.0:
-; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX950-SDAG-NEXT: v_or_b32_e64 v0, v0, v0
-; GFX950-SDAG-NEXT: s_nop 0
-; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-SDAG-NEXT: ; return to shader part epilog
-;
-; GFX950-GISEL-LABEL: or_self_complex:
-; GFX950-GISEL: ; %bb.0:
-; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX950-GISEL-NEXT: s_nop 0
-; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-GISEL-NEXT: ; return to shader part epilog
- %t1 = and i32 %a, %b
- %xor1 = xor i32 %t1, %c
- %res = or i32 %xor1, %xor1
- ret i32 %res
-}
diff --git a/llvm/test/CodeGen/AMDGPU/bitop3.ll b/llvm/test/CodeGen/AMDGPU/bitop3.ll
index 75039e447a4d9..45dfbf75a1d27 100644
--- a/llvm/test/CodeGen/AMDGPU/bitop3.ll
+++ b/llvm/test/CodeGen/AMDGPU/bitop3.ll
@@ -741,6 +741,123 @@ define amdgpu_ps half @test_and_or_b16(i16 %a, i16 %b, i16 %c) {
%ret_cast = bitcast i16 %or1 to half
ret half %ret_cast
}
+; ========= op(X, X) — verify the BITOP3 matcher does not corrupt cached
+; truth-table bits when both operands of an AND/OR/XOR share the same Src
+; slot. The `optnone` attribute keeps the self-op alive through DAGCombine
+; so selection actually sees the LHS == RHS shape.
+
+define amdgpu_ps i32 @xor_self_complex(i32 %a, i32 %b, i32 %c) #0 {
+; GFX950-SDAG-LABEL: xor_self_complex:
+; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-SDAG-NEXT: v_xor_b32_e64 v0, v0, v0
+; GFX950-SDAG-NEXT: s_nop 0
+; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX950-GISEL-LABEL: xor_self_complex:
+; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: s_mov_b32 s0, 0
+; GFX950-GISEL-NEXT: v_mov_b32_e32 v0, s0
+; GFX950-GISEL-NEXT: s_nop 0
+; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-GISEL-NEXT: ; return to shader part epilog
+;
+; GFX1250-SDAG-LABEL: xor_self_complex:
+; GFX1250-SDAG: ; %bb.0:
+; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX1250-SDAG-NEXT: v_xor_b32_e64 v0, v0, v0
+; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX1250-GISEL-LABEL: xor_self_complex:
+; GFX1250-GISEL: ; %bb.0:
+; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: s_mov_b32 s0, 0
+; GFX1250-GISEL-NEXT: v_mov_b32_e32 v0, s0
+; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-GISEL-NEXT: ; return to shader part epilog
+ %t1 = and i32 %a, %b
+ %xor1 = xor i32 %t1, %c
+ %res = xor i32 %xor1, %xor1
+ ret i32 %res
+}
+
+define amdgpu_ps i32 @and_self_complex(i32 %a, i32 %b, i32 %c) #0 {
+; GFX950-SDAG-LABEL: and_self_complex:
+; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-SDAG-NEXT: v_and_b32_e64 v0, v0, v0
+; GFX950-SDAG-NEXT: s_nop 0
+; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX950-GISEL-LABEL: and_self_complex:
+; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-GISEL-NEXT: s_nop 0
+; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-GISEL-NEXT: ; return to shader part epilog
+;
+; GFX1250-SDAG-LABEL: and_self_complex:
+; GFX1250-SDAG: ; %bb.0:
+; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX1250-SDAG-NEXT: v_and_b32_e64 v0, v0, v0
+; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX1250-GISEL-LABEL: and_self_complex:
+; GFX1250-GISEL: ; %bb.0:
+; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-GISEL-NEXT: ; return to shader part epilog
+ %t1 = and i32 %a, %b
+ %xor1 = xor i32 %t1, %c
+ %res = and i32 %xor1, %xor1
+ ret i32 %res
+}
+
+define amdgpu_ps i32 @or_self_complex(i32 %a, i32 %b, i32 %c) #0 {
+; GFX950-SDAG-LABEL: or_self_complex:
+; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-SDAG-NEXT: v_or_b32_e64 v0, v0, v0
+; GFX950-SDAG-NEXT: s_nop 0
+; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX950-GISEL-LABEL: or_self_complex:
+; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-GISEL-NEXT: s_nop 0
+; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-GISEL-NEXT: ; return to shader part epilog
+;
+; GFX1250-SDAG-LABEL: or_self_complex:
+; GFX1250-SDAG: ; %bb.0:
+; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX1250-SDAG-NEXT: v_or_b32_e64 v0, v0, v0
+; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX1250-GISEL-LABEL: or_self_complex:
+; GFX1250-GISEL: ; %bb.0:
+; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-GISEL-NEXT: ; return to shader part epilog
+ %t1 = and i32 %a, %b
+ %xor1 = xor i32 %t1, %c
+ %res = or i32 %xor1, %xor1
+ ret i32 %res
+}
+
+attributes #0 = { optnone noinline }
+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; GCN: {{.*}}
; GFX1250-FAKE16: {{.*}}
>From 7c3d546d7f20ba4a3eb5cd7be41ec7f34ffbd5ea Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 18 May 2026 21:51:06 +0200
Subject: [PATCH 3/4] Address comments
---
llvm/test/CodeGen/AMDGPU/bitop3.ll | 110 +++++++++++++++++++++++++++++
1 file changed, 110 insertions(+)
diff --git a/llvm/test/CodeGen/AMDGPU/bitop3.ll b/llvm/test/CodeGen/AMDGPU/bitop3.ll
index 45dfbf75a1d27..f94f9def4e5f1 100644
--- a/llvm/test/CodeGen/AMDGPU/bitop3.ll
+++ b/llvm/test/CodeGen/AMDGPU/bitop3.ll
@@ -856,6 +856,116 @@ define amdgpu_ps i32 @or_self_complex(i32 %a, i32 %b, i32 %c) #0 {
ret i32 %res
}
+define amdgpu_ps i32 @xor_self_complex_noundef(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 {
+; GFX950-SDAG-LABEL: xor_self_complex_noundef:
+; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-SDAG-NEXT: v_xor_b32_e64 v0, v0, v0
+; GFX950-SDAG-NEXT: s_nop 0
+; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX950-GISEL-LABEL: xor_self_complex_noundef:
+; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: s_mov_b32 s0, 0
+; GFX950-GISEL-NEXT: v_mov_b32_e32 v0, s0
+; GFX950-GISEL-NEXT: s_nop 0
+; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-GISEL-NEXT: ; return to shader part epilog
+;
+; GFX1250-SDAG-LABEL: xor_self_complex_noundef:
+; GFX1250-SDAG: ; %bb.0:
+; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX1250-SDAG-NEXT: v_xor_b32_e64 v0, v0, v0
+; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX1250-GISEL-LABEL: xor_self_complex_noundef:
+; GFX1250-GISEL: ; %bb.0:
+; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: s_mov_b32 s0, 0
+; GFX1250-GISEL-NEXT: v_mov_b32_e32 v0, s0
+; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-GISEL-NEXT: ; return to shader part epilog
+ %t1 = and i32 %a, %b
+ %xor1 = xor i32 %t1, %c
+ %res = xor i32 %xor1, %xor1
+ ret i32 %res
+}
+
+define amdgpu_ps i32 @and_self_complex_noundef(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 {
+; GFX950-SDAG-LABEL: and_self_complex_noundef:
+; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-SDAG-NEXT: v_and_b32_e64 v0, v0, v0
+; GFX950-SDAG-NEXT: s_nop 0
+; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX950-GISEL-LABEL: and_self_complex_noundef:
+; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-GISEL-NEXT: s_nop 0
+; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-GISEL-NEXT: ; return to shader part epilog
+;
+; GFX1250-SDAG-LABEL: and_self_complex_noundef:
+; GFX1250-SDAG: ; %bb.0:
+; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX1250-SDAG-NEXT: v_and_b32_e64 v0, v0, v0
+; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX1250-GISEL-LABEL: and_self_complex_noundef:
+; GFX1250-GISEL: ; %bb.0:
+; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-GISEL-NEXT: ; return to shader part epilog
+ %t1 = and i32 %a, %b
+ %xor1 = xor i32 %t1, %c
+ %res = and i32 %xor1, %xor1
+ ret i32 %res
+}
+
+define amdgpu_ps i32 @or_self_complex_noundef(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 {
+; GFX950-SDAG-LABEL: or_self_complex_noundef:
+; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-SDAG-NEXT: v_or_b32_e64 v0, v0, v0
+; GFX950-SDAG-NEXT: s_nop 0
+; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX950-GISEL-LABEL: or_self_complex_noundef:
+; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX950-GISEL-NEXT: s_nop 0
+; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX950-GISEL-NEXT: ; return to shader part epilog
+;
+; GFX1250-SDAG-LABEL: or_self_complex_noundef:
+; GFX1250-SDAG: ; %bb.0:
+; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX1250-SDAG-NEXT: v_or_b32_e64 v0, v0, v0
+; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX1250-GISEL-LABEL: or_self_complex_noundef:
+; GFX1250-GISEL: ; %bb.0:
+; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
+; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX1250-GISEL-NEXT: ; return to shader part epilog
+ %t1 = and i32 %a, %b
+ %xor1 = xor i32 %t1, %c
+ %res = or i32 %xor1, %xor1
+ ret i32 %res
+}
+
attributes #0 = { optnone noinline }
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
>From c232123ee8c1ce0390b42593f8b9c441169d914d Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 18 May 2026 23:42:07 +0200
Subject: [PATCH 4/4] drop CC
---
llvm/test/CodeGen/AMDGPU/bitop3.ll | 144 +++++++++++++----------------
1 file changed, 66 insertions(+), 78 deletions(-)
diff --git a/llvm/test/CodeGen/AMDGPU/bitop3.ll b/llvm/test/CodeGen/AMDGPU/bitop3.ll
index f94f9def4e5f1..f0f6a953e508c 100644
--- a/llvm/test/CodeGen/AMDGPU/bitop3.ll
+++ b/llvm/test/CodeGen/AMDGPU/bitop3.ll
@@ -746,220 +746,208 @@ define amdgpu_ps half @test_and_or_b16(i16 %a, i16 %b, i16 %c) {
; slot. The `optnone` attribute keeps the self-op alive through DAGCombine
; so selection actually sees the LHS == RHS shape.
-define amdgpu_ps i32 @xor_self_complex(i32 %a, i32 %b, i32 %c) #0 {
+define i32 @xor_self_complex(i32 %a, i32 %b, i32 %c) #0 {
; GFX950-SDAG-LABEL: xor_self_complex:
; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX950-SDAG-NEXT: v_xor_b32_e64 v0, v0, v0
-; GFX950-SDAG-NEXT: s_nop 0
-; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-SDAG-NEXT: ; return to shader part epilog
+; GFX950-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX950-GISEL-LABEL: xor_self_complex:
; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-GISEL-NEXT: s_mov_b32 s0, 0
; GFX950-GISEL-NEXT: v_mov_b32_e32 v0, s0
-; GFX950-GISEL-NEXT: s_nop 0
-; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-GISEL-NEXT: ; return to shader part epilog
+; GFX950-GISEL-NEXT: s_setpc_b64 s[30:31]
;
; GFX1250-SDAG-LABEL: xor_self_complex:
; GFX1250-SDAG: ; %bb.0:
-; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-SDAG-NEXT: s_wait_kmcnt 0x0
; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX1250-SDAG-NEXT: v_xor_b32_e64 v0, v0, v0
-; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-SDAG-NEXT: ; return to shader part epilog
+; GFX1250-SDAG-NEXT: s_set_pc_i64 s[30:31]
;
; GFX1250-GISEL-LABEL: xor_self_complex:
; GFX1250-GISEL: ; %bb.0:
-; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-GISEL-NEXT: s_wait_kmcnt 0x0
; GFX1250-GISEL-NEXT: s_mov_b32 s0, 0
; GFX1250-GISEL-NEXT: v_mov_b32_e32 v0, s0
-; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-GISEL-NEXT: ; return to shader part epilog
+; GFX1250-GISEL-NEXT: s_set_pc_i64 s[30:31]
%t1 = and i32 %a, %b
%xor1 = xor i32 %t1, %c
%res = xor i32 %xor1, %xor1
ret i32 %res
}
-define amdgpu_ps i32 @and_self_complex(i32 %a, i32 %b, i32 %c) #0 {
+define i32 @and_self_complex(i32 %a, i32 %b, i32 %c) #0 {
; GFX950-SDAG-LABEL: and_self_complex:
; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX950-SDAG-NEXT: v_and_b32_e64 v0, v0, v0
-; GFX950-SDAG-NEXT: s_nop 0
-; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-SDAG-NEXT: ; return to shader part epilog
+; GFX950-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX950-GISEL-LABEL: and_self_complex:
; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX950-GISEL-NEXT: s_nop 0
-; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-GISEL-NEXT: ; return to shader part epilog
+; GFX950-GISEL-NEXT: s_setpc_b64 s[30:31]
;
; GFX1250-SDAG-LABEL: and_self_complex:
; GFX1250-SDAG: ; %bb.0:
-; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-SDAG-NEXT: s_wait_kmcnt 0x0
; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX1250-SDAG-NEXT: v_and_b32_e64 v0, v0, v0
-; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-SDAG-NEXT: ; return to shader part epilog
+; GFX1250-SDAG-NEXT: s_set_pc_i64 s[30:31]
;
; GFX1250-GISEL-LABEL: and_self_complex:
; GFX1250-GISEL: ; %bb.0:
-; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-GISEL-NEXT: s_wait_kmcnt 0x0
; GFX1250-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-GISEL-NEXT: ; return to shader part epilog
+; GFX1250-GISEL-NEXT: s_set_pc_i64 s[30:31]
%t1 = and i32 %a, %b
%xor1 = xor i32 %t1, %c
%res = and i32 %xor1, %xor1
ret i32 %res
}
-define amdgpu_ps i32 @or_self_complex(i32 %a, i32 %b, i32 %c) #0 {
+define i32 @or_self_complex(i32 %a, i32 %b, i32 %c) #0 {
; GFX950-SDAG-LABEL: or_self_complex:
; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX950-SDAG-NEXT: v_or_b32_e64 v0, v0, v0
-; GFX950-SDAG-NEXT: s_nop 0
-; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-SDAG-NEXT: ; return to shader part epilog
+; GFX950-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX950-GISEL-LABEL: or_self_complex:
; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX950-GISEL-NEXT: s_nop 0
-; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-GISEL-NEXT: ; return to shader part epilog
+; GFX950-GISEL-NEXT: s_setpc_b64 s[30:31]
;
; GFX1250-SDAG-LABEL: or_self_complex:
; GFX1250-SDAG: ; %bb.0:
-; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-SDAG-NEXT: s_wait_kmcnt 0x0
; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX1250-SDAG-NEXT: v_or_b32_e64 v0, v0, v0
-; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-SDAG-NEXT: ; return to shader part epilog
+; GFX1250-SDAG-NEXT: s_set_pc_i64 s[30:31]
;
; GFX1250-GISEL-LABEL: or_self_complex:
; GFX1250-GISEL: ; %bb.0:
-; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-GISEL-NEXT: s_wait_kmcnt 0x0
; GFX1250-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-GISEL-NEXT: ; return to shader part epilog
+; GFX1250-GISEL-NEXT: s_set_pc_i64 s[30:31]
%t1 = and i32 %a, %b
%xor1 = xor i32 %t1, %c
%res = or i32 %xor1, %xor1
ret i32 %res
}
-define amdgpu_ps i32 @xor_self_complex_noundef(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 {
+define i32 @xor_self_complex_noundef(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 {
; GFX950-SDAG-LABEL: xor_self_complex_noundef:
; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX950-SDAG-NEXT: v_xor_b32_e64 v0, v0, v0
-; GFX950-SDAG-NEXT: s_nop 0
-; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-SDAG-NEXT: ; return to shader part epilog
+; GFX950-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX950-GISEL-LABEL: xor_self_complex_noundef:
; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-GISEL-NEXT: s_mov_b32 s0, 0
; GFX950-GISEL-NEXT: v_mov_b32_e32 v0, s0
-; GFX950-GISEL-NEXT: s_nop 0
-; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-GISEL-NEXT: ; return to shader part epilog
+; GFX950-GISEL-NEXT: s_setpc_b64 s[30:31]
;
; GFX1250-SDAG-LABEL: xor_self_complex_noundef:
; GFX1250-SDAG: ; %bb.0:
-; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-SDAG-NEXT: s_wait_kmcnt 0x0
; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX1250-SDAG-NEXT: v_xor_b32_e64 v0, v0, v0
-; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-SDAG-NEXT: ; return to shader part epilog
+; GFX1250-SDAG-NEXT: s_set_pc_i64 s[30:31]
;
; GFX1250-GISEL-LABEL: xor_self_complex_noundef:
; GFX1250-GISEL: ; %bb.0:
-; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-GISEL-NEXT: s_wait_kmcnt 0x0
; GFX1250-GISEL-NEXT: s_mov_b32 s0, 0
; GFX1250-GISEL-NEXT: v_mov_b32_e32 v0, s0
-; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-GISEL-NEXT: ; return to shader part epilog
+; GFX1250-GISEL-NEXT: s_set_pc_i64 s[30:31]
%t1 = and i32 %a, %b
%xor1 = xor i32 %t1, %c
%res = xor i32 %xor1, %xor1
ret i32 %res
}
-define amdgpu_ps i32 @and_self_complex_noundef(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 {
+define i32 @and_self_complex_noundef(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 {
; GFX950-SDAG-LABEL: and_self_complex_noundef:
; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX950-SDAG-NEXT: v_and_b32_e64 v0, v0, v0
-; GFX950-SDAG-NEXT: s_nop 0
-; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-SDAG-NEXT: ; return to shader part epilog
+; GFX950-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX950-GISEL-LABEL: and_self_complex_noundef:
; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX950-GISEL-NEXT: s_nop 0
-; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-GISEL-NEXT: ; return to shader part epilog
+; GFX950-GISEL-NEXT: s_setpc_b64 s[30:31]
;
; GFX1250-SDAG-LABEL: and_self_complex_noundef:
; GFX1250-SDAG: ; %bb.0:
-; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-SDAG-NEXT: s_wait_kmcnt 0x0
; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX1250-SDAG-NEXT: v_and_b32_e64 v0, v0, v0
-; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-SDAG-NEXT: ; return to shader part epilog
+; GFX1250-SDAG-NEXT: s_set_pc_i64 s[30:31]
;
; GFX1250-GISEL-LABEL: and_self_complex_noundef:
; GFX1250-GISEL: ; %bb.0:
-; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-GISEL-NEXT: s_wait_kmcnt 0x0
; GFX1250-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-GISEL-NEXT: ; return to shader part epilog
+; GFX1250-GISEL-NEXT: s_set_pc_i64 s[30:31]
%t1 = and i32 %a, %b
%xor1 = xor i32 %t1, %c
%res = and i32 %xor1, %xor1
ret i32 %res
}
-define amdgpu_ps i32 @or_self_complex_noundef(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 {
+define i32 @or_self_complex_noundef(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 {
; GFX950-SDAG-LABEL: or_self_complex_noundef:
; GFX950-SDAG: ; %bb.0:
+; GFX950-SDAG-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX950-SDAG-NEXT: v_or_b32_e64 v0, v0, v0
-; GFX950-SDAG-NEXT: s_nop 0
-; GFX950-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-SDAG-NEXT: ; return to shader part epilog
+; GFX950-SDAG-NEXT: s_setpc_b64 s[30:31]
;
; GFX950-GISEL-LABEL: or_self_complex_noundef:
; GFX950-GISEL: ; %bb.0:
+; GFX950-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX950-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX950-GISEL-NEXT: s_nop 0
-; GFX950-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX950-GISEL-NEXT: ; return to shader part epilog
+; GFX950-GISEL-NEXT: s_setpc_b64 s[30:31]
;
; GFX1250-SDAG-LABEL: or_self_complex_noundef:
; GFX1250-SDAG: ; %bb.0:
-; GFX1250-SDAG-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-SDAG-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-SDAG-NEXT: s_wait_kmcnt 0x0
; GFX1250-SDAG-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
; GFX1250-SDAG-NEXT: v_or_b32_e64 v0, v0, v0
-; GFX1250-SDAG-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-SDAG-NEXT: ; return to shader part epilog
+; GFX1250-SDAG-NEXT: s_set_pc_i64 s[30:31]
;
; GFX1250-GISEL-LABEL: or_self_complex_noundef:
; GFX1250-GISEL: ; %bb.0:
-; GFX1250-GISEL-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; GFX1250-GISEL-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX1250-GISEL-NEXT: s_wait_kmcnt 0x0
; GFX1250-GISEL-NEXT: v_bitop3_b32 v0, v0, v2, v1 bitop3:0x6c
-; GFX1250-GISEL-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1250-GISEL-NEXT: ; return to shader part epilog
+; GFX1250-GISEL-NEXT: s_set_pc_i64 s[30:31]
%t1 = and i32 %a, %b
%xor1 = xor i32 %t1, %c
%res = or i32 %xor1, %xor1
More information about the llvm-commits
mailing list