[llvm] [GlobalIsel] Combine logic of floating point compares (PR #81886)
Thorsten Schütt via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 20 00:39:42 PST 2024
================
@@ -6814,12 +6815,90 @@ bool CombinerHelper::tryFoldAndOrOrICmpsUsingRanges(GLogicalBinOp *Logic,
return true;
}
+bool CombinerHelper::tryFoldLogicOfFCmps(GLogicalBinOp *Logic,
+ BuildFnTy &MatchInfo) {
+ assert(Logic->getOpcode() != TargetOpcode::G_XOR && "unexpecte xor");
+ Register DestReg = Logic->getReg(0);
+ Register LHS = Logic->getLHSReg();
+ Register RHS = Logic->getRHSReg();
+ bool IsAnd = Logic->getOpcode() == TargetOpcode::G_AND;
+
+ // We need a compare on the LHS register.
+ GFCmp *Cmp1 = getOpcodeDef<GFCmp>(LHS, MRI);
+ if (!Cmp1)
+ return false;
+
+ // We need a compare on the RHS register.
+ GFCmp *Cmp2 = getOpcodeDef<GFCmp>(RHS, MRI);
+ if (!Cmp2)
+ return false;
+
+ LLT CmpTy = MRI.getType(Cmp1->getReg(0));
+ LLT CmpOperandTy = MRI.getType(Cmp1->getLHSReg());
+
+ // We build one fcmp, want to fold the fcmps, replace the logic op,
+ // and the fcmps must have the same shape.
+ if (!isLegalOrBeforeLegalizer(
+ {TargetOpcode::G_FCMP, {CmpTy, CmpOperandTy}}) ||
+ !MRI.hasOneNonDBGUse(Logic->getReg(0)) ||
+ !MRI.hasOneNonDBGUse(Cmp1->getReg(0)) ||
+ !MRI.hasOneNonDBGUse(Cmp2->getReg(0)) ||
+ MRI.getType(Cmp1->getLHSReg()) != MRI.getType(Cmp2->getLHSReg()))
+ return false;
+
+ CmpInst::Predicate PredL = Cmp1->getCond();
+ CmpInst::Predicate PredR = Cmp2->getCond();
+ Register LHS0 = Cmp1->getLHSReg();
+ Register LHS1 = Cmp1->getRHSReg();
+ Register RHS0 = Cmp2->getLHSReg();
+ Register RHS1 = Cmp2->getRHSReg();
+
+ if (LHS0 == RHS1 && LHS1 == RHS0) {
+ // Swap RHS operands to match LHS.
+ PredR = CmpInst::getSwappedPredicate(PredR);
+ std::swap(RHS0, RHS1);
+ }
+
+ if (LHS0 == RHS0 && LHS1 == RHS1) {
+ // We determine the new predicate.
+ unsigned CmpCodeL = getFCmpCode(PredL);
+ unsigned CmpCodeR = getFCmpCode(PredR);
+ unsigned NewPred = IsAnd ? CmpCodeL & CmpCodeR : CmpCodeL | CmpCodeR;
----------------
tschuett wrote:
The DAG uses:
```
ISD::CondCode NewCC = IsAnd ? ISD::getSetCCAndOperation(CC0, CC1, OpVT)
: ISD::getSetCCOrOperation(CC0, CC1, OpVT);
```
https://github.com/llvm/llvm-project/blob/1cbe26d302ca7d3573c1bf43114dfd7d2f0ca476/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp#L1363
https://github.com/llvm/llvm-project/pull/81886
More information about the llvm-commits
mailing list