blob: 7d117a5179ee07494a3644baebf225537a36b8aa [file] [log] [blame]
Amjad Aboudf1f57a32018-01-25 12:06:32 +00001//===- AggressiveInstCombine.cpp ------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the aggressive expression pattern combiner classes.
11// Currently, it handles expression patterns for:
12// * Truncate instruction
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h"
17#include "AggressiveInstCombineInternal.h"
18#include "llvm/Analysis/AliasAnalysis.h"
19#include "llvm/Analysis/BasicAliasAnalysis.h"
20#include "llvm/Analysis/GlobalsModRef.h"
21#include "llvm/Analysis/TargetLibraryInfo.h"
Sanjay Pateld2025a22018-05-01 21:02:09 +000022#include "llvm/Analysis/Utils/Local.h"
Amjad Aboudf1f57a32018-01-25 12:06:32 +000023#include "llvm/IR/DataLayout.h"
Amjad Aboudd895bff2018-01-31 10:41:31 +000024#include "llvm/IR/Dominators.h"
Sanjay Pateld2025a22018-05-01 21:02:09 +000025#include "llvm/IR/IRBuilder.h"
David Blaikieba47dd12018-04-24 15:40:07 +000026#include "llvm/IR/LegacyPassManager.h"
Sanjay Pateld2025a22018-05-01 21:02:09 +000027#include "llvm/IR/PatternMatch.h"
Amjad Aboudf1f57a32018-01-25 12:06:32 +000028#include "llvm/Pass.h"
Amjad Aboudf1f57a32018-01-25 12:06:32 +000029using namespace llvm;
Sanjay Pateld2025a22018-05-01 21:02:09 +000030using namespace PatternMatch;
Amjad Aboudf1f57a32018-01-25 12:06:32 +000031
32#define DEBUG_TYPE "aggressive-instcombine"
33
34namespace {
35/// Contains expression pattern combiner logic.
36/// This class provides both the logic to combine expression patterns and
37/// combine them. It differs from InstCombiner class in that each pattern
38/// combiner runs only once as opposed to InstCombine's multi-iteration,
39/// which allows pattern combiner to have higher complexity than the O(1)
40/// required by the instruction combiner.
41class AggressiveInstCombinerLegacyPass : public FunctionPass {
42public:
43 static char ID; // Pass identification, replacement for typeid
44
45 AggressiveInstCombinerLegacyPass() : FunctionPass(ID) {
46 initializeAggressiveInstCombinerLegacyPassPass(
47 *PassRegistry::getPassRegistry());
48 }
49
50 void getAnalysisUsage(AnalysisUsage &AU) const override;
51
52 /// Run all expression pattern optimizations on the given /p F function.
53 ///
54 /// \param F function to optimize.
55 /// \returns true if the IR is changed.
56 bool runOnFunction(Function &F) override;
57};
58} // namespace
59
Sanjay Pateld2025a22018-05-01 21:02:09 +000060/// This is a recursive helper for 'and X, 1' that walks through a chain of 'or'
61/// instructions looking for shift ops of a common source value (first member of
62/// the pair). The second member of the pair is a mask constant for all of the
63/// bits that are being compared. So this:
64/// or (or (or X, (X >> 3)), (X >> 5)), (X >> 8)
65/// returns {X, 0x129} and those are the operands of an 'and' that is compared
66/// to zero.
67static bool matchMaskedCmpOp(Value *V, std::pair<Value *, APInt> &Result) {
68 // Recurse through a chain of 'or' operands.
69 Value *Op0, *Op1;
70 if (match(V, m_Or(m_Value(Op0), m_Value(Op1))))
71 return matchMaskedCmpOp(Op0, Result) && matchMaskedCmpOp(Op1, Result);
72
73 // We need a shift-right or a bare value representing a compare of bit 0 of
74 // the original source operand.
75 Value *Candidate;
76 uint64_t BitIndex = 0;
77 if (!match(V, m_LShr(m_Value(Candidate), m_ConstantInt(BitIndex))))
78 Candidate = V;
79
80 // Initialize result source operand.
81 if (!Result.first)
82 Result.first = Candidate;
83
84 // Fill in the mask bit derived from the shift constant.
85 Result.second |= (1 << BitIndex);
86 return Result.first == Candidate;
87}
88
89/// Match an 'and' of a chain of or-shifted bits from a common source value into
90/// a masked compare:
91/// and (or (lshr X, C), ...), 1 --> (X & C') != 0
92static bool foldToMaskedCmp(Instruction &I) {
93 // TODO: This is only looking for 'any-bits-set' and 'all-bits-clear'.
94 // We should also match 'all-bits-set' and 'any-bits-clear' by looking for a
95 // a chain of 'and'.
96 if (!match(&I, m_And(m_OneUse(m_Or(m_Value(), m_Value())), m_One())))
97 return false;
98
99 std::pair<Value *, APInt>
100 MaskOps(nullptr, APInt::getNullValue(I.getType()->getScalarSizeInBits()));
101 if (!matchMaskedCmpOp(cast<BinaryOperator>(&I)->getOperand(0), MaskOps))
102 return false;
103
104 IRBuilder<> Builder(&I);
105 Value *Mask = Builder.CreateAnd(MaskOps.first, MaskOps.second);
106 Value *CmpZero = Builder.CreateIsNotNull(Mask);
107 Value *Zext = Builder.CreateZExt(CmpZero, I.getType());
108 I.replaceAllUsesWith(Zext);
109 return true;
110}
111
112/// This is the entry point for folds that could be implemented in regular
113/// InstCombine, but they are separated because they are not expected to
114/// occur frequently and/or have more than a constant-length pattern match.
115static bool foldUnusualPatterns(Function &F, DominatorTree &DT) {
116 bool MadeChange = false;
117 for (BasicBlock &BB : F) {
118 // Ignore unreachable basic blocks.
119 if (!DT.isReachableFromEntry(&BB))
120 continue;
121 // Do not delete instructions under here and invalidate the iterator.
122 for (Instruction &I : BB)
123 MadeChange |= foldToMaskedCmp(I);
124 }
125
126 // We're done with transforms, so remove dead instructions.
127 if (MadeChange)
128 for (BasicBlock &BB : F)
129 SimplifyInstructionsInBlock(&BB);
130
131 return MadeChange;
132}
133
134/// This is the entry point for all transforms. Pass manager differences are
135/// handled in the callers of this function.
136static bool runImpl(Function &F, TargetLibraryInfo &TLI, DominatorTree &DT) {
137 bool MadeChange = false;
138 const DataLayout &DL = F.getParent()->getDataLayout();
139 TruncInstCombine TIC(TLI, DL, DT);
140 MadeChange |= TIC.run(F);
141 MadeChange |= foldUnusualPatterns(F, DT);
142 return MadeChange;
143}
144
Amjad Aboudf1f57a32018-01-25 12:06:32 +0000145void AggressiveInstCombinerLegacyPass::getAnalysisUsage(
146 AnalysisUsage &AU) const {
147 AU.setPreservesCFG();
Amjad Aboudd895bff2018-01-31 10:41:31 +0000148 AU.addRequired<DominatorTreeWrapperPass>();
Amjad Aboudf1f57a32018-01-25 12:06:32 +0000149 AU.addRequired<TargetLibraryInfoWrapperPass>();
150 AU.addPreserved<AAResultsWrapperPass>();
151 AU.addPreserved<BasicAAWrapperPass>();
Amjad Aboudd895bff2018-01-31 10:41:31 +0000152 AU.addPreserved<DominatorTreeWrapperPass>();
Amjad Aboudf1f57a32018-01-25 12:06:32 +0000153 AU.addPreserved<GlobalsAAWrapperPass>();
154}
155
156bool AggressiveInstCombinerLegacyPass::runOnFunction(Function &F) {
157 auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
Sanjay Pateld2025a22018-05-01 21:02:09 +0000158 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
159 return runImpl(F, TLI, DT);
Amjad Aboudf1f57a32018-01-25 12:06:32 +0000160}
161
162PreservedAnalyses AggressiveInstCombinePass::run(Function &F,
163 FunctionAnalysisManager &AM) {
164 auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
Sanjay Pateld2025a22018-05-01 21:02:09 +0000165 auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
166 if (!runImpl(F, TLI, DT)) {
Amjad Aboudf1f57a32018-01-25 12:06:32 +0000167 // No changes, all analyses are preserved.
168 return PreservedAnalyses::all();
Sanjay Pateld2025a22018-05-01 21:02:09 +0000169 }
Amjad Aboudf1f57a32018-01-25 12:06:32 +0000170 // Mark all the analyses that instcombine updates as preserved.
171 PreservedAnalyses PA;
172 PA.preserveSet<CFGAnalyses>();
173 PA.preserve<AAManager>();
174 PA.preserve<GlobalsAA>();
175 return PA;
176}
177
178char AggressiveInstCombinerLegacyPass::ID = 0;
179INITIALIZE_PASS_BEGIN(AggressiveInstCombinerLegacyPass,
180 "aggressive-instcombine",
181 "Combine pattern based expressions", false, false)
Amjad Aboudd895bff2018-01-31 10:41:31 +0000182INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
Amjad Aboudf1f57a32018-01-25 12:06:32 +0000183INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
184INITIALIZE_PASS_END(AggressiveInstCombinerLegacyPass, "aggressive-instcombine",
185 "Combine pattern based expressions", false, false)
186
Craig Topperd4eb2072018-04-24 00:05:21 +0000187// Initialization Routines
188void llvm::initializeAggressiveInstCombine(PassRegistry &Registry) {
189 initializeAggressiveInstCombinerLegacyPassPass(Registry);
190}
191
Craig Topper1bcb2582018-04-24 00:39:29 +0000192void LLVMInitializeAggressiveInstCombiner(LLVMPassRegistryRef R) {
193 initializeAggressiveInstCombinerLegacyPassPass(*unwrap(R));
194}
195
Amjad Aboudf1f57a32018-01-25 12:06:32 +0000196FunctionPass *llvm::createAggressiveInstCombinerPass() {
197 return new AggressiveInstCombinerLegacyPass();
198}
David Blaikieba47dd12018-04-24 15:40:07 +0000199
200void LLVMAddAggressiveInstCombinerPass(LLVMPassManagerRef PM) {
201 unwrap(PM)->add(createAggressiveInstCombinerPass());
202}