Skip to content

Conversation

@tonykuttai
Copy link
Contributor

@tonykuttai tonykuttai commented May 28, 2025

Description

Adds support for ternary equivalent operations of the form ternary(A, X, and(B,C)) where X=[xor(B,C)| nor(B,C)| eqv(B,C)| not(B)| not(C)].

List of xxeval equivalent ternary operations added and the corresponding imm value required:

Ternary Operator Imm Value
ternary(A, xor(B,C), and(B,C)) 22
ternary(A, nor(B,C), and(B,C)) 24
ternary(A, eqv(B,C), and(B,C)) 25
ternary(A, not(C), and(B,C)) 26
ternary(A, not(B), and(B,C)) 28

eg. xxeval XT,XA,XB,XC,22

  • performs XA ? xor(XB, XC) : and(XB,XC)and places the result in XT.

@tonykuttai tonykuttai marked this pull request as ready for review May 28, 2025 10:46
@llvmbot
Copy link
Member

llvmbot commented May 28, 2025

@llvm/pr-subscribers-backend-powerpc

Author: Tony Varghese (tonykuttai)

Changes

Description

<!--- Title/Description will be Subject/Body of commit message. -->
<!--- Please be concise and limit the subject line to 50 characters, -->
<!--- and wrap the Description at 72 characters. -->
<!--- Describe why this is required, what problem it solves. -->
xxeval instruction can be used for supporting the ternary patterns.

Supporting the following patterns in this change:

  • ternary(A, X, and(B,C))
  • ternary(A, X, B)
  • ternary(A, X, C)
  • ternary(A, X, xor(B,C))
    This change make use of the patterns and its corresponding imm values to group the ternary operations so that appropriate tableGen multiclass were formed. The following patterns are handled:
Ternary Operators                     Imm Values
ternary(A,  xor(B,C),   and(B,C))	22
ternary(A,  nor(B,C),   and(B,C))	24
ternary(A,  eqv(B,C),   and(B,C))	25
ternary(A,  not(C),     and(B,C))	26
ternary(A,  not(B),     and(B,C))	28

ternary(A,  and(B,C),   B)	        49
ternary(A,  nor(B,C),   B)	        56
ternary(A,  eqv(B,C),   B)	        57
ternary(A,  not(C),     B)	        58
ternary(A,  nand(B,C),  B)	        62

ternary(A,  and(B,C),   C)	        81
ternary(A,  nor(B,C),   C)	        88
ternary(A,  eqv(B,C),   C)	        89
ternary(A,  nand(B,C),  C)	        94

ternary(A,  and(B,C),   xor(B,C))	97
ternary(A,  B,          xor(B,C))	99
ternary(A,  C,          xor(B,C))	101
ternary(A,  or(B,C),    xor(B,C))	103
ternary(A,  nor(B,C),   xor(B,C))	104

ternary(A, not(B), C) : 92 is omitted as it was a symmetrical to ternary(A, not(C), B) : 58


Patch is 33.13 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/141733.diff

5 Files Affected:

  • (modified) llvm/lib/Target/PowerPC/PPCInstrP10.td (+170-32)
  • (added) llvm/test/CodeGen/PowerPC/xxeval-vselect-x-and.ll (+134)
  • (added) llvm/test/CodeGen/PowerPC/xxeval-vselect-x-b.ll (+126)
  • (added) llvm/test/CodeGen/PowerPC/xxeval-vselect-x-c.ll (+104)
  • (added) llvm/test/CodeGen/PowerPC/xxeval-vselect-x-xor.ll (+128)
diff --git a/llvm/lib/Target/PowerPC/PPCInstrP10.td b/llvm/lib/Target/PowerPC/PPCInstrP10.td
index 39a1ab0d388a7..99f77e18e43a0 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrP10.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrP10.td
@@ -2159,8 +2159,133 @@ let AddedComplexity = 400, Predicates = [IsISA3_1, HasVSX] in {
                                (COPY_TO_REGCLASS $VRB, VSRC), 2)))>;
 }
 
-class xxevalPattern <dag pattern, bits<8> imm> :
-  Pat<(v4i32 pattern), (XXEVAL $vA, $vB, $vC, imm)> {}
+class xxevalPattern <ValueType vt, dag pattern, bits<8> imm> :
+  Pat<(vt pattern), (XXEVAL $vA, $vB, $vC, imm)> {}
+
+class DagUnaryVNot<ValueType vt, string opstr>{
+  // Defines a class that returns the UnaryVNot dag for an operand string based on a value type.
+  dag res = !cond(
+          !eq(vt, v4i32) : !dag(vnot, [v4i32], [opstr]),
+          !eq(vt, v2i64) : (v2i64 (bitconvert (vnot (v4i32 !dag(bitconvert, [v2i64], [opstr])))))
+          );
+}
+
+class DagCondVNot<dag d, bit negate> {
+  // Defines a class that generates a vnot around the dag.
+  dag res = !if(!ne(negate, 0),
+               (vnot d),
+               d);
+}
+
+class XXEvalUnaryNot<ValueType vt> {
+  // Defines a wrapper class for unary NOT operations for v4i32 and v2i64 vector types.
+  // Unary NOT on operand B or C based on value type.
+  dag opB = DagUnaryVNot<vt, "vB">.res;
+  dag opC = DagUnaryVNot<vt, "vC">.res;
+}
+
+class XXEvalBinaryPattern<ValueType vt, SDPatternOperator op, bit notResult = 0> {
+  // Defines a wrapper class for binary patterns with optional NOT on result.
+  // Generate op pattern with optional NOT wrapping for result depending on "notResult".
+      dag opPat = !cond(
+                !eq(vt, v4i32) : DagCondVNot<(op v4i32:$vB, v4i32:$vC), notResult>.res,
+                !eq(vt, v2i64) : (v2i64 (bitconvert DagCondVNot<(op
+                                      (v4i32 (bitconvert v2i64:$vB)),
+                                      (v4i32 (bitconvert v2i64:$vC))), notResult>.res))
+                );
+}
+
+multiclass XXEvalVSelectWithXAnd<ValueType vt, bits<8> baseImm> {
+  // Multiclass for Ternary(A, X, and(B, C)) style patterns.
+  // Ternary(A, xor(B,C), and(B,C)) => imm: baseImm
+  def : xxevalPattern<vt, 
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor>.opPat, XXEvalBinaryPattern<vt, and>.opPat), 
+        baseImm>;
+  // Ternary(A, nor(B,C), and(B,C)) => imm: baseImm + 2
+  def : xxevalPattern<vt, 
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 2)>;
+  // Ternary(A, eqv(B,C), and(B,C)) => imm: baseImm + 3
+  def : xxevalPattern<vt, 
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor, 1>.opPat, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 3)>;
+  // Ternary(A, not(C), and(B,C)) => imm: baseImm + 4
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalUnaryNot<vt>.opC, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 4)>;
+  // Ternary(A, not(B), and(B,C)) => imm: baseImm + 6
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalUnaryNot<vt>.opB, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 6)>;
+}
+
+multiclass XXEvalVSelectWithXB<ValueType vt, bits<8> baseImm>{
+  // Multiclass for Ternary(A, X, B) style patterns
+  // Ternary(A, and(B,C), B) => imm: baseImm
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and>.opPat, vt:$vB), 
+        baseImm>;
+  // Ternary(A, nor(B,C), B) => imm: baseImm + 7
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, vt:$vB), 
+        !add(baseImm, 7)>;
+  // Ternary(A, eqv(B,C), B) => imm: baseImm + 8
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor, 1>.opPat, vt:$vB), 
+        !add(baseImm, 8)>;
+  // Ternary(A, not(C), B) => imm: baseImm + 9
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalUnaryNot<vt>.opC, vt:$vB), 
+        !add(baseImm, 9)>;
+  // Ternary(A, nand(B,C), B) => imm: baseImm + 13
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and, 1>.opPat, vt:$vB), 
+        !add(baseImm, 13)>;
+}
+
+multiclass XXEvalVSelectWithXC<ValueType vt, bits<8> baseImm>{
+  // Multiclass for Ternary(A, X, C) style patterns
+  // Ternary(A, and(B,C), C) => imm: baseImm
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and>.opPat, vt:$vC), 
+        baseImm>;
+  // Ternary(A, nor(B,C), C) => imm: baseImm + 7
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, vt:$vC), 
+        !add(baseImm, 7)>;
+  // Ternary(A, eqv(B,C), C) => imm: baseImm + 8
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor, 1>.opPat, vt:$vC), 
+        !add(baseImm, 8)>;
+  // Ternary(A, nand(B,C), C) => imm: baseImm + 13
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and, 1>.opPat, vt:$vC), 
+        !add(baseImm, 13)>;
+}
+
+multiclass XXEvalVSelectWithXXor<ValueType vt, bits<8> baseImm>{
+  // Multiclass for Ternary(A, X, xor(B,C)) style patterns
+  // Ternary(A, and(B,C), xor(B,C)) => imm: baseImm
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and>.opPat, XXEvalBinaryPattern<vt, xor>.opPat), 
+        baseImm>;
+  // Ternary(A, B, xor(B,C)) => imm: baseImm + 2
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, vt:$vB, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 2)>;
+  // Ternary(A, C, xor(B,C)) => imm: baseImm + 4
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, vt:$vC, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 4)>;
+  // Ternary(A, or(B,C), xor(B,C)) => imm: baseImm + 6
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or>.opPat, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 6)>;
+  // Ternary(A, nor(B,C), xor(B,C)) => imm: baseImm + 7
+  def : xxevalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 7)>; 
+}
 
 let Predicates = [PrefixInstrs, HasP10Vector] in {
   let AddedComplexity = 400 in {
@@ -2192,83 +2317,96 @@ let Predicates = [PrefixInstrs, HasP10Vector] in {
     // Anonymous patterns for XXEVAL
     // AND
     // and(A, B, C)
-    def : xxevalPattern<(and v4i32:$vA, (and v4i32:$vB, v4i32:$vC)), 1>;
+    def : xxevalPattern<v4i32, (and v4i32:$vA, (and v4i32:$vB, v4i32:$vC)), 1>;
     // and(A, xor(B, C))
-    def : xxevalPattern<(and v4i32:$vA, (xor v4i32:$vB, v4i32:$vC)), 6>;
+    def : xxevalPattern<v4i32, (and v4i32:$vA, (xor v4i32:$vB, v4i32:$vC)), 6>;
     // and(A, or(B, C))
-    def : xxevalPattern<(and v4i32:$vA, (or v4i32:$vB, v4i32:$vC)), 7>;
+    def : xxevalPattern<v4i32, (and v4i32:$vA, (or v4i32:$vB, v4i32:$vC)), 7>;
     // and(A, nor(B, C))
-    def : xxevalPattern<(and v4i32:$vA, (vnot (or v4i32:$vB, v4i32:$vC))), 8>;
+    def : xxevalPattern<v4i32, (and v4i32:$vA, (vnot (or v4i32:$vB, v4i32:$vC))), 8>;
     // and(A, eqv(B, C))
-    def : xxevalPattern<(and v4i32:$vA, (vnot (xor v4i32:$vB, v4i32:$vC))), 9>;
+    def : xxevalPattern<v4i32, (and v4i32:$vA, (vnot (xor v4i32:$vB, v4i32:$vC))), 9>;
     // and(A, nand(B, C))
-    def : xxevalPattern<(and v4i32:$vA, (vnot (and v4i32:$vB, v4i32:$vC))), 14>;
+    def : xxevalPattern<v4i32, (and v4i32:$vA, (vnot (and v4i32:$vB, v4i32:$vC))), 14>;
 
     // NAND
     // nand(A, B, C)
-    def : xxevalPattern<(vnot (and v4i32:$vA, (and v4i32:$vB, v4i32:$vC))),
+    def : xxevalPattern<v4i32, (vnot (and v4i32:$vA, (and v4i32:$vB, v4i32:$vC))),
                          !sub(255, 1)>;
     // nand(A, xor(B, C))
-    def : xxevalPattern<(vnot (and v4i32:$vA, (xor v4i32:$vB, v4i32:$vC))),
+    def : xxevalPattern<v4i32, (vnot (and v4i32:$vA, (xor v4i32:$vB, v4i32:$vC))),
                          !sub(255, 6)>;
     // nand(A, or(B, C))
-    def : xxevalPattern<(vnot (and v4i32:$vA, (or v4i32:$vB, v4i32:$vC))),
+    def : xxevalPattern<v4i32, (vnot (and v4i32:$vA, (or v4i32:$vB, v4i32:$vC))),
                          !sub(255, 7)>;
     // nand(A, nor(B, C))
-    def : xxevalPattern<(or (vnot v4i32:$vA), (or v4i32:$vB, v4i32:$vC)),
+    def : xxevalPattern<v4i32, (or (vnot v4i32:$vA), (or v4i32:$vB, v4i32:$vC)),
                          !sub(255, 8)>;
     // nand(A, eqv(B, C))
-    def : xxevalPattern<(or (vnot v4i32:$vA), (xor v4i32:$vB, v4i32:$vC)),
+    def : xxevalPattern<v4i32, (or (vnot v4i32:$vA), (xor v4i32:$vB, v4i32:$vC)),
                          !sub(255, 9)>;
     // nand(A, nand(B, C))
-    def : xxevalPattern<(or (vnot v4i32:$vA), (and v4i32:$vB, v4i32:$vC)),
+    def : xxevalPattern<v4i32, (or (vnot v4i32:$vA), (and v4i32:$vB, v4i32:$vC)),
                          !sub(255, 14)>;
 
     // EQV
     // (eqv A, B, C)
-    def : xxevalPattern<(or (and v4i32:$vA, (and v4i32:$vB, v4i32:$vC)),
+    def : xxevalPattern<v4i32, (or (and v4i32:$vA, (and v4i32:$vB, v4i32:$vC)),
                             (vnot (or v4i32:$vA, (or v4i32:$vB, v4i32:$vC)))),
                          150>;
     // (eqv A, (and B, C))
-    def : xxevalPattern<(vnot (xor v4i32:$vA, (and v4i32:$vB, v4i32:$vC))), 225>;
+    def : xxevalPattern<v4i32, (vnot (xor v4i32:$vA, (and v4i32:$vB, v4i32:$vC))), 225>;
     // (eqv A, (or B, C))
-    def : xxevalPattern<(vnot (xor v4i32:$vA, (or v4i32:$vB, v4i32:$vC))), 135>;
+    def : xxevalPattern<v4i32, (vnot (xor v4i32:$vA, (or v4i32:$vB, v4i32:$vC))), 135>;
 
     // NOR
     // (nor A, B, C)
-    def : xxevalPattern<(vnot (or v4i32:$vA, (or v4i32:$vB, v4i32:$vC))), 128>;
+    def : xxevalPattern<v4i32, (vnot (or v4i32:$vA, (or v4i32:$vB, v4i32:$vC))), 128>;
     // (nor A, (and B, C))
-    def : xxevalPattern<(vnot (or v4i32:$vA, (and v4i32:$vB, v4i32:$vC))), 224>;
+    def : xxevalPattern<v4i32, (vnot (or v4i32:$vA, (and v4i32:$vB, v4i32:$vC))), 224>;
     // (nor A, (eqv B, C))
-    def : xxevalPattern<(and (vnot v4i32:$vA), (xor v4i32:$vB, v4i32:$vC)), 96>;
+    def : xxevalPattern<v4i32, (and (vnot v4i32:$vA), (xor v4i32:$vB, v4i32:$vC)), 96>;
     // (nor A, (nand B, C))
-    def : xxevalPattern<(and (vnot v4i32:$vA), (and v4i32:$vB, v4i32:$vC)), 16>;
+    def : xxevalPattern<v4i32, (and (vnot v4i32:$vA), (and v4i32:$vB, v4i32:$vC)), 16>;
     // (nor A, (nor B, C))
-    def : xxevalPattern<(and (vnot v4i32:$vA), (or v4i32:$vB, v4i32:$vC)), 112>;
+    def : xxevalPattern<v4i32, (and (vnot v4i32:$vA), (or v4i32:$vB, v4i32:$vC)), 112>;
     // (nor A, (xor B, C))
-    def : xxevalPattern<(vnot (or v4i32:$vA, (xor v4i32:$vB, v4i32:$vC))), 144>;
+    def : xxevalPattern<v4i32, (vnot (or v4i32:$vA, (xor v4i32:$vB, v4i32:$vC))), 144>;
 
     // OR
     // (or A, B, C)
-    def : xxevalPattern<(or v4i32:$vA, (or v4i32:$vB, v4i32:$vC)), 127>;
+    def : xxevalPattern<v4i32, (or v4i32:$vA, (or v4i32:$vB, v4i32:$vC)), 127>;
     // (or A, (and B, C))
-    def : xxevalPattern<(or v4i32:$vA, (and v4i32:$vB, v4i32:$vC)), 31>;
+    def : xxevalPattern<v4i32, (or v4i32:$vA, (and v4i32:$vB, v4i32:$vC)), 31>;
     // (or A, (eqv B, C))
-    def : xxevalPattern<(or v4i32:$vA, (vnot (xor v4i32:$vB, v4i32:$vC))), 159>;
+    def : xxevalPattern<v4i32, (or v4i32:$vA, (vnot (xor v4i32:$vB, v4i32:$vC))), 159>;
     // (or A, (nand B, C))
-    def : xxevalPattern<(or v4i32:$vA, (vnot (and v4i32:$vB, v4i32:$vC))), 239>;
+    def : xxevalPattern<v4i32, (or v4i32:$vA, (vnot (and v4i32:$vB, v4i32:$vC))), 239>;
     // (or A, (nor B, C))
-    def : xxevalPattern<(or v4i32:$vA, (vnot (or v4i32:$vB, v4i32:$vC))), 143>;
+    def : xxevalPattern<v4i32, (or v4i32:$vA, (vnot (or v4i32:$vB, v4i32:$vC))), 143>;
     // (or A, (xor B, C))
-    def : xxevalPattern<(or v4i32:$vA, (xor v4i32:$vB, v4i32:$vC)), 111>;
+    def : xxevalPattern<v4i32, (or v4i32:$vA, (xor v4i32:$vB, v4i32:$vC)), 111>;
 
     // XOR
     // (xor A, B, C)
-    def : xxevalPattern<(xor v4i32:$vA, (xor v4i32:$vB, v4i32:$vC)), 105>;
+    def : xxevalPattern<v4i32, (xor v4i32:$vA, (xor v4i32:$vB, v4i32:$vC)), 105>;
     // (xor A, (and B, C))
-    def : xxevalPattern<(xor v4i32:$vA, (and v4i32:$vB, v4i32:$vC)), 30>;
+    def : xxevalPattern<v4i32, (xor v4i32:$vA, (and v4i32:$vB, v4i32:$vC)), 30>;
     // (xor A, (or B, C))
-    def : xxevalPattern<(xor v4i32:$vA, (or v4i32:$vB, v4i32:$vC)), 120>;
+    def : xxevalPattern<v4i32, (xor v4i32:$vA, (or v4i32:$vB, v4i32:$vC)), 120>;
+
+    // Ternary operation support with the xxeval instruction.
+    defm : XXEvalVSelectWithXAnd<v4i32, 22>;
+    defm : XXEvalVSelectWithXAnd<v2i64, 22>;
+
+    defm : XXEvalVSelectWithXB<v4i32, 49>;
+    defm : XXEvalVSelectWithXB<v2i64, 49>;
+
+    defm : XXEvalVSelectWithXC<v4i32, 81>;
+    defm : XXEvalVSelectWithXC<v2i64, 81>;
+
+    defm : XXEvalVSelectWithXXor<v4i32, 97>;
+    defm : XXEvalVSelectWithXXor<v2i64, 97>;
 
     // Anonymous patterns to select prefixed VSX loads and stores.
     // Load / Store f128
diff --git a/llvm/test/CodeGen/PowerPC/xxeval-vselect-x-and.ll b/llvm/test/CodeGen/PowerPC/xxeval-vselect-x-and.ll
new file mode 100644
index 0000000000000..b30617469c901
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/xxeval-vselect-x-and.ll
@@ -0,0 +1,134 @@
+; Test file to verify the emission of xxeval instructions when ternary operators are used.
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr10 -mtriple=powerpc64le-unknown-unknown \
+; RUN:   -ppc-asm-full-reg-names --ppc-vsr-nums-as-vr < %s | FileCheck %s
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr10 -mtriple=powerpc-ibm-aix-xcoff \
+; RUN:   -ppc-asm-full-reg-names --ppc-vsr-nums-as-vr < %s | FileCheck %s
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr10 -mtriple=powerpc64-ibm-aix-xcoff \
+; RUN:   -ppc-asm-full-reg-names --ppc-vsr-nums-as-vr < %s | FileCheck %s
+
+; Function to test ternary(A, xor(B, C), and(B, C)) for <4 x i32>
+; CHECK-LABEL: ternary_A_xor_BC_and_BC_4x32
+; CHECK: xxeval v2, v2, v3, v4, 22
+; CHECK-NEXT: blr
+define dso_local <4 x i32> @ternary_A_xor_BC_and_BC_4x32(<4 x i1> %A, <4 x i32> %B, <4 x i32> %C) local_unnamed_addr #0 {
+entry:
+  %xor = xor <4 x i32> %B, %C
+  %and = and <4 x i32> %B, %C
+  %res = select <4 x i1> %A, <4 x i32> %xor, <4 x i32> %and
+  ret <4 x i32> %res
+}
+
+; Function to test ternary(A, xor(B, C), and(B, C)) for <2 x i64>
+; CHECK-LABEL: ternary_A_xor_BC_and_BC_2x64
+; CHECK: xxeval v2, v2, v3, v4, 22
+; CHECK-NEXT: blr
+define dso_local <2 x i64> @ternary_A_xor_BC_and_BC_2x64(<2 x i1> %A, <2 x i64> %B, <2 x i64> %C) local_unnamed_addr #0 {
+entry:
+  %xor = xor <2 x i64> %B, %C
+  %and = and <2 x i64> %B, %C
+  %res = select <2 x i1> %A, <2 x i64> %xor, <2 x i64> %and
+  ret <2 x i64> %res
+}
+
+; Function to test ternary(A, nor(B, C), and(B, C)) for <4 x i32>
+; CHECK-LABEL: ternary_A_nor_BC_and_BC_4x32
+; CHECK: xxeval v2, v2, v3, v4, 24
+; CHECK-NEXT: blr
+define dso_local <4 x i32> @ternary_A_nor_BC_and_BC_4x32(<4 x i1> %A, <4 x i32> %B, <4 x i32> %C) local_unnamed_addr #0 {
+entry:
+  %or = or <4 x i32> %B, %C
+  %nor = xor <4 x i32> %or, <i32 -1, i32 -1, i32 -1, i32 -1>  ; Vector NOR operation
+  %and = and <4 x i32> %B, %C
+  %res = select <4 x i1> %A, <4 x i32> %nor, <4 x i32> %and
+  ret <4 x i32> %res
+}
+
+; Function to test ternary(A, nor(B, C), and(B, C)) for <2 x i64>
+; CHECK-LABEL: ternary_A_nor_BC_and_BC_2x64
+; CHECK: xxeval v2, v2, v3, v4, 24
+; CHECK-NEXT: blr
+define dso_local <2 x i64> @ternary_A_nor_BC_and_BC_2x64(<2 x i1> %A, <2 x i64> %B, <2 x i64> %C) local_unnamed_addr #0 {
+entry:
+  %or = or <2 x i64> %B, %C
+  %nor = xor <2 x i64> %or, <i64 -1, i64 -1>  ; Vector NOR operation
+  %and = and <2 x i64> %B, %C
+  %res = select <2 x i1> %A, <2 x i64> %nor, <2 x i64> %and
+  ret <2 x i64> %res
+}
+
+; Function to test ternary(A, eqv(B, C), and(B, C)) for <4 x i32>
+; CHECK-LABEL: ternary_A_eqv_BC_and_BC_4x32
+; CHECK: xxeval v2, v2, v3, v4, 25
+; CHECK-NEXT: blr
+define dso_local <4 x i32> @ternary_A_eqv_BC_and_BC_4x32(<4 x i1> %A, <4 x i32> %B, <4 x i32> %C) local_unnamed_addr #0 {
+entry:
+  %xor = xor <4 x i32> %B, %C
+  %eqv = xor <4 x i32> %xor, <i32 -1, i32 -1, i32 -1, i32 -1>  ; Vector eqv operation
+  %and = and <4 x i32> %B, %C
+  %res = select <4 x i1> %A, <4 x i32> %eqv, <4 x i32> %and
+  ret <4 x i32> %res
+}
+
+; Function to test ternary(A, eqv(B, C), and(B, C)) for <2 x i64>
+; CHECK-LABEL: ternary_A_eqv_BC_and_BC_2x64
+; CHECK: xxeval v2, v2, v3, v4, 25
+; CHECK-NEXT: blr
+define dso_local <2 x i64> @ternary_A_eqv_BC_and_BC_2x64(<2 x i1> %A, <2 x i64> %B, <2 x i64> %C) local_unnamed_addr #0 {
+entry:
+  %xor = xor <2 x i64> %B, %C
+  %eqv = xor <2 x i64> %xor, <i64 -1, i64 -1>  ; Vector eqv operation
+  %and = and <2 x i64> %B, %C
+  %res = select <2 x i1> %A, <2 x i64> %eqv, <2 x i64> %and
+  ret <2 x i64> %res
+}
+
+; Function to test ternary(A, not(C), and(B, C)) for <4 x i32>
+; CHECK-LABEL: ternary_A_not_C_and_BC_4x32
+; CHECK: xxeval v2, v2, v3, v4, 26
+; CHECK-NEXT: blr
+define dso_local <4 x i32> @ternary_A_not_C_and_BC_4x32(<4 x i1> %A, <4 x i32> %B, <4 x i32> %C) local_unnamed_addr #0 {
+entry:
+  %not = xor <4 x i32> %C, <i32 -1, i32 -1, i32 -1, i32 -1>  ; Vector not operation
+  %and = and <4 x i32> %B, %C
+  %res = select <4 x i1> %A, <4 x i32> %not, <4 x i32> %and
+  ret <4 x i32> %res
+}
+
+; Function to test ternary(A, not(C), and(B, C)) for <2 x i64>
+; CHECK-LABEL: ternary_A_not_C_and_BC_2x64
+; CHECK: xxeval v2, v2, v3, v4, 26
+; CHECK-NEXT: blr
+define dso_local <2 x i64> @ternary_A_not_C_and_BC_2x64(<2 x i1> %A, <2 x i64> %B, <2 x i64> %C) local_unnamed_addr #0 {
+entry:
+  %not = xor <2 x i64> %C, <i64 -1, i64 -1>  ; Vector not operation
+  %and = and <2 x i64> %B, %C
+  %res = select <2 x i1> %A, <2 x i64> %not, <2 x i64> %and
+  ret <2 x i64> %res
+}
+
+; Function to test ternary(A, not(B), and(B, C)) for <4 x i32>
+; CHECK-LABEL: ternary_A_not_B_and_BC_4x32
+; CHECK: xxeval v2, v2, v3, v4, 28
+; CHECK-NEXT: blr
+define dso_local <4 x i32> @ternary_A_not_B_and_BC_4x32(<4 x i1> %A, <4 x i32> %B, <4 x i32> %C) local_unnamed_addr #0 {
+entry:
+  %not = xor <4 x i32> %B, <i32 -1, i32 -1, i32 -1, i32 -1>  ; Vector not operation
+  %and = and <4 x i32> %B, %C
+  %res = select <4 x i1> %A, <4 x i32> %not, <4 x i32> %and
+  ret <4 x i32> %res
+}
+
+; Function to test ternary(A, not(B), and(B, C)) for <2 x i64>
+; CHECK-LABEL: ternary_A_not_B_and_BC_2x64
+; CHECK: xxeval v2, v2, v3, v4, 28
+; CHECK-NEXT: blr
+define dso_local <2 x i64> @ternary_A_not_B_and_BC_2x64(<2 x i1> %A, <2 x i64> %B, <2 x i64> %C) local_unnamed_addr #0 {
+entry:
+  %not = xor <2 x i64> %B, <i64 -1, i64 -1>  ; Vector not operation
+  %and = and <2 x i64> %B, %C
+  %res = select <2 x i1> %A, <2 x i64> %not, <2 x i64> %and
+  ret <2 x i64> %res
+}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/PowerPC/xxeval-vselect-x-b.ll b/llvm/test/CodeGen/PowerPC/xxeval-vselect-x-b.ll
new file mode 100644
index 0000000000000..7ab5fa7d62688
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/xxeval-vselect-x-b.ll
@@ -0,0 +1,126 @@
+; Test file to verify the emission of xxeval instructions when ternary operators are used.
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr10 -mtriple=powerpc64le-unknown-unknown \
+; RUN:   -ppc-asm-full-reg-names --ppc-vsr-nums-as-vr < %s | FileCheck %s
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr10 -mtriple=powerpc-ibm-aix-xcoff \
+; RUN:   -ppc-asm-full-reg-names --ppc-vsr-nums-as-vr < %s | FileCheck %s
+
+; RUN: llc -verify-machineinstrs -mcpu=pwr10 -mtriple=powerpc64-ibm-aix-xcoff \
+; RUN:   -ppc-asm-full-reg-names --ppc-vsr-nums-as-vr < %s | FileCheck %s
+
+; Function to test ternary(A, and(B, C), B) for <4 x i32>
+; CHECK-LABEL: ternary_A_and_BC_B_4x32
+; CHECK: xxeval v2, v2, v3, v4, 49
+; CHECK-NEXT: blr
+define dso_local <4 x i32> @ternary_A_and_BC_B_4x32(<4 x i1> %A, <4 x i32> %B, <4 x i32> %C) local_unnamed_addr #0 {
+entry:
+  %and = and <4 x i32> %B, %C
+  %res = select <4 x i1> %A, <4 x i32> %and, <4 x i32> %B
+  ret <4 x i32> %res
+}
+
+; Function to test ternary(A, and(B, C), B) for <2 x i64>
+; CHECK-LABEL: ternary_A_and_BC_B_2x64
+; CHECK: xxeval v2, v2, v3, v4, 49
+; CHECK-NEXT: blr
+define dso_local <2 x i64> @ternary_A_and_BC_B_2x64(<2 x i1> %A, <2 x i64> %B, <2 x i64> %C) local_unnamed_addr #0 {
+entry:
+  %and = and <2 x i64> %B, %C
+  %res = select <2 x i1> %A, <2 x i64> %and, <2 x i64> %B
+  ret <2 x i64> %res
+}
+
+; Function to test ternary(A, nor(B, C), B) for <4 x i32>
+; CHECK-LABEL: ternary_A_...
[truncated]

@tonykuttai
Copy link
Contributor Author

@tonykuttai tonykuttai changed the title [P10][XXEVAL] Exploit xxeval instruction for cases of the ternary(A,X, and(B,C)), ternary(A,X,B), ternary(A,X,C), ternary(A,X,xor(B,C)) forms. [PowerPC10][XXEVAL] Exploit xxeval instruction for cases of the ternary(A,X, and(B,C)), ternary(A,X,B), ternary(A,X,C), ternary(A,X,xor(B,C)) forms. May 28, 2025
@tonykuttai tonykuttai force-pushed the tvarghese/xxeval branch 5 times, most recently from fcebb02 to 604d89b Compare June 3, 2025 16:23
@tonykuttai tonykuttai requested a review from lei137 June 3, 2025 16:25
@tonykuttai
Copy link
Contributor Author

tonykuttai commented Jun 3, 2025

Copy link
Contributor

@lei137 lei137 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure about all the class def that just contain a dag def.
Maybe we can have 1 XXEvalUnaryOp class with the different dag defined with descriptive names and have all the xxevalpattern classes derive from that and use the appropriate dag from there as needed?

@tonykuttai tonykuttai requested a review from lei137 June 11, 2025 08:56
@tonykuttai tonykuttai changed the title [PowerPC10][XXEVAL] Exploit xxeval instruction for cases of the ternary(A,X, and(B,C)), ternary(A,X,B), ternary(A,X,C), ternary(A,X,xor(B,C)) forms. [PowerPC][XXEVAL] Exploit xxeval instruction for cases of the ternary(A,X, and(B,C)), ternary(A,X,B), ternary(A,X,C), ternary(A,X,xor(B,C)) forms. Jun 11, 2025
@tonykuttai
Copy link
Contributor Author

Unsure about all the class def that just contain a dag def. Maybe we can have 1 XXEvalUnaryOp class with the different dag defined with descriptive names and have all the xxevalpattern classes derive from that and use the appropriate dag from there as needed?

Two classes defined for getting the Unary and the BinaryPattern.

  • XXEvalUnaryPattern
  • XXEvalBinaryPattern

For getting a simple dag of vt:$vB or vt:$vC, it would be simpler to do it without the use of a wrapper class. and hence I have excluded them from the XXEvalUnaryPattern.

@tonykuttai tonykuttai changed the title [PowerPC][XXEVAL] Exploit xxeval instruction for cases of the ternary(A,X, and(B,C)), ternary(A,X,B), ternary(A,X,C), ternary(A,X,xor(B,C)) forms. [PowerPC] Exploit xxeval instruction for ternary patterns - part 1 Jun 12, 2025
@tonykuttai tonykuttai force-pushed the tvarghese/xxeval branch 2 times, most recently from 9921b8c to 3ebc442 Compare June 12, 2025 05:29
@tonykuttai
Copy link
Contributor Author

Rebased the PR to the latest main branch. (NFC pre-commit patches already merged).

@tonykuttai tonykuttai changed the title [PowerPC] Exploit xxeval instruction for ternary patterns - part 1 [PowerPC] Exploit xxeval instruction for ternary patterns - ternary(A, X, and(B,C)) Jul 24, 2025
@tonykuttai
Copy link
Contributor Author

No need for clang test as we are not adding any clang code. Please update your description to be more concise. Remember your PR description will be part of git log and we are only looking for summary of the patch. Details of implementation should either be in the associated issue or if there is none as comments to this PR instread. Thx!

Noted. Updated the description. Thanx.

@lei137
Copy link
Contributor

lei137 commented Jul 24, 2025

I took the liberty of adding a few more tweaks to your description. Hope that is okay.

@tonykuttai tonykuttai force-pushed the tvarghese/xxeval branch 5 times, most recently from 8055f9b to 53a9874 Compare July 25, 2025 17:17
Copy link
Contributor

@lei137 lei137 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM
Thank-you for refactoring!

@tonykuttai tonykuttai merged commit 59c3fe6 into llvm:main Jul 29, 2025
9 checks passed
tonykuttai added a commit that referenced this pull request Aug 6, 2025
…EvalPattern class (#151462)

This change rebases the anonymous `xxeval` patterns to use the new
XXEvalPattern class based on the [[PowerPC] Exploit xxeval instruction
for ternary patterns - ternary(A, X,
and(B,C))](#141733 (comment))

Co-authored-by: Tony Varghese <[email protected]>
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Aug 6, 2025
… the new XXEvalPattern class (#151462)

This change rebases the anonymous `xxeval` patterns to use the new
XXEvalPattern class based on the [[PowerPC] Exploit xxeval instruction
for ternary patterns - ternary(A, X,
and(B,C))](llvm/llvm-project#141733 (comment))

Co-authored-by: Tony Varghese <[email protected]>
tonykuttai added a commit that referenced this pull request Sep 1, 2025
…ry(A,X,B) and ternary(A,X,C). (#152956)

Adds support for ternary equivalent operations of the form `ternary(A,
X, B)` and `ternary(A, X, C)` where `X=[and(B,C)| nor(B,C)| eqv(B,C)|
nand(B,C)]`.

The following are the patterns involved and the imm values:

| **Operation**              | **Immediate Value** |
|----------------------------|---------------------|
| ternary(A,  and(B,C),   B) | 49                  |
| ternary(A,  nor(B,C),   B) | 56                  |
| ternary(A,  eqv(B,C),   B) | 57                  |
| ternary(A,  nand(B,C),  B) | 62                  |
|                            |                     |
| ternary(A,  and(B,C),   C) | 81                  |
| ternary(A,  nor(B,C),   C) | 88                  |
| ternary(A,  eqv(B,C),   C) | 89                  |
| ternary(A,  nand(B,C),  C) | 94                  |

eg.  `xxeval XT, XA, XB, XC, 49` 
- performs `XA ? and(XB, XC) : B`and places the result in `XT`.

This is the continuation of [[PowerPC] Exploit xxeval instruction for
ternary patterns - ternary(A, X,
and(B,C))](#141733 (comment)).

---------

Co-authored-by: Tony Varghese <[email protected]>
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Sep 1, 2025
… form ternary(A,X,B) and ternary(A,X,C). (#152956)

Adds support for ternary equivalent operations of the form `ternary(A,
X, B)` and `ternary(A, X, C)` where `X=[and(B,C)| nor(B,C)| eqv(B,C)|
nand(B,C)]`.

The following are the patterns involved and the imm values:

| **Operation**              | **Immediate Value** |
|----------------------------|---------------------|
| ternary(A,  and(B,C),   B) | 49                  |
| ternary(A,  nor(B,C),   B) | 56                  |
| ternary(A,  eqv(B,C),   B) | 57                  |
| ternary(A,  nand(B,C),  B) | 62                  |
|                            |                     |
| ternary(A,  and(B,C),   C) | 81                  |
| ternary(A,  nor(B,C),   C) | 88                  |
| ternary(A,  eqv(B,C),   C) | 89                  |
| ternary(A,  nand(B,C),  C) | 94                  |

eg.  `xxeval XT, XA, XB, XC, 49`
- performs `XA ? and(XB, XC) : B`and places the result in `XT`.

This is the continuation of [[PowerPC] Exploit xxeval instruction for
ternary patterns - ternary(A, X,
and(B,C))](llvm/llvm-project#141733 (comment)).

---------

Co-authored-by: Tony Varghese <[email protected]>
tonykuttai added a commit that referenced this pull request Sep 22, 2025
…ry(A,X, XOR(B,C)) and ternary(A,X, OR(B,C)) (#157909)

Adds support for ternary equivalent operations of the form 
- `ternary(A, X, xor(B,C))` where `X=[and(B,C)| nor(B,C)| or(B,C)| B |
C]`.
- `ternary(A, X, or(B,C))` where `X = [and(B,C)| eqv(B,C)| not(B)|
not(C)| nand(B,C)| B | C]`.

The following are the patterns involved and the imm values:

```
ternary(A,  and(B,C),   xor(B,C))	97
ternary(A,  B,          xor(B,C))	99
ternary(A,  C,          xor(B,C))	101
ternary(A,  or(B,C),    xor(B,C))	103
ternary(A,  nor(B,C),   xor(B,C))	104

ternary(A,  and(B,C),   or(B,C))	113
ternary(A,  B,          or(B,C))	115
ternary(A,  C,          or(B,C))	117
ternary(A,  eqv(B,C),   or(B,C))	121
ternary(A,  not(C),     or(B,C))	122
ternary(A,  not(B),     or(B,C))	124
ternary(A,  nand(B,C),  or(B,C))	126
```
eg. `xxeval XT, XA, XB, XC, 97`

performs the ternary operation: `XA ? and(XB, XC) : xor(XB, XC)` and
places the result in `XT`.

This is the continuation of:
- [[PowerPC] Exploit xxeval instruction for ternary patterns -
ternary(A, X,
and(B,C))](#141733 (comment))
- [[PowerPC] Exploit xxeval instruction for operations of the form
ternary(A,X,B) and
ternary(A,X,C).](#152956 (comment))

---------

Co-authored-by: Tony Varghese <[email protected]>
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Sep 22, 2025
… form ternary(A,X, XOR(B,C)) and ternary(A,X, OR(B,C)) (#157909)

Adds support for ternary equivalent operations of the form
- `ternary(A, X, xor(B,C))` where `X=[and(B,C)| nor(B,C)| or(B,C)| B |
C]`.
- `ternary(A, X, or(B,C))` where `X = [and(B,C)| eqv(B,C)| not(B)|
not(C)| nand(B,C)| B | C]`.

The following are the patterns involved and the imm values:

```
ternary(A,  and(B,C),   xor(B,C))	97
ternary(A,  B,          xor(B,C))	99
ternary(A,  C,          xor(B,C))	101
ternary(A,  or(B,C),    xor(B,C))	103
ternary(A,  nor(B,C),   xor(B,C))	104

ternary(A,  and(B,C),   or(B,C))	113
ternary(A,  B,          or(B,C))	115
ternary(A,  C,          or(B,C))	117
ternary(A,  eqv(B,C),   or(B,C))	121
ternary(A,  not(C),     or(B,C))	122
ternary(A,  not(B),     or(B,C))	124
ternary(A,  nand(B,C),  or(B,C))	126
```
eg. `xxeval XT, XA, XB, XC, 97`

performs the ternary operation: `XA ? and(XB, XC) : xor(XB, XC)` and
places the result in `XT`.

This is the continuation of:
- [[PowerPC] Exploit xxeval instruction for ternary patterns -
ternary(A, X,
and(B,C))](llvm/llvm-project#141733 (comment))
- [[PowerPC] Exploit xxeval instruction for operations of the form
ternary(A,X,B) and
ternary(A,X,C).](llvm/llvm-project#152956 (comment))

---------

Co-authored-by: Tony Varghese <[email protected]>
tonykuttai added a commit that referenced this pull request Oct 15, 2025
…ry(A, X, nor(B,C)), ternary(A, X, eqv(B,C)), ternary(A, X, nand(B,C)), ternary(A, X, not(B)) and ternary(A, X, not(C)) (#158096)

Adds support for ternary equivalent operations of the form `ternary(A,
X, nor(B,C))`, `ternary(A, X, eqv(B,C))`, `ternary(A, X, nand(B,C))`,
`ternary(A, X, not(B))` and `ternary(A, X, not(C))` where `X=[xor(B,C)|
nor(B,C)| eqv(B,C)| not(B)| not(C)| and(B,C)| nand(B,C)]`.

This adds support for `v4i32, v2i64, v16i8, v8i16` operand types for the
following patterns.
List of xxeval equivalent ternary operations added and the corresponding
imm value required:
```
ternary(A,  and(B,C),   nor(B,C))	129
ternary(A,  B,          nor(B,C))	131
ternary(A,  C,          nor(B,C))	133
ternary(A,  xor(B,C),   nor(B,C))	134
ternary(A,  not(C),     nor(B,C))	138
ternary(A,  not(B),     nor(B,C))	140
ternary(A,  nand(B,C),  nor(B,C))	142

ternary(A,  or(B,C),    eqv(B,C))	151
ternary(A,  nor(B,C),   eqv(B,C))	152
ternary(A,  not(C),     eqv(B,C))	154
ternary(A,  nand(B,C),  eqv(B,C))	158

ternary(A,  and(B,C),   not(C))	    161
ternary(A,  B,          not(C))	    163
ternary(A,  xor(B,C),   not(C))	    166
ternary(A,  or(B,C),    not(C))	    167
ternary(A,  not(B),     not(C))	    172
ternary(A,  nand(B,C),  not(C))	    174

ternary(A,  and(B,C),   not(B))	    193
ternary(A,  xor(B,C),   not(B))	    198
ternary(A,  or(B,C),    not(B))	    199
ternary(A,  nand(B,C),  not(B))	    206

ternary(A,  B,          nand(B,C))	227
ternary(A,  C,          nand(B,C))	229
ternary(A,  xor(B,C),   nand(B,C))	230
ternary(A,  or(B,C),    nand(B,C))	231
ternary(A,  eqv(B,C),   nand(B,C))	233
```

eg. `xxeval XT, XA, XB, XC, 129`

performs the ternary operation: `XA ? and(XB, XC) : nor(XB, XC)` and
places the result in `XT`.

This is the continuation of:
- [[PowerPC] Exploit xxeval instruction for ternary patterns -
ternary(A, X,
and(B,C))](#141733 (comment))
- [[PowerPC] Exploit xxeval instruction for operations of the form
ternary(A,X,B) and
ternary(A,X,C).](#152956 (comment))
- [[PowerPC] Exploit xxeval instruction for operations of the form
ternary(A,X, XOR(B,C)) and ternary(A,X,
OR(B,C))](#157909 (comment))

Co-authored-by: Tony Varghese <[email protected]>
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Oct 15, 2025
… form ternary(A, X, nor(B,C)), ternary(A, X, eqv(B,C)), ternary(A, X, nand(B,C)), ternary(A, X, not(B)) and ternary(A, X, not(C)) (#158096)

Adds support for ternary equivalent operations of the form `ternary(A,
X, nor(B,C))`, `ternary(A, X, eqv(B,C))`, `ternary(A, X, nand(B,C))`,
`ternary(A, X, not(B))` and `ternary(A, X, not(C))` where `X=[xor(B,C)|
nor(B,C)| eqv(B,C)| not(B)| not(C)| and(B,C)| nand(B,C)]`.

This adds support for `v4i32, v2i64, v16i8, v8i16` operand types for the
following patterns.
List of xxeval equivalent ternary operations added and the corresponding
imm value required:
```
ternary(A,  and(B,C),   nor(B,C))	129
ternary(A,  B,          nor(B,C))	131
ternary(A,  C,          nor(B,C))	133
ternary(A,  xor(B,C),   nor(B,C))	134
ternary(A,  not(C),     nor(B,C))	138
ternary(A,  not(B),     nor(B,C))	140
ternary(A,  nand(B,C),  nor(B,C))	142

ternary(A,  or(B,C),    eqv(B,C))	151
ternary(A,  nor(B,C),   eqv(B,C))	152
ternary(A,  not(C),     eqv(B,C))	154
ternary(A,  nand(B,C),  eqv(B,C))	158

ternary(A,  and(B,C),   not(C))	    161
ternary(A,  B,          not(C))	    163
ternary(A,  xor(B,C),   not(C))	    166
ternary(A,  or(B,C),    not(C))	    167
ternary(A,  not(B),     not(C))	    172
ternary(A,  nand(B,C),  not(C))	    174

ternary(A,  and(B,C),   not(B))	    193
ternary(A,  xor(B,C),   not(B))	    198
ternary(A,  or(B,C),    not(B))	    199
ternary(A,  nand(B,C),  not(B))	    206

ternary(A,  B,          nand(B,C))	227
ternary(A,  C,          nand(B,C))	229
ternary(A,  xor(B,C),   nand(B,C))	230
ternary(A,  or(B,C),    nand(B,C))	231
ternary(A,  eqv(B,C),   nand(B,C))	233
```

eg. `xxeval XT, XA, XB, XC, 129`

performs the ternary operation: `XA ? and(XB, XC) : nor(XB, XC)` and
places the result in `XT`.

This is the continuation of:
- [[PowerPC] Exploit xxeval instruction for ternary patterns -
ternary(A, X,
and(B,C))](llvm/llvm-project#141733 (comment))
- [[PowerPC] Exploit xxeval instruction for operations of the form
ternary(A,X,B) and
ternary(A,X,C).](llvm/llvm-project#152956 (comment))
- [[PowerPC] Exploit xxeval instruction for operations of the form
ternary(A,X, XOR(B,C)) and ternary(A,X,
OR(B,C))](llvm/llvm-project#157909 (comment))

Co-authored-by: Tony Varghese <[email protected]>
@tonykuttai tonykuttai deleted the tvarghese/xxeval branch November 14, 2025 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants