-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[PowerPC ]convert (setcc (and X, 1), 0, eq) to XORI (and X, 1), 1
#168384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@llvm/pr-subscribers-backend-powerpc Author: zhijian lin (diggerlin) ChangesBased on the discussion in #158657 (comment), Full diff: https://github.com/llvm/llvm-project/pull/168384.diff 2 Files Affected:
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index f55336bafd251..ea0e31ae47082 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -15775,11 +15775,82 @@ SDValue convertTwoLoadsAndCmpToVCMPEQUB(SelectionDAG &DAG, SDNode *N,
CC == ISD::SETNE ? ISD::SETEQ : ISD::SETNE);
}
+// Detect whether there is a pattern like (setcc (and X, 1), 0, eq).
+// If it is , return true; otherwise return false.
+static bool canConvertSETCCToXori(SDNode *N) {
+ if (N->getOpcode() != ISD::SETCC)
+ return false;
+
+ ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+ if (CC != ISD::SETEQ)
+ return false;
+
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
+
+ // Check the `SDValue &V` is from `and` with `1`.
+ auto IsAndWithOne = [](SDValue &V) {
+ if (V.getOpcode() == ISD::AND) {
+ SDNode *AndNode = V.getNode();
+ for (const SDValue &Op : AndNode->ops())
+ if (auto *C = dyn_cast<ConstantSDNode>(Op))
+ if (C->isOne())
+ return true;
+ }
+ return false;
+ };
+
+ // Check whether the SETCC compare with zero.
+ auto IsCompareWithZero = [](SDValue &V) {
+ if (auto *C = dyn_cast<ConstantSDNode>(V))
+ if (C->isZero())
+ return true;
+ return false;
+ };
+
+ return (IsAndWithOne(LHS) && IsCompareWithZero(RHS)) ||
+ (IsAndWithOne(RHS) && IsCompareWithZero(LHS));
+}
+
+// You must check whether the `SDNode* N` can be converted to Xori using
+// the function `static bool canConvertSETCCToXori(SDNode *N)`
+// before calling the function; otherwise, it may produce incorrect results.
+static SDValue ConvertSETCCToXori(SDNode *N, SelectionDAG &DAG) {
+
+ assert(N->getOpcode() == ISD::SETCC && "Should SETCC SDNode here.");
+ SDValue LHS = N->getOperand(0);
+ SDValue RHS = N->getOperand(1);
+ SDLoc DL(N);
+
+ ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+ assert((CC == ISD::SETEQ) && "CC must be ISD::SETEQ.");
+ // Rewrite it as XORI (and X, 1), 1.
+ auto MakeXor1 = [&](SDValue V) {
+ EVT VT = V.getValueType();
+ SDValue One = DAG.getConstant(1, DL, VT);
+ SDValue Xor = DAG.getNode(ISD::XOR, DL, VT, V, One);
+ return DAG.getNode(ISD::TRUNCATE, DL, MVT::i1, Xor);
+ };
+
+ if (LHS.getOpcode() == ISD::AND && RHS.getOpcode() != ISD::AND)
+ return MakeXor1(LHS);
+
+ if (RHS.getOpcode() == ISD::AND && LHS.getOpcode() != ISD::AND)
+ return MakeXor1(RHS);
+
+ llvm_unreachable("Should not reach here.");
+}
+
SDValue PPCTargetLowering::combineSetCC(SDNode *N,
DAGCombinerInfo &DCI) const {
assert(N->getOpcode() == ISD::SETCC &&
"Should be called with a SETCC node");
+ // Check if the pattern (setcc (and X, 1), 0, eq) is present.
+ // If it is, rewrite it as XORI (and X, 1), 1.
+ if (canConvertSETCCToXori(N))
+ return ConvertSETCCToXori(N, DCI.DAG);
+
ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
if (CC == ISD::SETNE || CC == ISD::SETEQ) {
SDValue LHS = N->getOperand(0);
diff --git a/llvm/test/CodeGen/PowerPC/memCmpUsedInZeroEqualityComparison.ll b/llvm/test/CodeGen/PowerPC/memCmpUsedInZeroEqualityComparison.ll
index bf86695818689..8d4dce122a437 100644
--- a/llvm/test/CodeGen/PowerPC/memCmpUsedInZeroEqualityComparison.ll
+++ b/llvm/test/CodeGen/PowerPC/memCmpUsedInZeroEqualityComparison.ll
@@ -39,9 +39,8 @@ define signext i32 @zeroEqualityTest01(ptr %x, ptr %y) {
; CHECK-NEXT: lxvd2x 35, 0, 3
; CHECK-NEXT: vcmpequb. 2, 3, 2
; CHECK-NEXT: mfocrf 3, 2
+; CHECK-NEXT: not 3, 3
; CHECK-NEXT: rlwinm 3, 3, 25, 31, 31
-; CHECK-NEXT: cntlzw 3, 3
-; CHECK-NEXT: srwi 3, 3, 5
; CHECK-NEXT: blr
%call = tail call signext i32 @memcmp(ptr %x, ptr %y, i64 16)
%not.tobool = icmp ne i32 %call, 0
|
|
should this really be specific to powerpc |
It changes 2 ISD operations into 2 ISD operations. At the platform independent level it is not clearly an optimization. |
Based on the discussion in #158657 (comment),
We can convert
(setcc (and X, 1), 0, eq)toXORI (and X, 1), 1and save one instruction.