[llvm] [PowerPC] Exploit xxeval instruction for ternary patterns - part 1 (PR #141733)

Amy Kwan via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 16 07:49:21 PDT 2025


================
@@ -2159,8 +2159,243 @@ 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)> {}
+  // Defines a pattern for the XXEVAL instruction with a specific value type, 
+  // pattern, and immediate.
+class XXEvalPattern <ValueType vt, dag pattern, bits<8> imm> :
+  Pat<(vt pattern), (XXEVAL $vA, $vB, $vC, imm)> {}
+
+  // Helper class to generate unary NOT patterns for vector types.
+  // For v4i32, emits (vnot B) or (vnot C).
+  // For other types, bitcasts operand to v4i32, applies vnot, then bitcasts back.
+class XXEvalUnaryNotPattern<ValueType vt> {
+  dag vnotB = !if( !eq(vt, v4i32), 
+                   (vnot vt:$vB),
+                   (vt (bitconvert (vnot (v4i32 (bitconvert vt:$vB)))))
+                  );
+  dag vnotC = !if( !eq(vt, v4i32), 
+                   (vnot vt:$vC),
+                   (vt (bitconvert (vnot (v4i32 (bitconvert vt:$vC)))))
+                  );
+}
+
+  // Wrapper class for binary patterns with optional NOT on the result.
+  // If 'not' is 0, emits the binary op; if 1, emits vnot of the binary op.
+class XXEvalBinaryPattern<ValueType vt, SDPatternOperator op, bit not = 0> {
+  dag opPat = !if(!eq(not, 0),
+                    // DAG for the binary operation.
+                    !if(!eq(vt, v4i32),
+                        (op vt:$vB, vt:$vC),
+                        (vt (bitconvert (op (v4i32 (bitconvert vt:$vB)), (v4i32 (bitconvert vt:$vC)))))),
+                    // DAG for the binary operation with a NOT applied to the result.  
+                    !if(!eq(vt, v4i32),
+                        (vnot (op vt:$vB, vt:$vC)),
+                        (vt (bitconvert (vnot (op (v4i32 (bitconvert vt:$vB)), (v4i32 (bitconvert vt:$vC))))))));
+}
+
+multiclass XXEvalVSelectWithXAnd<ValueType vt, bits<8> baseImm> {
+  // Multiclass for ternary patterns of the form vselect(A, X, and(B, C)).
+  // vselect(A, xor(B,C), and(B,C)) => imm = baseImm = 22
+  def : XXEvalPattern<vt, 
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor>.opPat, XXEvalBinaryPattern<vt, and>.opPat), 
+        baseImm>;
+  // vselect(A, nor(B,C), and(B,C)) => imm = baseImm + 2 = 24
+  def : XXEvalPattern<vt, 
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 2)>;
+  // vselect(A, eqv(B,C), and(B,C)) => imm = baseImm + 3 = 25
+  def : XXEvalPattern<vt, 
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor, 1>.opPat, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 3)>;
+  // vselect(A, not(C), and(B,C)) => imm = baseImm + 4 = 26
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, XXEvalUnaryNotPattern<vt>.vnotC, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 4)>;
+  // vselect(A, not(B), and(B,C)) => imm = baseImm + 6 = 28
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, XXEvalUnaryNotPattern<vt>.vnotB, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 6)>;
+}
+
+multiclass XXEvalVSelectWithXB<ValueType vt, bits<8> baseImm>{
+  // Multiclass for ternary patterns of the form vselect(A, X, B).
+  // vselect(A, and(B,C), B) => imm = baseImm = 49
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and>.opPat, vt:$vB), 
+        baseImm>;
+  // vselect(A, nor(B,C), B) => imm = baseImm + 7 = 56
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, vt:$vB), 
+        !add(baseImm, 7)>;
+  // vselect(A, eqv(B,C), B) => imm = baseImm + 8 = 57
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor, 1>.opPat, vt:$vB), 
+        !add(baseImm, 8)>;
+  // vselect(A, nand(B,C), B) => imm = baseImm + 13 = 62
+  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 patterns of the form vselect(A, X, C).
+  // vselect(A, and(B,C), C) => imm = baseImm = 81
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and>.opPat, vt:$vC), 
+        baseImm>;
+  // vselect(A, nor(B,C), C) => imm = baseImm + 7 = 88
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, vt:$vC), 
+        !add(baseImm, 7)>;
+  // vselect(A, eqv(B,C), C) => imm = baseImm + 8 = 89
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor, 1>.opPat, vt:$vC), 
+        !add(baseImm, 8)>;
+  // vselect(A, nand(B,C), C) => imm = baseImm + 13 = 94
+  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 patterns of the form vselect(A, X, xor(B,C)).
+  // vselect(A, and(B,C), xor(B,C)) => imm = baseImm = 97
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and>.opPat, XXEvalBinaryPattern<vt, xor>.opPat), 
+        baseImm>;
+  // vselect(A, B, xor(B,C)) => imm = baseImm + 2 = 99
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, vt:$vB, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 2)>;
+  // vselect(A, C, xor(B,C)) => imm = baseImm + 4 = 101
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, vt:$vC, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 4)>;
+  // vselect(A, or(B,C), xor(B,C)) => imm = baseImm + 6 = 103
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or>.opPat, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 6)>;
+  // vselect(A, nor(B,C), xor(B,C)) => imm = baseImm + 7 = 104
+  def : XXEvalPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 7)>; 
+}
+
+  // Pattern class using COPY_TO_REGCLASS for type casting
+class XXEvalBitcastPattern<ValueType vt, dag pattern, bits<8> imm> : 
+  Pat<(vt pattern), 
+      (COPY_TO_REGCLASS 
+        (XXEVAL 
+          (COPY_TO_REGCLASS vt:$vA, VSRC), 
+          (COPY_TO_REGCLASS vt:$vB, VSRC), 
+          (COPY_TO_REGCLASS vt:$vC, VSRC), 
+          imm), 
+        VRRC)>;
+
+multiclass XXEvalVSelectWithXAndCast<ValueType vt, bits<8> baseImm> {
+  // Multiclass for ternary patterns using COPY_TO_REGCLASS for unsupported types
+  // vselect(A, xor(B,C), and(B,C)) => imm = baseImm = 22
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor>.opPat, XXEvalBinaryPattern<vt, and>.opPat), 
+        baseImm>;
+  // vselect(A, nor(B,C), and(B,C)) => imm = baseImm + 2 = 24
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 2)>;
+  // vselect(A, eqv(B,C), and(B,C)) => imm = baseImm + 3 = 25
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor, 1>.opPat, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 3)>;
+  // vselect(A, not(C), and(B,C)) => imm = baseImm + 4 = 26
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalUnaryNotPattern<vt>.vnotC, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 4)>;
+  // vselect(A, not(B), and(B,C)) => imm = baseImm + 6 = 28
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalUnaryNotPattern<vt>.vnotB, XXEvalBinaryPattern<vt, and>.opPat), 
+        !add(baseImm, 6)>;
+}
+
+multiclass XXEvalVSelectWithXBCast<ValueType vt, bits<8> baseImm>{
+  // vselect(A, and(B,C), B) => imm = baseImm = 49
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and>.opPat, vt:$vB), 
+        baseImm>;
+  // vselect(A, nor(B,C), B) => imm = baseImm + 7 = 56
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, vt:$vB), 
+        !add(baseImm, 7)>;
+  // vselect(A, eqv(B,C), B) => imm = baseImm + 8 = 57
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor, 1>.opPat, vt:$vB), 
+        !add(baseImm, 8)>;
+  // vselect(A, nand(B,C), B) => imm = baseImm + 13 = 62
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and, 1>.opPat, vt:$vB), 
+        !add(baseImm, 13)>;
+}
+
+multiclass XXEvalVSelectWithXCCast<ValueType vt, bits<8> baseImm>{
+  // vselect(A, and(B,C), C) => imm = baseImm = 81
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and>.opPat, vt:$vC), 
+        baseImm>;
+  // vselect(A, nor(B,C), C) => imm = baseImm + 7 = 88
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, vt:$vC), 
+        !add(baseImm, 7)>;
+  // vselect(A, eqv(B,C), C) => imm = baseImm + 8 = 89
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, xor, 1>.opPat, vt:$vC), 
+        !add(baseImm, 8)>;
+  // vselect(A, nand(B,C), C) => imm = baseImm + 13 = 94
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and, 1>.opPat, vt:$vC), 
+        !add(baseImm, 13)>;
+}
+
+multiclass XXEvalVSelectWithXXorCast<ValueType vt, bits<8> baseImm>{
+  // vselect(A, and(B,C), xor(B,C)) => imm = baseImm = 97
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, and>.opPat, XXEvalBinaryPattern<vt, xor>.opPat), 
+        baseImm>;
+  // vselect(A, B, xor(B,C)) => imm = baseImm + 2 = 99
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, vt:$vB, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 2)>;
+  // vselect(A, C, xor(B,C)) => imm = baseImm + 4 = 101
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, vt:$vC, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 4)>;
+  // vselect(A, or(B,C), xor(B,C)) => imm = baseImm + 6 = 103
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or>.opPat, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 6)>;
+  // vselect(A, nor(B,C), xor(B,C)) => imm = baseImm + 7 = 104
+  def : XXEvalBitcastPattern<vt,
+        (vselect vt:$vA, XXEvalBinaryPattern<vt, or, 1>.opPat, XXEvalBinaryPattern<vt, xor>.opPat), 
+        !add(baseImm, 7)>; 
+}
+
+// Instantiate XXEval patterns for all vector types
+let Predicates = [HasP10Vector] in {
+  let AddedComplexity = 400 in {
----------------
amy-kwan wrote:

I think you can probably combine the `AddedComplexity` on the same line as the `Predicates`.

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


More information about the llvm-commits mailing list