[llvm] [PowerPC] Exploit xxeval instruction for ternary patterns - part 1 (PR #141733)
Kamau Bridgeman via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 16 07:50:04 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 {
----------------
kamaub wrote:
I noticed the previous eval patterns that were for v4i32 only were also predicated on prefixed instrs, I think it makes sense to include this here incase the code path with p10 but no prefix instrs occurred? I guess if it were impossible to turn off the predicated would be useless though?
https://github.com/llvm/llvm-project/pull/141733
More information about the llvm-commits
mailing list