[PATCH] D44626: [InstCombine] Fold (A OR B) AND B code sequence over Phi node
Hiroshi Inoue via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 19 07:46:56 PDT 2018
inouehrs created this revision.
inouehrs added reviewers: efriedma, dberlin, echristo, hfinkel, kbarton, nemanjai.
This patch intends to enable jump threading with a method whose return type is std::pair<int, bool> or std::pair<bool, int>
For example, jump threading does not work for the if statement in func.
std::pair<int, bool> callee(int v) {
int a = dummy(v);
if (a) return std::make_pair(dummy(v), true);
else return std::make_pair(v, v < 0);
}
int func(int v) {
std::pair<int, bool> rc = callee(v);
if (rc.second) {
// do something
}
SROA executed before the method inlining replaces std::pair by i64 without splitting in both `callee` and `func` since at this point no access to the individual fields is seen to SROA.
After inlining, jump threading fails to identify that the incoming value is a constant due to additional instructions (like or, and, trunc).
This patch finds a phi node, which has OR instruction as an incoming value and AND instruction as its use. If the OR and AND instructions take the same operand, e.g. (%A OR %B) AND %B, then replace the incoming OR by %B. For example,
BB1:
%or = or i64 %val, 1
br %BB2
BB2:
%phi = phi i64 [ %or, %BB1 ], ... # -> phi i64 [ 1, %BB1 ], ...
%and = and i64 %phi, 1
This helps jump threading identify the opportunity listed above.
Later, in the CFG simplification pass, the similar code modification happens. But it is too late to help jump threading.
https://reviews.llvm.org/D44626
Files:
lib/Transforms/InstCombine/InstCombineInternal.h
lib/Transforms/InstCombine/InstCombinePHI.cpp
Index: lib/Transforms/InstCombine/InstCombinePHI.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombinePHI.cpp
+++ lib/Transforms/InstCombine/InstCombinePHI.cpp
@@ -635,6 +635,50 @@
return NewLI;
}
+// FoldPHIArgOrIntoPHI finds a phi node, which has OR instruction as an incoming value
+// and AND instruction as its use. If the OR and AND instructions take the same operand
+// as (%A OR %B) AND %B then replace the incoming value as %B.
+// For example,
+// BB1:
+// %or = or i64 %val, 1
+// br %BB2
+// BB2:
+// %phi = phi i64 [ %or, %BB1 ], ... # -> phi i64 [ 1, %BB1 ], ...
+// %and = and i64 %phi, 1
+// This optimization allows jump threading pass to find the opportunity in method call
+// whose return value is std::pair<int, bool>.
+Instruction *InstCombiner::FoldPHIArgOrIntoPHI(PHINode &Phi) {
+ for (User *User : Phi.users()) {
+ // Try to find OR - Phi - AND code sequence.
+ Value *UserVal = nullptr;
+ if (!match(User, m_And(m_Specific(&Phi), m_Value(UserVal))))
+ continue;
+
+ auto IsEligible = [&](Value *V) {
+ return match(V, m_Or(m_Value(), m_Specific(UserVal)));
+ };
+ if (llvm::none_of(Phi.incoming_values(), IsEligible))
+ continue;
+
+ PHINode* NewPhi = Φ
+ // If there is another use of the phi node, we create a new one
+ // for this AND instruction by cloning the original phi node.
+ if (!Phi.hasOneUse()) {
+ NewPhi = cast<PHINode>(Phi.clone());
+ InsertNewInstBefore(NewPhi, Phi);
+ cast<Instruction>(User)->setOperand(0, NewPhi);
+ }
+
+ // We replace the incoming OR with UserVal.
+ for (unsigned Idx = 0; Idx < NewPhi->getNumIncomingValues(); Idx++) {
+ Value *V = NewPhi->getIncomingValue(Idx);
+ if (match(V, m_Or(m_Value(), m_Specific(UserVal))))
+ NewPhi->setIncomingValue(Idx, UserVal);
+ }
+ }
+ return nullptr;
+}
+
/// TODO: This function could handle other cast types, but then it might
/// require special-casing a cast from the 'i1' type. See the comment in
/// FoldPHIArgOpIntoPHI() about pessimizing illegal integer types.
@@ -1130,6 +1174,9 @@
if (Instruction *Result = FoldPHIArgOpIntoPHI(PN))
return Result;
+ if (Instruction *Result = FoldPHIArgOrIntoPHI(PN))
+ return Result;
+
// If this is a trivial cycle in the PHI node graph, remove it. Basically, if
// this PHI only has a single use (a PHI), and if that PHI only has one use (a
// PHI)... break the cycle.
Index: lib/Transforms/InstCombine/InstCombineInternal.h
===================================================================
--- lib/Transforms/InstCombine/InstCombineInternal.h
+++ lib/Transforms/InstCombine/InstCombineInternal.h
@@ -703,6 +703,7 @@
Instruction *FoldPHIArgGEPIntoPHI(PHINode &PN);
Instruction *FoldPHIArgLoadIntoPHI(PHINode &PN);
Instruction *FoldPHIArgZextsIntoPHI(PHINode &PN);
+ Instruction *FoldPHIArgOrIntoPHI(PHINode &PN);
/// If an integer typed PHI has only one use which is an IntToPtr operation,
/// replace the PHI with an existing pointer typed PHI if it exists. Otherwise
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D44626.138908.patch
Type: text/x-patch
Size: 3150 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180319/4a46646f/attachment.bin>
More information about the llvm-commits
mailing list