blob: ba28040ed1a4ccd7744aa31d154835df87b61511 [file] [log] [blame]
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +00001//===-- PredicateSimplifier.cpp - Path Sensitive Simplifier -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Nick Lewycky and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===------------------------------------------------------------------===//
9//
10// Path-sensitive optimizer. In a branch where x == y, replace uses of
11// x with y. Permits further optimization, such as the elimination of
12// the unreachable call:
13//
14// void test(int *p, int *q)
15// {
16// if (p != q)
17// return;
18//
19// if (*p != *q)
20// foo(); // unreachable
21// }
22//
23//===------------------------------------------------------------------===//
24//
25// This optimization works by substituting %q for %p when protected by a
Nick Lewycky5f8f9af2006-08-30 02:46:48 +000026// conditional that assures us of that fact. Properties are stored as
27// relationships between two values.
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +000028//
29//===------------------------------------------------------------------===//
30
31// TODO:
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +000032// * Check handling of NAN in floating point types
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +000033
34#define DEBUG_TYPE "predsimplify"
35#include "llvm/Transforms/Scalar.h"
36#include "llvm/Constants.h"
37#include "llvm/Instructions.h"
38#include "llvm/Pass.h"
Nick Lewycky5f8f9af2006-08-30 02:46:48 +000039#include "llvm/ADT/EquivalenceClasses.h"
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +000040#include "llvm/ADT/Statistic.h"
41#include "llvm/ADT/STLExtras.h"
42#include "llvm/Analysis/Dominators.h"
43#include "llvm/Support/CFG.h"
44#include "llvm/Support/Debug.h"
45#include <iostream>
46using namespace llvm;
47
48namespace {
49 Statistic<>
50 NumVarsReplaced("predsimplify", "Number of argument substitutions");
51 Statistic<>
Nick Lewycky5f8f9af2006-08-30 02:46:48 +000052 NumInstruction("predsimplify", "Number of instructions removed");
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +000053 Statistic<>
54 NumSwitchCases("predsimplify", "Number of switch cases removed");
Nick Lewycky5f8f9af2006-08-30 02:46:48 +000055 Statistic<>
56 NumBranches("predsimplify", "Number of branches made unconditional");
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +000057
58 /// Used for choosing the canonical Value in a synonym set.
59 /// Leaves the better one in V1. Returns whether a swap took place.
60 static void order(Value *&V1, Value *&V2) {
61 if (isa<Constant>(V2)) {
62 if (!isa<Constant>(V1)) {
63 std::swap(V1, V2);
64 return;
65 }
66 } else if (isa<Argument>(V2)) {
67 if (!isa<Constant>(V1) && !isa<Argument>(V1)) {
68 std::swap(V1, V2);
69 return;
70 }
71 }
72 if (User *U1 = dyn_cast<User>(V1)) {
73 for (User::const_op_iterator I = U1->op_begin(), E = U1->op_end();
74 I != E; ++I) {
75 if (*I == V2) {
76 std::swap(V1, V2);
77 return;
78 }
79 }
80 }
81 return;
82 }
83
84 /// Represents the set of equivalent Value*s and provides insertion
85 /// and fast lookup. Also stores the set of inequality relationships.
86 class PropertySet {
87 struct Property;
Nick Lewycky5f8f9af2006-08-30 02:46:48 +000088 class EquivalenceClasses<Value *> union_find;
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +000089 public:
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +000090 typedef std::vector<Property>::iterator PropertyIterator;
91 typedef std::vector<Property>::const_iterator ConstPropertyIterator;
92
93 enum Ops {
94 EQ,
95 NE
96 };
97
98 Value *canonicalize(Value *V) const {
99 Value *C = lookup(V);
100 return C ? C : V;
101 }
102
103 Value *lookup(Value *V) const {
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000104 EquivalenceClasses<Value *>::member_iterator SI =
105 union_find.findLeader(V);
106 if (SI == union_find.member_end()) return NULL;
107 return *SI;
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000108 }
109
110 bool empty() const {
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000111 return union_find.empty();
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000112 }
113
114 void addEqual(Value *V1, Value *V2) {
115 order(V1, V2);
116 if (isa<Constant>(V2)) return; // refuse to set false == true.
117
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000118 union_find.unionSets(V1, V2);
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000119 addImpliedProperties(EQ, V1, V2);
120 }
121
122 void addNotEqual(Value *V1, Value *V2) {
123 DEBUG(std::cerr << "not equal: " << *V1 << " and " << *V2 << "\n");
Nick Lewycky08674ab2006-08-31 00:39:16 +0000124 if (findProperty(NE, V1, V2) != Properties.end())
125 return; // found.
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000126
127 // Add the property.
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000128 Properties.push_back(Property(NE, V1, V2));
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000129 addImpliedProperties(NE, V1, V2);
130 }
131
132 PropertyIterator findProperty(Ops Opcode, Value *V1, Value *V2) {
133 assert(Opcode != EQ && "Can't findProperty on EQ."
134 "Use the lookup method instead.");
135
Nick Lewycky08674ab2006-08-31 00:39:16 +0000136 V1 = canonicalize(V1);
137 V2 = canonicalize(V2);
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000138
139 // Does the property already exist?
140 for (PropertyIterator I = Properties.begin(), E = Properties.end();
141 I != E; ++I) {
142 if (I->Opcode != Opcode) continue;
143
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000144 I->V1 = canonicalize(I->V1);
145 I->V2 = canonicalize(I->V2);
146 if ((I->V1 == V1 && I->V2 == V2) ||
147 (I->V1 == V2 && I->V2 == V1)) {
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000148 return I; // Found.
149 }
150 }
151 return Properties.end();
152 }
153
154 ConstPropertyIterator
155 findProperty(Ops Opcode, Value *V1, Value *V2) const {
156 assert(Opcode != EQ && "Can't findProperty on EQ."
157 "Use the lookup method instead.");
158
Nick Lewycky08674ab2006-08-31 00:39:16 +0000159 V1 = canonicalize(V1);
160 V2 = canonicalize(V2);
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000161
162 // Does the property already exist?
163 for (ConstPropertyIterator I = Properties.begin(),
164 E = Properties.end(); I != E; ++I) {
165 if (I->Opcode != Opcode) continue;
166
Nick Lewycky08674ab2006-08-31 00:39:16 +0000167 Value *v1 = canonicalize(I->V1),
168 *v2 = canonicalize(I->V2);
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000169 if ((v1 == V1 && v2 == V2) ||
170 (v1 == V2 && v2 == V1)) {
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000171 return I; // Found.
172 }
173 }
174 return Properties.end();
175 }
176
177 private:
178 // Represents Head OP [Tail1, Tail2, ...]
179 // For example: %x != %a, %x != %b.
180 struct Property {
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000181 Property(Ops opcode, Value *v1, Value *v2)
182 : Opcode(opcode), V1(v1), V2(v2)
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000183 { assert(opcode != EQ && "Equality belongs in the synonym set,"
184 "not a property."); }
185
186 bool operator<(const Property &rhs) const {
187 if (Opcode != rhs.Opcode) return Opcode < rhs.Opcode;
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000188 if (V1 != rhs.V1) return V1 < rhs.V1;
189 return V2 < rhs.V2;
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000190 }
191
192 Ops Opcode;
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000193 Value *V1, *V2;
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000194 };
195
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000196 void add(Ops Opcode, Value *V1, Value *V2, bool invert) {
197 switch (Opcode) {
198 case EQ:
199 if (invert) addNotEqual(V1, V2);
200 else addEqual(V1, V2);
201 break;
202 case NE:
203 if (invert) addEqual(V1, V2);
204 else addNotEqual(V1, V2);
205 break;
206 default:
207 assert(0 && "Unknown property opcode.");
208 }
209 }
210
211 // Finds the properties implied by a synonym and adds them too.
212 // Example: ("seteq %a, %b", true, EQ) --> (%a, %b, EQ)
213 // ("seteq %a, %b", false, EQ) --> (%a, %b, NE)
214 void addImpliedProperties(Ops Opcode, Value *V1, Value *V2) {
215 order(V1, V2);
216
217 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(V2)) {
218 switch (BO->getOpcode()) {
219 case Instruction::SetEQ:
220 if (V1 == ConstantBool::True)
221 add(Opcode, BO->getOperand(0), BO->getOperand(1), false);
222 if (V1 == ConstantBool::False)
223 add(Opcode, BO->getOperand(0), BO->getOperand(1), true);
224 break;
225 case Instruction::SetNE:
226 if (V1 == ConstantBool::True)
227 add(Opcode, BO->getOperand(0), BO->getOperand(1), true);
228 if (V1 == ConstantBool::False)
229 add(Opcode, BO->getOperand(0), BO->getOperand(1), false);
230 break;
231 case Instruction::SetLT:
232 case Instruction::SetGT:
233 if (V1 == ConstantBool::True)
234 add(Opcode, BO->getOperand(0), BO->getOperand(1), true);
235 break;
236 case Instruction::SetLE:
237 case Instruction::SetGE:
238 if (V1 == ConstantBool::False)
239 add(Opcode, BO->getOperand(0), BO->getOperand(1), true);
240 break;
241 case Instruction::And:
242 if (V1 == ConstantBool::True) {
243 add(Opcode, ConstantBool::True, BO->getOperand(0), false);
244 add(Opcode, ConstantBool::True, BO->getOperand(1), false);
245 }
246 break;
247 case Instruction::Or:
248 if (V1 == ConstantBool::False) {
249 add(Opcode, ConstantBool::False, BO->getOperand(0), false);
250 add(Opcode, ConstantBool::False, BO->getOperand(1), false);
251 }
252 break;
253 case Instruction::Xor:
254 if (V1 == ConstantBool::True) {
255 if (BO->getOperand(0) == ConstantBool::True)
256 add(Opcode, ConstantBool::False, BO->getOperand(1), false);
257 if (BO->getOperand(1) == ConstantBool::True)
258 add(Opcode, ConstantBool::False, BO->getOperand(0), false);
259 }
260 if (V1 == ConstantBool::False) {
261 if (BO->getOperand(0) == ConstantBool::True)
262 add(Opcode, ConstantBool::True, BO->getOperand(1), false);
263 if (BO->getOperand(1) == ConstantBool::True)
264 add(Opcode, ConstantBool::True, BO->getOperand(0), false);
265 }
266 break;
267 default:
268 break;
269 }
270 }
271 }
272
273 std::map<Value *, unsigned> SynonymMap;
274 std::vector<Value *> Synonyms;
275
276 public:
277 void debug(std::ostream &os) const {
Nick Lewycky08674ab2006-08-31 00:39:16 +0000278 for (EquivalenceClasses<Value*>::iterator I = union_find.begin(),
279 E = union_find.end(); I != E; ++I) {
280 if (!I->isLeader()) continue;
281 for (EquivalenceClasses<Value*>::member_iterator MI =
282 union_find.member_begin(I); MI != union_find.member_end(); ++MI)
283 std::cerr << **MI << " ";
284 std::cerr << "\n--\n";
285 }
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000286 }
287
288 std::vector<Property> Properties;
289 };
290
291 /// PredicateSimplifier - This class is a simplifier that replaces
292 /// one equivalent variable with another. It also tracks what
293 /// can't be equal and will solve setcc instructions when possible.
294 class PredicateSimplifier : public FunctionPass {
295 public:
296 bool runOnFunction(Function &F);
297 virtual void getAnalysisUsage(AnalysisUsage &AU) const;
298
299 private:
300 // Try to replace the Use of the instruction with something simpler.
301 Value *resolve(SetCondInst *SCI, const PropertySet &);
302 Value *resolve(BinaryOperator *BO, const PropertySet &);
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000303 Value *resolve(SelectInst *SI, const PropertySet &);
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000304 Value *resolve(Value *V, const PropertySet &);
305
306 // Used by terminator instructions to proceed from the current basic
307 // block to the next. Verifies that "current" dominates "next",
308 // then calls visitBasicBlock.
309 void proceedToSuccessor(PropertySet &CurrentPS, PropertySet &NextPS,
310 DominatorTree::Node *Current, DominatorTree::Node *Next);
311 void proceedToSuccessor(PropertySet &CurrentPS,
312 DominatorTree::Node *Current, DominatorTree::Node *Next);
313
314 // Visits each instruction in the basic block.
315 void visitBasicBlock(DominatorTree::Node *DTNode,
316 PropertySet &KnownProperties);
317
318 // For each instruction, add the properties to KnownProperties.
319 void visit(Instruction *I, DominatorTree::Node *, PropertySet &);
320 void visit(TerminatorInst *TI, DominatorTree::Node *, PropertySet &);
321 void visit(BranchInst *BI, DominatorTree::Node *, PropertySet &);
322 void visit(SwitchInst *SI, DominatorTree::Node *, PropertySet);
323 void visit(LoadInst *LI, DominatorTree::Node *, PropertySet &);
324 void visit(StoreInst *SI, DominatorTree::Node *, PropertySet &);
325 void visit(BinaryOperator *BO, DominatorTree::Node *, PropertySet &);
326
327 DominatorTree *DT;
328 bool modified;
329 };
330
331 RegisterPass<PredicateSimplifier> X("predsimplify",
332 "Predicate Simplifier");
333}
334
335FunctionPass *llvm::createPredicateSimplifierPass() {
336 return new PredicateSimplifier();
337}
338
339bool PredicateSimplifier::runOnFunction(Function &F) {
340 DT = &getAnalysis<DominatorTree>();
341
342 modified = false;
343 PropertySet KnownProperties;
344 visitBasicBlock(DT->getRootNode(), KnownProperties);
345 return modified;
346}
347
348void PredicateSimplifier::getAnalysisUsage(AnalysisUsage &AU) const {
349 AU.addRequired<DominatorTree>();
350}
351
352// resolve catches cases addProperty won't because it wasn't used as a
353// condition in the branch, and that visit won't, because the instruction
354// was defined outside of the range that the properties apply to.
355Value *PredicateSimplifier::resolve(SetCondInst *SCI,
356 const PropertySet &KP) {
357 // Attempt to resolve the SetCondInst to a boolean.
358
359 Value *SCI0 = SCI->getOperand(0),
360 *SCI1 = SCI->getOperand(1);
361 PropertySet::ConstPropertyIterator NE =
362 KP.findProperty(PropertySet::NE, SCI0, SCI1);
363
364 if (NE != KP.Properties.end()) {
365 switch (SCI->getOpcode()) {
366 case Instruction::SetEQ:
367 return ConstantBool::False;
368 case Instruction::SetNE:
369 return ConstantBool::True;
370 case Instruction::SetLE:
371 case Instruction::SetGE:
372 case Instruction::SetLT:
373 case Instruction::SetGT:
374 break;
375 default:
376 assert(0 && "Unknown opcode in SetCondInst.");
377 break;
378 }
379 }
380
381 SCI0 = KP.canonicalize(SCI0);
382 SCI1 = KP.canonicalize(SCI1);
383
384 ConstantIntegral *CI1 = dyn_cast<ConstantIntegral>(SCI0),
385 *CI2 = dyn_cast<ConstantIntegral>(SCI1);
386
387 if (!CI1 || !CI2) return SCI;
388
389 switch(SCI->getOpcode()) {
390 case Instruction::SetLE:
391 case Instruction::SetGE:
392 case Instruction::SetEQ:
393 if (CI1->getRawValue() == CI2->getRawValue())
394 return ConstantBool::True;
395 else
396 return ConstantBool::False;
397 case Instruction::SetLT:
398 case Instruction::SetGT:
399 case Instruction::SetNE:
400 if (CI1->getRawValue() == CI2->getRawValue())
401 return ConstantBool::False;
402 else
403 return ConstantBool::True;
404 default:
405 assert(0 && "Unknown opcode in SetContInst.");
406 break;
407 }
408}
409
410Value *PredicateSimplifier::resolve(BinaryOperator *BO,
411 const PropertySet &KP) {
412 if (SetCondInst *SCI = dyn_cast<SetCondInst>(BO))
413 return resolve(SCI, KP);
414
415 DEBUG(std::cerr << "BO->getOperand(1) = " << *BO->getOperand(1) << "\n");
416
417 Value *lhs = resolve(BO->getOperand(0), KP),
418 *rhs = resolve(BO->getOperand(1), KP);
419 ConstantIntegral *CI1 = dyn_cast<ConstantIntegral>(lhs);
420 ConstantIntegral *CI2 = dyn_cast<ConstantIntegral>(rhs);
421
422 DEBUG(std::cerr << "resolveBO: lhs = " << *lhs
423 << ", rhs = " << *rhs << "\n");
424 if (CI1) DEBUG(std::cerr << "CI1 = " << *CI1);
425 if (CI2) DEBUG(std::cerr << "CI2 = " << *CI2);
426
427 if (!CI1 || !CI2) return BO;
428
429 Value *V = ConstantExpr::get(BO->getOpcode(), CI1, CI2);
430 if (V) return V;
431 return BO;
432}
433
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000434Value *PredicateSimplifier::resolve(SelectInst *SI, const PropertySet &KP) {
435 Value *Condition = resolve(SI->getCondition(), KP);
436 if (Condition == ConstantBool::True)
437 return resolve(SI->getTrueValue(), KP);
438 else if (Condition == ConstantBool::False)
439 return resolve(SI->getFalseValue(), KP);
440 return SI;
441}
442
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000443Value *PredicateSimplifier::resolve(Value *V, const PropertySet &KP) {
444 if (isa<Constant>(V) || isa<BasicBlock>(V) || KP.empty()) return V;
445
446 V = KP.canonicalize(V);
447
448 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(V))
449 return resolve(BO, KP);
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000450 else if (SelectInst *SI = dyn_cast<SelectInst>(V))
451 return resolve(SI, KP);
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000452
453 return V;
454}
455
456void PredicateSimplifier::visitBasicBlock(DominatorTree::Node *DTNode,
457 PropertySet &KnownProperties) {
458 BasicBlock *BB = DTNode->getBlock();
459 for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
460 visit(I, DTNode, KnownProperties);
461 }
462}
463
464void PredicateSimplifier::visit(Instruction *I, DominatorTree::Node *DTNode,
465 PropertySet &KnownProperties) {
466 DEBUG(std::cerr << "Considering instruction " << *I << "\n");
467 DEBUG(KnownProperties.debug(std::cerr));
468
469 // Substitute values known to be equal.
470 for (unsigned i = 0, E = I->getNumOperands(); i != E; ++i) {
471 Value *Oper = I->getOperand(i);
472 Value *V = resolve(Oper, KnownProperties);
473 assert(V && "resolve not supposed to return NULL.");
474 if (V != Oper) {
475 modified = true;
476 ++NumVarsReplaced;
477 DEBUG(std::cerr << "resolving " << *I);
478 I->setOperand(i, V);
479 DEBUG(std::cerr << "into " << *I);
480 }
481 }
482
483 Value *V = resolve(I, KnownProperties);
484 assert(V && "resolve not supposed to return NULL.");
485 if (V != I) {
486 modified = true;
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000487 ++NumInstruction;
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000488 I->replaceAllUsesWith(V);
489 I->eraseFromParent();
490 }
491
492 if (TerminatorInst *TI = dyn_cast<TerminatorInst>(I))
493 visit(TI, DTNode, KnownProperties);
494 else if (LoadInst *LI = dyn_cast<LoadInst>(I))
495 visit(LI, DTNode, KnownProperties);
496 else if (StoreInst *SI = dyn_cast<StoreInst>(I))
497 visit(SI, DTNode, KnownProperties);
498 else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(I))
499 visit(BO, DTNode, KnownProperties);
500}
501
502void PredicateSimplifier::proceedToSuccessor(PropertySet &CurrentPS,
503 PropertySet &NextPS, DominatorTree::Node *Current,
504 DominatorTree::Node *Next) {
505 if (Next->getBlock()->getSinglePredecessor() == Current->getBlock())
506 proceedToSuccessor(NextPS, Current, Next);
507 else
508 proceedToSuccessor(CurrentPS, Current, Next);
509}
510
511void PredicateSimplifier::proceedToSuccessor(PropertySet &KP,
512 DominatorTree::Node *Current, DominatorTree::Node *Next) {
513 if (Current->properlyDominates(Next))
514 visitBasicBlock(Next, KP);
515}
516
517void PredicateSimplifier::visit(TerminatorInst *TI,
518 DominatorTree::Node *Node, PropertySet &KP){
519 if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
520 visit(BI, Node, KP);
521 return;
522 }
523 if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
524 visit(SI, Node, KP);
525 return;
526 }
527
528 for (unsigned i = 0, E = TI->getNumSuccessors(); i != E; ++i) {
529 BasicBlock *BB = TI->getSuccessor(i);
530 PropertySet KPcopy(KP);
531 proceedToSuccessor(KPcopy, Node, DT->getNode(TI->getSuccessor(i)));
532 }
533}
534
535void PredicateSimplifier::visit(BranchInst *BI,
536 DominatorTree::Node *Node, PropertySet &KP){
537 if (BI->isUnconditional()) {
538 proceedToSuccessor(KP, Node, DT->getNode(BI->getSuccessor(0)));
539 return;
540 }
541
542 Value *Condition = BI->getCondition();
543
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000544 BasicBlock *TrueDest = BI->getSuccessor(0),
545 *FalseDest = BI->getSuccessor(1);
546
547 if (Condition == ConstantBool::True) {
548 FalseDest->removePredecessor(BI->getParent());
549 BI->setUnconditionalDest(TrueDest);
550 modified = true;
551 ++NumBranches;
552 proceedToSuccessor(KP, Node, DT->getNode(TrueDest));
553 return;
554 } else if (Condition == ConstantBool::False) {
555 TrueDest->removePredecessor(BI->getParent());
556 BI->setUnconditionalDest(FalseDest);
557 modified = true;
558 ++NumBranches;
559 proceedToSuccessor(KP, Node, DT->getNode(FalseDest));
560 return;
561 }
562
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000563 PropertySet TrueProperties(KP), FalseProperties(KP);
564 DEBUG(std::cerr << "true set:\n");
565 TrueProperties.addEqual(ConstantBool::True, Condition);
Nick Lewycky08674ab2006-08-31 00:39:16 +0000566 DEBUG(TrueProperties.debug(std::cerr));
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000567 DEBUG(std::cerr << "false set:\n");
568 FalseProperties.addEqual(ConstantBool::False, Condition);
Nick Lewycky08674ab2006-08-31 00:39:16 +0000569 DEBUG(FalseProperties.debug(std::cerr));
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000570
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000571 PropertySet KPcopy(KP);
572 proceedToSuccessor(KP, TrueProperties, Node, DT->getNode(TrueDest));
573 proceedToSuccessor(KPcopy, FalseProperties, Node, DT->getNode(FalseDest));
574}
575
576void PredicateSimplifier::visit(SwitchInst *SI,
577 DominatorTree::Node *DTNode, PropertySet KP) {
578 Value *Condition = SI->getCondition();
Nick Lewyckyf6f529d2006-09-01 03:26:35 +0000579 DEBUG(assert(Condition == KP.canonicalize(Condition) &&
580 "Instruction wasn't already canonicalized?"));
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000581
582 // If there's an NEProperty covering this SwitchInst, we may be able to
583 // eliminate one of the cases.
Nick Lewyckyf6f529d2006-09-01 03:26:35 +0000584 for (PropertySet::ConstPropertyIterator I = KP.Properties.begin(),
585 E = KP.Properties.end(); I != E; ++I) {
586 if (I->Opcode != PropertySet::NE) continue;
587 Value *V1 = KP.canonicalize(I->V1),
588 *V2 = KP.canonicalize(I->V2);
589 if (V1 != Condition && V2 != Condition) continue;
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000590
Nick Lewyckyf6f529d2006-09-01 03:26:35 +0000591 // Is one side a number?
592 ConstantInt *CI = dyn_cast<ConstantInt>(KP.canonicalize(I->V1));
593 if (!CI) CI = dyn_cast<ConstantInt>(KP.canonicalize(I->V2));
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000594
Nick Lewyckyf6f529d2006-09-01 03:26:35 +0000595 if (CI) {
596 unsigned i = SI->findCaseValue(CI);
597 if (i != 0) {
598 SI->getSuccessor(i)->removePredecessor(SI->getParent());
599 SI->removeCase(i);
600 modified = true;
601 ++NumSwitchCases;
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000602 }
603 }
604 }
605
606 // Set the EQProperty in each of the cases BBs,
607 // and the NEProperties in the default BB.
608 PropertySet DefaultProperties(KP);
609
610 DominatorTree::Node *Node = DT->getNode(SI->getParent()),
611 *DefaultNode = DT->getNode(SI->getSuccessor(0));
612 if (!Node->dominates(DefaultNode)) DefaultNode = NULL;
613
614 for (unsigned I = 1, E = SI->getNumCases(); I < E; ++I) {
615 ConstantInt *CI = SI->getCaseValue(I);
616
617 BasicBlock *SuccBB = SI->getSuccessor(I);
618 PropertySet copy(KP);
619 if (SuccBB->getSinglePredecessor()) {
620 PropertySet NewProperties(KP);
621 NewProperties.addEqual(Condition, CI);
622 proceedToSuccessor(copy, NewProperties, DTNode, DT->getNode(SuccBB));
623 } else
624 proceedToSuccessor(copy, DTNode, DT->getNode(SuccBB));
625
626 if (DefaultNode)
627 DefaultProperties.addNotEqual(Condition, CI);
628 }
629
630 if (DefaultNode)
631 proceedToSuccessor(DefaultProperties, DTNode, DefaultNode);
632}
633
634void PredicateSimplifier::visit(LoadInst *LI,
635 DominatorTree::Node *, PropertySet &KP) {
636 Value *Ptr = LI->getPointerOperand();
637 KP.addNotEqual(Constant::getNullValue(Ptr->getType()), Ptr);
638}
639
640void PredicateSimplifier::visit(StoreInst *SI,
641 DominatorTree::Node *, PropertySet &KP) {
642 Value *Ptr = SI->getPointerOperand();
643 KP.addNotEqual(Constant::getNullValue(Ptr->getType()), Ptr);
644}
645
646void PredicateSimplifier::visit(BinaryOperator *BO,
647 DominatorTree::Node *, PropertySet &KP) {
648 Instruction::BinaryOps ops = BO->getOpcode();
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000649
Nick Lewycky5f8f9af2006-08-30 02:46:48 +0000650 switch (ops) {
651 case Instruction::Div:
652 case Instruction::Rem: {
653 Value *Divisor = BO->getOperand(1);
654 KP.addNotEqual(Constant::getNullValue(Divisor->getType()), Divisor);
655 break;
656 }
657 default:
658 break;
659 }
Nick Lewyckyb2e8ae12006-08-28 22:44:55 +0000660
661 // Some other things we could do:
662 // In f=x*y, if x != 1 && y != 1 then f != x && f != y.
663 // In f=x+y, if x != 0 then f != y and if y != 0 then f != x.
664}