[llvm] r312420 - [InstCombine] combine foldAndOfFCmps and foldOrOfFcmps; NFCI
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 2 10:53:33 PDT 2017
Author: spatel
Date: Sat Sep 2 10:53:33 2017
New Revision: 312420
URL: http://llvm.org/viewvc/llvm-project?rev=312420&view=rev
Log:
[InstCombine] combine foldAndOfFCmps and foldOrOfFcmps; NFCI
In addition to removing chunks of duplicated code, we don't
want these to diverge. If there's a fold for one, there
should be a fold of the other via DeMorgan's Laws.
Modified:
llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp?rev=312420&r1=312419&r2=312420&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp Sat Sep 2 10:53:33 2017
@@ -901,9 +901,7 @@ Value *InstCombiner::foldAndOfICmps(ICmp
return nullptr;
}
-/// Optimize (fcmp)&(fcmp). NOTE: Unlike the rest of instcombine, this returns
-/// a Value which should already be inserted into the function.
-Value *InstCombiner::foldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS) {
+Value *InstCombiner::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS, bool IsAnd) {
Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);
FCmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
@@ -923,79 +921,42 @@ Value *InstCombiner::foldAndOfFCmps(FCmp
// bool(R & CC0) && bool(R & CC1)
// = bool((R & CC0) & (R & CC1))
// = bool(R & (CC0 & CC1)) <= by re-association, commutation, and idempotency
- if (LHS0 == RHS0 && LHS1 == RHS1)
- return getFCmpValue(getFCmpCode(PredL) & getFCmpCode(PredR), LHS0, LHS1,
- Builder);
-
- if (PredL == FCmpInst::FCMP_ORD && PredR == FCmpInst::FCMP_ORD) {
- if (LHS0->getType() != RHS0->getType())
- return nullptr;
-
- // (fcmp ord x, c) & (fcmp ord y, c) -> (fcmp ord x, y)
- if (auto *LHSC = dyn_cast<ConstantFP>(LHS1))
- if (auto *RHSC = dyn_cast<ConstantFP>(RHS1)) {
- // If either of the constants are nans, then the whole thing returns
- // false.
- if (LHSC->getValueAPF().isNaN() || RHSC->getValueAPF().isNaN())
- return Builder.getFalse();
- return Builder.CreateFCmpORD(LHS0, RHS0);
- }
-
- // Handle vector zeros. This occurs because the canonical form of
- // "fcmp ord x,x" is "fcmp ord x, 0".
- if (isa<ConstantAggregateZero>(LHS1) &&
- isa<ConstantAggregateZero>(RHS1))
- return Builder.CreateFCmpORD(LHS0, RHS0);
- }
-
- return nullptr;
-}
-
-/// Optimize (fcmp)|(fcmp). NOTE: Unlike the rest of instcombine, this returns
-/// a Value which should already be inserted into the function.
-Value *InstCombiner::foldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS) {
- Value *LHS0 = LHS->getOperand(0), *LHS1 = LHS->getOperand(1);
- Value *RHS0 = RHS->getOperand(0), *RHS1 = RHS->getOperand(1);
- FCmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
-
- if (LHS0 == RHS1 && RHS0 == LHS1) {
- // Swap RHS operands to match LHS.
- PredR = FCmpInst::getSwappedPredicate(PredR);
- std::swap(RHS0, RHS1);
- }
-
- // Simplify (fcmp cc0 x, y) | (fcmp cc1 x, y).
- // This is a similar transformation to the one in FoldAndOfFCmps.
//
// Since (R & CC0) and (R & CC1) are either R or 0, we actually have this:
// bool(R & CC0) || bool(R & CC1)
// = bool((R & CC0) | (R & CC1))
// = bool(R & (CC0 | CC1)) <= by reversed distribution (contribution? ;)
- if (LHS0 == RHS0 && LHS1 == RHS1)
- return getFCmpValue(getFCmpCode(PredL) | getFCmpCode(PredR), LHS0, LHS1,
- Builder);
+ if (LHS0 == RHS0 && LHS1 == RHS1) {
+ unsigned FCmpCodeL = getFCmpCode(PredL);
+ unsigned FCmpCodeR = getFCmpCode(PredR);
+ unsigned NewPred = IsAnd ? FCmpCodeL & FCmpCodeR : FCmpCodeL | FCmpCodeR;
+ return getFCmpValue(NewPred, LHS0, LHS1, Builder);
+ }
- if (PredL == FCmpInst::FCMP_UNO && PredR == FCmpInst::FCMP_UNO) {
+ if ((PredL == FCmpInst::FCMP_ORD && PredR == FCmpInst::FCMP_ORD && IsAnd) ||
+ (PredL == FCmpInst::FCMP_UNO && PredR == FCmpInst::FCMP_UNO && !IsAnd)) {
if (LHS0->getType() != RHS0->getType())
return nullptr;
- if (auto *LHSC = dyn_cast<ConstantFP>(LHS1))
- if (auto *RHSC = dyn_cast<ConstantFP>(RHS1)) {
- // If either of the constants are nans, then the whole thing returns
- // true.
- if (LHSC->getValueAPF().isNaN() || RHSC->getValueAPF().isNaN())
- return Builder.getTrue();
-
- // Otherwise, no need to compare the two constants, compare the
- // rest.
- return Builder.CreateFCmpUNO(LHS0, RHS0);
- }
+ auto *LHSC = dyn_cast<ConstantFP>(LHS1);
+ auto *RHSC = dyn_cast<ConstantFP>(RHS1);
+ if (LHSC && RHSC) {
+ // If either of the constants are nans, then the whole thing returns
+ // true or false.
+ if (LHSC->getValueAPF().isNaN() || RHSC->getValueAPF().isNaN())
+ return IsAnd ? Builder.getFalse() : Builder.getTrue();
+
+ // Otherwise, no need to compare the two constants. Compare the rest:
+ // (fcmp ord x, c) & (fcmp ord y, c) -> (fcmp ord x, y)
+ // (fcmp uno x, c) & (fcmp uno y, c) -> (fcmp uno x, y)
+ return Builder.CreateFCmp(PredL, LHS0, RHS0);
+ }
- // Handle vector zeros. This occurs because the canonical form of
- // "fcmp uno x,x" is "fcmp uno x, 0".
+ // Handle vector zeros. This occurs because the canonical form of
+ // "fcmp ord/uno x,x" is "fcmp ord/uno x, 0".
if (isa<ConstantAggregateZero>(LHS1) &&
isa<ConstantAggregateZero>(RHS1))
- return Builder.CreateFCmpUNO(LHS0, RHS0);
+ return Builder.CreateFCmp(PredL, LHS0, RHS0);
}
return nullptr;
@@ -1140,13 +1101,9 @@ Instruction *InstCombiner::foldCastedBit
// cast is otherwise not optimizable. This happens for vector sexts.
FCmpInst *FCmp0 = dyn_cast<FCmpInst>(Cast0Src);
FCmpInst *FCmp1 = dyn_cast<FCmpInst>(Cast1Src);
- if (FCmp0 && FCmp1) {
- Value *Res = LogicOpc == Instruction::And ? foldAndOfFCmps(FCmp0, FCmp1)
- : foldOrOfFCmps(FCmp0, FCmp1);
- if (Res)
- return CastInst::Create(CastOpcode, Res, DestTy);
- return nullptr;
- }
+ if (FCmp0 && FCmp1)
+ if (Value *R = foldLogicOfFCmps(FCmp0, FCmp1, LogicOpc == Instruction::And))
+ return CastInst::Create(CastOpcode, R, DestTy);
return nullptr;
}
@@ -1435,10 +1392,9 @@ Instruction *InstCombiner::visitAnd(Bina
}
}
- // If and'ing two fcmp, try combine them into one.
if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0)))
if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1)))
- if (Value *Res = foldAndOfFCmps(LHS, RHS))
+ if (Value *Res = foldLogicOfFCmps(LHS, RHS, true))
return replaceInstUsesWith(I, Res);
if (Instruction *CastedAnd = foldCastedBitwiseLogic(I))
@@ -2040,10 +1996,9 @@ Instruction *InstCombiner::visitOr(Binar
}
}
- // (fcmp uno x, c) | (fcmp uno y, c) -> (fcmp uno x, y)
if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0)))
if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1)))
- if (Value *Res = foldOrOfFCmps(LHS, RHS))
+ if (Value *Res = foldLogicOfFCmps(LHS, RHS, false))
return replaceInstUsesWith(I, Res);
if (Instruction *CastedOr = foldCastedBitwiseLogic(I))
Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h?rev=312420&r1=312419&r2=312420&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h Sat Sep 2 10:53:33 2017
@@ -456,11 +456,14 @@ private:
const CastInst *CI2);
Value *foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS, Instruction &CxtI);
- Value *foldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS);
Value *foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, Instruction &CxtI);
- Value *foldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS);
Value *foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS);
+ /// Optimize (fcmp)&(fcmp) or (fcmp)|(fcmp).
+ /// NOTE: Unlike most of instcombine, this returns a Value which should
+ /// already be inserted into the function.
+ Value *foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS, bool IsAnd);
+
Value *foldAndOrOfICmpsOfAndWithPow2(ICmpInst *LHS, ICmpInst *RHS,
bool JoinedByAnd, Instruction &CxtI);
public:
More information about the llvm-commits
mailing list