[llvm] [AMDGPU] Fix wrong truth table in BitOp3_Op for shared sub-expressions. (PR #198556)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 1 07:52:09 PDT 2026


================
@@ -4401,16 +4401,103 @@ 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);
-    if (Op.first) {
-      NumOpcodes += Op.first;
-      LHSBits = Op.second;
+    //
+    // When LHS and RHS share a common sub-expression, one side's recursion
+    // may decompose that sub-expression and replace the Src slot the other
+    // side occupies with sub-operands via the "replace parent" path in
+    // getOperandBits. The other side's cached bit-pattern then refers to a
+    // slot whose contents changed, producing a wrong truth table.
+    //
+    // We detect this in three ways:
+    // (A) If LHS recursed, its truth table is valid against the Src state
+    //     when LHS recursion completed (SrcAfterLHS). If RHS recursion
+    //     then mutates a Src slot that LHSBits depends on, LHSBits is
+    //     stale.
+    // (B) If RHS did not recurse, RHSBits came from getOperandBits and
+    //     refers to a specific Src slot. If that slot's contents changed
+    //     (by either recursion), RHSBits is stale.
+    // (C) Symmetrically for LHS if it did not recurse.
+    SmallVector<SDValue, 3> SrcBeforeRecurse(Src.begin(), Src.end());
----------------
carlobertolli wrote:

I agree with the aesthetic bit, but not allowing multiple uses of a slot is going to make the algorithm miss out on important cases where there is sharing between LHS and RHS. Example:

%t = and i32 %a, %b       ; used twice
%x = xor i32 %t, %c
%r = or  i32 %x, %t

With the current patch, %t decomposes into %a and %b, everything fits in 3 Src slots [%a, %b, %c]. We end up with a single v_bitop3 instruction.

With a hasOneUse guard, %t has 2 uses, so we refuse to decompose it, and we end up with a v_and and v_or.

It's only by doing a full LHS and RHS recursion that we can check whether we ended up in a pathological case.

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


More information about the llvm-commits mailing list