From evan.cheng at apple.com Mon Jun 4 01:41:49 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 4 Jun 2007 01:41:49 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/MachineBasicBlock.h Message-ID: <200706040641.l546fnUK008447@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: MachineBasicBlock.h updated: 1.64 -> 1.65 --- Log message: Move ReplaceUsesOfBlockWith() out of BranchFolding into a MachineBasicBlock general facility. --- Diffs of the changes: (+4 -0) MachineBasicBlock.h | 4 ++++ 1 files changed, 4 insertions(+) Index: llvm/include/llvm/CodeGen/MachineBasicBlock.h diff -u llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.64 llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.65 --- llvm/include/llvm/CodeGen/MachineBasicBlock.h:1.64 Thu May 17 18:58:52 2007 +++ llvm/include/llvm/CodeGen/MachineBasicBlock.h Mon Jun 4 01:41:17 2007 @@ -246,6 +246,10 @@ Insts.splice(where, Other->Insts, From, To); } + /// ReplaceUsesOfBlockWith - Given a machine basic block that branched to + /// 'Old', change the code and CFG so that it branches to 'New' instead. + void ReplaceUsesOfBlockWith(MachineBasicBlock *Old, MachineBasicBlock *New); + // Debugging methods. void dump() const; void print(std::ostream &OS) const; From evan.cheng at apple.com Mon Jun 4 01:44:23 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 4 Jun 2007 01:44:23 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/BranchFolding.cpp MachineBasicBlock.cpp Message-ID: <200706040644.l546iNlE008544@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: BranchFolding.cpp updated: 1.63 -> 1.64 MachineBasicBlock.cpp updated: 1.45 -> 1.46 --- Log message: Move ReplaceUsesOfBlockWith() out of BranchFolding into a MachineBasicBlock general facility. --- Diffs of the changes: (+29 -40) BranchFolding.cpp | 42 ++---------------------------------------- MachineBasicBlock.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 40 deletions(-) Index: llvm/lib/CodeGen/BranchFolding.cpp diff -u llvm/lib/CodeGen/BranchFolding.cpp:1.63 llvm/lib/CodeGen/BranchFolding.cpp:1.64 --- llvm/lib/CodeGen/BranchFolding.cpp:1.63 Fri Jun 1 19:08:15 2007 +++ llvm/lib/CodeGen/BranchFolding.cpp Mon Jun 4 01:44:01 2007 @@ -733,44 +733,6 @@ } -/// ReplaceUsesOfBlockWith - Given a machine basic block 'BB' that branched to -/// 'Old', change the code and CFG so that it branches to 'New' instead. -static void ReplaceUsesOfBlockWith(MachineBasicBlock *BB, - MachineBasicBlock *Old, - MachineBasicBlock *New, - const TargetInstrInfo *TII) { - assert(Old != New && "Cannot replace self with self!"); - - MachineBasicBlock::iterator I = BB->end(); - while (I != BB->begin()) { - --I; - if (!TII->isTerminatorInstr(I->getOpcode())) break; - - // Scan the operands of this machine instruction, replacing any uses of Old - // with New. - for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) - if (I->getOperand(i).isMachineBasicBlock() && - I->getOperand(i).getMachineBasicBlock() == Old) - I->getOperand(i).setMachineBasicBlock(New); - } - - // Update the successor information. If New was already a successor, just - // remove the link to Old instead of creating another one. PR 1444. - bool HadSuccessorNew = false; - std::vector Succs(BB->succ_begin(), BB->succ_end()); - for (int i = Succs.size()-1; i >= 0; --i) - if (Succs[i] == New) { - HadSuccessorNew = true; - break; - } - for (int i = Succs.size()-1; i >= 0; --i) - if (Succs[i] == Old) { - BB->removeSuccessor(Old); - if (!HadSuccessorNew) - BB->addSuccessor(New); - } -} - /// CanFallThrough - Return true if the specified block (with the specified /// branch condition) can implicitly transfer control to the block after it by /// falling off the end of it. This should return false if it can reach the @@ -865,7 +827,7 @@ // instead. while (!MBB->pred_empty()) { MachineBasicBlock *Pred = *(MBB->pred_end()-1); - ReplaceUsesOfBlockWith(Pred, MBB, FallThrough, TII); + Pred->ReplaceUsesOfBlockWith(MBB, FallThrough); } // If MBB was the target of a jump table, update jump tables to go to the @@ -1066,7 +1028,7 @@ HasBranchToSelf = true; } else { DidChange = true; - ReplaceUsesOfBlockWith(*PI, MBB, CurTBB, TII); + (*PI)->ReplaceUsesOfBlockWith(MBB, CurTBB); } } Index: llvm/lib/CodeGen/MachineBasicBlock.cpp diff -u llvm/lib/CodeGen/MachineBasicBlock.cpp:1.45 llvm/lib/CodeGen/MachineBasicBlock.cpp:1.46 --- llvm/lib/CodeGen/MachineBasicBlock.cpp:1.45 Thu May 17 18:58:53 2007 +++ llvm/lib/CodeGen/MachineBasicBlock.cpp Mon Jun 4 01:44:01 2007 @@ -198,3 +198,30 @@ std::find(Successors.begin(), Successors.end(), MBB); return I != Successors.end(); } + +/// ReplaceUsesOfBlockWith - Given a machine basic block that branched to +/// 'Old', change the code and CFG so that it branches to 'New' instead. +void MachineBasicBlock::ReplaceUsesOfBlockWith(MachineBasicBlock *Old, + MachineBasicBlock *New) { + assert(Old != New && "Cannot replace self with self!"); + + MachineBasicBlock::iterator I = end(); + while (I != begin()) { + --I; + if (!(I->getInstrDescriptor()->Flags & M_TERMINATOR_FLAG)) break; + + // Scan the operands of this machine instruction, replacing any uses of Old + // with New. + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) + if (I->getOperand(i).isMachineBasicBlock() && + I->getOperand(i).getMachineBasicBlock() == Old) + I->getOperand(i).setMachineBasicBlock(New); + } + + // Update the successor information. If New was already a successor, just + // remove the link to Old instead of creating another one. PR 1444. + removeSuccessor(Old); + if (!isSuccessor(New)) + addSuccessor(New); +} + From evan.cheng at apple.com Mon Jun 4 01:47:44 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 4 Jun 2007 01:47:44 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706040647.l546liMO008639@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.21 -> 1.22 --- Log message: Let IfConverter loose. Allow more aggressive subsumptions; reorder basic blocks to expose more ifcvt opportunities; code clean up and fixes. --- Diffs of the changes: (+264 -196) IfConversion.cpp | 460 +++++++++++++++++++++++++++++++------------------------ 1 files changed, 264 insertions(+), 196 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.21 llvm/lib/CodeGen/IfConversion.cpp:1.22 --- llvm/lib/CodeGen/IfConversion.cpp:1.21 Fri Jun 1 15:29:21 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Mon Jun 4 01:47:22 2007 @@ -24,6 +24,10 @@ #include "llvm/ADT/Statistic.h" using namespace llvm; +STATISTIC(NumSimple, "Number of simple if-conversions performed"); +STATISTIC(NumSimpleRev, "Number of simple (reversed) if-conversions performed"); +STATISTIC(NumTriangle, "Number of triangle if-conversions performed"); +STATISTIC(NumDiamonds, "Number of diamond if-conversions performed"); STATISTIC(NumIfConvBBs, "Number of if-converted blocks"); namespace { @@ -32,8 +36,8 @@ ICNotAnalyzed, // BB has not been analyzed. ICReAnalyze, // BB must be re-analyzed. ICNotClassfied, // BB data valid, but not classified. - ICEarlyExit, // BB is entry of an early-exit sub-CFG. - ICEarlyExitFalse,// Same as ICEarlyExit, but on the false path. + ICSimple, // BB is entry of an one split, no rejoin sub-CFG. + ICSimpleFalse, // Same as ICSimple, but on the false path. ICTriangle, // BB is entry of a triangle sub-CFG. ICDiamond, // BB is entry of a diamond sub-CFG. ICChild, // BB is part of the sub-CFG that'll be predicated. @@ -49,8 +53,7 @@ /// /// Kind - Type of block. See BBICKind. /// NonPredSize - Number of non-predicated instructions. - /// isPredicable - Is it predicable. (FIXME: Remove.) - /// hasEarlyExit - Ends with a return, indirect jump or br to jumptable. + /// IsAnalyzable - True if AnalyzeBranch() returns false. /// ModifyPredicate - FIXME: Not used right now. True if BB would modify /// the predicate (e.g. has cmp, call, etc.) /// BB - Corresponding MachineBasicBlock. @@ -60,8 +63,7 @@ struct BBInfo { BBICKind Kind; unsigned NonPredSize; - bool isPredicable; - bool hasEarlyExit; + bool IsAnalyzable; bool ModifyPredicate; MachineBasicBlock *BB; MachineBasicBlock *TrueBB; @@ -69,8 +71,8 @@ MachineBasicBlock *TailBB; std::vector BrCond; std::vector Predicate; - BBInfo() : Kind(ICNotAnalyzed), NonPredSize(0), isPredicable(false), - hasEarlyExit(false), ModifyPredicate(false), + BBInfo() : Kind(ICNotAnalyzed), NonPredSize(0), + IsAnalyzable(false), ModifyPredicate(false), BB(0), TrueBB(0), FalseBB(0), TailBB(0) {} }; @@ -93,14 +95,16 @@ virtual const char *getPassName() const { return "If converter"; } private: + bool ReverseBranchCondition(BBInfo &BBI); void StructuralAnalysis(MachineBasicBlock *BB); - void FeasibilityAnalysis(BBInfo &BBI, - std::vector &Cond); + bool FeasibilityAnalysis(BBInfo &BBI, + std::vector &Cond, + bool IgnoreTerm = false); bool AttemptRestructuring(BBInfo &BBI); bool AnalyzeBlocks(MachineFunction &MF, std::vector &Candidates); void ReTryPreds(MachineBasicBlock *BB); - bool IfConvertEarlyExit(BBInfo &BBI); + bool IfConvertSimple(BBInfo &BBI); bool IfConvertTriangle(BBInfo &BBI); bool IfConvertDiamond(BBInfo &BBI); void PredicateBlock(BBInfo &BBI, @@ -137,39 +141,49 @@ std::vector Candidates; MadeChange = false; while (true) { - bool Change = false; - // Do an intial analysis for each basic block and finding all the potential // candidates to perform if-convesion. - Change |= AnalyzeBlocks(MF, Candidates); + bool Change = AnalyzeBlocks(MF, Candidates); while (!Candidates.empty()) { BBInfo &BBI = *Candidates.back(); Candidates.pop_back(); + + bool RetVal = false; switch (BBI.Kind) { default: assert(false && "Unexpected!"); break; case ICReAnalyze: // One or more of 'childrean' have been modified, abort! break; - case ICEarlyExit: - case ICEarlyExitFalse: - DOUT << "Ifcvt (Early exit): BB#" << BBI.BB->getNumber() << "\n"; - Change |= IfConvertEarlyExit(BBI); - break; + case ICSimple: + case ICSimpleFalse: + DOUT << "Ifcvt (Simple" << (BBI.Kind == ICSimpleFalse ? " false" : "") + << "): BB#" << BBI.BB->getNumber() << " "; + RetVal = IfConvertSimple(BBI); + DOUT << (RetVal ? "succeeded!" : "failed!") << "\n"; + if (RetVal) + if (BBI.Kind == ICSimple) NumSimple++; + else NumSimpleRev++; + break; case ICTriangle: - DOUT << "Ifcvt (Triangle): BB#" << BBI.BB->getNumber() << "\n"; - Change |= IfConvertTriangle(BBI); + DOUT << "Ifcvt (Triangle): BB#" << BBI.BB->getNumber() << " "; + RetVal = IfConvertTriangle(BBI); + DOUT << (RetVal ? "succeeded!" : "failed!") << "\n"; + if (RetVal) NumTriangle++; break; case ICDiamond: - DOUT << "Ifcvt (Diamond): BB#" << BBI.BB->getNumber() << "\n"; - Change |= IfConvertDiamond(BBI); + DOUT << "Ifcvt (Diamond): BB#" << BBI.BB->getNumber() << " "; + RetVal = IfConvertDiamond(BBI); + DOUT << (RetVal ? "succeeded!" : "failed!") << "\n"; + if (RetVal) NumDiamonds++; break; } + Change |= RetVal; } - MadeChange |= Change; if (!Change) break; + MadeChange |= Change; } Roots.clear(); @@ -189,13 +203,25 @@ return NULL; } +bool IfConverter::ReverseBranchCondition(BBInfo &BBI) { + if (!TII->ReverseBranchCondition(BBI.BrCond)) { + TII->RemoveBranch(*BBI.BB); + TII->InsertBranch(*BBI.BB, BBI.FalseBB, BBI.TrueBB, BBI.BrCond); + std::swap(BBI.TrueBB, BBI.FalseBB); + return true; + } + return false; +} + /// StructuralAnalysis - Analyze the structure of the sub-CFG starting from /// the specified block. Record its successors and whether it looks like an /// if-conversion candidate. void IfConverter::StructuralAnalysis(MachineBasicBlock *BB) { BBInfo &BBI = BBAnalysis[BB->getNumber()]; - if (BBI.Kind != ICReAnalyze) { + if (BBI.Kind == ICReAnalyze) + BBI.BrCond.clear(); + else { if (BBI.Kind != ICNotAnalyzed) return; // Already analyzed. BBI.BB = BB; @@ -204,57 +230,64 @@ // Look for 'root' of a simple (non-nested) triangle or diamond. BBI.Kind = ICNotClassfied; - bool CanAnalyze = !TII->AnalyzeBranch(*BB, BBI.TrueBB, BBI.FalseBB, - BBI.BrCond); - // Does it end with a return, indirect jump, or jumptable branch? - BBI.hasEarlyExit = TII->BlockHasNoFallThrough(*BB) && !BBI.TrueBB; - if (!CanAnalyze || !BBI.TrueBB || BBI.BrCond.size() == 0) + BBI.IsAnalyzable = + !TII->AnalyzeBranch(*BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond); + if (!BBI.IsAnalyzable || BBI.BrCond.size() == 0) return; - // Not a candidate if 'true' block is going to be if-converted. StructuralAnalysis(BBI.TrueBB); BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; - // TODO: Only handle very simple cases for now. - if (TrueBBI.FalseBB || TrueBBI.BrCond.size()) - return; - // No false branch. This BB must end with a conditional branch and a // fallthrough. if (!BBI.FalseBB) BBI.FalseBB = findFalseBlock(BB, BBI.TrueBB); assert(BBI.FalseBB && "Expected to find the fallthrough block!"); - // Not a candidate if 'false' block is going to be if-converted. StructuralAnalysis(BBI.FalseBB); BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; - - // TODO: Only handle very simple cases for now. - if (FalseBBI.FalseBB || FalseBBI.BrCond.size()) - return; - - unsigned TrueNumPreds = BBI.TrueBB->pred_size(); - unsigned FalseNumPreds = BBI.FalseBB->pred_size(); - if ((TrueBBI.hasEarlyExit && TrueNumPreds <= 1) && - !(FalseBBI.hasEarlyExit && FalseNumPreds <=1)) { - BBI.Kind = ICEarlyExit; - TrueBBI.Kind = ICChild; - } else if (!(TrueBBI.hasEarlyExit && TrueNumPreds <= 1) && - (FalseBBI.hasEarlyExit && FalseNumPreds <=1)) { - BBI.Kind = ICEarlyExitFalse; - FalseBBI.Kind = ICChild; - } else if (TrueBBI.TrueBB && TrueBBI.TrueBB == BBI.FalseBB) { - // Triangle: - // EBB - // | \_ - // | | - // | TBB - // | / - // FBB - BBI.Kind = ICTriangle; - TrueBBI.Kind = FalseBBI.Kind = ICChild; - } else if (TrueBBI.TrueBB == FalseBBI.TrueBB && - TrueNumPreds <= 1 && FalseNumPreds <= 1) { + + // Look for more opportunities to if-convert a triangle. Try to restructure + // the CFG to form a triangle with the 'false' path. + std::vector RevCond(BBI.BrCond); + bool CanRevCond = !TII->ReverseBranchCondition(RevCond); + if (FalseBBI.FalseBB) { + if (TrueBBI.TrueBB && TrueBBI.TrueBB == BBI.FalseBB) + return; + std::vector Cond(BBI.BrCond); + if (CanRevCond && + FalseBBI.TrueBB && FalseBBI.BB->pred_size() == 1 && + FeasibilityAnalysis(FalseBBI, RevCond, true)) { + std::vector FalseCond(FalseBBI.BrCond); + if (FalseBBI.TrueBB == BBI.TrueBB && + TII->SubsumesPredicate(FalseCond, BBI.BrCond)) { + // Reverse 'true' and 'false' paths. + ReverseBranchCondition(BBI); + BBI.Kind = ICTriangle; + FalseBBI.Kind = ICChild; + } else if (FalseBBI.FalseBB == BBI.TrueBB && + !TII->ReverseBranchCondition(FalseCond) && + TII->SubsumesPredicate(FalseCond, BBI.BrCond)) { + // Reverse 'false' block's 'true' and 'false' paths and then + // reverse 'true' and 'false' paths. + ReverseBranchCondition(FalseBBI); + ReverseBranchCondition(BBI); + BBI.Kind = ICTriangle; + FalseBBI.Kind = ICChild; + } + } + } else if (TrueBBI.TrueBB == FalseBBI.TrueBB && CanRevCond && + TrueBBI.BB->pred_size() == 1 && + TrueBBI.BB->pred_size() == 1 && + // Check the 'true' and 'false' blocks if either isn't ended with + // a branch. If the block does not fallthrough to another block + // then we need to add a branch to its successor. + !(TrueBBI.ModifyPredicate && + !TrueBBI.TrueBB && TrueBBI.BB->succ_size()) && + !(FalseBBI.ModifyPredicate && + !FalseBBI.TrueBB && FalseBBI.BB->succ_size()) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond) && + FeasibilityAnalysis(FalseBBI, RevCond)) { // Diamond: // EBB // / \_ @@ -266,6 +299,44 @@ BBI.Kind = ICDiamond; TrueBBI.Kind = FalseBBI.Kind = ICChild; BBI.TailBB = TrueBBI.TrueBB; + } else { + // FIXME: Consider duplicating if BB is small. + bool TryTriangle = TrueBBI.TrueBB && TrueBBI.TrueBB == BBI.FalseBB && + BBI.TrueBB->pred_size() == 1; + bool TrySimple = TrueBBI.BrCond.size() == 0 && BBI.TrueBB->pred_size() == 1; + if ((TryTriangle || TrySimple) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond)) { + if (TryTriangle) { + // Triangle: + // EBB + // | \_ + // | | + // | TBB + // | / + // FBB + BBI.Kind = ICTriangle; + TrueBBI.Kind = ICChild; + } else { + // Simple (split, no rejoin): + // EBB + // | \_ + // | | + // | TBB---> exit + // | + // FBB + BBI.Kind = ICSimple; + TrueBBI.Kind = ICChild; + } + } else if (FalseBBI.BrCond.size() == 0 && BBI.FalseBB->pred_size() == 1) { + // Try 'simple' on the other path... + std::vector RevCond(BBI.BrCond); + if (TII->ReverseBranchCondition(RevCond)) + assert(false && "Unable to reverse branch condition!"); + if (FeasibilityAnalysis(FalseBBI, RevCond)) { + BBI.Kind = ICSimpleFalse; + FalseBBI.Kind = ICChild; + } + } } return; } @@ -274,25 +345,37 @@ /// cases, that means all the instructions in the block has M_PREDICABLE flag. /// Also checks if the block contains any instruction which can clobber a /// predicate (e.g. condition code register). If so, the block is not -/// predicable unless it's the last instruction. Note, this function assumes -/// all the terminator instructions can be converted or deleted so it ignore -/// them. -void IfConverter::FeasibilityAnalysis(BBInfo &BBI, - std::vector &Cond) { +/// predicable unless it's the last instruction. If IgnoreTerm is true then +/// all the terminator instructions are skipped. +bool IfConverter::FeasibilityAnalysis(BBInfo &BBI, + std::vector &Cond, + bool IgnoreTerm) { + // If the block is dead, or it is going to be the entry block of a sub-CFG + // that will be if-converted, then it cannot be predicated. + if (BBI.Kind != ICNotAnalyzed && + BBI.Kind != ICNotClassfied && + BBI.Kind != ICChild) + return false; + + // Check predication threshold. if (BBI.NonPredSize == 0 || BBI.NonPredSize > TLI->getIfCvtBlockSizeLimit()) - return; + return false; + + // If it is already predicated, check if its predicate subsumes the new + // predicate. + if (BBI.Predicate.size() && !TII->SubsumesPredicate(BBI.Predicate, Cond)) + return false; for (MachineBasicBlock::iterator I = BBI.BB->begin(), E = BBI.BB->end(); I != E; ++I) { + if (IgnoreTerm && TII->isTerminatorInstr(I->getOpcode())) + continue; // TODO: check if instruction clobbers predicate. if (!I->isPredicable()) - return; + return false; } - if (BBI.Predicate.size() && !TII->SubsumesPredicate(BBI.Predicate, Cond)) - return; - - BBI.isPredicable = true; + return true; } /// AttemptRestructuring - Restructure the sub-CFG rooted in the given block to @@ -336,8 +419,8 @@ StructuralAnalysis(BB); BBInfo &BBI = BBAnalysis[BB->getNumber()]; switch (BBI.Kind) { - case ICEarlyExit: - case ICEarlyExitFalse: + case ICSimple: + case ICSimpleFalse: case ICTriangle: case ICDiamond: Candidates.push_back(&BBI); @@ -355,37 +438,14 @@ return Change; } -/// TransferPreds - Transfer all the predecessors of FromBB to ToBB. -/// -static void TransferPreds(MachineBasicBlock *ToBB, MachineBasicBlock *FromBB) { - std::vector Preds(FromBB->pred_begin(), - FromBB->pred_end()); - for (unsigned i = 0, e = Preds.size(); i != e; ++i) { - MachineBasicBlock *Pred = Preds[i]; - Pred->removeSuccessor(FromBB); - if (!Pred->isSuccessor(ToBB)) - Pred->addSuccessor(ToBB); - } -} - -/// TransferSuccs - Transfer all the successors of FromBB to ToBB. -/// -static void TransferSuccs(MachineBasicBlock *ToBB, MachineBasicBlock *FromBB) { - std::vector Succs(FromBB->succ_begin(), - FromBB->succ_end()); - for (unsigned i = 0, e = Succs.size(); i != e; ++i) { - MachineBasicBlock *Succ = Succs[i]; - FromBB->removeSuccessor(Succ); - if (!ToBB->isSuccessor(Succ)) - ToBB->addSuccessor(Succ); - } -} - -/// isNextBlock - Returns true if ToBB the next basic block after BB. -/// +/// isNextBlock - Returns true either if ToBB the next block after BB or +/// that all the intervening blocks are empty. static bool isNextBlock(MachineBasicBlock *BB, MachineBasicBlock *ToBB) { - MachineFunction::iterator Fallthrough = BB; - return MachineFunction::iterator(ToBB) == ++Fallthrough; + MachineFunction::iterator I = BB; + while (++I != MachineFunction::iterator(ToBB)) + if (!I->empty()) + return false; + return true; } /// ReTryPreds - Invalidate predecessor BB info so it would be re-analyzed @@ -406,10 +466,10 @@ TII->InsertBranch(*BB, ToBB, NULL, NoCond); } -/// IfConvertEarlyExit - If convert a early exit sub-CFG. +/// IfConvertSimple - If convert a simple (split, no rejoin) sub-CFG. /// -bool IfConverter::IfConvertEarlyExit(BBInfo &BBI) { - bool ReverseCond = BBI.Kind == ICEarlyExitFalse; +bool IfConverter::IfConvertSimple(BBInfo &BBI) { + bool ReverseCond = BBI.Kind == ICSimpleFalse; BBI.Kind = ICNotClassfied; @@ -418,25 +478,29 @@ BBInfo *CvtBBI = &TrueBBI; BBInfo *NextBBI = &FalseBBI; - std::vector NewCond(BBI.BrCond); + std::vector Cond(BBI.BrCond); if (ReverseCond) { std::swap(CvtBBI, NextBBI); - TII->ReverseBranchCondition(NewCond); + TII->ReverseBranchCondition(Cond); } - FeasibilityAnalysis(*CvtBBI, NewCond); - if (!CvtBBI->isPredicable) - return false; - PredicateBlock(*CvtBBI, NewCond); + PredicateBlock(*CvtBBI, Cond); + // If the 'true' block ends without a branch, add a conditional branch + // to its successor unless that happens to be the 'false' block. + if (CvtBBI->IsAnalyzable && CvtBBI->TrueBB == NULL) { + assert(CvtBBI->BB->succ_size() == 1 && "Unexpected!"); + MachineBasicBlock *SuccBB = *CvtBBI->BB->succ_begin(); + if (SuccBB != NextBBI->BB) + TII->InsertBranch(*CvtBBI->BB, SuccBB, NULL, Cond); + } - // Merge converted block into entry block. Also convert the end of the - // block conditional branch (to the non-converted block) into an - // unconditional one. + // Merge converted block into entry block. Also add an unconditional branch + // to the 'false' branch. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); MergeBlocks(BBI, *CvtBBI); if (!isNextBlock(BBI.BB, NextBBI->BB)) InsertUncondBranch(BBI.BB, NextBBI->BB, TII); - std::copy(NewCond.begin(), NewCond.end(), std::back_inserter(BBI.Predicate)); + std::copy(Cond.begin(), Cond.end(), std::back_inserter(BBI.Predicate)); // Update block info. BB can be iteratively if-converted. BBI.Kind = ICNotAnalyzed; @@ -447,7 +511,6 @@ CvtBBI->Kind = ICDead; // FIXME: Must maintain LiveIns. - NumIfConvBBs++; return true; } @@ -457,19 +520,12 @@ BBI.Kind = ICNotClassfied; BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; - FeasibilityAnalysis(TrueBBI, BBI.BrCond); - if (!TrueBBI.isPredicable) - return false; - - // FIXME: Consider duplicating if BB is small. - if (BBI.TrueBB->pred_size() > 1) - return false; // Predicate the 'true' block after removing its branch. TrueBBI.NonPredSize -= TII->RemoveBranch(*BBI.TrueBB); PredicateBlock(TrueBBI, BBI.BrCond); - // If 'true' block has a 'false' successor, add a early exit branch to it. + // If 'true' block has a 'false' successor, add an exit branch to it. if (TrueBBI.FalseBB) { std::vector RevCond(TrueBBI.BrCond); if (TII->ReverseBranchCondition(RevCond)) @@ -482,7 +538,7 @@ BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; if (FalseBBI.BB->pred_size() == 2) MergeBlocks(TrueBBI, FalseBBI); - else + else if (!isNextBlock(TrueBBI.BB, FalseBBI.BB)) InsertUncondBranch(TrueBBI.BB, FalseBBI.BB, TII); // Now merge the entry of the triangle with the true block. @@ -500,7 +556,6 @@ TrueBBI.Kind = ICDead; // FIXME: Must maintain LiveIns. - NumIfConvBBs++; return true; } @@ -509,87 +564,66 @@ bool IfConverter::IfConvertDiamond(BBInfo &BBI) { BBI.Kind = ICNotClassfied; - bool TrueNeedBr; - bool FalseNeedBr; - BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; + BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; - FeasibilityAnalysis(TrueBBI, BBI.BrCond); - std::vector RevCond(BBI.BrCond); - TII->ReverseBranchCondition(RevCond); - FeasibilityAnalysis(FalseBBI, RevCond); SmallVector Dups; - bool Proceed = TrueBBI.isPredicable && FalseBBI.isPredicable; - if (Proceed) { - // Check the 'true' and 'false' blocks if either isn't ended with a branch. - // Either the block fallthrough to another block or it ends with a - // return. If it's the former, add a branch to its successor. - TrueNeedBr = !TrueBBI.TrueBB && BBI.TrueBB->succ_size(); - FalseNeedBr = !FalseBBI.TrueBB && BBI.FalseBB->succ_size(); - if (TrueNeedBr && TrueBBI.ModifyPredicate) { - TrueBBI.isPredicable = false; - Proceed = false; - } - if (FalseNeedBr && FalseBBI.ModifyPredicate) { - FalseBBI.isPredicable = false; - Proceed = false; + if (!BBI.TailBB) { + // No common merge block. Check if the terminators (e.g. return) are + // the same or predicable. + MachineBasicBlock::iterator TT = BBI.TrueBB->getFirstTerminator(); + MachineBasicBlock::iterator FT = BBI.FalseBB->getFirstTerminator(); + while (TT != BBI.TrueBB->end() && FT != BBI.FalseBB->end()) { + if (TT->isIdenticalTo(FT)) + Dups.push_back(TT); // Will erase these later. + else if (!TT->isPredicable() && !FT->isPredicable()) + return false; // Can't if-convert. Abort! + ++TT; + ++FT; } - if (Proceed) { - if (!BBI.TailBB) { - // No common merge block. Check if the terminators (e.g. return) are - // the same or predicable. - MachineBasicBlock::iterator TT = BBI.TrueBB->getFirstTerminator(); - MachineBasicBlock::iterator FT = BBI.FalseBB->getFirstTerminator(); - while (TT != BBI.TrueBB->end() && FT != BBI.FalseBB->end()) { - if (TT->isIdenticalTo(FT)) - Dups.push_back(TT); // Will erase these later. - else if (!TT->isPredicable() && !FT->isPredicable()) { - Proceed = false; - break; // Can't if-convert. Abort! - } - ++TT; - ++FT; - } - - // One of the two pathes have more terminators, make sure they are - // all predicable. - while (Proceed && TT != BBI.TrueBB->end()) - if (!TT->isPredicable()) { - Proceed = false; - break; // Can't if-convert. Abort! - } - while (Proceed && FT != BBI.FalseBB->end()) - if (!FT->isPredicable()) { - Proceed = false; - break; // Can't if-convert. Abort! - } + // One of the two pathes have more terminators, make sure they are + // all predicable. + while (TT != BBI.TrueBB->end()) { + if (!TT->isPredicable()) { + return false; // Can't if-convert. Abort! } + ++TT; + } + while (FT != BBI.FalseBB->end()) { + if (!FT->isPredicable()) { + return false; // Can't if-convert. Abort! + } + ++FT; } } - if (!Proceed) - return false; - // Remove the duplicated instructions from the 'true' block. for (unsigned i = 0, e = Dups.size(); i != e; ++i) { Dups[i]->eraseFromParent(); --TrueBBI.NonPredSize; } - // Predicate the 'true' block after removing its branch. - TrueBBI.NonPredSize -= TII->RemoveBranch(*BBI.TrueBB); - PredicateBlock(TrueBBI, BBI.BrCond); - - // Predicate the 'false' block. - PredicateBlock(FalseBBI, RevCond, true); + // Check the 'true' and 'false' blocks if either isn't ended with a branch. + // Either the block fallthrough to another block or it ends with a + // return. If it's the former, add a branch to its successor. + bool TrueNeedBr = !TrueBBI.TrueBB && BBI.TrueBB->succ_size(); + bool FalseNeedBr = !FalseBBI.TrueBB && BBI.FalseBB->succ_size(); // Merge the 'true' and 'false' blocks by copying the instructions // from the 'false' block to the 'true' block. That is, unless the true // block would clobber the predicate, in that case, do the opposite. + std::vector RevCond(BBI.BrCond); + TII->ReverseBranchCondition(RevCond); BBInfo *CvtBBI; if (!TrueBBI.ModifyPredicate) { - // Add a conditional branch from 'true' to 'true' successor if needed. + // Predicate the 'true' block after removing its branch. + TrueBBI.NonPredSize -= TII->RemoveBranch(*BBI.TrueBB); + PredicateBlock(TrueBBI, BBI.BrCond); + + // Predicate the 'false' block. + PredicateBlock(FalseBBI, RevCond, true); + if (TrueNeedBr) TII->InsertBranch(*BBI.TrueBB, *BBI.TrueBB->succ_begin(), NULL, BBI.BrCond); @@ -601,6 +635,13 @@ MergeBlocks(TrueBBI, FalseBBI); CvtBBI = &TrueBBI; } else { + // Predicate the 'false' block after removing its branch. + FalseBBI.NonPredSize -= TII->RemoveBranch(*BBI.FalseBB); + PredicateBlock(FalseBBI, RevCond); + + // Predicate the 'false' block. + PredicateBlock(TrueBBI, BBI.BrCond, true); + // Add a conditional branch from 'false' to 'false' successor if needed. if (FalseNeedBr) TII->InsertBranch(*BBI.FalseBB, *BBI.FalseBB->succ_begin(), NULL, @@ -625,7 +666,7 @@ MergeBlocks(BBI, *CvtBBI); CvtBBI = &BBI; OkToIfcvt = false; - } else + } else if (!isNextBlock(BBI.BB, CvtBBI->BB)) InsertUncondBranch(BBI.BB, CvtBBI->BB, TII); // If the if-converted block fallthrough or unconditionally branch into the @@ -651,7 +692,6 @@ FalseBBI.Kind = ICDead; // FIXME: Must maintain LiveIns. - NumIfConvBBs += 2; return true; } @@ -662,18 +702,41 @@ bool IgnoreTerm) { for (MachineBasicBlock::iterator I = BBI.BB->begin(), E = BBI.BB->end(); I != E; ++I) { - MachineInstr *MI = I; - if (IgnoreTerm && TII->isTerminatorInstr(MI->getOpcode())) + if (IgnoreTerm && TII->isTerminatorInstr(I->getOpcode())) continue; - if (TII->isPredicated(MI)) + if (TII->isPredicated(I)) continue; - if (!TII->PredicateInstruction(MI, Cond)) { + if (!TII->PredicateInstruction(I, Cond)) { cerr << "Unable to predicate " << *I << "!\n"; abort(); } } BBI.NonPredSize = 0; + NumIfConvBBs++; +} + +/// TransferPreds - Transfer all the predecessors of FromBB to ToBB. +/// +static void TransferPreds(MachineBasicBlock *ToBB, MachineBasicBlock *FromBB) { + for (MachineBasicBlock::pred_iterator I = FromBB->pred_begin(), + E = FromBB->pred_end(); I != E; ++I) { + MachineBasicBlock *Pred = *I; + Pred->removeSuccessor(FromBB); + if (!Pred->isSuccessor(ToBB)) + Pred->addSuccessor(ToBB); + } +} + +/// TransferSuccs - Transfer all the successors of FromBB to ToBB. +/// +static void TransferSuccs(MachineBasicBlock *ToBB, MachineBasicBlock *FromBB) { + for (MachineBasicBlock::succ_iterator I = FromBB->succ_begin(), + E = FromBB->succ_end(); I != E; ++I) { + FromBB->removeSuccessor(*I); + if (!ToBB->isSuccessor(*I)) + ToBB->addSuccessor(*I); + } } /// MergeBlocks - Move all instructions from FromBB to the end of ToBB. @@ -687,6 +750,11 @@ if (ToBBI.BB->isSuccessor(FromBBI.BB)) ToBBI.BB->removeSuccessor(FromBBI.BB); + // Redirect all branches to FromBB to ToBB. + for (MachineBasicBlock::pred_iterator I = FromBBI.BB->pred_begin(), + E = FromBBI.BB->pred_end(); I != E; ++I) + (*I)->ReplaceUsesOfBlockWith(FromBBI.BB, ToBBI.BB); + // Transfer preds / succs and update size. TransferPreds(ToBBI.BB, FromBBI.BB); TransferSuccs(ToBBI.BB, FromBBI.BB); From dpatel at apple.com Mon Jun 4 10:29:23 2007 From: dpatel at apple.com (Devang Patel) Date: Mon, 4 Jun 2007 10:29:23 -0500 Subject: [llvm-commits] CVS: llvm/lib/System/Unix/Program.inc Message-ID: <200706041529.l54FTNLf031199@zion.cs.uiuc.edu> Changes in directory llvm/lib/System/Unix: Program.inc updated: 1.24 -> 1.25 --- Log message: Fix LLVM build on NetBSD. Patch by Neil Booth. --- Diffs of the changes: (+2 -0) Program.inc | 2 ++ 1 files changed, 2 insertions(+) Index: llvm/lib/System/Unix/Program.inc diff -u llvm/lib/System/Unix/Program.inc:1.24 llvm/lib/System/Unix/Program.inc:1.25 --- llvm/lib/System/Unix/Program.inc:1.24 Mon Apr 23 02:22:51 2007 +++ llvm/lib/System/Unix/Program.inc Mon Jun 4 10:28:57 2007 @@ -125,11 +125,13 @@ r.rlim_cur = limit; setrlimit (RLIMIT_RSS, &r); #endif +#ifdef RLIMIT_AS // e.g. NetBSD doesn't have it. // Virtual memory. getrlimit (RLIMIT_AS, &r); r.rlim_cur = limit; setrlimit (RLIMIT_AS, &r); #endif +#endif } int From djg at cray.com Mon Jun 4 10:50:03 2007 From: djg at cray.com (Dan Gohman) Date: Mon, 4 Jun 2007 10:50:03 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200706041550.l54Fo3Et031770@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAG.cpp updated: 1.404 -> 1.405 --- Log message: Resolve implicit alignment before computing the FoldingSet information so that the CSE map always contains explicit alignment information. This allows more loads to be CSE'd when there is a mix of explicit-alignment loads and implicit-alignment loads. Also, in SelectionDAG::FindModifiedNodeSlot, add the operands to the FoldingSetNodeID before the load/store information instead of after, so that it matches what is done elsewhere. --- Diffs of the changes: (+49 -50) SelectionDAG.cpp | 99 +++++++++++++++++++++++++++---------------------------- 1 files changed, 49 insertions(+), 50 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.404 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.405 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.404 Thu May 24 09:33:05 2007 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Jun 4 10:49:41 2007 @@ -597,7 +597,7 @@ return 0; // Never CSE anything that produces a flag. FoldingSetNodeID ID; - AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), 0, 0); + AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, NumOps); if (const LoadSDNode *LD = dyn_cast(N)) { ID.AddInteger(LD->getAddressingMode()); @@ -617,7 +617,6 @@ ID.AddInteger(ST->isVolatile()); } - AddNodeIDOperands(ID, Ops, NumOps); return CSEMap.FindNodeOrInsertPos(ID, InsertPos); } @@ -1548,6 +1547,18 @@ SDOperand Chain, SDOperand Ptr, const Value *SV, int SVOffset, bool isVolatile, unsigned Alignment) { + if (Alignment == 0) { // Ensure that codegen never sees alignment 0 + const Type *Ty = 0; + if (VT != MVT::Vector && VT != MVT::iPTR) { + Ty = MVT::getTypeForValueType(VT); + } else if (SV) { + const PointerType *PT = dyn_cast(SV->getType()); + assert(PT && "Value for load must be a pointer"); + Ty = PT->getElementType(); + } + assert(Ty && "Could not get type information for load"); + Alignment = TLI.getTargetData()->getABITypeAlignment(Ty); + } SDVTList VTs = getVTList(VT, MVT::Other); SDOperand Undef = getNode(ISD::UNDEF, Ptr.getValueType()); SDOperand Ops[] = { Chain, Ptr, Undef }; @@ -1563,18 +1574,6 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDOperand(E, 0); - if (Alignment == 0) { // Ensure that codegen never sees alignment 0 - const Type *Ty = 0; - if (VT != MVT::Vector && VT != MVT::iPTR) { - Ty = MVT::getTypeForValueType(VT); - } else if (SV) { - const PointerType *PT = dyn_cast(SV->getType()); - assert(PT && "Value for load must be a pointer"); - Ty = PT->getElementType(); - } - assert(Ty && "Could not get type information for load"); - Alignment = TLI.getTargetData()->getABITypeAlignment(Ty); - } SDNode *N = new LoadSDNode(Ops, VTs, ISD::UNINDEXED, ISD::NON_EXTLOAD, VT, SV, SVOffset, Alignment, isVolatile); @@ -1602,6 +1601,18 @@ assert(MVT::isInteger(VT) == MVT::isInteger(EVT) && "Cannot convert from FP to Int or Int -> FP!"); + if (Alignment == 0) { // Ensure that codegen never sees alignment 0 + const Type *Ty = 0; + if (VT != MVT::Vector && VT != MVT::iPTR) { + Ty = MVT::getTypeForValueType(VT); + } else if (SV) { + const PointerType *PT = dyn_cast(SV->getType()); + assert(PT && "Value for load must be a pointer"); + Ty = PT->getElementType(); + } + assert(Ty && "Could not get type information for load"); + Alignment = TLI.getTargetData()->getABITypeAlignment(Ty); + } SDVTList VTs = getVTList(VT, MVT::Other); SDOperand Undef = getNode(ISD::UNDEF, Ptr.getValueType()); SDOperand Ops[] = { Chain, Ptr, Undef }; @@ -1617,18 +1628,6 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDOperand(E, 0); - if (Alignment == 0) { // Ensure that codegen never sees alignment 0 - const Type *Ty = 0; - if (VT != MVT::Vector && VT != MVT::iPTR) { - Ty = MVT::getTypeForValueType(VT); - } else if (SV) { - const PointerType *PT = dyn_cast(SV->getType()); - assert(PT && "Value for load must be a pointer"); - Ty = PT->getElementType(); - } - assert(Ty && "Could not get type information for load"); - Alignment = TLI.getTargetData()->getABITypeAlignment(Ty); - } SDNode *N = new LoadSDNode(Ops, VTs, ISD::UNINDEXED, ExtType, EVT, SV, SVOffset, Alignment, isVolatile); CSEMap.InsertNode(N, IP); @@ -1679,6 +1678,18 @@ bool isVolatile, unsigned Alignment) { MVT::ValueType VT = Val.getValueType(); + if (Alignment == 0) { // Ensure that codegen never sees alignment 0 + const Type *Ty = 0; + if (VT != MVT::Vector && VT != MVT::iPTR) { + Ty = MVT::getTypeForValueType(VT); + } else if (SV) { + const PointerType *PT = dyn_cast(SV->getType()); + assert(PT && "Value for store must be a pointer"); + Ty = PT->getElementType(); + } + assert(Ty && "Could not get type information for store"); + Alignment = TLI.getTargetData()->getABITypeAlignment(Ty); + } SDVTList VTs = getVTList(MVT::Other); SDOperand Undef = getNode(ISD::UNDEF, Ptr.getValueType()); SDOperand Ops[] = { Chain, Val, Ptr, Undef }; @@ -1694,18 +1705,6 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDOperand(E, 0); - if (Alignment == 0) { // Ensure that codegen never sees alignment 0 - const Type *Ty = 0; - if (VT != MVT::Vector && VT != MVT::iPTR) { - Ty = MVT::getTypeForValueType(VT); - } else if (SV) { - const PointerType *PT = dyn_cast(SV->getType()); - assert(PT && "Value for store must be a pointer"); - Ty = PT->getElementType(); - } - assert(Ty && "Could not get type information for store"); - Alignment = TLI.getTargetData()->getABITypeAlignment(Ty); - } SDNode *N = new StoreSDNode(Ops, VTs, ISD::UNINDEXED, false, VT, SV, SVOffset, Alignment, isVolatile); CSEMap.InsertNode(N, IP); @@ -1724,6 +1723,18 @@ assert(MVT::isInteger(VT) == MVT::isInteger(SVT) && "Can't do FP-INT conversion!"); + if (Alignment == 0) { // Ensure that codegen never sees alignment 0 + const Type *Ty = 0; + if (VT != MVT::Vector && VT != MVT::iPTR) { + Ty = MVT::getTypeForValueType(VT); + } else if (SV) { + const PointerType *PT = dyn_cast(SV->getType()); + assert(PT && "Value for store must be a pointer"); + Ty = PT->getElementType(); + } + assert(Ty && "Could not get type information for store"); + Alignment = TLI.getTargetData()->getABITypeAlignment(Ty); + } SDVTList VTs = getVTList(MVT::Other); SDOperand Undef = getNode(ISD::UNDEF, Ptr.getValueType()); SDOperand Ops[] = { Chain, Val, Ptr, Undef }; @@ -1739,18 +1750,6 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDOperand(E, 0); - if (Alignment == 0) { // Ensure that codegen never sees alignment 0 - const Type *Ty = 0; - if (VT != MVT::Vector && VT != MVT::iPTR) { - Ty = MVT::getTypeForValueType(VT); - } else if (SV) { - const PointerType *PT = dyn_cast(SV->getType()); - assert(PT && "Value for store must be a pointer"); - Ty = PT->getElementType(); - } - assert(Ty && "Could not get type information for store"); - Alignment = TLI.getTargetData()->getABITypeAlignment(Ty); - } SDNode *N = new StoreSDNode(Ops, VTs, ISD::UNINDEXED, isTrunc, SVT, SV, SVOffset, Alignment, isVolatile); CSEMap.InsertNode(N, IP); From djg at cray.com Mon Jun 4 11:11:25 2007 From: djg at cray.com (Dan Gohman) Date: Mon, 4 Jun 2007 11:11:25 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/CodeGenTarget.cpp CodeGenTarget.h RegisterInfoEmitter.cpp Message-ID: <200706041611.l54GBPKG032354@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: CodeGenTarget.cpp updated: 1.89 -> 1.90 CodeGenTarget.h updated: 1.29 -> 1.30 RegisterInfoEmitter.cpp updated: 1.54 -> 1.55 --- Log message: Remove the operator<< for MVT::ValueType in preparation for MVT::ValueType being changed from an enum to an integer type, which can't have a custom operator<< overload. --- Diffs of the changes: (+1 -7) CodeGenTarget.cpp | 5 ----- CodeGenTarget.h | 1 - RegisterInfoEmitter.cpp | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) Index: llvm/utils/TableGen/CodeGenTarget.cpp diff -u llvm/utils/TableGen/CodeGenTarget.cpp:1.89 llvm/utils/TableGen/CodeGenTarget.cpp:1.90 --- llvm/utils/TableGen/CodeGenTarget.cpp:1.89 Wed May 16 15:45:24 2007 +++ llvm/utils/TableGen/CodeGenTarget.cpp Mon Jun 4 11:11:03 2007 @@ -99,11 +99,6 @@ } -std::ostream &llvm::operator<<(std::ostream &OS, MVT::ValueType T) { - return OS << getName(T); -} - - /// getTarget - Return the current instance of the Target class. /// CodeGenTarget::CodeGenTarget() { Index: llvm/utils/TableGen/CodeGenTarget.h diff -u llvm/utils/TableGen/CodeGenTarget.h:1.29 llvm/utils/TableGen/CodeGenTarget.h:1.30 --- llvm/utils/TableGen/CodeGenTarget.h:1.29 Wed Oct 11 16:02:01 2006 +++ llvm/utils/TableGen/CodeGenTarget.h Mon Jun 4 11:11:03 2007 @@ -37,7 +37,6 @@ /// corresponds to. MVT::ValueType getValueType(Record *Rec, const CodeGenTarget *CGT = 0); -std::ostream &operator<<(std::ostream &OS, MVT::ValueType T); std::string getName(MVT::ValueType T); std::string getEnumName(MVT::ValueType T); Index: llvm/utils/TableGen/RegisterInfoEmitter.cpp diff -u llvm/utils/TableGen/RegisterInfoEmitter.cpp:1.54 llvm/utils/TableGen/RegisterInfoEmitter.cpp:1.55 --- llvm/utils/TableGen/RegisterInfoEmitter.cpp:1.54 Tue May 1 01:08:36 2007 +++ llvm/utils/TableGen/RegisterInfoEmitter.cpp Mon Jun 4 11:11:03 2007 @@ -209,7 +209,7 @@ << " static const MVT::ValueType " << Name << "[] = {\n "; for (unsigned i = 0, e = RC.VTs.size(); i != e; ++i) - OS << RC.VTs[i] << ", "; + OS << getName(RC.VTs[i]) << ", "; OS << "MVT::Other\n };\n\n"; } OS << "} // end anonymous namespace\n\n"; From djg at cray.com Mon Jun 4 11:17:55 2007 From: djg at cray.com (Dan Gohman) Date: Mon, 4 Jun 2007 11:17:55 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Message-ID: <200706041617.l54GHtPX032553@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: LegalizeDAG.cpp updated: 1.494 -> 1.495 --- Log message: Pass the DAG to SDNode::dump to let it do more detailed dumps in some cases. --- Diffs of the changes: (+5 -5) LegalizeDAG.cpp | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.494 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.495 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.494 Fri May 18 12:52:13 2007 +++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Mon Jun 4 11:17:33 2007 @@ -648,7 +648,7 @@ } // Otherwise this is an unhandled builtin node. splat. #ifndef NDEBUG - cerr << "NODE: "; Node->dump(); cerr << "\n"; + cerr << "NODE: "; Node->dump(&DAG); cerr << "\n"; #endif assert(0 && "Do not know how to legalize this operator!"); abort(); @@ -3181,7 +3181,7 @@ assert(0 && "CopyFromReg must be legal!"); default: #ifndef NDEBUG - cerr << "NODE: "; Node->dump(); cerr << "\n"; + cerr << "NODE: "; Node->dump(&DAG); cerr << "\n"; #endif assert(0 && "Do not know how to promote this operator!"); abort(); @@ -4721,7 +4721,7 @@ assert(0 && "CopyFromReg must be legal!"); default: #ifndef NDEBUG - cerr << "NODE: "; Node->dump(); cerr << "\n"; + cerr << "NODE: "; Node->dump(&DAG); cerr << "\n"; #endif assert(0 && "Do not know how to expand this operator!"); abort(); @@ -5484,7 +5484,7 @@ switch (Node->getOpcode()) { default: #ifndef NDEBUG - Node->dump(); + Node->dump(&DAG); #endif assert(0 && "Unhandled operation in SplitVectorOp!"); case ISD::VBUILD_VECTOR: { @@ -5606,7 +5606,7 @@ switch (Node->getOpcode()) { default: #ifndef NDEBUG - Node->dump(); cerr << "\n"; + Node->dump(&DAG); cerr << "\n"; #endif assert(0 && "Unknown vector operation in PackVectorOp!"); case ISD::VADD: From dpatel at apple.com Mon Jun 4 11:22:56 2007 From: dpatel at apple.com (Devang Patel) Date: Mon, 4 Jun 2007 11:22:56 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706041622.l54GMudF032683@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.85 -> 1.86 --- Log message: Add basic block level interface to change immediate dominator and create new node. --- Diffs of the changes: (+12 -3) Dominators.h | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.85 llvm/include/llvm/Analysis/Dominators.h:1.86 --- llvm/include/llvm/Analysis/Dominators.h:1.85 Sun Jun 3 19:32:21 2007 +++ llvm/include/llvm/Analysis/Dominators.h Mon Jun 4 11:22:33 2007 @@ -110,7 +110,7 @@ /// DominatorTree - Calculate the immediate dominator tree for a function. /// class DominatorTreeBase : public DominatorBase { -public: + protected: std::map DomTreeNodes; void reset(); @@ -118,6 +118,7 @@ DomTreeNode *RootNode; + // Information record used during immediate dominators computation. struct InfoRec { unsigned Semi; unsigned Size; @@ -136,8 +137,7 @@ // Info - Collection of information used during the computation of idoms. std::map Info; -public: -public: + public: DominatorTreeBase(intptr_t ID, bool isPostDom) : DominatorBase(ID, isPostDom) {} ~DominatorTreeBase() { reset(); } @@ -180,6 +180,10 @@ return DomTreeNodes[BB] = IDomNode->addChild(new DomTreeNode(BB, IDomNode)); } + void createNewNode(BasicBlock *BB, BasicBlock *DomBB) { + createNewNode(BB, getNode(DomBB)); + } + /// changeImmediateDominator - This method is used to update the dominator /// tree information when a node's immediate dominator changes. /// @@ -188,6 +192,11 @@ N->setIDom(NewIDom); } + void changeImmediateDominator(BasicBlock *BB, BasicBlock *NewBB) { + changeImmediateDominator(getNode(BB), getNode(NewBB)); + } + + /// removeNode - Removes a node from the dominator tree. Block must not /// dominate any other blocks. Invalidates any node pointing to removed /// block. From dpatel at apple.com Mon Jun 4 11:22:55 2007 From: dpatel at apple.com (Devang Patel) Date: Mon, 4 Jun 2007 11:22:55 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/CodeExtractor.cpp Message-ID: <200706041622.l54GMtxE032680@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CodeExtractor.cpp updated: 1.54 -> 1.55 --- Log message: Add basic block level interface to change immediate dominator and create new node. --- Diffs of the changes: (+2 -2) CodeExtractor.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp diff -u llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.54 llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.55 --- llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.54 Tue Apr 17 23:46:35 2007 +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp Mon Jun 4 11:22:33 2007 @@ -143,14 +143,14 @@ // blocks that dominate TIBB plus the new block itself. if (EF) { BasicBlock* idom = EF->getIDom(OldPred); - DT->createNewNode(NewBB, DT->getNode(idom)); + DT->createNewNode(NewBB, idom); EF->addNewBlock(NewBB, idom); // Additionally, NewBB replaces OldPred as the immediate dominator of blocks Function *F = Header->getParent(); for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) if (EF->getIDom(I) == OldPred) { - DT->changeImmediateDominator(DT->getNode(I), DT->getNode(NewBB)); + DT->changeImmediateDominator(I, NewBB); EF->setImmediateDominator(I, NewBB); } } From dpatel at apple.com Mon Jun 4 11:43:47 2007 From: dpatel at apple.com (Devang Patel) Date: Mon, 4 Jun 2007 11:43:47 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706041643.l54Ghldv000793@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.86 -> 1.87 --- Log message: s/DominatorTree::createNewNode/DominatorTree::addNewBlock/g --- Diffs of the changes: (+6 -7) Dominators.h | 13 ++++++------- 1 files changed, 6 insertions(+), 7 deletions(-) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.86 llvm/include/llvm/Analysis/Dominators.h:1.87 --- llvm/include/llvm/Analysis/Dominators.h:1.86 Mon Jun 4 11:22:33 2007 +++ llvm/include/llvm/Analysis/Dominators.h Mon Jun 4 11:43:25 2007 @@ -170,18 +170,17 @@ // API to update (Post)DominatorTree information based on modifications to // the CFG... - /// createNewNode - Add a new node to the dominator tree information. This - /// creates a new node as a child of IDomNode, linking it into the children - /// list of the immediate dominator. - /// - DomTreeNode *createNewNode(BasicBlock *BB, DomTreeNode *IDomNode) { + /// addNewBlock - Add a new node to the dominator tree information. This + /// creates a new node as a child of DomBB dominator node,linking it into + /// the children list of the immediate dominator. + DomTreeNode *addNewBlock(BasicBlock *BB, DomTreeNode *IDomNode) { assert(getNode(BB) == 0 && "Block already in dominator tree!"); assert(IDomNode && "Not immediate dominator specified for block!"); return DomTreeNodes[BB] = IDomNode->addChild(new DomTreeNode(BB, IDomNode)); } - void createNewNode(BasicBlock *BB, BasicBlock *DomBB) { - createNewNode(BB, getNode(DomBB)); + DomTreeNode *addNewBlock(BasicBlock *BB, BasicBlock *DomBB) { + return addNewBlock(BB, getNode(DomBB)); } /// changeImmediateDominator - This method is used to update the dominator From dpatel at apple.com Mon Jun 4 11:43:47 2007 From: dpatel at apple.com (Devang Patel) Date: Mon, 4 Jun 2007 11:43:47 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp CodeExtractor.cpp LoopSimplify.cpp Message-ID: <200706041643.l54GhlAC000802@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: BreakCriticalEdges.cpp updated: 1.50 -> 1.51 CodeExtractor.cpp updated: 1.55 -> 1.56 LoopSimplify.cpp updated: 1.98 -> 1.99 --- Log message: s/DominatorTree::createNewNode/DominatorTree::addNewBlock/g --- Diffs of the changes: (+3 -4) BreakCriticalEdges.cpp | 2 +- CodeExtractor.cpp | 2 +- LoopSimplify.cpp | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) Index: llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp diff -u llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp:1.50 llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp:1.51 --- llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp:1.50 Sun Jun 3 19:32:22 2007 +++ llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp Mon Jun 4 11:43:25 2007 @@ -209,7 +209,7 @@ // TINode is the immediate dominator for the new node. // if (TINode) { // Don't break unreachable code! - DomTreeNode *NewBBNode = DT->createNewNode(NewBB, TINode); + DomTreeNode *NewBBNode = DT->addNewBlock(NewBB, TIBB); DomTreeNode *DestBBNode = 0; // If NewBBDominatesDestBB hasn't been computed yet, do so with DT. Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp diff -u llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.55 llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.56 --- llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.55 Mon Jun 4 11:22:33 2007 +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp Mon Jun 4 11:43:25 2007 @@ -143,7 +143,7 @@ // blocks that dominate TIBB plus the new block itself. if (EF) { BasicBlock* idom = EF->getIDom(OldPred); - DT->createNewNode(NewBB, idom); + DT->addNewBlock(NewBB, idom); EF->addNewBlock(NewBB, idom); // Additionally, NewBB replaces OldPred as the immediate dominator of blocks Index: llvm/lib/Transforms/Utils/LoopSimplify.cpp diff -u llvm/lib/Transforms/Utils/LoopSimplify.cpp:1.98 llvm/lib/Transforms/Utils/LoopSimplify.cpp:1.99 --- llvm/lib/Transforms/Utils/LoopSimplify.cpp:1.98 Sun Jun 3 19:32:22 2007 +++ llvm/lib/Transforms/Utils/LoopSimplify.cpp Mon Jun 4 11:43:25 2007 @@ -778,10 +778,9 @@ } assert(NewBBIDom && "No immediate dominator found??"); } - DomTreeNode *NewBBIDomNode = DT->getNode(NewBBIDom); // Create the new dominator tree node... and set the idom of NewBB. - DomTreeNode *NewBBNode = DT->createNewNode(NewBB, NewBBIDomNode); + DomTreeNode *NewBBNode = DT->addNewBlock(NewBB, NewBBIDom); // If NewBB strictly dominates other blocks, then it is now the immediate // dominator of NewBBSucc. Update the dominator tree as appropriate. From dpatel at apple.com Mon Jun 4 11:49:59 2007 From: dpatel at apple.com (Devang Patel) Date: Mon, 4 Jun 2007 11:49:59 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706041649.l54GnxLv001079@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.87 -> 1.88 --- Log message: Remove unused method. --- Diffs of the changes: (+2 -5) Dominators.h | 7 ++----- 1 files changed, 2 insertions(+), 5 deletions(-) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.87 llvm/include/llvm/Analysis/Dominators.h:1.88 --- llvm/include/llvm/Analysis/Dominators.h:1.87 Mon Jun 4 11:43:25 2007 +++ llvm/include/llvm/Analysis/Dominators.h Mon Jun 4 11:49:36 2007 @@ -173,16 +173,13 @@ /// addNewBlock - Add a new node to the dominator tree information. This /// creates a new node as a child of DomBB dominator node,linking it into /// the children list of the immediate dominator. - DomTreeNode *addNewBlock(BasicBlock *BB, DomTreeNode *IDomNode) { + DomTreeNode *addNewBlock(BasicBlock *BB, BasicBlock *DomBB) { assert(getNode(BB) == 0 && "Block already in dominator tree!"); + DomTreeNode *IDomNode = getNode(DomBB); assert(IDomNode && "Not immediate dominator specified for block!"); return DomTreeNodes[BB] = IDomNode->addChild(new DomTreeNode(BB, IDomNode)); } - DomTreeNode *addNewBlock(BasicBlock *BB, BasicBlock *DomBB) { - return addNewBlock(BB, getNode(DomBB)); - } - /// changeImmediateDominator - This method is used to update the dominator /// tree information when a node's immediate dominator changes. /// From dpatel at apple.com Mon Jun 4 12:38:24 2007 From: dpatel at apple.com (Devang Patel) Date: Mon, 4 Jun 2007 12:38:24 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706041738.l54HcOAj002628@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.88 -> 1.89 --- Log message: Add FIXMEs. --- Diffs of the changes: (+4 -0) Dominators.h | 4 ++++ 1 files changed, 4 insertions(+) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.88 llvm/include/llvm/Analysis/Dominators.h:1.89 --- llvm/include/llvm/Analysis/Dominators.h:1.88 Mon Jun 4 11:49:36 2007 +++ llvm/include/llvm/Analysis/Dominators.h Mon Jun 4 12:37:59 2007 @@ -283,6 +283,8 @@ typedef std::map ETMapType; + // FIXME : There is no need to make this interface public. + // Fix predicate simplifier. void updateDFSNumbers(); /// dominates - Return true if A dominates B. @@ -426,6 +428,8 @@ } void calculate(const DominatorTree &DT); + // FIXME : There is no need to make getNodeForBlock public. Fix + // predicate simplifier. ETNode *getNodeForBlock(BasicBlock *BB); }; From dpatel at apple.com Mon Jun 4 12:38:24 2007 From: dpatel at apple.com (Devang Patel) Date: Mon, 4 Jun 2007 12:38:24 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp Message-ID: <200706041738.l54HcOO8002633@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Dominators.cpp updated: 1.104 -> 1.105 --- Log message: Add FIXMEs. --- Diffs of the changes: (+2 -0) Dominators.cpp | 2 ++ 1 files changed, 2 insertions(+) Index: llvm/lib/VMCore/Dominators.cpp diff -u llvm/lib/VMCore/Dominators.cpp:1.104 llvm/lib/VMCore/Dominators.cpp:1.105 --- llvm/lib/VMCore/Dominators.cpp:1.104 Sun Jun 3 19:32:22 2007 +++ llvm/lib/VMCore/Dominators.cpp Mon Jun 4 12:38:00 2007 @@ -921,6 +921,8 @@ return dominates(&A->getParent()->getEntryBlock(), A); } +// FIXME : There is no need to make getNodeForBlock public. Fix +// predicate simplifier. ETNode *ETForest::getNodeForBlock(BasicBlock *BB) { ETNode *&BBNode = Nodes[BB]; if (BBNode) return BBNode; From resistor at mac.com Mon Jun 4 13:05:46 2007 From: resistor at mac.com (Owen Anderson) Date: Mon, 4 Jun 2007 13:05:46 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706041805.l54I5kCT003369@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.15 -> 1.16 --- Log message: Make phi_translate correct. --- Diffs of the changes: (+50 -47) GVNPRE.cpp | 97 +++++++++++++++++++++++++++++++------------------------------ 1 files changed, 50 insertions(+), 47 deletions(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.15 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.16 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.15 Sun Jun 3 19:32:21 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Mon Jun 4 13:05:26 2007 @@ -78,7 +78,10 @@ void clean(ValueTable VN, std::set& set); bool add(ValueTable& VN, std::set& MS, Value* V); Value* find_leader(ValueTable VN, std::set& vals, uint32_t v); - void phi_translate(ValueTable& VN, std::set& MS, + Value* phi_translate(ValueTable& VN, std::set& MS, + std::set& set, + Value* V, BasicBlock* pred); + void phi_translate_set(ValueTable& VN, std::set& MS, std::set& anticIn, BasicBlock* B, std::set& out); @@ -128,53 +131,52 @@ return 0; } -void GVNPRE::phi_translate(GVNPRE::ValueTable& VN, +Value* GVNPRE::phi_translate(ValueTable& VN, std::set& MS, + std::set& set, + Value* V, BasicBlock* pred) { + if (V == 0) + return 0; + + if (BinaryOperator* BO = dyn_cast(V)) { + Value* newOp1 = phi_translate(VN, MS, set, + find_leader(VN, set, VN[BO->getOperand(0)]), + pred); + if (newOp1 == 0) + return 0; + + Value* newOp2 = phi_translate(VN, MS, set, + find_leader(VN, set, VN[BO->getOperand(1)]), + pred); + if (newOp2 == 0) + return 0; + + if (newOp1 != BO->getOperand(0) || newOp2 != BO->getOperand(1)) { + Value* newVal = BinaryOperator::create(BO->getOpcode(), + newOp1, newOp2, + BO->getName()+".gvnpre"); + add(VN, MS, newVal); + if (!find_leader(VN, set, VN[newVal])) + return newVal; + else + return 0; + } + } else if (PHINode* P = dyn_cast(V)) { + if (P->getParent() == pred->getTerminator()->getSuccessor(0)) + return P->getIncomingValueForBlock(pred); + } + + return V; +} + +void GVNPRE::phi_translate_set(GVNPRE::ValueTable& VN, std::set& MS, std::set& anticIn, BasicBlock* B, std::set& out) { - BasicBlock* succ = B->getTerminator()->getSuccessor(0); - - for (std::set::iterator I = anticIn.begin(), E = anticIn.end(); - I != E; ++I) { - if (!isa(*I)) { - if (PHINode* p = dyn_cast(*I)) { - if (p->getParent() == succ) - out.insert(p); - } else { - out.insert(*I); - } - } else { - BinaryOperator* BO = cast(*I); - Value* lhs = find_leader(VN, anticIn, VN[BO->getOperand(0)]); - if (lhs == 0) - continue; - - if (PHINode* p = dyn_cast(lhs)) - if (p->getParent() == succ) { - lhs = p->getIncomingValueForBlock(B); - out.insert(lhs); - } - - Value* rhs = find_leader(VN, anticIn, VN[BO->getOperand(1)]); - if (rhs == 0) - continue; - - if (PHINode* p = dyn_cast(rhs)) - if (p->getParent() == succ) { - rhs = p->getIncomingValueForBlock(B); - out.insert(rhs); - } - - if (lhs != BO->getOperand(0) || rhs != BO->getOperand(1)) { - BO = BinaryOperator::create(BO->getOpcode(), lhs, rhs, BO->getName()+".gvnpre"); - if (VN.insert(std::make_pair(BO, nextValueNumber)).second) - nextValueNumber++; - MS.insert(BO); - } - - out.insert(BO); - - } + for (std::set::iterator I = anticIn.begin(), + E = anticIn.end(); I != E; ++I) { + Value* V = phi_translate(VN, MS, anticIn, *I, B); + if (V != 0) + out.insert(V); } } @@ -371,9 +373,9 @@ if (BB->getTerminator()->getNumSuccessors() == 1) { if (visited.find(BB) == visited.end()) - phi_translate(VN, maximalSet, anticIn, BB, anticOut); + phi_translate_set(VN, maximalSet, anticIn, BB, anticOut); else - phi_translate(VN, anticIn, anticIn, BB, anticOut); + phi_translate_set(VN, anticIn, anticIn, BB, anticOut); } else if (BB->getTerminator()->getNumSuccessors() > 1) { for (unsigned i = 0; i < BB->getTerminator()->getNumSuccessors(); ++i) { BasicBlock* currSucc = BB->getTerminator()->getSuccessor(i); @@ -419,6 +421,7 @@ anticOut.clear(); } + iterations++; } From evan.cheng at apple.com Mon Jun 4 13:55:37 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 4 Jun 2007 13:55:37 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86ATTAsmPrinter.cpp Message-ID: <200706041855.l54ItbO8004506@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86ATTAsmPrinter.cpp updated: 1.105 -> 1.106 --- Log message: Misuse of hasExternalLinkage(), should be checking isDeclaration(). --- Diffs of the changes: (+2 -2) X86ATTAsmPrinter.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/Target/X86/X86ATTAsmPrinter.cpp diff -u llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.105 llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.106 --- llvm/lib/Target/X86/X86ATTAsmPrinter.cpp:1.105 Sat May 5 04:04:50 2007 +++ llvm/lib/Target/X86/X86ATTAsmPrinter.cpp Mon Jun 4 13:54:57 2007 @@ -286,7 +286,7 @@ } if (printStub(TM, Subtarget)) { - // Link-once, External, or Weakly-linked global variables need + // Link-once, declaration, or Weakly-linked global variables need // non-lazily-resolved stubs if (GV->isDeclaration() || GV->hasWeakLinkage() || @@ -351,7 +351,7 @@ else O << "@GOTOFF"; } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel) { - if ((GV->hasExternalLinkage() || + if ((GV->isDeclaration() || GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) && TM.getRelocationModel() != Reloc::Static) From evan.cheng at apple.com Mon Jun 4 15:34:55 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 4 Jun 2007 15:34:55 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706042034.l54KYtg7007640@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.22 -> 1.23 --- Log message: Forgot to check for if iterator reached the end. --- Diffs of the changes: (+2 -1) IfConversion.cpp | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.22 llvm/lib/CodeGen/IfConversion.cpp:1.23 --- llvm/lib/CodeGen/IfConversion.cpp:1.22 Mon Jun 4 01:47:22 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Mon Jun 4 15:33:36 2007 @@ -441,8 +441,9 @@ /// isNextBlock - Returns true either if ToBB the next block after BB or /// that all the intervening blocks are empty. static bool isNextBlock(MachineBasicBlock *BB, MachineBasicBlock *ToBB) { + MachineFunction *MF = BB->getParent(); MachineFunction::iterator I = BB; - while (++I != MachineFunction::iterator(ToBB)) + while (++I != MF->end() && I != MachineFunction::iterator(ToBB)) if (!I->empty()) return false; return true; From evan.cheng at apple.com Mon Jun 4 15:40:12 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 4 Jun 2007 15:40:12 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/AsmPrinter.cpp Message-ID: <200706042040.l54KeC1H007814@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: AsmPrinter.cpp updated: 1.164 -> 1.165 --- Log message: Global ctors / dtors alignment shouldn't be hard-coded at 4. e.g. It could be 8 for 64-bit targets. --- Diffs of the changes: (+4 -2) AsmPrinter.cpp | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) Index: llvm/lib/CodeGen/AsmPrinter.cpp diff -u llvm/lib/CodeGen/AsmPrinter.cpp:1.164 llvm/lib/CodeGen/AsmPrinter.cpp:1.165 --- llvm/lib/CodeGen/AsmPrinter.cpp:1.164 Thu May 31 13:57:45 2007 +++ llvm/lib/CodeGen/AsmPrinter.cpp Mon Jun 4 15:39:18 2007 @@ -327,16 +327,18 @@ return true; } + const TargetData *TD = TM.getTargetData(); + unsigned Align = Log2_32(TD->getPointerPrefAlignment()); if (GV->getName() == "llvm.global_ctors" && GV->use_empty()) { SwitchToDataSection(TAI->getStaticCtorsSection()); - EmitAlignment(2, 0); + EmitAlignment(Align, 0); EmitXXStructorList(GV->getInitializer()); return true; } if (GV->getName() == "llvm.global_dtors" && GV->use_empty()) { SwitchToDataSection(TAI->getStaticDtorsSection()); - EmitAlignment(2, 0); + EmitAlignment(Align, 0); EmitXXStructorList(GV->getInitializer()); return true; } From sabre at nondot.org Mon Jun 4 17:23:48 2007 From: sabre at nondot.org (Chris Lattner) Date: Mon, 4 Jun 2007 17:23:48 -0500 Subject: [llvm-commits] CVS: llvm/test/Transforms/GlobalOpt/2007-06-04-PackedStruct.ll Message-ID: <200706042223.l54MNmbN011003@zion.cs.uiuc.edu> Changes in directory llvm/test/Transforms/GlobalOpt: 2007-06-04-PackedStruct.ll added (r1.1) --- Log message: new testcase for PR1491: http://llvm.org/PR1491 --- Diffs of the changes: (+36 -0) 2007-06-04-PackedStruct.ll | 36 ++++++++++++++++++++++++++++++++++++ 1 files changed, 36 insertions(+) Index: llvm/test/Transforms/GlobalOpt/2007-06-04-PackedStruct.ll diff -c /dev/null llvm/test/Transforms/GlobalOpt/2007-06-04-PackedStruct.ll:1.1 *** /dev/null Mon Jun 4 17:23:27 2007 --- llvm/test/Transforms/GlobalOpt/2007-06-04-PackedStruct.ll Mon Jun 4 17:23:17 2007 *************** *** 0 **** --- 1,36 ---- + ; RUN: llvm-as < %s | opt -globalopt -disable-output + ; PR1491 + + target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64" + target triple = "i686-pc-linux-gnu" + %"struct.__gnu_cxx::new_allocator > >" = type <{ i8 }> + %"struct.std::_Rb_tree,std::_Select1st >,std::less,std::allocator > >" = type { %"struct.std::_Rb_tree,std::_Select1st >,std::less,std::allocator > >::_Rb_tree_impl,false>" } + %"struct.std::_Rb_tree,std::_Select1st >,std::less,std::allocator > >::_Rb_tree_impl,false>" = type { %"struct.__gnu_cxx::new_allocator > >", %"struct.std::_Rb_tree_node_base", i32 } + %"struct.std::_Rb_tree_node_base" = type { i32, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"*, %"struct.std::_Rb_tree_node_base"* } + %"struct.std::map,std::allocator > >" = type { %"struct.std::_Rb_tree,std::_Select1st >,std::less,std::allocator > >" } + @someMap = global %"struct.std::map,std::allocator > >" zeroinitializer ; <%"struct.std::map,std::allocator > >"*> [#uses=1] + @llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_someMap } ] ; <[1 x { i32, void ()* }]*> [#uses=0] + @llvm.global_dtors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__D_someMap } ] ; <[1 x { i32, void ()* }]*> [#uses=0] + + define void @_GLOBAL__I_someMap() { + entry: + call void @_Z41__static_initialization_and_destruction_0ii( i32 1, i32 65535 ) + ret void + } + + declare void @_GLOBAL__D_someMap() + + define void @_Z41__static_initialization_and_destruction_0ii(i32 %__initialize_p, i32 %__priority) { + entry: + %tmp1 = icmp eq i32 %__priority, 65535 ; [#uses=1] + %tmp4 = icmp eq i32 %__initialize_p, 1 ; [#uses=1] + %tmp7 = and i1 %tmp1, %tmp4 ; [#uses=1] + br i1 %tmp7, label %cond_true, label %cond_next + + cond_true: ; preds = %entry + store i8 0, i8* getelementptr (%"struct.std::map,std::allocator > >"* @someMap, i32 0, i32 0, i32 0, i32 0, i32 0) + ret void + + cond_next: ; preds = %entry + ret void + } From sabre at nondot.org Mon Jun 4 17:24:04 2007 From: sabre at nondot.org (Chris Lattner) Date: Mon, 4 Jun 2007 17:24:04 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/GlobalOpt.cpp Message-ID: <200706042224.l54MO4Gm011034@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: GlobalOpt.cpp updated: 1.107 -> 1.108 --- Log message: When rebuilding constant structs, make sure to honor the isPacked bit. This fixes PR1491: http://llvm.org/PR1491 and GlobalOpt/2007-06-04-PackedStruct.ll --- Diffs of the changes: (+1 -1) GlobalOpt.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Transforms/IPO/GlobalOpt.cpp diff -u llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.107 llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.108 --- llvm/lib/Transforms/IPO/GlobalOpt.cpp:1.107 Tue May 15 01:42:04 2007 +++ llvm/lib/Transforms/IPO/GlobalOpt.cpp Mon Jun 4 17:23:42 2007 @@ -1625,7 +1625,7 @@ Elts[Idx] = EvaluateStoreInto(Elts[Idx], Val, Addr, OpNo+1); // Return the modified struct. - return ConstantStruct::get(Elts); + return ConstantStruct::get(&Elts[0], Elts.size(), STy->isPacked()); } else { ConstantInt *CI = cast(Addr->getOperand(OpNo)); const ArrayType *ATy = cast(Init->getType()); From lattner at apple.com Mon Jun 4 18:10:04 2007 From: lattner at apple.com (Tanya Lattner) Date: Mon, 4 Jun 2007 16:10:04 -0700 Subject: [llvm-commits] noinline attributes patch Message-ID: This is my first time sending a patch for llvm-gcc, so please let me know if I am not following correct procedure. The attached patch creates a global to track functions that should not be inlined (noinline attribute). The llvm inliner will need to be modified to make use of it. -------------- next part -------------- A non-text attachment was scrubbed... Name: noinlinePatch Type: application/octet-stream Size: 2488 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20070604/422ceaaf/attachment.obj -------------- next part -------------- Thanks, Tanya From echeng at apple.com Mon Jun 4 18:17:19 2007 From: echeng at apple.com (echeng at apple.com) Date: Mon, 4 Jun 2007 16:17:19 -0700 (PDT) Subject: [llvm-commits] [127994] LLVM x86-64 is capable of generating static code. Message-ID: <20070604231719.F06396CA00B1@src> Revision: 127994 Author: echeng Date: 2007-06-04 16:17:19 -0700 (Mon, 04 Jun 2007) Log Message: ----------- LLVM x86-64 is capable of generating static code. Disable gcc hack. Modified Paths: -------------- apple-local/branches/llvm/gcc/config/i386/i386.c Modified: apple-local/branches/llvm/gcc/config/i386/i386.c =================================================================== --- apple-local/branches/llvm/gcc/config/i386/i386.c 2007-06-04 20:51:49 UTC (rev 127993) +++ apple-local/branches/llvm/gcc/config/i386/i386.c 2007-06-04 23:17:19 UTC (rev 127994) @@ -1637,11 +1637,15 @@ #endif /* APPLE LOCAL end mainline */ +/* APPLE LOCAL begin LLVM */ +#ifndef ENABLE_LLVM /* APPLE LOCAL begin x86_64 support 2006-02-02 */ if (TARGET_MACHO && TARGET_64BIT) /* -fPIC is the default for x86_64 */ flag_pic = 2; /* APPLE LOCAL end x86_64 support 2006-02-02 */ +#endif +/* APPLE LOCAL end LLVM */ /* Set the default values for switches whose default depends on TARGET_64BIT in case they weren't overwritten by command line options. */ From lattner at apple.com Mon Jun 4 18:22:06 2007 From: lattner at apple.com (lattner at apple.com) Date: Mon, 4 Jun 2007 16:22:06 -0700 (PDT) Subject: [llvm-commits] [127995] Handle noinline attribute in the frontend. Message-ID: <20070604232206.921D46CA61A3@src> Revision: 127995 Author: lattner Date: 2007-06-04 16:22:06 -0700 (Mon, 04 Jun 2007) Log Message: ----------- Handle noinline attribute in the frontend. Modified Paths: -------------- apple-local/branches/llvm/gcc/llvm-backend.cpp apple-local/branches/llvm/gcc/llvm-convert.cpp apple-local/branches/llvm/gcc/llvm-internal.h Modified: apple-local/branches/llvm/gcc/llvm-backend.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-04 23:17:19 UTC (rev 127994) +++ apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-04 23:22:06 UTC (rev 127995) @@ -80,6 +80,7 @@ std::vector > StaticCtors, StaticDtors; std::vector AttributeUsedGlobals; +std::vector AttributeNoinlineFunctions; /// PerFunctionPasses - This is the list of cleanup passes run per-function /// as each is compiled. In cases where we are not doing IPO, it includes the @@ -477,6 +478,20 @@ "llvm.used", TheModule); } + // Add llvm.noinline + if (!AttributeNoinlineFunctions.empty()) { + std::vector GlobalInit; + const Type *SBP= PointerType::get(Type::Int8Ty); + for (unsigned i = 0, e = AttributeNoinlineFunctions.size(); i != e; ++i) + GlobalInit.push_back(ConstantExpr::getBitCast(AttributeNoinlineFunctions[i], + SBP)); + ArrayType *AT = ArrayType::get(SBP, AttributeNoinlineFunctions.size()); + Constant *Init = ConstantArray::get(AT, GlobalInit); + GlobalValue *gv = new GlobalVariable(AT, false, GlobalValue::AppendingLinkage, Init, + "llvm.noinline", TheModule); + gv->setSection("llvm.metadata"); + } + // Finish off the per-function pass. if (PerFunctionPasses) PerFunctionPasses->doFinalization(); Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-06-04 23:17:19 UTC (rev 127994) +++ apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-06-04 23:22:06 UTC (rev 127995) @@ -592,6 +592,10 @@ if (DECL_PRESERVE_P (FnDecl)) AttributeUsedGlobals.push_back(Fn); + // Handle noinline Functions + if (DECL_UNINLINABLE (FnDecl)) + AttributeNoinlineFunctions.push_back(Fn); + // Create a new basic block for the function. Builder.SetInsertPoint(new BasicBlock("entry", Fn)); Modified: apple-local/branches/llvm/gcc/llvm-internal.h =================================================================== --- apple-local/branches/llvm/gcc/llvm-internal.h 2007-06-04 23:17:19 UTC (rev 127994) +++ apple-local/branches/llvm/gcc/llvm-internal.h 2007-06-04 23:22:06 UTC (rev 127995) @@ -88,6 +88,9 @@ /// AttributeUsedGlobals - The list of globals that are marked attribute(used). extern std::vector AttributeUsedGlobals; +/// AttributeNoinlineFunctions - The list of functions that are marked attribute(noinline) +extern std::vector AttributeNoinlineFunctions; + void changeLLVMValue(Value *Old, Value *New); void readLLVMTypesStringTable(); void writeLLVMTypesStringTable(); From resistor at mac.com Mon Jun 4 18:28:55 2007 From: resistor at mac.com (Owen Anderson) Date: Mon, 4 Jun 2007 18:28:55 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706042328.l54NStmC012721@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.16 -> 1.17 --- Log message: Fix a bunch of small bugs, and improve the debugging output significantly. --- Diffs of the changes: (+44 -26) GVNPRE.cpp | 70 ++++++++++++++++++++++++++++++++++++++----------------------- 1 files changed, 44 insertions(+), 26 deletions(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.16 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.17 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.16 Mon Jun 4 13:05:26 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Mon Jun 4 18:28:33 2007 @@ -138,15 +138,19 @@ return 0; if (BinaryOperator* BO = dyn_cast(V)) { - Value* newOp1 = phi_translate(VN, MS, set, + Value* newOp1 = isa(BO->getOperand(0)) + ? phi_translate(VN, MS, set, find_leader(VN, set, VN[BO->getOperand(0)]), - pred); + pred) + : BO->getOperand(0); if (newOp1 == 0) return 0; - Value* newOp2 = phi_translate(VN, MS, set, - find_leader(VN, set, VN[BO->getOperand(1)]), - pred); + Value* newOp2 = isa(BO->getOperand(1)) + ? phi_translate(VN, MS, set, + find_leader(VN, set, VN[BO->getOperand(0)]), + pred) + : BO->getOperand(1); if (newOp2 == 0) return 0; @@ -303,8 +307,10 @@ add(VN, MS, BO); - currExps.insert(leftValue); - currExps.insert(rightValue); + if (isa(leftValue)) + currExps.insert(leftValue); + if (isa(rightValue)) + currExps.insert(rightValue); currExps.insert(BO); currTemps.insert(BO); @@ -365,7 +371,13 @@ df_begin(PDT.getRootNode()), E = df_end(DT.getRootNode()); PDI != E; ++PDI) { BasicBlock* BB = PDI->getBlock(); - + DOUT << "Block: " << BB->getName() << "\n"; + DOUT << "TMP_GEN: "; + dump(VN, generatedTemporaries[BB]); + DOUT << "\n"; + + DOUT << "EXP_GEN: "; + dump_unique(VN, generatedExpressions[BB]); visited.insert(BB); std::set& anticIn = anticipatedIn[BB]; @@ -373,31 +385,33 @@ if (BB->getTerminator()->getNumSuccessors() == 1) { if (visited.find(BB) == visited.end()) - phi_translate_set(VN, maximalSet, anticIn, BB, anticOut); + phi_translate_set(VN, maximalSet, maximalSet, BB, anticOut); else - phi_translate_set(VN, anticIn, anticIn, BB, anticOut); + phi_translate_set(VN, maximalSet, anticipatedIn[BB->getTerminator()->getSuccessor(0)], BB, anticOut); } else if (BB->getTerminator()->getNumSuccessors() > 1) { - for (unsigned i = 0; i < BB->getTerminator()->getNumSuccessors(); ++i) { + BasicBlock* first = BB->getTerminator()->getSuccessor(0); + anticOut.insert(anticipatedIn[first].begin(), + anticipatedIn[first].end()); + for (unsigned i = 1; i < BB->getTerminator()->getNumSuccessors(); ++i) { BasicBlock* currSucc = BB->getTerminator()->getSuccessor(i); + std::set& succAnticIn = anticipatedIn[currSucc]; + std::set temp; - if (visited.find(currSucc) == visited.end()) - temp.insert(maximalSet.begin(), maximalSet.end()); - else - temp.insert(anticIn.begin(), anticIn.end()); - - anticIn.clear(); - std::insert_iterator > ai_ins(anticIn, - anticIn.begin()); - - std::set_difference(anticipatedIn[currSucc].begin(), - anticipatedIn[currSucc].end(), - temp.begin(), - temp.end(), - ai_ins, - ExprLT()); + std::insert_iterator > temp_ins(temp, + temp.begin()); + std::set_intersection(anticOut.begin(), anticOut.end(), + succAnticIn.begin(), succAnticIn.end(), + temp_ins, ExprLT()); + + anticOut.clear(); + anticOut.insert(temp.begin(), temp.end()); } } + DOUT << "ANTIC_OUT: "; + dump_unique(VN, anticOut); + DOUT << "\n"; + std::set S; std::insert_iterator > s_ins(S, S.begin()); std::set_union(anticOut.begin(), anticOut.end(), @@ -416,6 +430,10 @@ clean(VN, anticIn); + DOUT << "ANTIC_IN: "; + dump_unique(VN, anticIn); + DOUT << "\n"; + if (old != anticIn) changed = true; From resistor at mac.com Mon Jun 4 18:35:18 2007 From: resistor at mac.com (Owen Anderson) Date: Mon, 4 Jun 2007 18:35:18 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706042335.l54NZI7b012841@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.17 -> 1.18 --- Log message: Don't use std::set_difference when the two sets are sorted differently. Compute the difference manually instead. This allows GVNPRE to produce correct analysis for the example in the GVNPRE paper. --- Diffs of the changes: (+6 -7) GVNPRE.cpp | 13 ++++++------- 1 files changed, 6 insertions(+), 7 deletions(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.17 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.18 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.17 Mon Jun 4 18:28:33 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Mon Jun 4 18:34:56 2007 @@ -420,13 +420,12 @@ s_ins, ExprLT()); anticIn.clear(); - std::insert_iterator > antic_ins(anticIn, - anticIn.begin()); - std::set_difference(S.begin(), S.end(), - generatedTemporaries[BB].begin(), - generatedTemporaries[BB].end(), - antic_ins, - ExprLT()); + + for (std::set::iterator I = S.begin(), E = S.end(); + I != E; ++I) { + if (generatedTemporaries[BB].find(*I) == generatedTemporaries[BB].end()) + anticIn.insert(*I); + } clean(VN, anticIn); From dpatel at apple.com Mon Jun 4 18:45:24 2007 From: dpatel at apple.com (Devang Patel) Date: Mon, 4 Jun 2007 18:45:24 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706042345.l54NjOjX013071@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.89 -> 1.90 --- Log message: s/ETNode::getChildren/ETNode::getETNodeChildren/g --- Diffs of the changes: (+1 -1) Dominators.h | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.89 llvm/include/llvm/Analysis/Dominators.h:1.90 --- llvm/include/llvm/Analysis/Dominators.h:1.89 Mon Jun 4 12:37:59 2007 +++ llvm/include/llvm/Analysis/Dominators.h Mon Jun 4 18:45:02 2007 @@ -343,7 +343,7 @@ return idom ? idom->getData() : 0; } - void getChildren(BasicBlock *A, std::vector& children) const { + void getETNodeChildren(BasicBlock *A, std::vector& children) const { ETNode *NodeA = getNode(A); if (!NodeA) return; const ETNode* son = NodeA->getSon(); From dpatel at apple.com Mon Jun 4 18:45:24 2007 From: dpatel at apple.com (Devang Patel) Date: Mon, 4 Jun 2007 18:45:24 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp Message-ID: <200706042345.l54NjOw2013074@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: CorrelatedExprs.cpp updated: 1.62 -> 1.63 --- Log message: s/ETNode::getChildren/ETNode::getETNodeChildren/g --- Diffs of the changes: (+1 -1) CorrelatedExprs.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp diff -u llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp:1.62 llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp:1.63 --- llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp:1.62 Sun May 6 08:37:16 2007 +++ llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp Mon Jun 4 18:45:02 2007 @@ -352,7 +352,7 @@ // information down now. // std::vector children; - EF->getChildren(BB, children); + EF->getETNodeChildren(BB, children); if (!RI.empty()) { // Time opt: only propagate if we can change something for (std::vector::iterator CI = children.begin(), E = children.end(); CI != E; ++CI) { From dalej at apple.com Mon Jun 4 18:53:25 2007 From: dalej at apple.com (Dale Johannesen) Date: Mon, 4 Jun 2007 18:53:25 -0500 Subject: [llvm-commits] CVS: llvm/test/CodeGen/X86/2007-06-04-tailmerge4.ll Message-ID: <200706042353.l54NrPTm013280@zion.cs.uiuc.edu> Changes in directory llvm/test/CodeGen/X86: 2007-06-04-tailmerge4.ll added (r1.1) --- Log message: Tail merging wasn't working for predecessors of landing pads. PR 1496: http://llvm.org/PR1496 . --- Diffs of the changes: (+454 -0) 2007-06-04-tailmerge4.ll | 454 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 454 insertions(+) Index: llvm/test/CodeGen/X86/2007-06-04-tailmerge4.ll diff -c /dev/null llvm/test/CodeGen/X86/2007-06-04-tailmerge4.ll:1.1 *** /dev/null Mon Jun 4 18:53:04 2007 --- llvm/test/CodeGen/X86/2007-06-04-tailmerge4.ll Mon Jun 4 18:52:54 2007 *************** *** 0 **** --- 1,454 ---- + ; RUN: llvm-as < %s | llc -enable-eh | grep invcont131 + ; PR 1496: tail merge was incorrectly removing this block + + ; ModuleID = 'report.1.bc' + target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64" + target triple = "i686-pc-linux-gnu" + %struct.ALLOC = type { %struct.string___XUB, [2 x i8] } + %struct.RETURN = type { i32, i32, i32, i64 } + %struct.ada__streams__root_stream_type = type { %struct.ada__tags__dispatch_table* } + %struct.ada__tags__dispatch_table = type { [1 x i8*] } + %struct.ada__text_io__text_afcb = type { %struct.system__file_control_block__afcb, i32, i32, i32, i32, i32, %struct.ada__text_io__text_afcb*, i8, i8 } + %struct.string___XUB = type { i32, i32 } + %struct.string___XUP = type { i8*, %struct.string___XUB* } + %struct.system__file_control_block__afcb = type { %struct.ada__streams__root_stream_type, i32, %struct.string___XUP, i32, %struct.string___XUP, i8, i8, i8, i8, i8, i8, i8, %struct.system__file_control_block__afcb*, %struct.system__file_control_block__afcb* } + %struct.system__secondary_stack__mark_id = type { i8*, i32 } + %struct.wide_string___XUP = type { i16*, %struct.string___XUB* } + @report_E = global i8 0 ; [#uses=0] + @report__test_status = internal global i8 1 ; [#uses=8] + @report__test_name = internal global [15 x i8] zeroinitializer ; <[15 x i8]*> [#uses=10] + @report__test_name_len = internal global i32 0 ; [#uses=15] + @.str = internal constant [12 x i8] c"report.adb\00\00" ; <[12 x i8]*> [#uses=1] + @C.26.599 = internal constant %struct.string___XUB { i32 1, i32 1 } ; <%struct.string___XUB*> [#uses=1] + @.str1 = internal constant [1 x i8] c":" ; <[1 x i8]*> [#uses=1] + @.str2 = internal constant [1 x i8] c" " ; <[1 x i8]*> [#uses=1] + @.str3 = internal constant [1 x i8] c"-" ; <[1 x i8]*> [#uses=1] + @.str5 = internal constant [10 x i8] c"0123456789" ; <[10 x i8]*> [#uses=12] + @C.59.855 = internal constant %struct.string___XUB { i32 1, i32 0 } ; <%struct.string___XUB*> [#uses=1] + @C.69.876 = internal constant %struct.string___XUB { i32 1, i32 3 } ; <%struct.string___XUB*> [#uses=1] + @C.70.879 = internal constant %struct.string___XUB { i32 1, i32 6 } ; <%struct.string___XUB*> [#uses=1] + @C.81.900 = internal constant %struct.string___XUB { i32 1, i32 5 } ; <%struct.string___XUB*> [#uses=1] + @.str6 = internal constant [0 x i8] zeroinitializer ; <[0 x i8]*> [#uses=1] + @.str7 = internal constant [3 x i8] c"2.5" ; <[3 x i8]*> [#uses=1] + @.str8 = internal constant [6 x i8] c"ACATS " ; <[6 x i8]*> [#uses=1] + @.str9 = internal constant [5 x i8] c",.,. " ; <[5 x i8]*> [#uses=1] + @.str10 = internal constant [1 x i8] c"." ; <[1 x i8]*> [#uses=1] + @.str11 = internal constant [5 x i8] c"---- " ; <[5 x i8]*> [#uses=1] + @.str12 = internal constant [5 x i8] c" - " ; <[5 x i8]*> [#uses=1] + @.str13 = internal constant [5 x i8] c" * " ; <[5 x i8]*> [#uses=1] + @.str14 = internal constant [5 x i8] c" + " ; <[5 x i8]*> [#uses=1] + @.str15 = internal constant [5 x i8] c" ! " ; <[5 x i8]*> [#uses=1] + @C.209.1380 = internal constant %struct.string___XUB { i32 1, i32 37 } ; <%struct.string___XUB*> [#uses=1] + @.str16 = internal constant [37 x i8] c" PASSED ============================." ; <[37 x i8]*> [#uses=1] + @.str17 = internal constant [5 x i8] c"==== " ; <[5 x i8]*> [#uses=1] + @.str18 = internal constant [37 x i8] c" NOT-APPLICABLE ++++++++++++++++++++." ; <[37 x i8]*> [#uses=1] + @.str19 = internal constant [5 x i8] c"++++ " ; <[5 x i8]*> [#uses=1] + @.str20 = internal constant [37 x i8] c" TENTATIVELY PASSED !!!!!!!!!!!!!!!!." ; <[37 x i8]*> [#uses=1] + @.str21 = internal constant [5 x i8] c"!!!! " ; <[5 x i8]*> [#uses=1] + @.str22 = internal constant [37 x i8] c" SEE '!' COMMENTS FOR SPECIAL NOTES!!" ; <[37 x i8]*> [#uses=1] + @.str23 = internal constant [37 x i8] c" FAILED ****************************." ; <[37 x i8]*> [#uses=1] + @.str24 = internal constant [5 x i8] c"**** " ; <[5 x i8]*> [#uses=1] + @__gnat_others_value = external constant i32 ; [#uses=2] + @system__soft_links__abort_undefer = external global void ()* ; [#uses=1] + @C.320.1854 = internal constant %struct.string___XUB { i32 2, i32 6 } ; <%struct.string___XUB*> [#uses=1] + + declare void @report__put_msg(i64 %msg.0.0) + + declare void @__gnat_rcheck_05(i8*, i32) + + declare void @__gnat_rcheck_12(i8*, i32) + + declare %struct.ada__text_io__text_afcb* @ada__text_io__standard_output() + + declare void @ada__text_io__set_col(%struct.ada__text_io__text_afcb*, i32) + + declare void @ada__text_io__put_line(%struct.ada__text_io__text_afcb*, i64) + + declare void @report__time_stamp(%struct.string___XUP* sret %agg.result) + + declare i64 @ada__calendar__clock() + + declare void @ada__calendar__split(%struct.RETURN* sret , i64) + + declare void @system__string_ops_concat_5__str_concat_5(%struct.string___XUP* sret , i64, i64, i64, i64, i64) + + declare void @system__string_ops_concat_3__str_concat_3(%struct.string___XUP* sret , i64, i64, i64) + + declare i8* @system__secondary_stack__ss_allocate(i32) + + declare void @report__test(i64 %name.0.0, i64 %descr.0.0) + + declare void @system__secondary_stack__ss_mark(%struct.system__secondary_stack__mark_id* sret ) + + declare i8* @llvm.eh.exception() + + declare i32 @llvm.eh.selector(i8*, i8*, ...) + + declare i32 @llvm.eh.typeid.for(i8*) + + declare i32 @__gnat_eh_personality(...) + + declare i32 @_Unwind_Resume(...) + + declare void @__gnat_rcheck_07(i8*, i32) + + declare void @system__secondary_stack__ss_release(i64) + + declare void @report__comment(i64 %descr.0.0) + + declare void @report__failed(i64 %descr.0.0) + + declare void @report__not_applicable(i64 %descr.0.0) + + declare void @report__special_action(i64 %descr.0.0) + + define void @report__result() { + entry: + %tmp = alloca %struct.system__secondary_stack__mark_id, align 8 ; <%struct.system__secondary_stack__mark_id*> [#uses=3] + %A.210 = alloca %struct.string___XUB, align 8 ; <%struct.string___XUB*> [#uses=3] + %tmp5 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %A.229 = alloca %struct.string___XUB, align 8 ; <%struct.string___XUB*> [#uses=3] + %tmp10 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %A.248 = alloca %struct.string___XUB, align 8 ; <%struct.string___XUB*> [#uses=3] + %tmp15 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %A.270 = alloca %struct.string___XUB, align 8 ; <%struct.string___XUB*> [#uses=3] + %tmp20 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %A.284 = alloca %struct.string___XUB, align 8 ; <%struct.string___XUB*> [#uses=3] + %tmp25 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + call void @system__secondary_stack__ss_mark( %struct.system__secondary_stack__mark_id* %tmp sret ) + %tmp28 = getelementptr %struct.system__secondary_stack__mark_id* %tmp, i32 0, i32 0 ; [#uses=1] + %tmp29 = load i8** %tmp28 ; [#uses=2] + %tmp31 = getelementptr %struct.system__secondary_stack__mark_id* %tmp, i32 0, i32 1 ; [#uses=1] + %tmp32 = load i32* %tmp31 ; [#uses=2] + %tmp33 = load i8* @report__test_status ; [#uses=1] + switch i8 %tmp33, label %bb483 [ + i8 0, label %bb + i8 2, label %bb143 + i8 3, label %bb261 + ] + + bb: ; preds = %entry + %tmp34 = load i32* @report__test_name_len ; [#uses=4] + %tmp35 = icmp sgt i32 %tmp34, 0 ; [#uses=2] + %tmp40 = icmp sgt i32 %tmp34, 15 ; [#uses=1] + %bothcond139 = and i1 %tmp35, %tmp40 ; [#uses=1] + br i1 %bothcond139, label %cond_true43, label %cond_next44 + + cond_true43: ; preds = %bb + invoke void @__gnat_rcheck_12( i8* getelementptr ([12 x i8]* @.str, i32 0, i32 0), i32 212 ) + to label %UnifiedUnreachableBlock unwind label %unwind + + unwind: ; preds = %invcont589, %cond_next567, %bb555, %cond_true497, %invcont249, %cond_next227, %bb215, %cond_true157, %invcont131, %cond_next109, %bb97, %cond_true43 + %eh_ptr = call i8* @llvm.eh.exception( ) ; [#uses=1] + br label %cleanup717 + + cond_next44: ; preds = %bb + %tmp72 = getelementptr %struct.string___XUB* %A.210, i32 0, i32 0 ; [#uses=1] + store i32 1, i32* %tmp72 + %tmp73 = getelementptr %struct.string___XUB* %A.210, i32 0, i32 1 ; [#uses=1] + store i32 %tmp34, i32* %tmp73 + br i1 %tmp35, label %cond_true80, label %cond_next109 + + cond_true80: ; preds = %cond_next44 + %tmp45.off = add i32 %tmp34, -1 ; [#uses=1] + %bothcond = icmp ugt i32 %tmp45.off, 14 ; [#uses=1] + br i1 %bothcond, label %bb97, label %cond_next109 + + bb97: ; preds = %cond_true80 + invoke void @__gnat_rcheck_05( i8* getelementptr ([12 x i8]* @.str, i32 0, i32 0), i32 212 ) + to label %UnifiedUnreachableBlock unwind label %unwind + + cond_next109: ; preds = %cond_true80, %cond_next44 + %A.210128 = ptrtoint %struct.string___XUB* %A.210 to i32 ; [#uses=1] + %A.210128129 = zext i32 %A.210128 to i64 ; [#uses=1] + %A.210128129130 = shl i64 %A.210128129, 32 ; [#uses=1] + %A.210128129130.ins = or i64 %A.210128129130, zext (i32 ptrtoint ([15 x i8]* @report__test_name to i32) to i64) ; [#uses=1] + invoke void @system__string_ops_concat_3__str_concat_3( %struct.string___XUP* %tmp5 sret , i64 or (i64 zext (i32 ptrtoint ([5 x i8]* @.str17 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.81.900 to i32) to i64), i64 32)), i64 %A.210128129130.ins, i64 or (i64 zext (i32 ptrtoint ([37 x i8]* @.str16 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.209.1380 to i32) to i64), i64 32)) ) + to label %invcont131 unwind label %unwind + + invcont131: ; preds = %cond_next109 + %tmp133 = getelementptr %struct.string___XUP* %tmp5, i32 0, i32 0 ; [#uses=1] + %tmp134 = load i8** %tmp133 ; [#uses=1] + %tmp134120 = ptrtoint i8* %tmp134 to i32 ; [#uses=1] + %tmp134120121 = zext i32 %tmp134120 to i64 ; [#uses=1] + %tmp136 = getelementptr %struct.string___XUP* %tmp5, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp137 = load %struct.string___XUB** %tmp136 ; <%struct.string___XUB*> [#uses=1] + %tmp137116 = ptrtoint %struct.string___XUB* %tmp137 to i32 ; [#uses=1] + %tmp137116117 = zext i32 %tmp137116 to i64 ; [#uses=1] + %tmp137116117118 = shl i64 %tmp137116117, 32 ; [#uses=1] + %tmp137116117118.ins = or i64 %tmp137116117118, %tmp134120121 ; [#uses=1] + invoke fastcc void @report__put_msg( i64 %tmp137116117118.ins ) + to label %cond_next618 unwind label %unwind + + bb143: ; preds = %entry + %tmp144 = load i32* @report__test_name_len ; [#uses=4] + %tmp147 = icmp sgt i32 %tmp144, 0 ; [#uses=2] + %tmp154 = icmp sgt i32 %tmp144, 15 ; [#uses=1] + %bothcond140 = and i1 %tmp147, %tmp154 ; [#uses=1] + br i1 %bothcond140, label %cond_true157, label %cond_next160 + + cond_true157: ; preds = %bb143 + invoke void @__gnat_rcheck_12( i8* getelementptr ([12 x i8]* @.str, i32 0, i32 0), i32 215 ) + to label %UnifiedUnreachableBlock unwind label %unwind + + cond_next160: ; preds = %bb143 + %tmp189 = getelementptr %struct.string___XUB* %A.229, i32 0, i32 0 ; [#uses=1] + store i32 1, i32* %tmp189 + %tmp190 = getelementptr %struct.string___XUB* %A.229, i32 0, i32 1 ; [#uses=1] + store i32 %tmp144, i32* %tmp190 + br i1 %tmp147, label %cond_true197, label %cond_next227 + + cond_true197: ; preds = %cond_next160 + %tmp161.off = add i32 %tmp144, -1 ; [#uses=1] + %bothcond1 = icmp ugt i32 %tmp161.off, 14 ; [#uses=1] + br i1 %bothcond1, label %bb215, label %cond_next227 + + bb215: ; preds = %cond_true197 + invoke void @__gnat_rcheck_05( i8* getelementptr ([12 x i8]* @.str, i32 0, i32 0), i32 215 ) + to label %UnifiedUnreachableBlock unwind label %unwind + + cond_next227: ; preds = %cond_true197, %cond_next160 + %A.229105 = ptrtoint %struct.string___XUB* %A.229 to i32 ; [#uses=1] + %A.229105106 = zext i32 %A.229105 to i64 ; [#uses=1] + %A.229105106107 = shl i64 %A.229105106, 32 ; [#uses=1] + %A.229105106107.ins = or i64 %A.229105106107, zext (i32 ptrtoint ([15 x i8]* @report__test_name to i32) to i64) ; [#uses=1] + invoke void @system__string_ops_concat_3__str_concat_3( %struct.string___XUP* %tmp10 sret , i64 or (i64 zext (i32 ptrtoint ([5 x i8]* @.str19 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.81.900 to i32) to i64), i64 32)), i64 %A.229105106107.ins, i64 or (i64 zext (i32 ptrtoint ([37 x i8]* @.str18 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.209.1380 to i32) to i64), i64 32)) ) + to label %invcont249 unwind label %unwind + + invcont249: ; preds = %cond_next227 + %tmp251 = getelementptr %struct.string___XUP* %tmp10, i32 0, i32 0 ; [#uses=1] + %tmp252 = load i8** %tmp251 ; [#uses=1] + %tmp25297 = ptrtoint i8* %tmp252 to i32 ; [#uses=1] + %tmp2529798 = zext i32 %tmp25297 to i64 ; [#uses=1] + %tmp254 = getelementptr %struct.string___XUP* %tmp10, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp255 = load %struct.string___XUB** %tmp254 ; <%struct.string___XUB*> [#uses=1] + %tmp25593 = ptrtoint %struct.string___XUB* %tmp255 to i32 ; [#uses=1] + %tmp2559394 = zext i32 %tmp25593 to i64 ; [#uses=1] + %tmp255939495 = shl i64 %tmp2559394, 32 ; [#uses=1] + %tmp255939495.ins = or i64 %tmp255939495, %tmp2529798 ; [#uses=1] + invoke fastcc void @report__put_msg( i64 %tmp255939495.ins ) + to label %cond_next618 unwind label %unwind + + bb261: ; preds = %entry + %tmp262 = call i8* @llvm.stacksave( ) ; [#uses=2] + %tmp263 = load i32* @report__test_name_len ; [#uses=4] + %tmp266 = icmp sgt i32 %tmp263, 0 ; [#uses=2] + %tmp273 = icmp sgt i32 %tmp263, 15 ; [#uses=1] + %bothcond141 = and i1 %tmp266, %tmp273 ; [#uses=1] + br i1 %bothcond141, label %cond_true276, label %cond_next281 + + cond_true276: ; preds = %bb261 + invoke void @__gnat_rcheck_12( i8* getelementptr ([12 x i8]* @.str, i32 0, i32 0), i32 218 ) + to label %UnifiedUnreachableBlock unwind label %unwind277 + + unwind277: ; preds = %invcont467, %cond_next442, %invcont370, %cond_next348, %bb336, %cond_true276 + %eh_ptr278 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @llvm.stackrestore( i8* %tmp262 ) + br label %cleanup717 + + cond_next281: ; preds = %bb261 + %tmp310 = getelementptr %struct.string___XUB* %A.248, i32 0, i32 0 ; [#uses=1] + store i32 1, i32* %tmp310 + %tmp311 = getelementptr %struct.string___XUB* %A.248, i32 0, i32 1 ; [#uses=1] + store i32 %tmp263, i32* %tmp311 + br i1 %tmp266, label %cond_true318, label %cond_next348 + + cond_true318: ; preds = %cond_next281 + %tmp282.off = add i32 %tmp263, -1 ; [#uses=1] + %bothcond2 = icmp ugt i32 %tmp282.off, 14 ; [#uses=1] + br i1 %bothcond2, label %bb336, label %cond_next348 + + bb336: ; preds = %cond_true318 + invoke void @__gnat_rcheck_05( i8* getelementptr ([12 x i8]* @.str, i32 0, i32 0), i32 218 ) + to label %UnifiedUnreachableBlock unwind label %unwind277 + + cond_next348: ; preds = %cond_true318, %cond_next281 + %A.24882 = ptrtoint %struct.string___XUB* %A.248 to i32 ; [#uses=1] + %A.2488283 = zext i32 %A.24882 to i64 ; [#uses=1] + %A.248828384 = shl i64 %A.2488283, 32 ; [#uses=1] + %A.248828384.ins = or i64 %A.248828384, zext (i32 ptrtoint ([15 x i8]* @report__test_name to i32) to i64) ; [#uses=1] + invoke void @system__string_ops_concat_3__str_concat_3( %struct.string___XUP* %tmp15 sret , i64 or (i64 zext (i32 ptrtoint ([5 x i8]* @.str21 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.81.900 to i32) to i64), i64 32)), i64 %A.248828384.ins, i64 or (i64 zext (i32 ptrtoint ([37 x i8]* @.str20 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.209.1380 to i32) to i64), i64 32)) ) + to label %invcont370 unwind label %unwind277 + + invcont370: ; preds = %cond_next348 + %tmp372 = getelementptr %struct.string___XUP* %tmp15, i32 0, i32 0 ; [#uses=1] + %tmp373 = load i8** %tmp372 ; [#uses=1] + %tmp37374 = ptrtoint i8* %tmp373 to i32 ; [#uses=1] + %tmp3737475 = zext i32 %tmp37374 to i64 ; [#uses=1] + %tmp375 = getelementptr %struct.string___XUP* %tmp15, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp376 = load %struct.string___XUB** %tmp375 ; <%struct.string___XUB*> [#uses=1] + %tmp37670 = ptrtoint %struct.string___XUB* %tmp376 to i32 ; [#uses=1] + %tmp3767071 = zext i32 %tmp37670 to i64 ; [#uses=1] + %tmp376707172 = shl i64 %tmp3767071, 32 ; [#uses=1] + %tmp376707172.ins = or i64 %tmp376707172, %tmp3737475 ; [#uses=1] + invoke fastcc void @report__put_msg( i64 %tmp376707172.ins ) + to label %invcont381 unwind label %unwind277 + + invcont381: ; preds = %invcont370 + %tmp382 = load i32* @report__test_name_len ; [#uses=6] + %tmp415 = icmp sgt i32 %tmp382, -1 ; [#uses=1] + %max416 = select i1 %tmp415, i32 %tmp382, i32 0 ; [#uses=1] + %tmp417 = alloca i8, i32 %max416 ; [#uses=3] + %tmp423 = icmp sgt i32 %tmp382, 0 ; [#uses=1] + br i1 %tmp423, label %bb427, label %cond_next442 + + bb427: ; preds = %invcont381 + store i8 32, i8* %tmp417 + %tmp434 = icmp eq i32 %tmp382, 1 ; [#uses=1] + br i1 %tmp434, label %cond_next442, label %cond_next438.preheader + + cond_next438.preheader: ; preds = %bb427 + %tmp. = add i32 %tmp382, -1 ; [#uses=1] + br label %cond_next438 + + cond_next438: ; preds = %cond_next438, %cond_next438.preheader + %indvar = phi i32 [ 0, %cond_next438.preheader ], [ %J130b.513.5, %cond_next438 ] ; [#uses=1] + %J130b.513.5 = add i32 %indvar, 1 ; [#uses=3] + %tmp43118 = getelementptr i8* %tmp417, i32 %J130b.513.5 ; [#uses=1] + store i8 32, i8* %tmp43118 + %exitcond = icmp eq i32 %J130b.513.5, %tmp. ; [#uses=1] + br i1 %exitcond, label %cond_next442, label %cond_next438 + + cond_next442: ; preds = %cond_next438, %bb427, %invcont381 + %tmp448 = getelementptr %struct.string___XUB* %A.270, i32 0, i32 0 ; [#uses=1] + store i32 1, i32* %tmp448 + %tmp449 = getelementptr %struct.string___XUB* %A.270, i32 0, i32 1 ; [#uses=1] + store i32 %tmp382, i32* %tmp449 + %tmp41762 = ptrtoint i8* %tmp417 to i32 ; [#uses=1] + %tmp4176263 = zext i32 %tmp41762 to i64 ; [#uses=1] + %A.27058 = ptrtoint %struct.string___XUB* %A.270 to i32 ; [#uses=1] + %A.2705859 = zext i32 %A.27058 to i64 ; [#uses=1] + %A.270585960 = shl i64 %A.2705859, 32 ; [#uses=1] + %A.270585960.ins = or i64 %tmp4176263, %A.270585960 ; [#uses=1] + invoke void @system__string_ops_concat_3__str_concat_3( %struct.string___XUP* %tmp20 sret , i64 or (i64 zext (i32 ptrtoint ([5 x i8]* @.str21 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.81.900 to i32) to i64), i64 32)), i64 %A.270585960.ins, i64 or (i64 zext (i32 ptrtoint ([37 x i8]* @.str22 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.209.1380 to i32) to i64), i64 32)) ) + to label %invcont467 unwind label %unwind277 + + invcont467: ; preds = %cond_next442 + %tmp469 = getelementptr %struct.string___XUP* %tmp20, i32 0, i32 0 ; [#uses=1] + %tmp470 = load i8** %tmp469 ; [#uses=1] + %tmp47050 = ptrtoint i8* %tmp470 to i32 ; [#uses=1] + %tmp4705051 = zext i32 %tmp47050 to i64 ; [#uses=1] + %tmp472 = getelementptr %struct.string___XUP* %tmp20, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp473 = load %struct.string___XUB** %tmp472 ; <%struct.string___XUB*> [#uses=1] + %tmp47346 = ptrtoint %struct.string___XUB* %tmp473 to i32 ; [#uses=1] + %tmp4734647 = zext i32 %tmp47346 to i64 ; [#uses=1] + %tmp473464748 = shl i64 %tmp4734647, 32 ; [#uses=1] + %tmp473464748.ins = or i64 %tmp473464748, %tmp4705051 ; [#uses=1] + invoke fastcc void @report__put_msg( i64 %tmp473464748.ins ) + to label %cleanup unwind label %unwind277 + + cleanup: ; preds = %invcont467 + call void @llvm.stackrestore( i8* %tmp262 ) + br label %cond_next618 + + bb483: ; preds = %entry + %tmp484 = load i32* @report__test_name_len ; [#uses=4] + %tmp487 = icmp sgt i32 %tmp484, 0 ; [#uses=2] + %tmp494 = icmp sgt i32 %tmp484, 15 ; [#uses=1] + %bothcond142 = and i1 %tmp487, %tmp494 ; [#uses=1] + br i1 %bothcond142, label %cond_true497, label %cond_next500 + + cond_true497: ; preds = %bb483 + invoke void @__gnat_rcheck_12( i8* getelementptr ([12 x i8]* @.str, i32 0, i32 0), i32 223 ) + to label %UnifiedUnreachableBlock unwind label %unwind + + cond_next500: ; preds = %bb483 + %tmp529 = getelementptr %struct.string___XUB* %A.284, i32 0, i32 0 ; [#uses=1] + store i32 1, i32* %tmp529 + %tmp530 = getelementptr %struct.string___XUB* %A.284, i32 0, i32 1 ; [#uses=1] + store i32 %tmp484, i32* %tmp530 + br i1 %tmp487, label %cond_true537, label %cond_next567 + + cond_true537: ; preds = %cond_next500 + %tmp501.off = add i32 %tmp484, -1 ; [#uses=1] + %bothcond3 = icmp ugt i32 %tmp501.off, 14 ; [#uses=1] + br i1 %bothcond3, label %bb555, label %cond_next567 + + bb555: ; preds = %cond_true537 + invoke void @__gnat_rcheck_05( i8* getelementptr ([12 x i8]* @.str, i32 0, i32 0), i32 223 ) + to label %UnifiedUnreachableBlock unwind label %unwind + + cond_next567: ; preds = %cond_true537, %cond_next500 + %A.28435 = ptrtoint %struct.string___XUB* %A.284 to i32 ; [#uses=1] + %A.2843536 = zext i32 %A.28435 to i64 ; [#uses=1] + %A.284353637 = shl i64 %A.2843536, 32 ; [#uses=1] + %A.284353637.ins = or i64 %A.284353637, zext (i32 ptrtoint ([15 x i8]* @report__test_name to i32) to i64) ; [#uses=1] + invoke void @system__string_ops_concat_3__str_concat_3( %struct.string___XUP* %tmp25 sret , i64 or (i64 zext (i32 ptrtoint ([5 x i8]* @.str24 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.81.900 to i32) to i64), i64 32)), i64 %A.284353637.ins, i64 or (i64 zext (i32 ptrtoint ([37 x i8]* @.str23 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.209.1380 to i32) to i64), i64 32)) ) + to label %invcont589 unwind label %unwind + + invcont589: ; preds = %cond_next567 + %tmp591 = getelementptr %struct.string___XUP* %tmp25, i32 0, i32 0 ; [#uses=1] + %tmp592 = load i8** %tmp591 ; [#uses=1] + %tmp59228 = ptrtoint i8* %tmp592 to i32 ; [#uses=1] + %tmp5922829 = zext i32 %tmp59228 to i64 ; [#uses=1] + %tmp594 = getelementptr %struct.string___XUP* %tmp25, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp595 = load %struct.string___XUB** %tmp594 ; <%struct.string___XUB*> [#uses=1] + %tmp59524 = ptrtoint %struct.string___XUB* %tmp595 to i32 ; [#uses=1] + %tmp5952425 = zext i32 %tmp59524 to i64 ; [#uses=1] + %tmp595242526 = shl i64 %tmp5952425, 32 ; [#uses=1] + %tmp595242526.ins = or i64 %tmp595242526, %tmp5922829 ; [#uses=1] + invoke fastcc void @report__put_msg( i64 %tmp595242526.ins ) + to label %cond_next618 unwind label %unwind + + cond_next618: ; preds = %invcont589, %cleanup, %invcont249, %invcont131 + store i8 1, i8* @report__test_status + store i32 7, i32* @report__test_name_len + store i8 78, i8* getelementptr ([15 x i8]* @report__test_name, i32 0, i32 0) + store i8 79, i8* getelementptr ([15 x i8]* @report__test_name, i32 0, i32 1) + store i8 95, i8* getelementptr ([15 x i8]* @report__test_name, i32 0, i32 2) + store i8 78, i8* getelementptr ([15 x i8]* @report__test_name, i32 0, i32 3) + store i8 65, i8* getelementptr ([15 x i8]* @report__test_name, i32 0, i32 4) + store i8 77, i8* getelementptr ([15 x i8]* @report__test_name, i32 0, i32 5) + store i8 69, i8* getelementptr ([15 x i8]* @report__test_name, i32 0, i32 6) + %CHAIN.310.0.0.0.val5.i = ptrtoint i8* %tmp29 to i32 ; [#uses=1] + %CHAIN.310.0.0.0.val56.i = zext i32 %CHAIN.310.0.0.0.val5.i to i64 ; [#uses=1] + %CHAIN.310.0.0.1.val2.i = zext i32 %tmp32 to i64 ; [#uses=1] + %CHAIN.310.0.0.1.val23.i = shl i64 %CHAIN.310.0.0.1.val2.i, 32 ; [#uses=1] + %CHAIN.310.0.0.1.val23.ins.i = or i64 %CHAIN.310.0.0.1.val23.i, %CHAIN.310.0.0.0.val56.i ; [#uses=1] + call void @system__secondary_stack__ss_release( i64 %CHAIN.310.0.0.1.val23.ins.i ) + ret void + + cleanup717: ; preds = %unwind277, %unwind + %eh_exception.0 = phi i8* [ %eh_ptr278, %unwind277 ], [ %eh_ptr, %unwind ] ; [#uses=1] + %CHAIN.310.0.0.0.val5.i8 = ptrtoint i8* %tmp29 to i32 ; [#uses=1] + %CHAIN.310.0.0.0.val56.i9 = zext i32 %CHAIN.310.0.0.0.val5.i8 to i64 ; [#uses=1] + %CHAIN.310.0.0.1.val2.i10 = zext i32 %tmp32 to i64 ; [#uses=1] + %CHAIN.310.0.0.1.val23.i11 = shl i64 %CHAIN.310.0.0.1.val2.i10, 32 ; [#uses=1] + %CHAIN.310.0.0.1.val23.ins.i12 = or i64 %CHAIN.310.0.0.1.val23.i11, %CHAIN.310.0.0.0.val56.i9 ; [#uses=1] + call void @system__secondary_stack__ss_release( i64 %CHAIN.310.0.0.1.val23.ins.i12 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_exception.0 ) ; :0 [#uses=0] + unreachable + + UnifiedUnreachableBlock: ; preds = %bb555, %cond_true497, %bb336, %cond_true276, %bb215, %cond_true157, %bb97, %cond_true43 + unreachable + } + + declare i8* @llvm.stacksave() + + declare void @llvm.stackrestore(i8*) + + declare i32 @report__ident_int(i32 %x) + + declare i8 @report__equal(i32 %x, i32 %y) + + declare i8 @report__ident_char(i8 zext %x) + + declare i16 @report__ident_wide_char(i16 zext %x) + + declare i8 @report__ident_bool(i8 %x) + + declare void @report__ident_str(%struct.string___XUP* sret %agg.result, i64 %x.0.0) + + declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) + + declare void @report__ident_wide_str(%struct.wide_string___XUP* sret %agg.result, i64 %x.0.0) + + declare void @__gnat_begin_handler(i8*) + + declare void @__gnat_end_handler(i8*) + + declare void @report__legal_file_name(%struct.string___XUP* sret %agg.result, i32 %x, i64 %nam.0.0) + + declare void @__gnat_rcheck_06(i8*, i32) + + declare void @system__string_ops__str_concat_cs(%struct.string___XUP* sret , i8 zext , i64) From isanbard at gmail.com Mon Jun 4 18:53:30 2007 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 4 Jun 2007 18:53:30 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp Message-ID: <200706042353.l54NrUIf013286@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: PredicateSimplifier.cpp updated: 1.77 -> 1.78 --- Log message: Patches by Chuck Rose to unbreak V Studio builds. Thanks Chuck! --- Diffs of the changes: (+15 -0) PredicateSimplifier.cpp | 15 +++++++++++++++ 1 files changed, 15 insertions(+) Index: llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp diff -u llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp:1.77 llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp:1.78 --- llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp:1.77 Sun Jun 3 19:32:21 2007 +++ llvm/lib/Transforms/Scalar/PredicateSimplifier.cpp Mon Jun 4 18:52:59 2007 @@ -232,6 +232,13 @@ bool operator<(unsigned to) const { return To < to; } + bool operator>(unsigned to) const { + return To > to; + } + + friend bool operator<(unsigned to, const Edge &edge) { + return edge.operator>(to); + } }; /// A single node in the InequalityGraph. This stores the canonical Value @@ -669,6 +676,14 @@ bool operator<(const Value *value) const { return V < value; } + + bool operator>(const Value *value) const { + return V > value; + } + + friend bool operator<(const Value *value, const ScopedRange &range) { + return range.operator>(value); + } }; TargetData *TD; From dalej at apple.com Mon Jun 4 18:53:31 2007 From: dalej at apple.com (Dale Johannesen) Date: Mon, 4 Jun 2007 18:53:31 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/BranchFolding.cpp Message-ID: <200706042353.l54NrVMo013292@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: BranchFolding.cpp updated: 1.64 -> 1.65 --- Log message: Tail merging wasn't working for predecessors of landing pads. PR 1496: http://llvm.org/PR1496 . --- Diffs of the changes: (+22 -0) BranchFolding.cpp | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+) Index: llvm/lib/CodeGen/BranchFolding.cpp diff -u llvm/lib/CodeGen/BranchFolding.cpp:1.64 llvm/lib/CodeGen/BranchFolding.cpp:1.65 --- llvm/lib/CodeGen/BranchFolding.cpp:1.64 Mon Jun 4 01:44:01 2007 +++ llvm/lib/CodeGen/BranchFolding.cpp Mon Jun 4 18:52:54 2007 @@ -622,6 +622,28 @@ if (!FBB) FBB = next(MachineFunction::iterator(PBB)); } + // Failing case: the only way IBB can be reached from PBB is via + // exception handling. Happens for landing pads. Would be nice + // to have a bit in the edge so we didn't have to do all this. + if (IBB->isLandingPad()) { + MachineFunction::iterator IP = PBB; IP++; + MachineBasicBlock* PredNextBB = NULL; + if (IP!=MF.end()) + PredNextBB = IP; + if (TBB==NULL) { + if (IBB!=PredNextBB) // fallthrough + continue; + } else if (FBB) { + if (TBB!=IBB && FBB!=IBB) // cbr then ubr + continue; + } else if (Cond.size() == 0) { + if (TBB!=IBB) // ubr + continue; + } else { + if (TBB!=IBB && IBB!=PredNextBB) // cbr + continue; + } + } // Remove the unconditional branch at the end, if any. if (TBB && (Cond.size()==0 || FBB)) { TII->RemoveBranch(*PBB); From isanbard at gmail.com Mon Jun 4 18:53:32 2007 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 4 Jun 2007 18:53:32 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/RegisterInfoEmitter.cpp Message-ID: <200706042353.l54NrWO1013297@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: RegisterInfoEmitter.cpp updated: 1.55 -> 1.56 --- Log message: Patches by Chuck Rose to unbreak V Studio builds. Thanks Chuck! --- Diffs of the changes: (+1 -0) RegisterInfoEmitter.cpp | 1 + 1 files changed, 1 insertion(+) Index: llvm/utils/TableGen/RegisterInfoEmitter.cpp diff -u llvm/utils/TableGen/RegisterInfoEmitter.cpp:1.55 llvm/utils/TableGen/RegisterInfoEmitter.cpp:1.56 --- llvm/utils/TableGen/RegisterInfoEmitter.cpp:1.55 Mon Jun 4 11:11:03 2007 +++ llvm/utils/TableGen/RegisterInfoEmitter.cpp Mon Jun 4 18:52:59 2007 @@ -478,6 +478,7 @@ OS << " }; break;\n"; } OS << " };\n"; + OS << " return 0;\n"; OS << "}\n\n"; // Emit the constructor of the class... From isanbard at gmail.com Mon Jun 4 18:54:06 2007 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 4 Jun 2007 16:54:06 -0700 Subject: [llvm-commits] Patch for review-- for VStudio build breaks In-Reply-To: <680422C0AA225644931C2F6DD07200DD3EE799@namail5.corp.adobe.com> References: <680422C0AA225644931C2F6DD07200DD3EE799@namail5.corp.adobe.com> Message-ID: <16e5fdf90706041654j30d1c089k4682bcb804fe7897@mail.gmail.com> On 6/1/07, Chuck Rose III wrote: > > Hola LLVMers, > Guten tag! :-) > I've attached a patch I've built against a newly sync'ed tree for the > VStudio-related build breaks for your review. I do not have commit access, > so I will need one of you to commit it once it's blessed. > > I've compiled it against MacOSX to check to see that everything still built > ok on my other primary system, but I haven't checked it against a wider set > of targets. > > Apologies if this isn't the right place to send this, I haven't done a patch > before, but the instructions seemed to indicate that this was the procedure. > This list should be okay to send patches. I applied the changes. Thanks! -bw From evan.cheng at apple.com Mon Jun 4 19:07:59 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 4 Jun 2007 19:07:59 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706050007.l5507xd3013842@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.23 -> 1.24 --- Log message: Fix some subtle bugs: bug during succeessor copying; incorrectly updating states of ifcvted blocks. --- Diffs of the changes: (+19 -20) IfConversion.cpp | 39 +++++++++++++++++++-------------------- 1 files changed, 19 insertions(+), 20 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.23 llvm/lib/CodeGen/IfConversion.cpp:1.24 --- llvm/lib/CodeGen/IfConversion.cpp:1.23 Mon Jun 4 15:33:36 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Mon Jun 4 19:07:37 2007 @@ -153,7 +153,9 @@ default: assert(false && "Unexpected!"); break; case ICReAnalyze: - // One or more of 'childrean' have been modified, abort! + // One or more of 'children' have been modified, abort! + case ICDead: + // Block has been already been if-converted, abort! break; case ICSimple: case ICSimpleFalse: @@ -219,9 +221,10 @@ void IfConverter::StructuralAnalysis(MachineBasicBlock *BB) { BBInfo &BBI = BBAnalysis[BB->getNumber()]; - if (BBI.Kind == ICReAnalyze) + if (BBI.Kind == ICReAnalyze) { BBI.BrCond.clear(); - else { + BBI.TrueBB = BBI.FalseBB = NULL; + } else { if (BBI.Kind != ICNotAnalyzed) return; // Already analyzed. BBI.BB = BB; @@ -504,10 +507,7 @@ std::copy(Cond.begin(), Cond.end(), std::back_inserter(BBI.Predicate)); // Update block info. BB can be iteratively if-converted. - BBI.Kind = ICNotAnalyzed; - BBI.TrueBB = BBI.FalseBB = NULL; - BBI.BrCond.clear(); - TII->AnalyzeBranch(*BBI.BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond); + BBI.Kind = ICReAnalyze; ReTryPreds(BBI.BB); CvtBBI->Kind = ICDead; @@ -537,9 +537,11 @@ // Join the 'true' and 'false' blocks if the 'false' block has no other // predecessors. Otherwise, add a unconditional branch from 'true' to 'false'. BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; - if (FalseBBI.BB->pred_size() == 2) + bool FalseBBDead = false; + if (FalseBBI.BB->pred_size() == 2) { MergeBlocks(TrueBBI, FalseBBI); - else if (!isNextBlock(TrueBBI.BB, FalseBBI.BB)) + FalseBBDead = true; + } else if (!isNextBlock(TrueBBI.BB, FalseBBI.BB)) InsertUncondBranch(TrueBBI.BB, FalseBBI.BB, TII); // Now merge the entry of the triangle with the true block. @@ -549,12 +551,11 @@ std::back_inserter(BBI.Predicate)); // Update block info. BB can be iteratively if-converted. - BBI.Kind = ICNotClassfied; - BBI.TrueBB = BBI.FalseBB = NULL; - BBI.BrCond.clear(); - TII->AnalyzeBranch(*BBI.BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond); + BBI.Kind = ICReAnalyze; ReTryPreds(BBI.BB); TrueBBI.Kind = ICDead; + if (FalseBBDead) + FalseBBI.Kind = ICDead; // FIXME: Must maintain LiveIns. return true; @@ -683,10 +684,7 @@ // Update block info. BB may be iteratively if-converted. if (OkToIfcvt) { - BBI.Kind = ICNotClassfied; - BBI.TrueBB = BBI.FalseBB = NULL; - BBI.BrCond.clear(); - TII->AnalyzeBranch(*BBI.BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond); + BBI.Kind = ICReAnalyze; ReTryPreds(BBI.BB); } TrueBBI.Kind = ICDead; @@ -734,9 +732,10 @@ static void TransferSuccs(MachineBasicBlock *ToBB, MachineBasicBlock *FromBB) { for (MachineBasicBlock::succ_iterator I = FromBB->succ_begin(), E = FromBB->succ_end(); I != E; ++I) { - FromBB->removeSuccessor(*I); - if (!ToBB->isSuccessor(*I)) - ToBB->addSuccessor(*I); + MachineBasicBlock *Succ = *I; + FromBB->removeSuccessor(Succ); + if (!ToBB->isSuccessor(Succ)) + ToBB->addSuccessor(Succ); } } From lattner at apple.com Mon Jun 4 20:00:25 2007 From: lattner at apple.com (lattner at apple.com) Date: Mon, 4 Jun 2007 18:00:25 -0700 (PDT) Subject: [llvm-commits] [127997] Fix tabs and column width Message-ID: <20070605010025.E0FB96CF12C1@src> Revision: 127997 Author: lattner Date: 2007-06-04 18:00:25 -0700 (Mon, 04 Jun 2007) Log Message: ----------- Fix tabs and column width Modified Paths: -------------- apple-local/branches/llvm/gcc/llvm-backend.cpp apple-local/branches/llvm/gcc/llvm-convert.cpp apple-local/branches/llvm/gcc/llvm-internal.h Modified: apple-local/branches/llvm/gcc/llvm-backend.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-04 23:45:52 UTC (rev 127996) +++ apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-05 01:00:25 UTC (rev 127997) @@ -480,16 +480,18 @@ // Add llvm.noinline if (!AttributeNoinlineFunctions.empty()) { - std::vector GlobalInit; + std::vector GlobalInit; const Type *SBP= PointerType::get(Type::Int8Ty); for (unsigned i = 0, e = AttributeNoinlineFunctions.size(); i != e; ++i) - GlobalInit.push_back(ConstantExpr::getBitCast(AttributeNoinlineFunctions[i], - SBP)); + GlobalInit.push_back(ConstantExpr::getBitCast( + AttributeNoinlineFunctions[i], + SBP)); ArrayType *AT = ArrayType::get(SBP, AttributeNoinlineFunctions.size()); Constant *Init = ConstantArray::get(AT, GlobalInit); - GlobalValue *gv = new GlobalVariable(AT, false, GlobalValue::AppendingLinkage, Init, - "llvm.noinline", TheModule); - gv->setSection("llvm.metadata"); + GlobalValue *gv = new GlobalVariable(AT, false, + GlobalValue::AppendingLinkage, Init, + "llvm.noinline", TheModule); + gv->setSection("llvm.metadata"); } // Finish off the per-function pass. Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-06-04 23:45:52 UTC (rev 127996) +++ apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-06-05 01:00:25 UTC (rev 127997) @@ -594,7 +594,7 @@ // Handle noinline Functions if (DECL_UNINLINABLE (FnDecl)) - AttributeNoinlineFunctions.push_back(Fn); + AttributeNoinlineFunctions.push_back(Fn); // Create a new basic block for the function. Builder.SetInsertPoint(new BasicBlock("entry", Fn)); Modified: apple-local/branches/llvm/gcc/llvm-internal.h =================================================================== --- apple-local/branches/llvm/gcc/llvm-internal.h 2007-06-04 23:45:52 UTC (rev 127996) +++ apple-local/branches/llvm/gcc/llvm-internal.h 2007-06-05 01:00:25 UTC (rev 127997) @@ -88,7 +88,8 @@ /// AttributeUsedGlobals - The list of globals that are marked attribute(used). extern std::vector AttributeUsedGlobals; -/// AttributeNoinlineFunctions - The list of functions that are marked attribute(noinline) +/// AttributeNoinlineFunctions - The list of functions that are +/// marked attribute(noinline) extern std::vector AttributeNoinlineFunctions; void changeLLVMValue(Value *Old, Value *New); From evan.cheng at apple.com Mon Jun 4 20:32:02 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 4 Jun 2007 20:32:02 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706050132.l551W29F016080@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.24 -> 1.25 --- Log message: If the predicated block requires an early exit, end the block there and add a unconditional branch to false block. AnalyzeBranch() does not understand early exits. --- Diffs of the changes: (+3 -2) IfConversion.cpp | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.24 llvm/lib/CodeGen/IfConversion.cpp:1.25 --- llvm/lib/CodeGen/IfConversion.cpp:1.24 Mon Jun 4 19:07:37 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Mon Jun 4 20:31:40 2007 @@ -527,7 +527,8 @@ PredicateBlock(TrueBBI, BBI.BrCond); // If 'true' block has a 'false' successor, add an exit branch to it. - if (TrueBBI.FalseBB) { + bool HasEarlyExit = TrueBBI.FalseBB != NULL; + if (HasEarlyExit) { std::vector RevCond(TrueBBI.BrCond); if (TII->ReverseBranchCondition(RevCond)) assert(false && "Unable to reverse branch condition!"); @@ -538,7 +539,7 @@ // predecessors. Otherwise, add a unconditional branch from 'true' to 'false'. BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; bool FalseBBDead = false; - if (FalseBBI.BB->pred_size() == 2) { + if (!HasEarlyExit && FalseBBI.BB->pred_size() == 2) { MergeBlocks(TrueBBI, FalseBBI); FalseBBDead = true; } else if (!isNextBlock(TrueBBI.BB, FalseBBI.BB)) From evan.cheng at apple.com Mon Jun 4 20:45:30 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 4 Jun 2007 20:45:30 -0500 Subject: [llvm-commits] CVS: llvm/test/CodeGen/X86/2007-06-04-X86-64-CtorAsmBugs.ll Message-ID: <200706050145.l551jUXp016671@zion.cs.uiuc.edu> Changes in directory llvm/test/CodeGen/X86: 2007-06-04-X86-64-CtorAsmBugs.ll added (r1.1) --- Log message: New test. --- Diffs of the changes: (+28 -0) 2007-06-04-X86-64-CtorAsmBugs.ll | 28 ++++++++++++++++++++++++++++ 1 files changed, 28 insertions(+) Index: llvm/test/CodeGen/X86/2007-06-04-X86-64-CtorAsmBugs.ll diff -c /dev/null llvm/test/CodeGen/X86/2007-06-04-X86-64-CtorAsmBugs.ll:1.1 *** /dev/null Mon Jun 4 20:45:18 2007 --- llvm/test/CodeGen/X86/2007-06-04-X86-64-CtorAsmBugs.ll Mon Jun 4 20:45:08 2007 *************** *** 0 **** --- 1,28 ---- + ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin | not grep GOTPCREL + ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin | grep ".align.*3" + + %struct.A = type { [1024 x i8] } + @_ZN1A1aE = global %struct.A zeroinitializer, align 32 ; <%struct.A*> [#uses=1] + @llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I__ZN1A1aE } ] ; <[1 x { i32, void ()* }]*> [#uses=0] + + define internal void @_GLOBAL__I__ZN1A1aE() section "__TEXT,__StaticInit,regular,pure_instructions" { + entry: + br label %bb.i + + bb.i: ; preds = %bb.i, %entry + %i.1.i1.0 = phi i32 [ 0, %entry ], [ %indvar.next, %bb.i ] ; [#uses=2] + %tmp1012.i = sext i32 %i.1.i1.0 to i64 ; [#uses=1] + %tmp13.i = getelementptr %struct.A* @_ZN1A1aE, i32 0, i32 0, i64 %tmp1012.i ; [#uses=1] + store i8 0, i8* %tmp13.i + %indvar.next = add i32 %i.1.i1.0, 1 ; [#uses=2] + %exitcond = icmp eq i32 %indvar.next, 1024 ; [#uses=1] + br i1 %exitcond, label %_Z41__static_initialization_and_destruction_0ii.exit, label %bb.i + + _Z41__static_initialization_and_destruction_0ii.exit: ; preds = %bb.i + ret void + } + + define i32 @main(i32 %argc, i8** %argv) { + entry: + ret i32 0 + } From zhousheng00 at gmail.com Tue Jun 5 00:29:01 2007 From: zhousheng00 at gmail.com (Zhou Sheng) Date: Tue, 5 Jun 2007 00:29:01 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/ParameterAttributes.h Message-ID: <200706050529.l555T1fv022785@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm: ParameterAttributes.h updated: 1.12 -> 1.13 --- Log message: Commit first round work of PR1373: http://llvm.org/PR1373 . "noalias" is now fully supported in VMCore, BitCode, and Assembly. Documentation and test case paramattrs.ll updated also. --- Diffs of the changes: (+2 -1) ParameterAttributes.h | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-) Index: llvm/include/llvm/ParameterAttributes.h diff -u llvm/include/llvm/ParameterAttributes.h:1.12 llvm/include/llvm/ParameterAttributes.h:1.13 --- llvm/include/llvm/ParameterAttributes.h:1.12 Thu May 3 22:13:39 2007 +++ llvm/include/llvm/ParameterAttributes.h Tue Jun 5 00:28:25 2007 @@ -35,7 +35,8 @@ NoReturn = 1 << 2, ///< mark the function as not returning InReg = 1 << 3, ///< force argument to be passed in register StructRet = 1 << 4, ///< hidden pointer to structure to return - NoUnwind = 1 << 5 ///< Function doesn't unwind stack + NoUnwind = 1 << 5, ///< Function doesn't unwind stack + NoAlias = 1 << 6 ///< Considered to not alias after call. }; } From zhousheng00 at gmail.com Tue Jun 5 00:29:01 2007 From: zhousheng00 at gmail.com (Zhou Sheng) Date: Tue, 5 Jun 2007 00:29:01 -0500 Subject: [llvm-commits] CVS: llvm/tools/llvm2cpp/CppWriter.cpp Message-ID: <200706050529.l555T1Vd022790@zion.cs.uiuc.edu> Changes in directory llvm/tools/llvm2cpp: CppWriter.cpp updated: 1.48 -> 1.49 --- Log message: Commit first round work of PR1373: http://llvm.org/PR1373 . "noalias" is now fully supported in VMCore, BitCode, and Assembly. Documentation and test case paramattrs.ll updated also. --- Diffs of the changes: (+2 -0) CppWriter.cpp | 2 ++ 1 files changed, 2 insertions(+) Index: llvm/tools/llvm2cpp/CppWriter.cpp diff -u llvm/tools/llvm2cpp/CppWriter.cpp:1.48 llvm/tools/llvm2cpp/CppWriter.cpp:1.49 --- llvm/tools/llvm2cpp/CppWriter.cpp:1.48 Sun Apr 22 00:46:44 2007 +++ llvm/tools/llvm2cpp/CppWriter.cpp Tue Jun 5 00:28:26 2007 @@ -473,6 +473,8 @@ Out << " | ParamAttr::SExt"; if (attrs & ParamAttr::ZExt) Out << " | ParamAttr::ZExt"; + if (attrs & ParamAttr::NoAlias) + Out << " | ParamAttr::NoAlias"; if (attrs & ParamAttr::StructRet) Out << " | ParamAttr::StructRet"; if (attrs & ParamAttr::InReg) From zhousheng00 at gmail.com Tue Jun 5 00:29:02 2007 From: zhousheng00 at gmail.com (Zhou Sheng) Date: Tue, 5 Jun 2007 00:29:02 -0500 Subject: [llvm-commits] CVS: llvm/lib/AsmParser/Lexer.l llvmAsmParser.y Message-ID: <200706050529.l555T2Jv022797@zion.cs.uiuc.edu> Changes in directory llvm/lib/AsmParser: Lexer.l updated: 1.112 -> 1.113 llvmAsmParser.y updated: 1.358 -> 1.359 --- Log message: Commit first round work of PR1373: http://llvm.org/PR1373 . "noalias" is now fully supported in VMCore, BitCode, and Assembly. Documentation and test case paramattrs.ll updated also. --- Diffs of the changes: (+7 -5) Lexer.l | 1 + llvmAsmParser.y | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) Index: llvm/lib/AsmParser/Lexer.l diff -u llvm/lib/AsmParser/Lexer.l:1.112 llvm/lib/AsmParser/Lexer.l:1.113 --- llvm/lib/AsmParser/Lexer.l:1.112 Tue May 22 14:07:45 2007 +++ llvm/lib/AsmParser/Lexer.l Tue Jun 5 00:28:25 2007 @@ -229,6 +229,7 @@ sret { return SRET; } nounwind { return NOUNWIND; } noreturn { return NORETURN; } +noalias { return NOALIAS; } void { RET_TY(Type::VoidTy, VOID); } float { RET_TY(Type::FloatTy, FLOAT); } Index: llvm/lib/AsmParser/llvmAsmParser.y diff -u llvm/lib/AsmParser/llvmAsmParser.y:1.358 llvm/lib/AsmParser/llvmAsmParser.y:1.359 --- llvm/lib/AsmParser/llvmAsmParser.y:1.358 Tue May 22 13:52:21 2007 +++ llvm/lib/AsmParser/llvmAsmParser.y Tue Jun 5 00:28:25 2007 @@ -1101,7 +1101,7 @@ %token EXTRACTELEMENT INSERTELEMENT SHUFFLEVECTOR // Function Attributes -%token NORETURN INREG SRET NOUNWIND +%token NORETURN INREG SRET NOUNWIND NOALIAS // Visibility Styles %token DEFAULT HIDDEN PROTECTED @@ -1224,10 +1224,11 @@ CHECK_FOR_ERROR }; -ParamAttr : ZEXT { $$ = ParamAttr::ZExt; } - | SEXT { $$ = ParamAttr::SExt; } - | INREG { $$ = ParamAttr::InReg; } - | SRET { $$ = ParamAttr::StructRet; } +ParamAttr : ZEXT { $$ = ParamAttr::ZExt; } + | SEXT { $$ = ParamAttr::SExt; } + | INREG { $$ = ParamAttr::InReg; } + | SRET { $$ = ParamAttr::StructRet; } + | NOALIAS { $$ = ParamAttr::NoAlias; } ; OptParamAttrs : /* empty */ { $$ = ParamAttr::None; } From zhousheng00 at gmail.com Tue Jun 5 00:29:02 2007 From: zhousheng00 at gmail.com (Zhou Sheng) Date: Tue, 5 Jun 2007 00:29:02 -0500 Subject: [llvm-commits] CVS: llvm/docs/LangRef.html Message-ID: <200706050529.l555T2Ww022805@zion.cs.uiuc.edu> Changes in directory llvm/docs: LangRef.html updated: 1.249 -> 1.250 --- Log message: Commit first round work of PR1373: http://llvm.org/PR1373 . "noalias" is now fully supported in VMCore, BitCode, and Assembly. Documentation and test case paramattrs.ll updated also. --- Diffs of the changes: (+4 -1) LangRef.html | 5 ++++- 1 files changed, 4 insertions(+), 1 deletion(-) Index: llvm/docs/LangRef.html diff -u llvm/docs/LangRef.html:1.249 llvm/docs/LangRef.html:1.250 --- llvm/docs/LangRef.html:1.249 Tue May 29 10:43:56 2007 +++ llvm/docs/LangRef.html Tue Jun 5 00:28:25 2007 @@ -784,6 +784,9 @@
sret
This indicates that the parameter specifies the address of a structure that is the return value of the function in the source program.
+
noalias
+
This indicates that the parameter not alias any other object or any + other "noalias" objects during the function call.
noreturn
This function attribute indicates that the function never returns. This indicates to LLVM that every call to this function should be treated as if @@ -4827,7 +4830,7 @@ Chris Lattner
The LLVM Compiler Infrastructure
- Last modified: $Date: 2007/05/29 15:43:56 $ + Last modified: $Date: 2007/06/05 05:28:25 $ From zhousheng00 at gmail.com Tue Jun 5 00:29:02 2007 From: zhousheng00 at gmail.com (Zhou Sheng) Date: Tue, 5 Jun 2007 00:29:02 -0500 Subject: [llvm-commits] CVS: llvm/test/Feature/paramattrs.ll Message-ID: <200706050529.l555T2fC022802@zion.cs.uiuc.edu> Changes in directory llvm/test/Feature: paramattrs.ll updated: 1.6 -> 1.7 --- Log message: Commit first round work of PR1373: http://llvm.org/PR1373 . "noalias" is now fully supported in VMCore, BitCode, and Assembly. Documentation and test case paramattrs.ll updated also. --- Diffs of the changes: (+2 -0) paramattrs.ll | 2 ++ 1 files changed, 2 insertions(+) Index: llvm/test/Feature/paramattrs.ll diff -u llvm/test/Feature/paramattrs.ll:1.6 llvm/test/Feature/paramattrs.ll:1.7 --- llvm/test/Feature/paramattrs.ll:1.6 Wed Mar 21 21:15:17 2007 +++ llvm/test/Feature/paramattrs.ll Tue Jun 5 00:28:26 2007 @@ -8,6 +8,8 @@ declare i16 @"test"(i16 sext %arg) sext declare i8 @"test2" (i16 zext %a2) zext +declare i32 @"test3"(i32* noalias %p) + declare void @exit(i32) noreturn nounwind define i32 @main(i32 %argc, i8 **%argv) nounwind inreg { From zhousheng00 at gmail.com Tue Jun 5 00:29:02 2007 From: zhousheng00 at gmail.com (Zhou Sheng) Date: Tue, 5 Jun 2007 00:29:02 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Function.cpp Message-ID: <200706050529.l555T2Hf022813@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Function.cpp updated: 1.127 -> 1.128 --- Log message: Commit first round work of PR1373: http://llvm.org/PR1373 . "noalias" is now fully supported in VMCore, BitCode, and Assembly. Documentation and test case paramattrs.ll updated also. --- Diffs of the changes: (+2 -0) Function.cpp | 2 ++ 1 files changed, 2 insertions(+) Index: llvm/lib/VMCore/Function.cpp diff -u llvm/lib/VMCore/Function.cpp:1.127 llvm/lib/VMCore/Function.cpp:1.128 --- llvm/lib/VMCore/Function.cpp:1.127 Wed Apr 25 00:49:09 2007 +++ llvm/lib/VMCore/Function.cpp Tue Jun 5 00:28:26 2007 @@ -99,6 +99,8 @@ Result += "nounwind "; if (Attrs & ParamAttr::InReg) Result += "inreg "; + if (Attrs & ParamAttr::NoAlias) + Result += "noalias "; if (Attrs & ParamAttr::StructRet) Result += "sret "; return Result; From baldrick at free.fr Tue Jun 5 00:57:56 2007 From: baldrick at free.fr (Duncan Sands) Date: Tue, 5 Jun 2007 07:57:56 +0200 Subject: [llvm-commits] noinline attributes patch In-Reply-To: References: Message-ID: <200706050757.56957.baldrick@free.fr> Hi Tanya, I notice that a least one line seems to be more than 80 characters wide, and also that in some places tabs are used for indentation rather than spaces. Ciao, Duncan. From clattner at apple.com Tue Jun 5 01:04:53 2007 From: clattner at apple.com (Chris Lattner) Date: Mon, 4 Jun 2007 23:04:53 -0700 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Function.cpp In-Reply-To: <200706050529.l555T2Hf022813@zion.cs.uiuc.edu> References: <200706050529.l555T2Hf022813@zion.cs.uiuc.edu> Message-ID: <46475C48-ADB9-4B11-8DA2-99518FAFB483@apple.com> > Commit first round work of PR1373: http://llvm.org/PR1373 . > "noalias" is now fully supported in > VMCore, BitCode, and Assembly. Documentation and test case > paramattrs.ll > updated also. Cool. Please also make the verifier assert that this attribute is only applied to pointers as well. Thanks! -Chris > > --- > Diffs of the changes: (+2 -0) > > Function.cpp | 2 ++ > 1 files changed, 2 insertions(+) > > > Index: llvm/lib/VMCore/Function.cpp > diff -u llvm/lib/VMCore/Function.cpp:1.127 llvm/lib/VMCore/ > Function.cpp:1.128 > --- llvm/lib/VMCore/Function.cpp:1.127 Wed Apr 25 00:49:09 2007 > +++ llvm/lib/VMCore/Function.cpp Tue Jun 5 00:28:26 2007 > @@ -99,6 +99,8 @@ > Result += "nounwind "; > if (Attrs & ParamAttr::InReg) > Result += "inreg "; > + if (Attrs & ParamAttr::NoAlias) > + Result += "noalias "; > if (Attrs & ParamAttr::StructRet) > Result += "sret "; > return Result; > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From asl at math.spbu.ru Tue Jun 5 01:59:41 2007 From: asl at math.spbu.ru (Anton Korobeynikov) Date: Tue, 05 Jun 2007 10:59:41 +0400 Subject: [llvm-commits] noinline attributes patch In-Reply-To: References: Message-ID: <1181026781.30952.76.camel@asl.dorms.spbu.ru> Tanya, > The attached patch creates a global to track functions that should > not be inlined (noinline attribute). The llvm inliner will need to be > modified to make use of it. Why don't use the function attribute for "noinline"? This seems to be natural way to handle such things. -- With best regards, Anton Korobeynikov. Faculty of Mathematics & Mechanics, Saint Petersburg State University. From evan.cheng at apple.com Tue Jun 5 02:05:47 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 5 Jun 2007 02:05:47 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706050705.l5575l2g025603@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.25 -> 1.26 --- Log message: I had a senior moment. --- Diffs of the changes: (+4 -3) IfConversion.cpp | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.25 llvm/lib/CodeGen/IfConversion.cpp:1.26 --- llvm/lib/CodeGen/IfConversion.cpp:1.25 Mon Jun 4 20:31:40 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Tue Jun 5 02:05:25 2007 @@ -444,10 +444,11 @@ /// isNextBlock - Returns true either if ToBB the next block after BB or /// that all the intervening blocks are empty. static bool isNextBlock(MachineBasicBlock *BB, MachineBasicBlock *ToBB) { - MachineFunction *MF = BB->getParent(); MachineFunction::iterator I = BB; - while (++I != MF->end() && I != MachineFunction::iterator(ToBB)) - if (!I->empty()) + MachineFunction::iterator TI = ToBB; + MachineFunction::iterator E = BB->getParent()->end(); + while (++I != TI) + if (I == E || !I->empty()) return false; return true; } From evan.cheng at apple.com Tue Jun 5 02:37:00 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 5 Jun 2007 02:37:00 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/ARM/ARMAsmPrinter.cpp Message-ID: <200706050737.l557b0l1003661@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/ARM: ARMAsmPrinter.cpp updated: 1.75 -> 1.76 --- Log message: PIC label asm printing cosmetic changes. --- Diffs of the changes: (+9 -0) ARMAsmPrinter.cpp | 9 +++++++++ 1 files changed, 9 insertions(+) Index: llvm/lib/Target/ARM/ARMAsmPrinter.cpp diff -u llvm/lib/Target/ARM/ARMAsmPrinter.cpp:1.75 llvm/lib/Target/ARM/ARMAsmPrinter.cpp:1.76 --- llvm/lib/Target/ARM/ARMAsmPrinter.cpp:1.75 Thu May 31 13:57:45 2007 +++ llvm/lib/Target/ARM/ARMAsmPrinter.cpp Tue Jun 5 02:36:38 2007 @@ -753,6 +753,15 @@ switch (Opc) { case ARM::PICADD: case ARM::PICLD: + case ARM::PICLDZH: + case ARM::PICLDZB: + case ARM::PICLDH: + case ARM::PICLDB: + case ARM::PICLDSH: + case ARM::PICLDSB: + case ARM::PICSTR: + case ARM::PICSTRH: + case ARM::PICSTRB: case ARM::tPICADD: break; default: From dpatel at apple.com Tue Jun 5 10:42:19 2007 From: dpatel at apple.com (Devang Patel) Date: Tue, 5 Jun 2007 08:42:19 -0700 Subject: [llvm-commits] noinline attributes patch In-Reply-To: <1181026781.30952.76.camel@asl.dorms.spbu.ru> References: <1181026781.30952.76.camel@asl.dorms.spbu.ru> Message-ID: <96435267-4EE2-467F-BD3D-4B2D692A2208@apple.com> On Jun 4, 2007, at 11:59 PM, Anton Korobeynikov wrote: > Tanya, > >> The attached patch creates a global to track functions that should >> not be inlined (noinline attribute). The llvm inliner will need to be >> modified to make use of it. > Why don't use the function attribute for "noinline"? This seems to be > natural way to handle such things. Attribute is natural way, if significant percentage of total functions is annotated with "noinline", which is not the case here. - Devang From djg at cray.com Tue Jun 5 11:06:19 2007 From: djg at cray.com (Dan Gohman) Date: Tue, 5 Jun 2007 11:06:19 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LICM.cpp Message-ID: <200706051606.l55G6J8O017660@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LICM.cpp updated: 1.104 -> 1.105 --- Log message: Allow insertelement, extractelement, and shufflevector to be hoisted/sunk by LICM. --- Diffs of the changes: (+3 -1) LICM.cpp | 4 +++- 1 files changed, 3 insertions(+), 1 deletion(-) Index: llvm/lib/Transforms/Scalar/LICM.cpp diff -u llvm/lib/Transforms/Scalar/LICM.cpp:1.104 llvm/lib/Transforms/Scalar/LICM.cpp:1.105 --- llvm/lib/Transforms/Scalar/LICM.cpp:1.104 Sun Jun 3 19:32:21 2007 +++ llvm/lib/Transforms/Scalar/LICM.cpp Tue Jun 5 11:05:55 2007 @@ -389,7 +389,9 @@ // Otherwise these instructions are hoistable/sinkable return isa(I) || isa(I) || - isa(I) || isa(I) || isa(I); + isa(I) || isa(I) || isa(I) || + isa(I) || isa(I) || + isa(I); } /// isNotUsedInLoop - Return true if the only users of this instruction are From resistor at mac.com Tue Jun 5 12:31:45 2007 From: resistor at mac.com (Owen Anderson) Date: Tue, 5 Jun 2007 12:31:45 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706051731.l55HVjTZ019564@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.18 -> 1.19 --- Log message: Fix a small bug, some 80 cols violations, and add some more debugging output. --- Diffs of the changes: (+8 -2) GVNPRE.cpp | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.18 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.19 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.18 Mon Jun 4 18:34:56 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Tue Jun 5 12:31:23 2007 @@ -354,6 +354,10 @@ currTemps, currAvail, availableOut); } + DOUT << "Maximal Set: "; + dump_unique(VN, maximalSet); + DOUT << "\n"; + PostDominatorTree &PDT = getAnalysis(); // Second Phase of BuildSets - calculate ANTIC_IN @@ -384,10 +388,12 @@ std::set old (anticIn.begin(), anticIn.end()); if (BB->getTerminator()->getNumSuccessors() == 1) { - if (visited.find(BB) == visited.end()) + if (visited.find(BB->getTerminator()->getSuccessor(0)) == + visited.end()) phi_translate_set(VN, maximalSet, maximalSet, BB, anticOut); else - phi_translate_set(VN, maximalSet, anticipatedIn[BB->getTerminator()->getSuccessor(0)], BB, anticOut); + phi_translate_set(VN, maximalSet, + anticipatedIn[BB->getTerminator()->getSuccessor(0)], BB, anticOut); } else if (BB->getTerminator()->getNumSuccessors() > 1) { BasicBlock* first = BB->getTerminator()->getSuccessor(0); anticOut.insert(anticipatedIn[first].begin(), From evan.cheng at apple.com Tue Jun 5 13:55:40 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 5 Jun 2007 13:55:40 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/ARM/ARMAsmPrinter.cpp Message-ID: <200706051855.l55IteYw021179@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/ARM: ARMAsmPrinter.cpp updated: 1.76 -> 1.77 --- Log message: Print predicate of the second instruction of the two-piece constant MI. --- Diffs of the changes: (+3 -1) ARMAsmPrinter.cpp | 4 +++- 1 files changed, 3 insertions(+), 1 deletion(-) Index: llvm/lib/Target/ARM/ARMAsmPrinter.cpp diff -u llvm/lib/Target/ARM/ARMAsmPrinter.cpp:1.76 llvm/lib/Target/ARM/ARMAsmPrinter.cpp:1.77 --- llvm/lib/Target/ARM/ARMAsmPrinter.cpp:1.76 Tue Jun 5 02:36:38 2007 +++ llvm/lib/Target/ARM/ARMAsmPrinter.cpp Tue Jun 5 13:55:18 2007 @@ -361,7 +361,9 @@ unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImmedValue()); unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImmedValue()); printSOImm(O, ARM_AM::getSOImmVal(V1), TAI); - O << "\n\torr "; + O << "\n\torr"; + printPredicateOperand(MI, 2); + O << " "; printOperand(MI, 0); O << ", "; printOperand(MI, 0); From dpatel at apple.com Tue Jun 5 15:23:42 2007 From: dpatel at apple.com (Devang Patel) Date: Tue, 5 Jun 2007 15:23:42 -0500 Subject: [llvm-commits] CVS: llvm/test/Other/2007-06-05-PassID.ll Message-ID: <200706052023.l55KNg3f022965@zion.cs.uiuc.edu> Changes in directory llvm/test/Other: 2007-06-05-PassID.ll added (r1.1) --- Log message: New test. --- Diffs of the changes: (+11 -0) 2007-06-05-PassID.ll | 11 +++++++++++ 1 files changed, 11 insertions(+) Index: llvm/test/Other/2007-06-05-PassID.ll diff -c /dev/null llvm/test/Other/2007-06-05-PassID.ll:1.1 *** /dev/null Tue Jun 5 15:23:30 2007 --- llvm/test/Other/2007-06-05-PassID.ll Tue Jun 5 15:23:20 2007 *************** *** 0 **** --- 1,11 ---- + ;RUN: llvm-as < %s | opt -analyze -print-cfg-only -disable-output + ;PR 1497 + + define void @foo() { + entry: + br label %return + + return: ; preds = %entry + ret void + } + From dpatel at apple.com Tue Jun 5 15:24:58 2007 From: dpatel at apple.com (Devang Patel) Date: Tue, 5 Jun 2007 15:24:58 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/CFGPrinter.cpp Message-ID: <200706052024.l55KOwJV023010@zion.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: CFGPrinter.cpp updated: 1.27 -> 1.28 --- Log message: Fix PR 1497: http://llvm.org/PR1497 Use separate pass id for CFGOnlyPrinter. --- Diffs of the changes: (+2 -0) CFGPrinter.cpp | 2 ++ 1 files changed, 2 insertions(+) Index: llvm/lib/Analysis/CFGPrinter.cpp diff -u llvm/lib/Analysis/CFGPrinter.cpp:1.27 llvm/lib/Analysis/CFGPrinter.cpp:1.28 --- llvm/lib/Analysis/CFGPrinter.cpp:1.27 Mon May 14 09:25:08 2007 +++ llvm/lib/Analysis/CFGPrinter.cpp Tue Jun 5 15:24:36 2007 @@ -135,6 +135,7 @@ struct VISIBILITY_HIDDEN CFGPrinter : public FunctionPass { static char ID; // Pass identification, replacement for typeid CFGPrinter() : FunctionPass((intptr_t)&ID) {} + CFGPrinter(intptr_t pid) : FunctionPass(pid) {} virtual bool runOnFunction(Function &F) { std::string Filename = "cfg." + F.getName() + ".dot"; @@ -162,6 +163,7 @@ struct VISIBILITY_HIDDEN CFGOnlyPrinter : public CFGPrinter { static char ID; // Pass identification, replacement for typeid + CFGOnlyPrinter() : CFGPrinter((intptr_t)&ID) {} virtual bool runOnFunction(Function &F) { bool OldCFGOnly = CFGOnly; CFGOnly = true; From evan.cheng at apple.com Tue Jun 5 15:39:04 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 5 Jun 2007 15:39:04 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706052039.l55Kd4wM023285@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.26 -> 1.27 --- Log message: Do not ifcvt if either true / false path is a backedge. Not profitable in almost all cases. --- Diffs of the changes: (+3 -0) IfConversion.cpp | 3 +++ 1 files changed, 3 insertions(+) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.26 llvm/lib/CodeGen/IfConversion.cpp:1.27 --- llvm/lib/CodeGen/IfConversion.cpp:1.26 Tue Jun 5 02:05:25 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Tue Jun 5 15:38:42 2007 @@ -237,6 +237,9 @@ !TII->AnalyzeBranch(*BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond); if (!BBI.IsAnalyzable || BBI.BrCond.size() == 0) return; + // Do not ifcvt if either path is a back edge to the entry block. + if (BBI.TrueBB == BB || BBI.FalseBB == BB) + return; StructuralAnalysis(BBI.TrueBB); BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; From lattner at apple.com Tue Jun 5 16:15:34 2007 From: lattner at apple.com (Tanya Lattner) Date: Tue, 5 Jun 2007 14:15:34 -0700 Subject: [llvm-commits] noinline attributes patch In-Reply-To: <1181026781.30952.76.camel@asl.dorms.spbu.ru> References: <1181026781.30952.76.camel@asl.dorms.spbu.ru> Message-ID: On Jun 4, 2007, at 11:59 PM, Anton Korobeynikov wrote: > Tanya, > >> The attached patch creates a global to track functions that should >> not be inlined (noinline attribute). The llvm inliner will need to be >> modified to make use of it. > Why don't use the function attribute for "noinline"? This seems to be > natural way to handle such things. That is another way to do it. I thought this was simpler. What are the pros/cons of using function attribute? -Tanya > -- > With best regards, Anton Korobeynikov. > > Faculty of Mathematics & Mechanics, Saint Petersburg State University. > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From evan.cheng at apple.com Tue Jun 5 17:04:15 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 5 Jun 2007 17:04:15 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706052204.l55M4FCx027239@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.27 -> 1.28 --- Log message: ReplaceUsesOfBlockWith() can modify the predecessors list. --- Diffs of the changes: (+4 -3) IfConversion.cpp | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.27 llvm/lib/CodeGen/IfConversion.cpp:1.28 --- llvm/lib/CodeGen/IfConversion.cpp:1.27 Tue Jun 5 15:38:42 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Tue Jun 5 17:03:53 2007 @@ -756,9 +756,10 @@ ToBBI.BB->removeSuccessor(FromBBI.BB); // Redirect all branches to FromBB to ToBB. - for (MachineBasicBlock::pred_iterator I = FromBBI.BB->pred_begin(), - E = FromBBI.BB->pred_end(); I != E; ++I) - (*I)->ReplaceUsesOfBlockWith(FromBBI.BB, ToBBI.BB); + std::vector Preds(FromBBI.BB->pred_begin(), + FromBBI.BB->pred_end()); + for (unsigned i = 0, e = Preds.size(); i != e; ++i) + Preds[i]->ReplaceUsesOfBlockWith(FromBBI.BB, ToBBI.BB); // Transfer preds / succs and update size. TransferPreds(ToBBI.BB, FromBBI.BB); From resistor at mac.com Tue Jun 5 17:12:11 2007 From: resistor at mac.com (Owen Anderson) Date: Tue, 5 Jun 2007 17:12:11 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706052212.l55MCBph027452@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.19 -> 1.20 --- Log message: Don't leak memory. --- Diffs of the changes: (+6 -3) GVNPRE.cpp | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.19 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.20 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.19 Tue Jun 5 12:31:23 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Tue Jun 5 17:11:49 2007 @@ -158,11 +158,14 @@ Value* newVal = BinaryOperator::create(BO->getOpcode(), newOp1, newOp2, BO->getName()+".gvnpre"); - add(VN, MS, newVal); - if (!find_leader(VN, set, VN[newVal])) + + if (!find_leader(VN, set, VN[newVal])) { + add(VN, MS, newVal); return newVal; - else + } else { + delete newVal; return 0; + } } } else if (PHINode* P = dyn_cast(V)) { if (P->getParent() == pred->getTerminator()->getSuccessor(0)) From lattner at apple.com Tue Jun 5 18:45:36 2007 From: lattner at apple.com (lattner at apple.com) Date: Tue, 5 Jun 2007 16:45:36 -0700 (PDT) Subject: [llvm-commits] [128026] Do bitcase before pushing onto vector and remove GlobalInit. Message-ID: <20070605234536.926E3703C187@src> Revision: 128026 Author: lattner Date: 2007-06-05 16:45:35 -0700 (Tue, 05 Jun 2007) Log Message: ----------- Do bitcase before pushing onto vector and remove GlobalInit. Clear vectors for used and noinline attributes when finished. Modified Paths: -------------- apple-local/branches/llvm/gcc/llvm-backend.cpp apple-local/branches/llvm/gcc/llvm-convert.cpp apple-local/branches/llvm/gcc/llvm-internal.h Modified: apple-local/branches/llvm/gcc/llvm-backend.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-05 17:39:31 UTC (rev 128025) +++ apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-05 23:45:35 UTC (rev 128026) @@ -79,8 +79,8 @@ llvm::OStream *AsmOutFile = 0; std::vector > StaticCtors, StaticDtors; -std::vector AttributeUsedGlobals; -std::vector AttributeNoinlineFunctions; +std::vector AttributeUsedGlobals; +std::vector AttributeNoinlineFunctions; /// PerFunctionPasses - This is the list of cleanup passes run per-function /// as each is compiled. In cases where we are not doing IPO, it includes the @@ -467,31 +467,26 @@ CreateStructorsList(StaticDtors, "llvm.global_dtors"); if (!AttributeUsedGlobals.empty()) { - std::vector GlobalInit; const Type *SBP = PointerType::get(Type::Int8Ty); - for (unsigned i = 0, e = AttributeUsedGlobals.size(); i != e; ++i) - GlobalInit.push_back(ConstantExpr::getBitCast(AttributeUsedGlobals[i], - SBP)); ArrayType *AT = ArrayType::get(SBP, AttributeUsedGlobals.size()); - Constant *Init = ConstantArray::get(AT, GlobalInit); + Constant *Init = ConstantArray::get(AT, AttributeUsedGlobals); new GlobalVariable(AT, false, GlobalValue::AppendingLinkage, Init, "llvm.used", TheModule); + AttributeUsedGlobals.clear(); } // Add llvm.noinline if (!AttributeNoinlineFunctions.empty()) { - std::vector GlobalInit; const Type *SBP= PointerType::get(Type::Int8Ty); - for (unsigned i = 0, e = AttributeNoinlineFunctions.size(); i != e; ++i) - GlobalInit.push_back(ConstantExpr::getBitCast( - AttributeNoinlineFunctions[i], - SBP)); ArrayType *AT = ArrayType::get(SBP, AttributeNoinlineFunctions.size()); - Constant *Init = ConstantArray::get(AT, GlobalInit); + Constant *Init = ConstantArray::get(AT, AttributeUsedGlobals); GlobalValue *gv = new GlobalVariable(AT, false, GlobalValue::AppendingLinkage, Init, "llvm.noinline", TheModule); gv->setSection("llvm.metadata"); + + // Clear vector + AttributeNoinlineFunctions.clear(); } // Finish off the per-function pass. @@ -763,8 +758,10 @@ } // Handle used decls - if (DECL_PRESERVE_P (decl)) - AttributeUsedGlobals.push_back(GV); + if (DECL_PRESERVE_P (decl)) { + const Type *SBP= PointerType::get(Type::Int8Ty); + AttributeUsedGlobals.push_back(ConstantExpr::getBitCast(GV, SBP)); + } } if (TheDebugInfo) TheDebugInfo->EmitGlobalVariable(GV, decl); Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-06-05 17:39:31 UTC (rev 128025) +++ apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-06-05 23:45:35 UTC (rev 128026) @@ -589,12 +589,16 @@ Fn->setSection(TREE_STRING_POINTER(DECL_SECTION_NAME(FnDecl))); // Handle used Functions - if (DECL_PRESERVE_P (FnDecl)) - AttributeUsedGlobals.push_back(Fn); + if (DECL_PRESERVE_P (FnDecl)) { + const Type *SBP= PointerType::get(Type::Int8Ty); + AttributeUsedGlobals.push_back(ConstantExpr::getBitCast(Fn,SBP)); + } // Handle noinline Functions - if (DECL_UNINLINABLE (FnDecl)) - AttributeNoinlineFunctions.push_back(Fn); + if (DECL_UNINLINABLE (FnDecl)) { + const Type *SBP= PointerType::get(Type::Int8Ty); + AttributeNoinlineFunctions.push_back(ConstantExpr::getBitCast(Fn,SBP)); + } // Create a new basic block for the function. Builder.SetInsertPoint(new BasicBlock("entry", Fn)); Modified: apple-local/branches/llvm/gcc/llvm-internal.h =================================================================== --- apple-local/branches/llvm/gcc/llvm-internal.h 2007-06-05 17:39:31 UTC (rev 128025) +++ apple-local/branches/llvm/gcc/llvm-internal.h 2007-06-05 23:45:35 UTC (rev 128026) @@ -86,11 +86,11 @@ extern std::vector > StaticCtors, StaticDtors; /// AttributeUsedGlobals - The list of globals that are marked attribute(used). -extern std::vector AttributeUsedGlobals; +extern std::vector AttributeUsedGlobals; /// AttributeNoinlineFunctions - The list of functions that are /// marked attribute(noinline) -extern std::vector AttributeNoinlineFunctions; +extern std::vector AttributeNoinlineFunctions; void changeLLVMValue(Value *Old, Value *New); void readLLVMTypesStringTable(); From resistor at mac.com Tue Jun 5 18:46:37 2007 From: resistor at mac.com (Owen Anderson) Date: Tue, 5 Jun 2007 18:46:37 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706052346.l55Nkbp1029785@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.20 -> 1.21 --- Log message: Fix a misunderstanding of the algorithm. Really, we should be tracking values and expression separately. We can get around this, however, by only keeping opaque values in TMP_GEN. --- Diffs of the changes: (+17 -14) GVNPRE.cpp | 31 +++++++++++++++++-------------- 1 files changed, 17 insertions(+), 14 deletions(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.20 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.21 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.20 Tue Jun 5 17:11:49 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Tue Jun 5 18:46:12 2007 @@ -77,7 +77,7 @@ void dump_unique(ValueTable& VN, std::set& s); void clean(ValueTable VN, std::set& set); bool add(ValueTable& VN, std::set& MS, Value* V); - Value* find_leader(ValueTable VN, std::set& vals, uint32_t v); + Value* find_leader(ValueTable VN, std::set& vals, Value* v); Value* phi_translate(ValueTable& VN, std::set& MS, std::set& set, Value* V, BasicBlock* pred); @@ -122,10 +122,11 @@ Value* GVNPRE::find_leader(GVNPRE::ValueTable VN, std::set& vals, - uint32_t v) { + Value* v) { + ExprLT cmp; for (std::set::iterator I = vals.begin(), E = vals.end(); I != E; ++I) - if (VN[*I] == v) + if (!cmp(v, *I) && !cmp(*I, v)) return *I; return 0; @@ -140,7 +141,7 @@ if (BinaryOperator* BO = dyn_cast(V)) { Value* newOp1 = isa(BO->getOperand(0)) ? phi_translate(VN, MS, set, - find_leader(VN, set, VN[BO->getOperand(0)]), + find_leader(VN, set, BO->getOperand(0)), pred) : BO->getOperand(0); if (newOp1 == 0) @@ -148,7 +149,7 @@ Value* newOp2 = isa(BO->getOperand(1)) ? phi_translate(VN, MS, set, - find_leader(VN, set, VN[BO->getOperand(0)]), + find_leader(VN, set, BO->getOperand(1)), pred) : BO->getOperand(1); if (newOp2 == 0) @@ -159,7 +160,7 @@ newOp1, newOp2, BO->getName()+".gvnpre"); - if (!find_leader(VN, set, VN[newVal])) { + if (!find_leader(VN, set, newVal)) { add(VN, MS, newVal); return newVal; } else { @@ -233,19 +234,21 @@ std::insert_iterator > q_ins(Q, Q.begin()); std::set_difference(set.begin(), set.end(), toErase.begin(), toErase.end(), - q_ins, ExprLT()); + q_ins); - std::set visited; + std::set visited; while (!Q.empty()) { Value* e = Q.back(); if (BinaryOperator* BO = dyn_cast(e)) { - Value* l = find_leader(VN, set, VN[BO->getOperand(0)]); - Value* r = find_leader(VN, set, VN[BO->getOperand(1)]); + Value* l = find_leader(VN, set, BO->getOperand(0)); + Value* r = find_leader(VN, set, BO->getOperand(1)); - if (l != 0 && visited.find(l) == visited.end()) + if (l != 0 && isa(l) && + visited.find(l) == visited.end()) Q.push_back(l); - else if (r != 0 && visited.find(r) == visited.end()) + else if (r != 0 && isa(r) && + visited.find(r) == visited.end()) Q.push_back(r); else { vec.push_back(e); @@ -316,7 +319,7 @@ currExps.insert(rightValue); currExps.insert(BO); - currTemps.insert(BO); + //currTemps.insert(BO); // Handle unsupported ops } else if (!BI->isTerminator()){ @@ -442,7 +445,7 @@ dump_unique(VN, anticIn); DOUT << "\n"; - if (old != anticIn) + if (old.size() != anticIn.size()) changed = true; anticOut.clear(); From evan.cheng at apple.com Tue Jun 5 18:46:41 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 5 Jun 2007 18:46:41 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706052346.l55NkfDc029791@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.28 -> 1.29 --- Log message: Fix diamond shape ifcvt bugs. --- Diffs of the changes: (+41 -61) IfConversion.cpp | 102 ++++++++++++++++++++++--------------------------------- 1 files changed, 41 insertions(+), 61 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.28 llvm/lib/CodeGen/IfConversion.cpp:1.29 --- llvm/lib/CodeGen/IfConversion.cpp:1.28 Tue Jun 5 17:03:53 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Tue Jun 5 18:46:14 2007 @@ -284,7 +284,7 @@ } } else if (TrueBBI.TrueBB == FalseBBI.TrueBB && CanRevCond && TrueBBI.BB->pred_size() == 1 && - TrueBBI.BB->pred_size() == 1 && + FalseBBI.BB->pred_size() == 1 && // Check the 'true' and 'false' blocks if either isn't ended with // a branch. If the block does not fallthrough to another block // then we need to add a branch to its successor. @@ -301,7 +301,7 @@ // TBB FBB // \ / // TailBB - // Note MBB can be empty in case both TBB and FBB are return blocks. + // Note TailBB can be empty. BBI.Kind = ICDiamond; TrueBBI.Kind = FalseBBI.Kind = ICChild; BBI.TailBB = TrueBBI.TrueBB; @@ -611,74 +611,58 @@ --TrueBBI.NonPredSize; } - // Check the 'true' and 'false' blocks if either isn't ended with a branch. - // Either the block fallthrough to another block or it ends with a - // return. If it's the former, add a branch to its successor. - bool TrueNeedBr = !TrueBBI.TrueBB && BBI.TrueBB->succ_size(); - bool FalseNeedBr = !FalseBBI.TrueBB && BBI.FalseBB->succ_size(); - // Merge the 'true' and 'false' blocks by copying the instructions // from the 'false' block to the 'true' block. That is, unless the true // block would clobber the predicate, in that case, do the opposite. + BBInfo *BBI1 = &TrueBBI; + BBInfo *BBI2 = &FalseBBI; std::vector RevCond(BBI.BrCond); TII->ReverseBranchCondition(RevCond); - BBInfo *CvtBBI; - if (!TrueBBI.ModifyPredicate) { - // Predicate the 'true' block after removing its branch. - TrueBBI.NonPredSize -= TII->RemoveBranch(*BBI.TrueBB); - PredicateBlock(TrueBBI, BBI.BrCond); - - // Predicate the 'false' block. - PredicateBlock(FalseBBI, RevCond, true); - - if (TrueNeedBr) - TII->InsertBranch(*BBI.TrueBB, *BBI.TrueBB->succ_begin(), NULL, - BBI.BrCond); - // Add an unconditional branch from 'false' to to 'false' successor if it - // will not be the fallthrough block. - if (FalseNeedBr && - !isNextBlock(BBI.BB, *BBI.FalseBB->succ_begin())) - InsertUncondBranch(BBI.FalseBB, *BBI.FalseBB->succ_begin(), TII); - MergeBlocks(TrueBBI, FalseBBI); - CvtBBI = &TrueBBI; - } else { - // Predicate the 'false' block after removing its branch. - FalseBBI.NonPredSize -= TII->RemoveBranch(*BBI.FalseBB); - PredicateBlock(FalseBBI, RevCond); - - // Predicate the 'false' block. - PredicateBlock(TrueBBI, BBI.BrCond, true); - - // Add a conditional branch from 'false' to 'false' successor if needed. - if (FalseNeedBr) - TII->InsertBranch(*BBI.FalseBB, *BBI.FalseBB->succ_begin(), NULL, - RevCond); - // Add an unconditional branch from 'true' to to 'true' successor if it - // will not be the fallthrough block. - if (TrueNeedBr && - !isNextBlock(BBI.BB, *BBI.TrueBB->succ_begin())) - InsertUncondBranch(BBI.TrueBB, *BBI.TrueBB->succ_begin(), TII); - MergeBlocks(FalseBBI, TrueBBI); - CvtBBI = &FalseBBI; + std::vector *Cond1 = &BBI.BrCond; + std::vector *Cond2 = &RevCond; + if (TrueBBI.ModifyPredicate) { + std::swap(BBI1, BBI2); + std::swap(Cond1, Cond2); } + // Check the 'true' and 'false' blocks if either isn't ended with a branch. + // Either the block fallthrough to another block or it ends with a + // return. If it's the former, add a branch to its successor. + bool NeedBr1 = !BBI1->TrueBB && BBI1->BB->succ_size(); + bool NeedBr2 = !BBI2->TrueBB && BBI1->BB->succ_size(); + + // Predicate the 'true' block after removing its branch. + BBI1->NonPredSize -= TII->RemoveBranch(*BBI1->BB); + PredicateBlock(*BBI1, *Cond1); + + // Add an early exit branch if needed. + if (NeedBr1) + TII->InsertBranch(*BBI1->BB, *BBI1->BB->succ_begin(), NULL, *Cond1); + + // Predicate the 'false' block. + PredicateBlock(*BBI2, *Cond2, true); + + // Add an unconditional branch from 'false' to to 'false' successor if it + // will not be the fallthrough block. + if (NeedBr2 && !isNextBlock(BBI2->BB, *BBI2->BB->succ_begin())) + InsertUncondBranch(BBI2->BB, *BBI2->BB->succ_begin(), TII); + + // Keep them as two separate blocks if there is an early exit. + if (!NeedBr1) + MergeBlocks(*BBI1, *BBI2); + else if (!isNextBlock(BBI1->BB, BBI2->BB)) + InsertUncondBranch(BBI1->BB, BBI2->BB, TII); + // Remove the conditional branch from entry to the blocks. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); - bool OkToIfcvt = true; - // Merge the combined block into the entry of the diamond if the entry - // block is its only predecessor. Otherwise, insert an unconditional - // branch from entry to the if-converted block. - if (CvtBBI->BB->pred_size() == 1) { - MergeBlocks(BBI, *CvtBBI); - CvtBBI = &BBI; - OkToIfcvt = false; - } else if (!isNextBlock(BBI.BB, CvtBBI->BB)) - InsertUncondBranch(BBI.BB, CvtBBI->BB, TII); + // Merge the combined block into the entry of the diamond. + MergeBlocks(BBI, *BBI1); // If the if-converted block fallthrough or unconditionally branch into the // tail block, and the tail block does not have other predecessors, then // fold the tail block in as well. + BBInfo *CvtBBI = NeedBr1 ? BBI2 : &BBI; if (BBI.TailBB && BBI.TailBB->pred_size() == 1 && CvtBBI->BB->succ_size() == 1) { CvtBBI->NonPredSize -= TII->RemoveBranch(*CvtBBI->BB); @@ -687,11 +671,7 @@ TailBBI.Kind = ICDead; } - // Update block info. BB may be iteratively if-converted. - if (OkToIfcvt) { - BBI.Kind = ICReAnalyze; - ReTryPreds(BBI.BB); - } + // Update block info. TrueBBI.Kind = ICDead; FalseBBI.Kind = ICDead; From sabre at nondot.org Tue Jun 5 18:49:28 2007 From: sabre at nondot.org (Chris Lattner) Date: Tue, 5 Jun 2007 18:49:28 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Function.cpp Message-ID: <200706052349.l55NnSit029867@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Function.cpp updated: 1.128 -> 1.129 --- Log message: Fix a user-reported error building with GCC 3.4.4 on Cygwin. --- Diffs of the changes: (+1 -1) Function.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/VMCore/Function.cpp diff -u llvm/lib/VMCore/Function.cpp:1.128 llvm/lib/VMCore/Function.cpp:1.129 --- llvm/lib/VMCore/Function.cpp:1.128 Tue Jun 5 00:28:26 2007 +++ llvm/lib/VMCore/Function.cpp Tue Jun 5 18:49:06 2007 @@ -271,7 +271,7 @@ } const FunctionType *Intrinsic::getType(ID id, const Type **Tys, - uint32_t numTys) { + unsigned numTys) { const Type *ResultTy = NULL; std::vector ArgTys; bool IsVarArg = false; From dpatel at apple.com Tue Jun 5 19:21:24 2007 From: dpatel at apple.com (Devang Patel) Date: Tue, 5 Jun 2007 19:21:24 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Scalar.h Message-ID: <200706060021.l560LO26030795@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms: Scalar.h updated: 1.80 -> 1.81 --- Log message: Avoid non-trivial loop unswitching while optimizing for size. --- Diffs of the changes: (+1 -1) Scalar.h | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/include/llvm/Transforms/Scalar.h diff -u llvm/include/llvm/Transforms/Scalar.h:1.80 llvm/include/llvm/Transforms/Scalar.h:1.81 --- llvm/include/llvm/Transforms/Scalar.h:1.80 Tue May 29 18:36:32 2007 +++ llvm/include/llvm/Transforms/Scalar.h Tue Jun 5 19:21:03 2007 @@ -127,7 +127,7 @@ // // LoopUnswitch - This pass is a simple loop unswitching pass. // -LoopPass *createLoopUnswitchPass(); +LoopPass *createLoopUnswitchPass(bool Os = false); //===----------------------------------------------------------------------===// // From dpatel at apple.com Tue Jun 5 19:21:25 2007 From: dpatel at apple.com (Devang Patel) Date: Tue, 5 Jun 2007 19:21:25 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopUnswitch.cpp Message-ID: <200706060021.l560LP9K030800@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopUnswitch.cpp updated: 1.69 -> 1.70 --- Log message: Avoid non-trivial loop unswitching while optimizing for size. --- Diffs of the changes: (+12 -3) LoopUnswitch.cpp | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-) Index: llvm/lib/Transforms/Scalar/LoopUnswitch.cpp diff -u llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.69 llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.70 --- llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.69 Wed May 9 03:24:12 2007 +++ llvm/lib/Transforms/Scalar/LoopUnswitch.cpp Tue Jun 5 19:21:03 2007 @@ -67,10 +67,12 @@ // after RewriteLoopBodyWithConditionConstant rewrites first loop. std::vector LoopProcessWorklist; SmallPtrSet UnswitchedVals; - + + bool OptimizeForSize; public: static char ID; // Pass ID, replacement for typeid - LoopUnswitch() : LoopPass((intptr_t)&ID) {} + LoopUnswitch(bool Os = false) : + LoopPass((intptr_t)&ID), OptimizeForSize(Os) {} bool runOnLoop(Loop *L, LPPassManager &LPM); @@ -116,7 +118,9 @@ RegisterPass X("loop-unswitch", "Unswitch loops"); } -LoopPass *llvm::createLoopUnswitchPass() { return new LoopUnswitch(); } +LoopPass *llvm::createLoopUnswitchPass(bool Os) { + return new LoopUnswitch(Os); +} /// FindLIVLoopCondition - Cond is a condition that occurs in L. If it is /// invariant in the loop, or has an invariant piece, return the invariant. @@ -359,6 +363,11 @@ bool LoopUnswitch::UnswitchIfProfitable(Value *LoopCond, Constant *Val,Loop *L){ // Check to see if it would be profitable to unswitch this loop. unsigned Cost = getLoopUnswitchCost(L, LoopCond); + + // Do not do non-trivial unswitch while optimizing for size. + if (Cost && OptimizeForSize) + return false; + if (Cost > Threshold) { // FIXME: this should estimate growth by the amount of code shared by the // resultant unswitched loops. From dpatel at apple.com Tue Jun 5 19:23:17 2007 From: dpatel at apple.com (dpatel at apple.com) Date: Tue, 5 Jun 2007 17:23:17 -0700 (PDT) Subject: [llvm-commits] [128027] Let loop unswitch pass know whether we are optimizing for size or not. Message-ID: <20070606002317.5AAAE70871EA@src> Revision: 128027 Author: dpatel Date: 2007-06-05 17:23:16 -0700 (Tue, 05 Jun 2007) Log Message: ----------- Let loop unswitch pass know whether we are optimizing for size or not. Modified Paths: -------------- apple-local/branches/llvm/gcc/llvm-backend.cpp Modified: apple-local/branches/llvm/gcc/llvm-backend.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-05 23:45:35 UTC (rev 128026) +++ apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-06 00:23:16 UTC (rev 128027) @@ -327,7 +327,7 @@ PM->add(createReassociatePass()); // Reassociate expressions PM->add(createLoopRotatePass()); // Rotate Loop PM->add(createLICMPass()); // Hoist loop invariants - PM->add(createLoopUnswitchPass()); // Unswitch loops. + PM->add(createLoopUnswitchPass(optimize_size ? true : false)); PM->add(createInstructionCombiningPass()); // Clean up after LICM/reassoc PM->add(createIndVarSimplifyPass()); // Canonicalize indvars if (flag_unroll_loops) From clattner at apple.com Tue Jun 5 19:42:04 2007 From: clattner at apple.com (Chris Lattner) Date: Tue, 5 Jun 2007 17:42:04 -0700 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Scalar.h In-Reply-To: <200706060021.l560LO26030795@zion.cs.uiuc.edu> References: <200706060021.l560LO26030795@zion.cs.uiuc.edu> Message-ID: > // > // LoopUnswitch - This pass is a simple loop unswitching pass. > // > -LoopPass *createLoopUnswitchPass(); > +LoopPass *createLoopUnswitchPass(bool Os = false); Hey Devang, please name this something like "OptimizeForSize" or something, instead of Os :) -Chris From dpatel at apple.com Tue Jun 5 19:46:58 2007 From: dpatel at apple.com (Devang Patel) Date: Tue, 5 Jun 2007 19:46:58 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706060046.l560kw66031225@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.90 -> 1.91 --- Log message: Simplify class hierarchy. --- Diffs of the changes: (+1 -3) Dominators.h | 4 +--- 1 files changed, 1 insertion(+), 3 deletions(-) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.90 llvm/include/llvm/Analysis/Dominators.h:1.91 --- llvm/include/llvm/Analysis/Dominators.h:1.90 Mon Jun 4 18:45:02 2007 +++ llvm/include/llvm/Analysis/Dominators.h Tue Jun 5 19:46:36 2007 @@ -63,7 +63,7 @@ class DomTreeNode { friend class DominatorTree; friend struct PostDominatorTree; - friend class DominatorTreeBase; + BasicBlock *TheBB; DomTreeNode *IDom; std::vector Children; @@ -99,10 +99,8 @@ return properlyDominates(N); } -private: inline DomTreeNode(BasicBlock *BB, DomTreeNode *iDom) : TheBB(BB), IDom(iDom) {} inline DomTreeNode *addChild(DomTreeNode *C) { Children.push_back(C); return C; } - void setIDom(DomTreeNode *NewIDom); }; From dpatel at apple.com Tue Jun 5 19:49:25 2007 From: dpatel at apple.com (Devang Patel) Date: Tue, 5 Jun 2007 19:49:25 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Scalar.h Message-ID: <200706060049.l560nPYH031277@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms: Scalar.h updated: 1.81 -> 1.82 --- Log message: Rename. --- Diffs of the changes: (+1 -1) Scalar.h | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/include/llvm/Transforms/Scalar.h diff -u llvm/include/llvm/Transforms/Scalar.h:1.81 llvm/include/llvm/Transforms/Scalar.h:1.82 --- llvm/include/llvm/Transforms/Scalar.h:1.81 Tue Jun 5 19:21:03 2007 +++ llvm/include/llvm/Transforms/Scalar.h Tue Jun 5 19:49:02 2007 @@ -127,7 +127,7 @@ // // LoopUnswitch - This pass is a simple loop unswitching pass. // -LoopPass *createLoopUnswitchPass(bool Os = false); +LoopPass *createLoopUnswitchPass(bool OptimizeForSize = false); //===----------------------------------------------------------------------===// // From clattner at apple.com Tue Jun 5 19:56:15 2007 From: clattner at apple.com (clattner at apple.com) Date: Tue, 5 Jun 2007 17:56:15 -0700 (PDT) Subject: [llvm-commits] [128028] Fix a bug in debug info emission that causes an ICE on a really horrible C++ Message-ID: <20070606005615.08F5F70A7C3E@src> Revision: 128028 Author: clattner Date: 2007-06-05 17:56:14 -0700 (Tue, 05 Jun 2007) Log Message: ----------- Fix a bug in debug info emission that causes an ICE on a really horrible C++ testcase (54KLOC) that Wolfgang Bangerth provided. Modified Paths: -------------- apple-local/branches/llvm/gcc/llvm-debug.cpp Modified: apple-local/branches/llvm/gcc/llvm-debug.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-debug.cpp 2007-06-06 00:23:16 UTC (rev 128027) +++ apple-local/branches/llvm/gcc/llvm-debug.cpp 2007-06-06 00:56:14 UTC (rev 128028) @@ -674,7 +674,8 @@ NULL; if (TREE_CODE(Member) == FIELD_DECL) { - if (TREE_CODE(DECL_FIELD_OFFSET(Member)) != INTEGER_CST) + if (DECL_FIELD_OFFSET(Member) == 0 || + TREE_CODE(DECL_FIELD_OFFSET(Member)) != INTEGER_CST) // FIXME: field with variable position, skip it for now. continue; From evan.cheng at apple.com Tue Jun 5 19:58:13 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 5 Jun 2007 19:58:13 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706060058.l560wDVP031549@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.29 -> 1.30 --- Log message: Fix a couple of typos and be smarter about order of blocks when ifcvt a diamond. --- Diffs of the changes: (+30 -17) IfConversion.cpp | 47 ++++++++++++++++++++++++++++++----------------- 1 files changed, 30 insertions(+), 17 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.29 llvm/lib/CodeGen/IfConversion.cpp:1.30 --- llvm/lib/CodeGen/IfConversion.cpp:1.29 Tue Jun 5 18:46:14 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Tue Jun 5 19:57:55 2007 @@ -308,8 +308,8 @@ } else { // FIXME: Consider duplicating if BB is small. bool TryTriangle = TrueBBI.TrueBB && TrueBBI.TrueBB == BBI.FalseBB && - BBI.TrueBB->pred_size() == 1; - bool TrySimple = TrueBBI.BrCond.size() == 0 && BBI.TrueBB->pred_size() == 1; + TrueBBI.BB->pred_size() == 1; + bool TrySimple = TrueBBI.BrCond.size() == 0 && TrueBBI.BB->pred_size() == 1; if ((TryTriangle || TrySimple) && FeasibilityAnalysis(TrueBBI, BBI.BrCond)) { if (TryTriangle) { @@ -333,14 +333,21 @@ BBI.Kind = ICSimple; TrueBBI.Kind = ICChild; } - } else if (FalseBBI.BrCond.size() == 0 && BBI.FalseBB->pred_size() == 1) { - // Try 'simple' on the other path... + } else if (FalseBBI.BrCond.size() == 0 && FalseBBI.BB->pred_size() == 1) { + // Try the other path... std::vector RevCond(BBI.BrCond); - if (TII->ReverseBranchCondition(RevCond)) - assert(false && "Unable to reverse branch condition!"); - if (FeasibilityAnalysis(FalseBBI, RevCond)) { - BBI.Kind = ICSimpleFalse; - FalseBBI.Kind = ICChild; + if (!TII->ReverseBranchCondition(RevCond) && + FeasibilityAnalysis(FalseBBI, RevCond)) { + if (FalseBBI.TrueBB && FalseBBI.TrueBB == BBI.TrueBB && + FalseBBI.BB->pred_size() == 1) { + // Reverse 'true' and 'false' paths. + ReverseBranchCondition(BBI); + BBI.Kind = ICTriangle; + FalseBBI.Kind = ICChild; + } else { + BBI.Kind = ICSimpleFalse; + FalseBBI.Kind = ICChild; + } } } } @@ -620,16 +627,19 @@ TII->ReverseBranchCondition(RevCond); std::vector *Cond1 = &BBI.BrCond; std::vector *Cond2 = &RevCond; - if (TrueBBI.ModifyPredicate) { - std::swap(BBI1, BBI2); - std::swap(Cond1, Cond2); - } - // Check the 'true' and 'false' blocks if either isn't ended with a branch. // Either the block fallthrough to another block or it ends with a // return. If it's the former, add a branch to its successor. bool NeedBr1 = !BBI1->TrueBB && BBI1->BB->succ_size(); - bool NeedBr2 = !BBI2->TrueBB && BBI1->BB->succ_size(); + bool NeedBr2 = !BBI2->TrueBB && BBI2->BB->succ_size(); + + if ((TrueBBI.ModifyPredicate && !FalseBBI.ModifyPredicate) || + (!TrueBBI.ModifyPredicate && !FalseBBI.ModifyPredicate && + NeedBr1 && !NeedBr2)) { + std::swap(BBI1, BBI2); + std::swap(Cond1, Cond2); + std::swap(NeedBr1, NeedBr2); + } // Predicate the 'true' block after removing its branch. BBI1->NonPredSize -= TII->RemoveBranch(*BBI1->BB); @@ -650,8 +660,6 @@ // Keep them as two separate blocks if there is an early exit. if (!NeedBr1) MergeBlocks(*BBI1, *BBI2); - else if (!isNextBlock(BBI1->BB, BBI2->BB)) - InsertUncondBranch(BBI1->BB, BBI2->BB, TII); // Remove the conditional branch from entry to the blocks. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); @@ -659,6 +667,11 @@ // Merge the combined block into the entry of the diamond. MergeBlocks(BBI, *BBI1); + // 'True' and 'false' aren't combined, see if we need to add a unconditional + // branch to the 'false' block. + if (NeedBr1 && !isNextBlock(BBI.BB, BBI2->BB)) + InsertUncondBranch(BBI1->BB, BBI2->BB, TII); + // If the if-converted block fallthrough or unconditionally branch into the // tail block, and the tail block does not have other predecessors, then // fold the tail block in as well. From dpatel at apple.com Tue Jun 5 20:00:10 2007 From: dpatel at apple.com (Devang Patel) Date: Tue, 5 Jun 2007 20:00:10 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706060100.l5610Arp031644@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.91 -> 1.92 --- Log message: Break friendship. --- Diffs of the changes: (+0 -3) Dominators.h | 3 --- 1 files changed, 3 deletions(-) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.91 llvm/include/llvm/Analysis/Dominators.h:1.92 --- llvm/include/llvm/Analysis/Dominators.h:1.91 Tue Jun 5 19:46:36 2007 +++ llvm/include/llvm/Analysis/Dominators.h Tue Jun 5 19:59:48 2007 @@ -61,9 +61,6 @@ // DomTreeNode - Dominator Tree Node class DomTreeNode { - friend class DominatorTree; - friend struct PostDominatorTree; - BasicBlock *TheBB; DomTreeNode *IDom; std::vector Children; From evan.cheng at apple.com Tue Jun 5 20:13:06 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 5 Jun 2007 20:13:06 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706060113.l561D6uv031877@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.30 -> 1.31 --- Log message: Minor statistics counting bug. --- Diffs of the changes: (+5 -3) IfConversion.cpp | 8 +++++--- 1 files changed, 5 insertions(+), 3 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.30 llvm/lib/CodeGen/IfConversion.cpp:1.31 --- llvm/lib/CodeGen/IfConversion.cpp:1.30 Tue Jun 5 19:57:55 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Tue Jun 5 20:12:44 2007 @@ -158,15 +158,17 @@ // Block has been already been if-converted, abort! break; case ICSimple: - case ICSimpleFalse: + case ICSimpleFalse: { + bool isRev = BBI.Kind == ICSimpleFalse; DOUT << "Ifcvt (Simple" << (BBI.Kind == ICSimpleFalse ? " false" : "") << "): BB#" << BBI.BB->getNumber() << " "; RetVal = IfConvertSimple(BBI); DOUT << (RetVal ? "succeeded!" : "failed!") << "\n"; if (RetVal) - if (BBI.Kind == ICSimple) NumSimple++; - else NumSimpleRev++; + if (isRev) NumSimple++; + else NumSimpleRev++; break; + } case ICTriangle: DOUT << "Ifcvt (Triangle): BB#" << BBI.BB->getNumber() << " "; RetVal = IfConvertTriangle(BBI); From sabre at nondot.org Tue Jun 5 20:22:08 2007 From: sabre at nondot.org (Chris Lattner) Date: Tue, 5 Jun 2007 20:22:08 -0500 Subject: [llvm-commits] CVS: llvm/test/CodeGen/X86/2007-06-05-LSR-Dominator.ll Message-ID: <200706060122.l561M8bx032160@zion.cs.uiuc.edu> Changes in directory llvm/test/CodeGen/X86: 2007-06-05-LSR-Dominator.ll added (r1.1) --- Log message: new testcase for PR1495: http://llvm.org/PR1495 --- Diffs of the changes: (+129 -0) 2007-06-05-LSR-Dominator.ll | 129 ++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 129 insertions(+) Index: llvm/test/CodeGen/X86/2007-06-05-LSR-Dominator.ll diff -c /dev/null llvm/test/CodeGen/X86/2007-06-05-LSR-Dominator.ll:1.1 *** /dev/null Tue Jun 5 20:21:56 2007 --- llvm/test/CodeGen/X86/2007-06-05-LSR-Dominator.ll Tue Jun 5 20:21:46 2007 *************** *** 0 **** --- 1,129 ---- + ; PR1495 + ; RUN: llvm-as < %s | llc -march=x86 + + target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64" + target triple = "i686-pc-linux-gnu" + %struct.AVRational = type { i32, i32 } + %struct.FFTComplex = type { float, float } + %struct.FFTContext = type { i32, i32, i16*, %struct.FFTComplex*, %struct.FFTComplex*, void (%struct.FFTContext*, %struct.FFTComplex*)*, void (%struct.MDCTContext*, float*, float*, float*)* } + %struct.MDCTContext = type { i32, i32, float*, float*, %struct.FFTContext } + %struct.Minima = type { i32, i32, i32, i32 } + %struct.codebook_t = type { i32, i8*, i32*, i32, float, float, i32, i32, i32*, float*, float* } + %struct.floor_class_t = type { i32, i32, i32, i32* } + %struct.floor_t = type { i32, i32*, i32, %struct.floor_class_t*, i32, i32, i32, %struct.Minima* } + %struct.mapping_t = type { i32, i32*, i32*, i32*, i32, i32*, i32* } + %struct.residue_t = type { i32, i32, i32, i32, i32, i32, [8 x i8]*, [2 x float]* } + %struct.venc_context_t = type { i32, i32, [2 x i32], [2 x %struct.MDCTContext], [2 x float*], i32, float*, float*, float*, float*, float, i32, %struct.codebook_t*, i32, %struct.floor_t*, i32, %struct.residue_t*, i32, %struct.mapping_t*, i32, %struct.AVRational* } + + define fastcc i32 @put_main_header(%struct.venc_context_t* %venc, i8** %out) { + entry: + br i1 false, label %bb1820, label %bb288.bb148_crit_edge + + bb288.bb148_crit_edge: ; preds = %entry + ret i32 0 + + cond_next1712: ; preds = %bb1820.bb1680_crit_edge + ret i32 0 + + bb1817: ; preds = %bb1820.bb1680_crit_edge + br label %bb1820 + + bb1820: ; preds = %bb1817, %entry + %pb.1.50 = phi i32 [ %tmp1693, %bb1817 ], [ 8, %entry ] ; [#uses=3] + br i1 false, label %bb2093, label %bb1820.bb1680_crit_edge + + bb1820.bb1680_crit_edge: ; preds = %bb1820 + %tmp1693 = add i32 %pb.1.50, 8 ; [#uses=2] + %tmp1702 = icmp slt i32 %tmp1693, 0 ; [#uses=1] + br i1 %tmp1702, label %cond_next1712, label %bb1817 + + bb2093: ; preds = %bb1820 + %tmp2102 = add i32 %pb.1.50, 65 ; [#uses=0] + %tmp2236 = add i32 %pb.1.50, 72 ; [#uses=1] + %tmp2237 = sdiv i32 %tmp2236, 8 ; [#uses=2] + br i1 false, label %bb2543, label %bb2536.bb2396_crit_edge + + bb2536.bb2396_crit_edge: ; preds = %bb2093 + ret i32 0 + + bb2543: ; preds = %bb2093 + br i1 false, label %cond_next2576, label %bb2690 + + cond_next2576: ; preds = %bb2543 + ret i32 0 + + bb2682: ; preds = %bb2690 + ret i32 0 + + bb2690: ; preds = %bb2543 + br i1 false, label %bb2682, label %bb2698 + + bb2698: ; preds = %bb2690 + br i1 false, label %cond_next2726, label %bb2831 + + cond_next2726: ; preds = %bb2698 + ret i32 0 + + bb2831: ; preds = %bb2698 + br i1 false, label %cond_next2859, label %bb2964 + + cond_next2859: ; preds = %bb2831 + br i1 false, label %bb2943, label %cond_true2866 + + cond_true2866: ; preds = %cond_next2859 + br i1 false, label %cond_true2874, label %cond_false2897 + + cond_true2874: ; preds = %cond_true2866 + ret i32 0 + + cond_false2897: ; preds = %cond_true2866 + ret i32 0 + + bb2943: ; preds = %cond_next2859 + ret i32 0 + + bb2964: ; preds = %bb2831 + br i1 false, label %cond_next2997, label %bb4589 + + cond_next2997: ; preds = %bb2964 + ret i32 0 + + bb3103: ; preds = %bb4589 + ret i32 0 + + bb4589: ; preds = %bb2964 + br i1 false, label %bb3103, label %bb4597 + + bb4597: ; preds = %bb4589 + br i1 false, label %cond_next4630, label %bb4744 + + cond_next4630: ; preds = %bb4597 + br i1 false, label %bb4744, label %cond_true4724 + + cond_true4724: ; preds = %cond_next4630 + br i1 false, label %bb4736, label %bb7531 + + bb4736: ; preds = %cond_true4724 + ret i32 0 + + bb4744: ; preds = %cond_next4630, %bb4597 + ret i32 0 + + bb7531: ; preds = %cond_true4724 + %v_addr.023.0.i6 = add i32 %tmp2237, -255 ; [#uses=1] + br label %bb.i14 + + bb.i14: ; preds = %bb.i14, %bb7531 + %n.021.0.i8 = phi i32 [ 0, %bb7531 ], [ %indvar.next, %bb.i14 ] ; [#uses=2] + %tmp..i9 = mul i32 %n.021.0.i8, -255 ; [#uses=1] + %tmp5.i11 = add i32 %v_addr.023.0.i6, %tmp..i9 ; [#uses=1] + %tmp10.i12 = icmp ugt i32 %tmp5.i11, 254 ; [#uses=1] + %indvar.next = add i32 %n.021.0.i8, 1 ; [#uses=1] + br i1 %tmp10.i12, label %bb.i14, label %bb12.loopexit.i18 + + bb12.loopexit.i18: ; preds = %bb.i14 + call void @llvm.memcpy.i32( i8* null, i8* null, i32 %tmp2237, i32 1 ) + ret i32 0 + } + + declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) From sabre at nondot.org Tue Jun 5 20:22:31 2007 From: sabre at nondot.org (Chris Lattner) Date: Tue, 5 Jun 2007 20:22:31 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/ScalarEvolutionExpander.h Message-ID: <200706060122.l561MVrF032189@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: ScalarEvolutionExpander.h updated: 1.15 -> 1.16 --- Log message: add accessor --- Diffs of the changes: (+2 -0) ScalarEvolutionExpander.h | 2 ++ 1 files changed, 2 insertions(+) Index: llvm/include/llvm/Analysis/ScalarEvolutionExpander.h diff -u llvm/include/llvm/Analysis/ScalarEvolutionExpander.h:1.15 llvm/include/llvm/Analysis/ScalarEvolutionExpander.h:1.16 --- llvm/include/llvm/Analysis/ScalarEvolutionExpander.h:1.15 Tue Apr 17 19:43:05 2007 +++ llvm/include/llvm/Analysis/ScalarEvolutionExpander.h Tue Jun 5 20:22:09 2007 @@ -73,6 +73,8 @@ InsertedInstructions.insert(I); } + Instruction *getInsertionPoint() const { return InsertPt; } + /// expandCodeFor - Insert code to directly compute the specified SCEV /// expression into the program. The inserted code is inserted into the /// specified block. From sabre at nondot.org Tue Jun 5 20:24:17 2007 From: sabre at nondot.org (Chris Lattner) Date: Tue, 5 Jun 2007 20:24:17 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200706060124.l561OHon032291@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopStrengthReduce.cpp updated: 1.138 -> 1.139 --- Log message: Fix PR1495: http://llvm.org/PR1495 and CodeGen/X86/2007-06-05-LSR-Dominator.ll --- Diffs of the changes: (+6 -0) LoopStrengthReduce.cpp | 6 ++++++ 1 files changed, 6 insertions(+) Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp diff -u llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.138 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.139 --- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.138 Fri May 18 20:22:21 2007 +++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Tue Jun 5 20:23:55 2007 @@ -560,11 +560,17 @@ OperandValToReplace->getType()); Value *Base = Rewriter.expandCodeFor(NewBase, BaseInsertPt); + + // If we are inserting the base and imm values in the same block, make sure to + // adjust the IP position if insertion reused a result. + if (IP == BaseInsertPt) + IP = Rewriter.getInsertionPoint(); // Always emit the immediate (if non-zero) into the same block as the user. SCEVHandle NewValSCEV = SCEVAddExpr::get(SCEVUnknown::get(Base), Imm); return Rewriter.expandCodeFor(NewValSCEV, IP, OperandValToReplace->getType()); + } From resistor at mac.com Tue Jun 5 20:28:09 2007 From: resistor at mac.com (Owen Anderson) Date: Tue, 5 Jun 2007 20:28:09 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706060128.l561S9Fw032386@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.21 -> 1.22 --- Log message: Add simple full redundancy elimination. --- Diffs of the changes: (+38 -12) GVNPRE.cpp | 50 ++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 38 insertions(+), 12 deletions(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.21 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.22 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.21 Tue Jun 5 18:46:12 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Tue Jun 5 20:27:49 2007 @@ -77,7 +77,7 @@ void dump_unique(ValueTable& VN, std::set& s); void clean(ValueTable VN, std::set& set); bool add(ValueTable& VN, std::set& MS, Value* V); - Value* find_leader(ValueTable VN, std::set& vals, Value* v); + Value* find_leader(std::set& vals, Value* v); Value* phi_translate(ValueTable& VN, std::set& MS, std::set& set, Value* V, BasicBlock* pred); @@ -120,8 +120,7 @@ return ret.second; } -Value* GVNPRE::find_leader(GVNPRE::ValueTable VN, - std::set& vals, +Value* GVNPRE::find_leader(std::set& vals, Value* v) { ExprLT cmp; for (std::set::iterator I = vals.begin(), E = vals.end(); @@ -141,7 +140,7 @@ if (BinaryOperator* BO = dyn_cast(V)) { Value* newOp1 = isa(BO->getOperand(0)) ? phi_translate(VN, MS, set, - find_leader(VN, set, BO->getOperand(0)), + find_leader(set, BO->getOperand(0)), pred) : BO->getOperand(0); if (newOp1 == 0) @@ -149,7 +148,7 @@ Value* newOp2 = isa(BO->getOperand(1)) ? phi_translate(VN, MS, set, - find_leader(VN, set, BO->getOperand(1)), + find_leader(set, BO->getOperand(1)), pred) : BO->getOperand(1); if (newOp2 == 0) @@ -160,7 +159,7 @@ newOp1, newOp2, BO->getName()+".gvnpre"); - if (!find_leader(VN, set, newVal)) { + if (!find_leader(set, newVal)) { add(VN, MS, newVal); return newVal; } else { @@ -241,8 +240,8 @@ Value* e = Q.back(); if (BinaryOperator* BO = dyn_cast(e)) { - Value* l = find_leader(VN, set, BO->getOperand(0)); - Value* r = find_leader(VN, set, BO->getOperand(1)); + Value* l = find_leader(set, BO->getOperand(0)); + Value* r = find_leader(set, BO->getOperand(1)); if (l != 0 && isa(l) && visited.find(l) == visited.end()) @@ -319,8 +318,6 @@ currExps.insert(rightValue); currExps.insert(BO); - //currTemps.insert(BO); - // Handle unsupported ops } else if (!BI->isTerminator()){ add(VN, MS, BI); @@ -344,7 +341,9 @@ DominatorTree &DT = getAnalysis(); - // First Phase of BuildSets - calculate AVAIL_OUT + // Phase 1: BuildSets + + // Phase 1, Part 1: calculate AVAIL_OUT // Top-down walk of the dominator tree for (df_iterator DI = df_begin(DT.getRootNode()), @@ -366,7 +365,7 @@ PostDominatorTree &PDT = getAnalysis(); - // Second Phase of BuildSets - calculate ANTIC_IN + // Phase 1, Part 2: calculate ANTIC_IN std::set visited; @@ -476,5 +475,32 @@ DOUT << "\n"; } + + // Phase 2: Insert + // FIXME: Not implemented yet + + // Phase 3: Eliminate + for (df_iterator DI = df_begin(DT.getRootNode()), + E = df_end(DT.getRootNode()); DI != E; ++DI) { + BasicBlock* BB = DI->getBlock(); + + std::vector erase; + + for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); + BI != BE; ++BI) { + Value* leader = find_leader(availableOut[BB], BI); + if (leader != 0) + if (Instruction* Instr = dyn_cast(leader)) + if (Instr->getParent() != 0 && Instr != BI) { + BI->replaceAllUsesWith(leader); + erase.push_back(BI); + } + } + + for (std::vector::iterator I = erase.begin(), E = erase.end(); + I != E; ++I) + (*I)->eraseFromParent(); + } + return false; } From evan.cheng at apple.com Tue Jun 5 21:10:26 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 5 Jun 2007 21:10:26 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706060210.l562AQ4D000641@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.31 -> 1.32 --- Log message: If a unconditional branch is added to branch to the false path during ifcvt, the predicated block cannot be iteratively ifcvted. --- Diffs of the changes: (+33 -6) IfConversion.cpp | 39 +++++++++++++++++++++++++++++++++------ 1 files changed, 33 insertions(+), 6 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.31 llvm/lib/CodeGen/IfConversion.cpp:1.32 --- llvm/lib/CodeGen/IfConversion.cpp:1.31 Tue Jun 5 20:12:44 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Tue Jun 5 21:08:52 2007 @@ -165,8 +165,8 @@ RetVal = IfConvertSimple(BBI); DOUT << (RetVal ? "succeeded!" : "failed!") << "\n"; if (RetVal) - if (isRev) NumSimple++; - else NumSimpleRev++; + if (isRev) NumSimpleRev++; + else NumSimple++; break; } case ICTriangle: @@ -515,12 +515,25 @@ // to the 'false' branch. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); MergeBlocks(BBI, *CvtBBI); - if (!isNextBlock(BBI.BB, NextBBI->BB)) + bool IterIfcvt = true; + if (!isNextBlock(BBI.BB, NextBBI->BB)) { + // Now ifcvt'd block will look like this: + // BB: + // ... + // t, f = cmp + // if t op + // b BBf + // + // We cannot further ifcvt this block because the unconditional branch will + // have to be predicated on the new condition, that will not be available + // if cmp executes. InsertUncondBranch(BBI.BB, NextBBI->BB, TII); + } std::copy(Cond.begin(), Cond.end(), std::back_inserter(BBI.Predicate)); // Update block info. BB can be iteratively if-converted. - BBI.Kind = ICReAnalyze; + if (IterIfcvt) + BBI.Kind = ICReAnalyze; ReTryPreds(BBI.BB); CvtBBI->Kind = ICDead; @@ -552,11 +565,24 @@ // predecessors. Otherwise, add a unconditional branch from 'true' to 'false'. BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; bool FalseBBDead = false; + bool IterIfcvt = true; if (!HasEarlyExit && FalseBBI.BB->pred_size() == 2) { MergeBlocks(TrueBBI, FalseBBI); FalseBBDead = true; - } else if (!isNextBlock(TrueBBI.BB, FalseBBI.BB)) + } else if (!isNextBlock(TrueBBI.BB, FalseBBI.BB)) { InsertUncondBranch(TrueBBI.BB, FalseBBI.BB, TII); + // Now ifcvt'd block will look like this: + // BB: + // ... + // t, f = cmp + // if t op + // b BBf + // + // We cannot further ifcvt this block because the unconditional branch will + // have to be predicated on the new condition, that will not be available + // if cmp executes. + IterIfcvt = false; + } // Now merge the entry of the triangle with the true block. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); @@ -565,7 +591,8 @@ std::back_inserter(BBI.Predicate)); // Update block info. BB can be iteratively if-converted. - BBI.Kind = ICReAnalyze; + if (IterIfcvt) + BBI.Kind = ICReAnalyze; ReTryPreds(BBI.BB); TrueBBI.Kind = ICDead; if (FalseBBDead) From nicholas at mxc.ca Tue Jun 5 22:52:18 2007 From: nicholas at mxc.ca (Nick Lewycky) Date: Tue, 5 Jun 2007 22:52:18 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/IndVarSimplify.cpp Message-ID: <200706060352.l563qIgY003235@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: IndVarSimplify.cpp updated: 1.119 -> 1.120 --- Log message: Inform ScalarEvolutions that we're deleting Values. This is the obviously correct part of the fix for PR1487: http://llvm.org/PR1487 . --- Diffs of the changes: (+2 -0) IndVarSimplify.cpp | 2 ++ 1 files changed, 2 insertions(+) Index: llvm/lib/Transforms/Scalar/IndVarSimplify.cpp diff -u llvm/lib/Transforms/Scalar/IndVarSimplify.cpp:1.119 llvm/lib/Transforms/Scalar/IndVarSimplify.cpp:1.120 --- llvm/lib/Transforms/Scalar/IndVarSimplify.cpp:1.119 Sun May 6 08:37:16 2007 +++ llvm/lib/Transforms/Scalar/IndVarSimplify.cpp Tue Jun 5 22:51:56 2007 @@ -181,6 +181,7 @@ GetElementPtrInst *NGEPI = new GetElementPtrInst( NCE, Constant::getNullValue(Type::Int32Ty), NewAdd, GEPI->getName(), GEPI); + SE->deleteInstructionFromRecords(GEPI); GEPI->replaceAllUsesWith(NGEPI); GEPI->eraseFromParent(); GEPI = NGEPI; @@ -398,6 +399,7 @@ // the PHI entirely. This is safe, because the NewVal won't be variant // in the loop, so we don't need an LCSSA phi node anymore. if (NumPreds == 1) { + SE->deleteInstructionFromRecords(PN); PN->replaceAllUsesWith(ExitVal); PN->eraseFromParent(); break; From nicholas at mxc.ca Tue Jun 5 23:11:43 2007 From: nicholas at mxc.ca (Nick Lewycky) Date: Tue, 5 Jun 2007 23:11:43 -0500 Subject: [llvm-commits] CVS: llvm/test/Transforms/IndVarsSimplify/2007-06-06-DeleteDanglesPtr.ll Message-ID: <200706060411.l564BhYL003834@zion.cs.uiuc.edu> Changes in directory llvm/test/Transforms/IndVarsSimplify: 2007-06-06-DeleteDanglesPtr.ll added (r1.1) --- Log message: new testcase for PR1487: http://llvm.org/PR1487 --- Diffs of the changes: (+117 -0) 2007-06-06-DeleteDanglesPtr.ll | 117 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 117 insertions(+) Index: llvm/test/Transforms/IndVarsSimplify/2007-06-06-DeleteDanglesPtr.ll diff -c /dev/null llvm/test/Transforms/IndVarsSimplify/2007-06-06-DeleteDanglesPtr.ll:1.1 *** /dev/null Tue Jun 5 23:11:31 2007 --- llvm/test/Transforms/IndVarsSimplify/2007-06-06-DeleteDanglesPtr.ll Tue Jun 5 23:11:21 2007 *************** *** 0 **** --- 1,117 ---- + ; RUN: llvm-as < %s | opt -indvars -disable-output + ; PR1487 + + %struct.AVClass = type { i8*, i8* (i8*)*, %struct.AVOption* } + %struct.AVCodec = type { i8*, i32, i32, i32, i32 (%struct.AVCodecContext*)*, i32 (%struct.AVCodecContext*, i8*, i32, i8*)*, i32 (%struct.AVCodecContext*)*, i32 (%struct.AVCodecContext*, i8*, i32*, i8*, i32)*, i32, %struct.AVCodec*, void (%struct.AVCodecContext*)*, %struct.AVCodecTag*, i32* } + %struct.AVCodecContext = type { %struct.AVClass*, i32, i32, i32, i32, i32, i8*, i32, %struct.AVCodecTag, i32, i32, i32, i32, i32, void (%struct.AVCodecContext*, %struct.AVFrame*, i32*, i32, i32, i32)*, i32, i32, i32, i32, i32, i32, i32, float, float, i32, i32, i32, i32, float, i32, i32, i32, %struct.AVCodec*, i8*, i32, i32, void (%struct.AVCodecContext*, i8*, i32, i32)*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i8*, [32 x i8], i32, i32, i32, i32, i32, i32, i32, float, i32, i32 (%struct.AVCodecContext*, %struct.AVFrame*)*, void (%struct.AVCodecContext*, %struct.AVFrame*)*, i32, i32, i32, i32, i8*, i8*, float, float, i32, %struct.RcOverride*, i32, i8*, i32, i32, i32, float, float, float, float, i32, float, float, float, float, float, i32, i32, i32, i32*, i32, i32, i32, i32, %struct.AVCodecTag, %struct.AVFrame*, i32, i32, [4 x i64], i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32 (%struct.AVCodecContext*, i32*)*, i32, i32, i32, i32, i32, i32, i8*, i32, i3! 2, i32, i32, i32, i32, i16*, i16*, i32, i32, i32, i32, %struct.AVPaletteControl*, i32, i32 (%struct.AVCodecContext*, %struct.AVFrame*)*, i32, i32, i32, i32, i32, i32, i32, i32 (%struct.AVCodecContext*, i32 (%struct.AVCodecContext*, i8*)*, i8**, i32*, i32)*, i8*, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, float, i32, i32, i32, i32, i32, i32, i32, i32, float, i32, i32, i32, i32, i32, i32, float, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i64 } + %struct.AVCodecTag = type { i32, i32 } + %struct.AVFrame = type { [4 x i8*], [4 x i32], [4 x i8*], i32, i32, i64, i32, i32, i32, i32, i32, i8*, i32, i8*, [2 x [2 x i16]*], i32*, i8, i8*, [4 x i64], i32, i32, i32, i32, i32, %struct.AVPanScan*, i32, i32, i16*, [2 x i8*] } + %struct.AVOption = type { i8*, i8*, i32, i32, double, double, double, i32, i8* } + %struct.AVPaletteControl = type { i32, [256 x i32] } + %struct.AVPanScan = type { i32, i32, i32, [3 x [2 x i16]] } + %struct.RcOverride = type { i32, i32, i32, float } + + define i32 @smc_decode_frame(%struct.AVCodecContext* %avctx, i8* %data, i32* %data_size, i8* %buf, i32 %buf_size) { + entry: + br i1 false, label %cond_next, label %cond_true + + cond_true: ; preds = %entry + ret i32 -1 + + cond_next: ; preds = %entry + br i1 false, label %bb.outer5.split.split.split.us, label %cond_true194.split + + bb.outer5.split.split.split.us: ; preds = %cond_next + br i1 false, label %cond_next188.us503.us, label %bb.us481 + + bb275.us493.us: ; preds = %cond_next188.us503.us, %cond_next188.us503.us + ret i32 0 + + cond_next188.us503.us: ; preds = %bb.outer5.split.split.split.us + switch i32 0, label %bb1401 [ + i32 0, label %cond_next202.bb215_crit_edge.split + i32 16, label %bb215 + i32 32, label %bb275.us493.us + i32 48, label %bb275.us493.us + i32 64, label %cond_next202.bb417_crit_edge.split + i32 80, label %bb417 + i32 96, label %cond_next202.bb615_crit_edge.split + i32 112, label %bb615 + i32 128, label %cond_next202.bb716_crit_edge.split + i32 144, label %bb716 + i32 160, label %cond_next202.bb882_crit_edge.split + i32 176, label %bb882 + i32 192, label %cond_next202.bb1062_crit_edge.split + i32 208, label %bb1062 + i32 224, label %bb1326.us.outer.outer + ] + + bb.us481: ; preds = %bb.outer5.split.split.split.us + ret i32 0 + + cond_true194.split: ; preds = %cond_next + ret i32 %buf_size + + cond_next202.bb1062_crit_edge.split: ; preds = %cond_next188.us503.us + ret i32 0 + + cond_next202.bb882_crit_edge.split: ; preds = %cond_next188.us503.us + ret i32 0 + + cond_next202.bb716_crit_edge.split: ; preds = %cond_next188.us503.us + ret i32 0 + + cond_next202.bb615_crit_edge.split: ; preds = %cond_next188.us503.us + ret i32 0 + + cond_next202.bb417_crit_edge.split: ; preds = %cond_next188.us503.us + ret i32 0 + + cond_next202.bb215_crit_edge.split: ; preds = %cond_next188.us503.us + ret i32 0 + + bb215: ; preds = %cond_next188.us503.us + ret i32 0 + + bb417: ; preds = %cond_next188.us503.us + ret i32 0 + + bb615: ; preds = %cond_next188.us503.us + ret i32 0 + + bb716: ; preds = %cond_next188.us503.us + ret i32 0 + + bb882: ; preds = %cond_next188.us503.us + ret i32 0 + + bb1062: ; preds = %cond_next188.us503.us + ret i32 0 + + bb1326.us: ; preds = %bb1326.us.outer.outer, %bb1347.loopexit.us, %bb1326.us + %pixel_y.162036.us.ph = phi i32 [ %tmp1352.us, %bb1347.loopexit.us ], [ 0, %bb1326.us.outer.outer ], [ %pixel_y.162036.us.ph, %bb1326.us ] ; [#uses=2] + %stream_ptr.142038.us.ph = phi i32 [ %tmp1339.us, %bb1347.loopexit.us ], [ %stream_ptr.142038.us.ph.ph, %bb1326.us.outer.outer ], [ %stream_ptr.142038.us.ph, %bb1326.us ] ; [#uses=2] + %pixel_x.232031.us = phi i32 [ %tmp1341.us, %bb1326.us ], [ 0, %bb1326.us.outer.outer ], [ 0, %bb1347.loopexit.us ] ; [#uses=3] + %block_ptr.222030.us = add i32 0, %pixel_x.232031.us ; [#uses=1] + %stream_ptr.132032.us = add i32 %pixel_x.232031.us, %stream_ptr.142038.us.ph ; [#uses=1] + %tmp1341.us = add i32 %pixel_x.232031.us, 1 ; [#uses=2] + %tmp1344.us = icmp slt i32 %tmp1341.us, 4 ; [#uses=1] + br i1 %tmp1344.us, label %bb1326.us, label %bb1347.loopexit.us + + bb1347.loopexit.us: ; preds = %bb1326.us + %tmp1339.us = add i32 %stream_ptr.132032.us, 1 ; [#uses=2] + %tmp1337.us = add i32 %block_ptr.222030.us, 1 ; [#uses=0] + %tmp1352.us = add i32 %pixel_y.162036.us.ph, 1 ; [#uses=2] + %tmp1355.us = icmp slt i32 %tmp1352.us, 4 ; [#uses=1] + br i1 %tmp1355.us, label %bb1326.us, label %bb1358 + + bb1358: ; preds = %bb1347.loopexit.us + br label %bb1326.us.outer.outer + + bb1326.us.outer.outer: ; preds = %bb1358, %cond_next188.us503.us + %stream_ptr.142038.us.ph.ph = phi i32 [ %tmp1339.us, %bb1358 ], [ 0, %cond_next188.us503.us ] ; [#uses=1] + br label %bb1326.us + + bb1401: ; preds = %cond_next188.us503.us + ret i32 0 + } From nicholas at mxc.ca Tue Jun 5 23:12:42 2007 From: nicholas at mxc.ca (Nick Lewycky) Date: Tue, 5 Jun 2007 23:12:42 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/ScalarEvolution.cpp Message-ID: <200706060412.l564CgV9003861@zion.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: ScalarEvolution.cpp updated: 1.116 -> 1.117 --- Log message: Fix PR1487: http://llvm.org/PR1487 and Transforms/IndVar/2007-06-06-DeleteDanglesPtr.ll --- Diffs of the changes: (+22 -3) ScalarEvolution.cpp | 25 ++++++++++++++++++++++--- 1 files changed, 22 insertions(+), 3 deletions(-) Index: llvm/lib/Analysis/ScalarEvolution.cpp diff -u llvm/lib/Analysis/ScalarEvolution.cpp:1.116 llvm/lib/Analysis/ScalarEvolution.cpp:1.117 --- llvm/lib/Analysis/ScalarEvolution.cpp:1.116 Wed May 2 20:11:53 2007 +++ llvm/lib/Analysis/ScalarEvolution.cpp Tue Jun 5 23:12:20 2007 @@ -1196,9 +1196,28 @@ /// client before it removes an instruction from the program, to make sure /// that no dangling references are left around. void ScalarEvolutionsImpl::deleteInstructionFromRecords(Instruction *I) { - Scalars.erase(I); - if (PHINode *PN = dyn_cast(I)) - ConstantEvolutionLoopExitValue.erase(PN); + SmallVector Worklist; + + if (Scalars.erase(I)) { + if (PHINode *PN = dyn_cast(I)) + ConstantEvolutionLoopExitValue.erase(PN); + Worklist.push_back(I); + } + + while (!Worklist.empty()) { + Instruction *II = Worklist.back(); + Worklist.pop_back(); + + for (Instruction::use_iterator UI = II->use_begin(), UE = II->use_end(); + UI != UE; ++UI) { + Instruction *Inst = dyn_cast(*UI); + if (Inst && hasSCEV(Inst) && Scalars.erase(Inst)) { + if (PHINode *PN = dyn_cast(II)) + ConstantEvolutionLoopExitValue.erase(PN); + Worklist.push_back(Inst); + } + } + } } From clattner at apple.com Tue Jun 5 23:24:40 2007 From: clattner at apple.com (Chris Lattner) Date: Tue, 5 Jun 2007 21:24:40 -0700 Subject: [llvm-commits] CVS: llvm/lib/Analysis/ScalarEvolution.cpp In-Reply-To: <200706060412.l564CgV9003861@zion.cs.uiuc.edu> References: <200706060412.l564CgV9003861@zion.cs.uiuc.edu> Message-ID: <7731079E-CD1B-4975-A68C-1FA2CA686925@apple.com> > Fix PR1487: http://llvm.org/PR1487 and Transforms/IndVar/ > 2007-06-06-DeleteDanglesPtr.ll Thanks Nicholas, > /// client before it removes an instruction from the program, to > make sure > /// that no dangling references are left around. > void ScalarEvolutionsImpl::deleteInstructionFromRecords > (Instruction *I) { > + while (!Worklist.empty()) { > + Instruction *II = Worklist.back(); > + Worklist.pop_back(); > + > + for (Instruction::use_iterator UI = II->use_begin(), UE = II- > >use_end(); > + UI != UE; ++UI) { > + Instruction *Inst = dyn_cast(*UI); > + if (Inst && hasSCEV(Inst) && Scalars.erase(Inst)) { One more thing, sorry I didn't notice this before: The only thing that can use Instructions are other intstructions. As such, you can change the dyn_cast into cast and there is no need to check for null in the next line. -Chris > + if (PHINode *PN = dyn_cast(II)) > + ConstantEvolutionLoopExitValue.erase(PN); > + Worklist.push_back(Inst); > + } > + } > + } > } > > > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From tonic at nondot.org Wed Jun 6 00:54:12 2007 From: tonic at nondot.org (Tanya Lattner) Date: Wed, 6 Jun 2007 00:54:12 -0500 Subject: [llvm-commits] CVS: llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr 2003-11-18-MemberInitializationCasting.cpp.tr 2005-07-21-VirtualBaseAccess.cpp Message-ID: <200706060554.l565sCoS005868@zion.cs.uiuc.edu> Changes in directory llvm/test/C++Frontend: 2003-11-09-ConstructorTypeSafety.cpp.tr updated: 1.3 -> 1.4 2003-11-18-MemberInitializationCasting.cpp.tr updated: 1.3 -> 1.4 2005-07-21-VirtualBaseAccess.cpp updated: 1.2 -> 1.3 --- Log message: Ignore llvm.noinline --- Diffs of the changes: (+3 -3) 2003-11-09-ConstructorTypeSafety.cpp.tr | 2 +- 2003-11-18-MemberInitializationCasting.cpp.tr | 2 +- 2005-07-21-VirtualBaseAccess.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) Index: llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr diff -u llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr:1.3 llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr:1.4 --- llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr:1.3 Sun Apr 15 15:41:31 2007 +++ llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr Wed Jun 6 00:53:50 2007 @@ -1,6 +1,6 @@ // The code generated for this testcase should be completely typesafe! // RUN: %llvmgcc -xc++ -S -o - %s | llvm-as | opt -die | llvm-dis | \ -// RUN: notcast +// RUN: grep -v llvm.noinline | notcast struct contained { unsigned X; Index: llvm/test/C++Frontend/2003-11-18-MemberInitializationCasting.cpp.tr diff -u llvm/test/C++Frontend/2003-11-18-MemberInitializationCasting.cpp.tr:1.3 llvm/test/C++Frontend/2003-11-18-MemberInitializationCasting.cpp.tr:1.4 --- llvm/test/C++Frontend/2003-11-18-MemberInitializationCasting.cpp.tr:1.3 Sun Apr 15 15:41:31 2007 +++ llvm/test/C++Frontend/2003-11-18-MemberInitializationCasting.cpp.tr Wed Jun 6 00:53:50 2007 @@ -1,4 +1,4 @@ -// RUN: %llvmgcc -xc++ -S -o - %s | llvm-as | opt -die | llvm-dis | notcast +// RUN: %llvmgcc -xc++ -S -o - %s | llvm-as | opt -die | llvm-dis | grep -v llvm.noinline | notcast struct A { A() : i(0) {} Index: llvm/test/C++Frontend/2005-07-21-VirtualBaseAccess.cpp diff -u llvm/test/C++Frontend/2005-07-21-VirtualBaseAccess.cpp:1.2 llvm/test/C++Frontend/2005-07-21-VirtualBaseAccess.cpp:1.3 --- llvm/test/C++Frontend/2005-07-21-VirtualBaseAccess.cpp:1.2 Thu Apr 13 12:28:28 2006 +++ llvm/test/C++Frontend/2005-07-21-VirtualBaseAccess.cpp Wed Jun 6 00:53:50 2007 @@ -1,4 +1,4 @@ -// RUN: %llvmgxx -xc++ %s -c -o - | opt -die | llvm-dis | not grep cast +// RUN: %llvmgxx -xc++ %s -c -o - | opt -die | llvm-dis | grep -v llvm.noinline | not grep cast void foo(int*); From tonic at nondot.org Wed Jun 6 00:54:12 2007 From: tonic at nondot.org (Tanya Lattner) Date: Wed, 6 Jun 2007 00:54:12 -0500 Subject: [llvm-commits] CVS: llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr Message-ID: <200706060554.l565sCN2005873@zion.cs.uiuc.edu> Changes in directory llvm/test/CFrontend: 2003-07-22-ArrayAccessTypeSafety.c.tr updated: 1.6 -> 1.7 --- Log message: Ignore llvm.noinline --- Diffs of the changes: (+1 -1) 2003-07-22-ArrayAccessTypeSafety.c.tr | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr diff -u llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr:1.6 llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr:1.7 --- llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr:1.6 Mon Apr 16 01:04:03 2007 +++ llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr Wed Jun 6 00:53:50 2007 @@ -1,4 +1,4 @@ -/* RUN: %llvmgcc -xc %s -S -o - | grep -v alloca | not grep bitcast +/* RUN: %llvmgcc -xc %s -S -o - | grep -v alloca | grep -v llvm.noinline | not grep bitcast */ void test(int* array, long long N) { From lattner at apple.com Wed Jun 6 00:58:44 2007 From: lattner at apple.com (lattner at apple.com) Date: Tue, 5 Jun 2007 22:58:44 -0700 (PDT) Subject: [llvm-commits] [128029] Fixing paste error so noinline uses the right vector. Message-ID: <20070606055844.2EB45712BE57@src> Revision: 128029 Author: lattner Date: 2007-06-05 22:58:43 -0700 (Tue, 05 Jun 2007) Log Message: ----------- Fixing paste error so noinline uses the right vector. Modified Paths: -------------- apple-local/branches/llvm/gcc/llvm-backend.cpp Modified: apple-local/branches/llvm/gcc/llvm-backend.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-06 00:56:14 UTC (rev 128028) +++ apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-06 05:58:43 UTC (rev 128029) @@ -479,7 +479,7 @@ if (!AttributeNoinlineFunctions.empty()) { const Type *SBP= PointerType::get(Type::Int8Ty); ArrayType *AT = ArrayType::get(SBP, AttributeNoinlineFunctions.size()); - Constant *Init = ConstantArray::get(AT, AttributeUsedGlobals); + Constant *Init = ConstantArray::get(AT, AttributeNoinlineFunctions); GlobalValue *gv = new GlobalVariable(AT, false, GlobalValue::AppendingLinkage, Init, "llvm.noinline", TheModule); From lattner at apple.com Wed Jun 6 01:40:10 2007 From: lattner at apple.com (lattner at apple.com) Date: Tue, 5 Jun 2007 23:40:10 -0700 (PDT) Subject: [llvm-commits] [128030] Do not use the uninlinable flag for functions the inliner decides not to inline . Message-ID: <20070606064010.5AE9C714EA81@src> Revision: 128030 Author: lattner Date: 2007-06-05 23:40:10 -0700 (Tue, 05 Jun 2007) Log Message: ----------- Do not use the uninlinable flag for functions the inliner decides not to inline. Modified Paths: -------------- apple-local/branches/llvm/gcc/tree-inline.c Modified: apple-local/branches/llvm/gcc/tree-inline.c =================================================================== --- apple-local/branches/llvm/gcc/tree-inline.c 2007-06-06 05:58:43 UTC (rev 128029) +++ apple-local/branches/llvm/gcc/tree-inline.c 2007-06-06 06:40:10 UTC (rev 128030) @@ -1220,9 +1220,16 @@ inlinable = false; } + /* APPLE LOCAL begin LLVM */ + #ifndef ENABLE_LLVM + /* LLVM uses the uninlinable flag to know when the noinline attribute + was used. This code will cause all functions that this inliner decides + not to inline to appear to have been marked noinline. */ /* Squirrel away the result so that we don't have to check again. */ DECL_UNINLINABLE (fn) = !inlinable; - + #endif + /* APPLE LOCAL end LLVM */ + return inlinable; } From lattner at apple.com Wed Jun 6 02:01:41 2007 From: lattner at apple.com (lattner at apple.com) Date: Wed, 6 Jun 2007 00:01:41 -0700 (PDT) Subject: [llvm-commits] [128031] Disable noinline for now. Message-ID: <20070606070141.2EC3A7156CD0@src> Revision: 128031 Author: lattner Date: 2007-06-06 00:01:40 -0700 (Wed, 06 Jun 2007) Log Message: ----------- Disable noinline for now. Modified Paths: -------------- apple-local/branches/llvm/gcc/llvm-backend.cpp Modified: apple-local/branches/llvm/gcc/llvm-backend.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-06 06:40:10 UTC (rev 128030) +++ apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-06 07:01:40 UTC (rev 128031) @@ -476,6 +476,7 @@ } // Add llvm.noinline +#ifdef 0 if (!AttributeNoinlineFunctions.empty()) { const Type *SBP= PointerType::get(Type::Int8Ty); ArrayType *AT = ArrayType::get(SBP, AttributeNoinlineFunctions.size()); @@ -488,6 +489,7 @@ // Clear vector AttributeNoinlineFunctions.clear(); } +#endif // Finish off the per-function pass. if (PerFunctionPasses) From llvm at cs.uiuc.edu Wed Jun 6 02:29:15 2007 From: llvm at cs.uiuc.edu (LLVM) Date: Wed, 6 Jun 2007 02:29:15 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Mips/ Message-ID: <200706060729.l567TF7H016688@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Mips: --- Log message: Directory /var/cvs/llvm/llvm/lib/Target/Mips added to the repository --- Diffs of the changes: (+0 -0) 0 files changed From bruno.cardoso at gmail.com Wed Jun 6 02:43:12 2007 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Wed, 6 Jun 2007 02:43:12 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Mips/Makefile Mips.h Mips.td MipsAsmPrinter.cpp MipsCallingConv.td MipsISelDAGToDAG.cpp MipsISelLowering.cpp MipsISelLowering.h MipsInstrFormats.td MipsInstrInfo.cpp MipsInstrInfo.h MipsInstrInfo.td MipsRegisterInfo.cpp MipsRegisterInfo.h MipsRegisterInfo.td MipsSubtarget.cpp MipsSubtarget.h MipsTargetAsmInfo.cpp MipsTargetAsmInfo.h MipsTargetMachine.cpp MipsTargetMachine.h Message-ID: <200706060743.l567hC52017058@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Mips: Makefile added (r1.1) Mips.h added (r1.1) Mips.td added (r1.1) MipsAsmPrinter.cpp added (r1.1) MipsCallingConv.td added (r1.1) MipsISelDAGToDAG.cpp added (r1.1) MipsISelLowering.cpp added (r1.1) MipsISelLowering.h added (r1.1) MipsInstrFormats.td added (r1.1) MipsInstrInfo.cpp added (r1.1) MipsInstrInfo.h added (r1.1) MipsInstrInfo.td added (r1.1) MipsRegisterInfo.cpp added (r1.1) MipsRegisterInfo.h added (r1.1) MipsRegisterInfo.td added (r1.1) MipsSubtarget.cpp added (r1.1) MipsSubtarget.h added (r1.1) MipsTargetAsmInfo.cpp added (r1.1) MipsTargetAsmInfo.h added (r1.1) MipsTargetMachine.cpp added (r1.1) MipsTargetMachine.h added (r1.1) --- Log message: Initial Mips support, here we go! =) - Modifications from the last patch included (issues pointed by Evan Cheng are now fixed). - Added more MipsI instructions. - Added more patterns to match branch instructions. --- Diffs of the changes: (+2788 -0) Makefile | 21 ++ Mips.h | 38 +++ Mips.td | 63 ++++++ MipsAsmPrinter.cpp | 294 ++++++++++++++++++++++++++++ MipsCallingConv.td | 39 +++ MipsISelDAGToDAG.cpp | 272 ++++++++++++++++++++++++++ MipsISelLowering.cpp | 519 ++++++++++++++++++++++++++++++++++++++++++++++++++ MipsISelLowering.h | 83 +++++++ MipsInstrFormats.td | 96 +++++++++ MipsInstrInfo.cpp | 114 ++++++++++ MipsInstrInfo.h | 63 ++++++ MipsInstrInfo.td | 468 +++++++++++++++++++++++++++++++++++++++++++++ MipsRegisterInfo.cpp | 288 +++++++++++++++++++++++++++ MipsRegisterInfo.h | 83 +++++++ MipsRegisterInfo.td | 80 +++++++ MipsSubtarget.cpp | 26 ++ MipsSubtarget.h | 43 ++++ MipsTargetAsmInfo.cpp | 22 ++ MipsTargetAsmInfo.h | 30 ++ MipsTargetMachine.cpp | 81 +++++++ MipsTargetMachine.h | 65 ++++++ 21 files changed, 2788 insertions(+) Index: llvm/lib/Target/Mips/Makefile diff -c /dev/null llvm/lib/Target/Mips/Makefile:1.1 *** /dev/null Wed Jun 6 02:42:17 2007 --- llvm/lib/Target/Mips/Makefile Wed Jun 6 02:42:05 2007 *************** *** 0 **** --- 1,21 ---- + ##===- lib/Target/Mips/Makefile ----------------------------*- Makefile -*-===## + # + # The LLVM Compiler Infrastructure + # + # This file was developed by Bruno Cardoso Lopes and is distributed under the + # University of Illinois Open Source License. See LICENSE.TXT for details. + # + ##===----------------------------------------------------------------------===## + LEVEL = ../../.. + LIBRARYNAME = LLVMMips + TARGET = Mips + + # Make sure that tblgen is run, first thing. + BUILT_SOURCES = MipsGenRegisterInfo.h.inc MipsGenRegisterNames.inc \ + MipsGenRegisterInfo.inc MipsGenInstrNames.inc \ + MipsGenInstrInfo.inc MipsGenAsmWriter.inc \ + MipsGenDAGISel.inc MipsGenCallingConv.inc \ + MipsGenSubtarget.inc + + include $(LEVEL)/Makefile.common + Index: llvm/lib/Target/Mips/Mips.h diff -c /dev/null llvm/lib/Target/Mips/Mips.h:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/Mips.h Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,38 ---- + //===-- Mips.h - Top-level interface for Mips representation ----*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file contains the entry points for global functions defined in + // the LLVM Mips back-end. + // + //===----------------------------------------------------------------------===// + + #ifndef TARGET_MIPS_H + #define TARGET_MIPS_H + + #include + + namespace llvm { + class MipsTargetMachine; + class FunctionPassManager; + class FunctionPass; + class MachineCodeEmitter; + + FunctionPass *createMipsCodePrinterPass(std::ostream &OS, + MipsTargetMachine &TM); + FunctionPass *createMipsISelDag(MipsTargetMachine &TM); + } // end namespace llvm; + + // Defines symbolic names for Mips registers. This defines a mapping from + // register name to register number. + #include "MipsGenRegisterNames.inc" + + // Defines symbolic names for the Mips instructions. + #include "MipsGenInstrNames.inc" + + #endif Index: llvm/lib/Target/Mips/Mips.td diff -c /dev/null llvm/lib/Target/Mips/Mips.td:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/Mips.td Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,63 ---- + //===- Mips.td - Describe the Mips Target Machine ---------------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// + // Target-independent interfaces which we are implementing + //===----------------------------------------------------------------------===// + + include "../Target.td" + + //===----------------------------------------------------------------------===// + // Register File Description + //===----------------------------------------------------------------------===// + + include "MipsRegisterInfo.td" + + //===----------------------------------------------------------------------===// + // Subtarget features + //===----------------------------------------------------------------------===// + + // TODO: dummy, needed to compile + def FeatureCIX : SubtargetFeature<"r3000", "isR3000", "true", + "Enable r3000 extentions">; + + //===----------------------------------------------------------------------===// + // Instruction Description + //===----------------------------------------------------------------------===// + + include "MipsInstrInfo.td" + + def MipsInstrInfo : InstrInfo { + // Define how we want to layout our target-specific information field. + let TSFlagsFields = []; + let TSFlagsShifts = []; + } + //===----------------------------------------------------------------------===// + // Calling Conventions + //===----------------------------------------------------------------------===// + + include "MipsCallingConv.td" + + //===----------------------------------------------------------------------===// + // Mips processors supported. + //===----------------------------------------------------------------------===// + + class Proc Features> + : Processor; + + def : Proc<"generic", []>; + + //===----------------------------------------------------------------------===// + // Declare the target which we are implementing + //===----------------------------------------------------------------------===// + + def Mips : Target { + // Pull in Instruction Info: + let InstructionSet = MipsInstrInfo; + } Index: llvm/lib/Target/Mips/MipsAsmPrinter.cpp diff -c /dev/null llvm/lib/Target/Mips/MipsAsmPrinter.cpp:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsAsmPrinter.cpp Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,294 ---- + //===-- MipsAsmPrinter.cpp - Mips LLVM assembly writer --------------------===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file contains a printer that converts from our internal representation + // of machine-dependent LLVM code to GAS-format MIPS assembly language. + // + //===----------------------------------------------------------------------===// + + #define DEBUG_TYPE "mips-asm-printer" + + #include "Mips.h" + #include "MipsInstrInfo.h" + #include "MipsTargetMachine.h" + #include "llvm/Constants.h" + #include "llvm/DerivedTypes.h" + #include "llvm/Module.h" + #include "llvm/CodeGen/AsmPrinter.h" + #include "llvm/CodeGen/MachineFunctionPass.h" + #include "llvm/CodeGen/MachineConstantPool.h" + #include "llvm/CodeGen/MachineInstr.h" + #include "llvm/Target/TargetAsmInfo.h" + #include "llvm/Target/TargetData.h" + #include "llvm/Target/TargetMachine.h" + #include "llvm/Support/Mangler.h" + #include "llvm/ADT/Statistic.h" + #include "llvm/ADT/StringExtras.h" + #include "llvm/Support/CommandLine.h" + #include "llvm/Support/MathExtras.h" + #include + + using namespace llvm; + + STATISTIC(EmittedInsts, "Number of machine instrs printed"); + + namespace { + struct VISIBILITY_HIDDEN MipsAsmPrinter : public AsmPrinter { + MipsAsmPrinter(std::ostream &O, MipsTargetMachine &TM, + const TargetAsmInfo *T): + AsmPrinter(O, TM, T) {} + + virtual const char *getPassName() const { + return "Mips Assembly Printer"; + } + + void printOperand(const MachineInstr *MI, int opNum); + void printMemOperand(const MachineInstr *MI, int opNum, + const char *Modifier = 0); + + bool printInstruction(const MachineInstr *MI); // autogenerated. + bool runOnMachineFunction(MachineFunction &F); + bool doInitialization(Module &M); + bool doFinalization(Module &M); + }; + } // end of anonymous namespace + + #include "MipsGenAsmWriter.inc" + + /// createMipsCodePrinterPass - Returns a pass that prints the MIPS + /// assembly code for a MachineFunction to the given output stream, + /// using the given target machine description. This should work + /// regardless of whether the function is in SSA form. + FunctionPass *llvm::createMipsCodePrinterPass(std::ostream &o, + MipsTargetMachine &tm) + { + return new MipsAsmPrinter(o, tm, tm.getTargetAsmInfo()); + } + + /// runOnMachineFunction - This uses the printMachineInstruction() + /// method to print assembly for each instruction. + bool MipsAsmPrinter:: + runOnMachineFunction(MachineFunction &MF) + { + SetupMachineFunction(MF); + + // Print out constants referenced by the function + EmitConstantPool(MF.getConstantPool()); + + O << "\n\n"; + + // What's my mangled name? + CurrentFnName = Mang->getValueName(MF.getFunction()); + + // Print out the label for the function. + const Function *F = MF.getFunction(); + SwitchToTextSection(getSectionForFunction(*F).c_str(), F); + + // On Mips GAS if .align #n is present, #n means the number of bits + // to be cleared to align. So, if we want 4 byte alignment, we must + // have .align 2 + // TODO: + // add gas ".mask" and ".fmask" + EmitAlignment(1, F); + O << "\t.globl\t" << CurrentFnName << "\n"; + O << "\t.ent\t" << CurrentFnName << "\n"; + O << "\t.type\t" << CurrentFnName << ", @function\n"; + O << CurrentFnName << ":\n"; + + // Print out code for the function. + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + + // Print a label for the basic block. + if (I != MF.begin()) { + printBasicBlockLabel(I, true); + O << '\n'; + } + + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + O << "\t"; + printInstruction(II); + ++EmittedInsts; + } + } + + // close function with asm directive + O << "\t.end\t" << CurrentFnName << "\n"; + + // We didn't modify anything. + return false; + } + + void MipsAsmPrinter:: + printOperand(const MachineInstr *MI, int opNum) + { + const MachineOperand &MO = MI->getOperand(opNum); + const MRegisterInfo &RI = *TM.getRegisterInfo(); + bool closeP=false; + + // %hi and %lo used on mips gas to break large constants + if (MI->getOpcode() == Mips::LUi && !MO.isRegister() + && !MO.isImmediate()) { + O << "%hi("; + closeP = true; + } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister() + && !MO.isImmediate()) { + O << "%lo("; + closeP = true; + } + + switch (MO.getType()) + { + case MachineOperand::MO_Register: + if (MRegisterInfo::isPhysicalRegister(MO.getReg())) + O << "$" << LowercaseString (RI.get(MO.getReg()).Name); + else + O << "$" << MO.getReg(); + break; + + case MachineOperand::MO_Immediate: + if ((MI->getOpcode() == Mips::SLTiu) || (MI->getOpcode() == Mips::ORi) || + (MI->getOpcode() == Mips::LUi) || (MI->getOpcode() == Mips::ANDi)) + O << (unsigned int)MO.getImmedValue(); + else + O << (int)MO.getImmedValue(); + break; + + case MachineOperand::MO_MachineBasicBlock: + printBasicBlockLabel(MO.getMachineBasicBlock()); + return; + + case MachineOperand::MO_GlobalAddress: + O << Mang->getValueName(MO.getGlobal()); + break; + + case MachineOperand::MO_ExternalSymbol: + O << MO.getSymbolName(); + break; + + case MachineOperand::MO_ConstantPoolIndex: + O << TAI->getPrivateGlobalPrefix() << "CPI" + << getFunctionNumber() << "_" << MO.getConstantPoolIndex(); + break; + + default: + O << ""; abort (); break; + } + + if (closeP) O << ")"; + } + + void MipsAsmPrinter:: + printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier) + { + // lw/sw $reg, MemOperand + // will turn into : + // lw/sw $reg, imm($reg) + printOperand(MI, opNum); + O << "("; + printOperand(MI, opNum+1); + O << ")"; + } + + bool MipsAsmPrinter:: + doInitialization(Module &M) + { + Mang = new Mangler(M); + return false; // success + } + + bool MipsAsmPrinter:: + doFinalization(Module &M) + { + const TargetData *TD = TM.getTargetData(); + + // Print out module-level global variables here. + for (Module::const_global_iterator I = M.global_begin(), + E = M.global_end(); I != E; ++I) + + // External global require no code + if (I->hasInitializer()) { + + // Check to see if this is a special global + // used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(I)) + continue; + + O << "\n\n"; + std::string name = Mang->getValueName(I); + Constant *C = I->getInitializer(); + unsigned Size = TD->getTypeSize(C->getType()); + unsigned Align = TD->getPrefTypeAlignment(C->getType()); + + if (C->isNullValue() && (I->hasLinkOnceLinkage() || + I->hasInternalLinkage() || I->hasWeakLinkage() + /* FIXME: Verify correct */)) { + + SwitchToDataSection(".data", I); + if (I->hasInternalLinkage()) + O << "\t.local " << name << "\n"; + + O << "\t.comm " << name << "," + << TD->getTypeSize(C->getType()) + << "," << Align << "\n"; + + } else { + + switch (I->getLinkage()) + { + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: + // FIXME: Verify correct for weak. + // Nonnull linkonce -> weak + O << "\t.weak " << name << "\n"; + SwitchToDataSection("", I); + O << "\t.section\t\".llvm.linkonce.d." << name + << "\",\"aw\", at progbits\n"; + break; + case GlobalValue::AppendingLinkage: + // FIXME: appending linkage variables + // should go into a section of their name or + // something. For now, just emit them as external. + case GlobalValue::ExternalLinkage: + // If external or appending, declare as a global symbol + O << "\t.globl " << name << "\n"; + case GlobalValue::InternalLinkage: + if (C->isNullValue()) + SwitchToDataSection(".bss", I); + else + SwitchToDataSection(".data", I); + break; + case GlobalValue::GhostLinkage: + cerr << "Should not have any" + << "unmaterialized functions!\n"; + abort(); + case GlobalValue::DLLImportLinkage: + cerr << "DLLImport linkage is" + << "not supported by this target!\n"; + abort(); + case GlobalValue::DLLExportLinkage: + cerr << "DLLExport linkage is" + << "not supported by this target!\n"; + abort(); + default: + assert(0 && "Unknown linkage type!"); + } + O << "\t.align " << Align << "\n"; + O << "\t.type " << name << ", at object\n"; + O << "\t.size " << name << "," << Size << "\n"; + O << name << ":\n"; + EmitGlobalConstant(C); + } + } + + AsmPrinter::doFinalization(M); + return false; // success + } Index: llvm/lib/Target/Mips/MipsCallingConv.td diff -c /dev/null llvm/lib/Target/Mips/MipsCallingConv.td:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsCallingConv.td Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,39 ---- + //===- MipsCallingConv.td - Calling Conventions for Mips --------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // This describes the calling conventions for Mips architecture. + //===----------------------------------------------------------------------===// + + /// CCIfSubtarget - Match if the current subtarget has a feature F. + class CCIfSubtarget: + CCIf().", F), A>; + + //===----------------------------------------------------------------------===// + // Mips Return Value Calling Convention + //===----------------------------------------------------------------------===// + def RetCC_Mips : CallingConv<[ + // i32 are returned in registers V0, V1 + CCIfType<[i32], CCAssignToReg<[V0, V1]>> + ]>; + + + //===----------------------------------------------------------------------===// + // Mips Argument Calling Conventions + //===----------------------------------------------------------------------===// + def CC_Mips : CallingConv<[ + // Promote i8/i16 arguments to i32. + CCIfType<[i8, i16], CCPromoteToType>, + + // The first 4 integer arguments are passed in integer registers. + CCIfType<[i32], CCAssignToReg<[A0, A1, A2, A3]>>, + + // Integer values get stored in stack slots that are 4 bytes in + // size and 4-byte aligned. + CCIfType<[i32], CCAssignToStack<4, 4>> + ]>; + Index: llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp diff -c /dev/null llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,272 ---- + //===-- MipsISelDAGToDAG.cpp - A dag to dag inst selector for Mips --------===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file defines an instruction selector for the MIPS target. + // + //===----------------------------------------------------------------------===// + + #define DEBUG_TYPE "mips-isel" + + #include "Mips.h" + #include "MipsISelLowering.h" + #include "MipsRegisterInfo.h" + #include "MipsSubtarget.h" + #include "MipsTargetMachine.h" + #include "llvm/GlobalValue.h" + #include "llvm/Instructions.h" + #include "llvm/Intrinsics.h" + #include "llvm/Support/CFG.h" + #include "llvm/Type.h" + #include "llvm/CodeGen/MachineConstantPool.h" + #include "llvm/CodeGen/MachineFunction.h" + #include "llvm/CodeGen/MachineFrameInfo.h" + #include "llvm/CodeGen/MachineInstrBuilder.h" + #include "llvm/CodeGen/SelectionDAGISel.h" + #include "llvm/Target/TargetMachine.h" + #include "llvm/Support/Compiler.h" + #include "llvm/Support/Debug.h" + #include + #include + + using namespace llvm; + + //===----------------------------------------------------------------------===// + // Instruction Selector Implementation + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// + // MipsDAGToDAGISel - MIPS specific code to select MIPS machine + // instructions for SelectionDAG operations. + //===----------------------------------------------------------------------===// + namespace { + + class VISIBILITY_HIDDEN MipsDAGToDAGISel : public SelectionDAGISel { + + /// TM - Keep a reference to MipsTargetMachine. + MipsTargetMachine &TM; + + /// MipsLowering - This object fully describes how to lower LLVM code to an + /// Mips-specific SelectionDAG. + MipsTargetLowering MipsLowering; + + /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can + /// make the right decision when generating code for different targets. + //TODO: add initialization on constructor + //const MipsSubtarget *Subtarget; + + public: + MipsDAGToDAGISel(MipsTargetMachine &tm) : + SelectionDAGISel(MipsLowering), + TM(tm), MipsLowering(*TM.getTargetLowering()) {} + + virtual void InstructionSelectBasicBlock(SelectionDAG &SD); + + // Pass Name + virtual const char *getPassName() const { + return "MIPS DAG->DAG Pattern Instruction Selection"; + } + + + private: + // Include the pieces autogenerated from the target description. + #include "MipsGenDAGISel.inc" + + SDNode *Select(SDOperand N); + + // Complex Pattern. + bool SelectAddr(SDOperand Op, SDOperand N, + SDOperand &Base, SDOperand &Offset); + + + // getI32Imm - Return a target constant with the specified + // value, of type i32. + inline SDOperand getI32Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i32); + } + + + #ifndef NDEBUG + unsigned Indent; + #endif + }; + + } + + /// InstructionSelectBasicBlock - This callback is invoked by + /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. + void MipsDAGToDAGISel:: + InstructionSelectBasicBlock(SelectionDAG &SD) + { + DEBUG(BB->dump()); + // Codegen the basic block. + #ifndef NDEBUG + DOUT << "===== Instruction selection begins:\n"; + Indent = 0; + #endif + + // Select target instructions for the DAG. + SD.setRoot(SelectRoot(SD.getRoot())); + + #ifndef NDEBUG + DOUT << "===== Instruction selection ends:\n"; + #endif + + SD.RemoveDeadNodes(); + + // Emit machine code to BB. + ScheduleAndEmitDAG(SD); + } + + /// ComplexPattern used on MipsInstrInfo + /// Used on Mips Load/Store instructions + bool MipsDAGToDAGISel:: + SelectAddr(SDOperand Op, SDOperand Addr, SDOperand &Offset, SDOperand &Base) + { + // if Address is FI, get the TargetFrameIndex. + if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + // TargetExternalSymbol and TargetGlobalAddress are + // lowered and their addresses go into registers, so + // they should not be touched here. + if ((Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress)) + return false; + + // Operand is an result from an ADD. + if (Addr.getOpcode() == ISD::ADD) + { + if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) + { + if (Predicate_immSExt16(CN)) + { + // If the first operand is a FI, get the TargetFI Node + if (FrameIndexSDNode *FIN = dyn_cast + (Addr.getOperand(0))) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + } else { + Base = Addr.getOperand(0); + } + + Offset = CurDAG->getTargetConstant(CN->getValue(), MVT::i32); + return true; + } + } + } + + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + /// Select instructions not customized! Used for + /// expanded, promoted and normal instructions + SDNode* MipsDAGToDAGISel:: + Select(SDOperand N) + { + SDNode *Node = N.Val; + unsigned Opcode = Node->getOpcode(); + + // Dump information about the Node being selected + #ifndef NDEBUG + DOUT << std::string(Indent, ' ') << "Selecting: "; + DEBUG(Node->dump(CurDAG)); + DOUT << "\n"; + Indent += 2; + #endif + + // If we have a custom node, we already have selected! + if (Opcode >= ISD::BUILTIN_OP_END && Opcode < MipsISD::FIRST_NUMBER) { + #ifndef NDEBUG + DOUT << std::string(Indent-2, ' ') << "== "; + DEBUG(Node->dump(CurDAG)); + DOUT << "\n"; + Indent -= 2; + #endif + return NULL; + } + + /// + // Instruction Selection not handled by custom or by the + // auto-generated tablegen selection should be handled here + /// + switch(Opcode) { + + default: break; + + /// Special Mul operations + case ISD::MULHS: + case ISD::MULHU: { + SDOperand MulOp1 = Node->getOperand(0); + SDOperand MulOp2 = Node->getOperand(1); + AddToISelQueue(MulOp1); + AddToISelQueue(MulOp2); + + unsigned MulOp = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT); + SDNode *MulNode = CurDAG->getTargetNode(MulOp, MVT::Flag, MulOp1, MulOp2); + + SDOperand MFInFlag = SDOperand(MulNode, 0); + return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag); + } + + /// Div operations + case ISD::SDIV: + case ISD::UDIV: { + SDOperand DivOp1 = Node->getOperand(0); + SDOperand DivOp2 = Node->getOperand(1); + AddToISelQueue(DivOp1); + AddToISelQueue(DivOp2); + + unsigned DivOp = (Opcode == ISD::SDIV ? Mips::DIV : Mips::DIVu); + SDNode *DivNode = CurDAG->getTargetNode(DivOp, MVT::Flag, DivOp1, DivOp2); + + SDOperand MFInFlag = SDOperand(DivNode, 0); + return CurDAG->getTargetNode(Mips::MFLO, MVT::i32, MFInFlag); + } + + /// Rem operations + case ISD::SREM: + case ISD::UREM: { + SDOperand RemOp1 = Node->getOperand(0); + SDOperand RemOp2 = Node->getOperand(1); + AddToISelQueue(RemOp1); + AddToISelQueue(RemOp2); + + unsigned RemOp = (Opcode == ISD::SREM ? Mips::DIV : Mips::DIVu); + SDNode *RemNode = CurDAG->getTargetNode(RemOp, MVT::Flag, RemOp1, RemOp2); + + SDOperand MFInFlag = SDOperand(RemNode, 0); + return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag); + } + } + + // Select the default instruction + SDNode *ResNode = SelectCode(N); + + #ifndef NDEBUG + DOUT << std::string(Indent-2, ' ') << "=> "; + if (ResNode == NULL || ResNode == N.Val) + DEBUG(N.Val->dump(CurDAG)); + else + DEBUG(ResNode->dump(CurDAG)); + DOUT << "\n"; + Indent -= 2; + #endif + + return ResNode; + } + + /// createMipsISelDag - This pass converts a legalized DAG into a + /// MIPS-specific DAG, ready for instruction scheduling. + FunctionPass *llvm::createMipsISelDag(MipsTargetMachine &TM) { + return new MipsDAGToDAGISel(TM); + } Index: llvm/lib/Target/Mips/MipsISelLowering.cpp diff -c /dev/null llvm/lib/Target/Mips/MipsISelLowering.cpp:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsISelLowering.cpp Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,519 ---- + //===-- MipsISelLowering.cpp - Mips DAG Lowering Implementation -----------===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file defines the interfaces that Mips uses to lower LLVM code into a + // selection DAG. + // + //===----------------------------------------------------------------------===// + + #define DEBUG_TYPE "mips-lower" + + #include "MipsISelLowering.h" + #include "MipsTargetMachine.h" + #include "llvm/DerivedTypes.h" + #include "llvm/Function.h" + #include "llvm/Intrinsics.h" + #include "llvm/CallingConv.h" + #include "llvm/CodeGen/CallingConvLower.h" + #include "llvm/CodeGen/MachineFrameInfo.h" + #include "llvm/CodeGen/MachineFunction.h" + #include "llvm/CodeGen/MachineInstrBuilder.h" + #include "llvm/CodeGen/SelectionDAGISel.h" + #include "llvm/CodeGen/SSARegMap.h" + #include "llvm/CodeGen/ValueTypes.h" + #include "llvm/Support/Debug.h" + #include + #include + + using namespace llvm; + + const char *MipsTargetLowering:: + getTargetNodeName(unsigned Opcode) const + { + switch (Opcode) + { + case MipsISD::JmpLink : return "MipsISD::JmpLink"; + case MipsISD::Hi : return "MipsISD::Hi"; + case MipsISD::Lo : return "MipsISD::Lo"; + case MipsISD::Ret : return "MipsISD::Ret"; + default : return NULL; + } + } + + MipsTargetLowering:: + MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM) + { + // Mips does not have i1 type, so use i32 for + // setcc operations results (slt, sgt, ...). + setSetCCResultType(MVT::i32); + setSetCCResultContents(ZeroOrOneSetCCResult); + + // Set up the register classes + addRegisterClass(MVT::i32, Mips::CPURegsRegisterClass); + + // Custom + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::RET, MVT::Other, Custom); + + // Load extented operations for i1 types must be promoted + setLoadXAction(ISD::EXTLOAD, MVT::i1, Promote); + setLoadXAction(ISD::ZEXTLOAD, MVT::i1, Promote); + setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote); + + // Store operations for i1 types must be promoted + setStoreXAction(MVT::i1, Promote); + + // Mips does not have these NodeTypes below. + setOperationAction(ISD::BR_JT, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::Other, Expand); + setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + setOperationAction(ISD::SELECT, MVT::i32, Expand); + + // Mips not supported intrinsics. + setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); + setOperationAction(ISD::MEMSET, MVT::Other, Expand); + setOperationAction(ISD::MEMCPY, MVT::Other, Expand); + + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + setOperationAction(ISD::CTTZ , MVT::i32, Expand); + setOperationAction(ISD::CTLZ , MVT::i32, Expand); + setOperationAction(ISD::ROTL , MVT::i32, Expand); + setOperationAction(ISD::ROTR , MVT::i32, Expand); + setOperationAction(ISD::BSWAP, MVT::i32, Expand); + + setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); + + // We don't have line number support yet. + setOperationAction(ISD::LOCATION, MVT::Other, Expand); + setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); + setOperationAction(ISD::LABEL, MVT::Other, Expand); + + // Use the default for now + setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); + + setStackPointerRegisterToSaveRestore(Mips::SP); + computeRegisterProperties(); + } + + + SDOperand MipsTargetLowering:: + LowerOperation(SDOperand Op, SelectionDAG &DAG) + { + switch (Op.getOpcode()) + { + case ISD::CALL: return LowerCALL(Op, DAG); + case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG); + case ISD::RET: return LowerRET(Op, DAG); + case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); + } + return SDOperand(); + } + + //===----------------------------------------------------------------------===// + // Lower helper functions + //===----------------------------------------------------------------------===// + + // AddLiveIn - This helper function adds the specified physical register to the + // MachineFunction as a live in value. It also creates a corresponding + // virtual register for it. + static unsigned + AddLiveIn(MachineFunction &MF, unsigned PReg, TargetRegisterClass *RC) + { + assert(RC->contains(PReg) && "Not the correct regclass!"); + unsigned VReg = MF.getSSARegMap()->createVirtualRegister(RC); + MF.addLiveIn(PReg, VReg); + return VReg; + } + + // Set up a frame object for the return address. + SDOperand MipsTargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) { + if (ReturnAddrIndex == 0) { + MachineFunction &MF = DAG.getMachineFunction(); + ReturnAddrIndex = MF.getFrameInfo()->CreateFixedObject(4, 0); + } + + return DAG.getFrameIndex(ReturnAddrIndex, getPointerTy()); + } + + + //===----------------------------------------------------------------------===// + // Misc Lower Operation implementation + //===----------------------------------------------------------------------===// + SDOperand MipsTargetLowering:: + LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) + { + GlobalValue *GV = cast(Op)->getGlobal(); + + SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32); + SDOperand Hi = DAG.getNode(MipsISD::Hi, MVT::i32, GA); + SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA); + + return DAG.getNode(ISD::ADD, MVT::i32, Lo, Hi); + } + + SDOperand MipsTargetLowering:: + LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG) { + // Depths > 0 not supported yet! + if (cast(Op.getOperand(0))->getValue() > 0) + return SDOperand(); + + // Just load the return address + SDOperand RetAddrFI = getReturnAddressFrameIndex(DAG); + return DAG.getLoad(getPointerTy(), DAG.getEntryNode(), RetAddrFI, NULL, 0); + } + + //===----------------------------------------------------------------------===// + // Calling Convention Implementation + // + // The lower operations present on calling convention works on this order: + // LowerCALL (virt regs --> phys regs, virt regs --> stack) + // LowerFORMAL_ARGUMENTS (phys --> virt regs, stack --> virt regs) + // LowerRET (virt regs --> phys regs) + // LowerCALL (phys regs --> virt regs) + // + //===----------------------------------------------------------------------===// + + #include "MipsGenCallingConv.inc" + + //===----------------------------------------------------------------------===// + // CALL Calling Convention Implementation + //===----------------------------------------------------------------------===// + + /// Mips custom CALL implementation + SDOperand MipsTargetLowering:: + LowerCALL(SDOperand Op, SelectionDAG &DAG) + { + unsigned CallingConv= cast(Op.getOperand(1))->getValue(); + + // By now, only CallingConv::C implemented + switch (CallingConv) + { + default: + assert(0 && "Unsupported calling convention"); + case CallingConv::Fast: + case CallingConv::C: + return LowerCCCCallTo(Op, DAG, CallingConv); + } + } + + /// LowerCCCCallTo - functions arguments are copied from virtual + /// regs to (physical regs)/(stack frame), CALLSEQ_START and + /// CALLSEQ_END are emitted. + /// TODO: isVarArg, isTailCall, sret, GOT, linkage types. + SDOperand MipsTargetLowering:: + LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC) + { + SDOperand Chain = Op.getOperand(0); + SDOperand Callee = Op.getOperand(4); + + // Analyze operands of the call, assigning locations to each operand. + SmallVector ArgLocs; + CCState CCInfo(CC, getTargetMachine(), ArgLocs); + CCInfo.AnalyzeCallOperands(Op.Val, CC_Mips); + + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + + Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, + getPointerTy())); + + SmallVector, 8> RegsToPass; + SmallVector MemOpChains; + + SDOperand StackPtr; + + // Walk the register/memloc assignments, inserting copies/loads. + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + // Arguments start after the 5 first operands of ISD::CALL + SDOperand Arg = Op.getOperand(5+2*VA.getValNo()); + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: assert(0 && "Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, VA.getLocVT(), Arg); + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, VA.getLocVT(), Arg); + break; + case CCValAssign::AExt: + Arg = DAG.getNode(ISD::ANY_EXTEND, VA.getLocVT(), Arg); + break; + } + + // Arguments that can be passed on register, + // must be kept at RegsToPass vector + if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else { + assert(VA.isMemLoc()); + // Mips::SP holds our stack pointer + if (StackPtr.Val == 0) + StackPtr = DAG.getRegister(Mips::SP, getPointerTy()); + + SDOperand PtrOff = DAG.getConstant(VA.getLocMemOffset(), + getPointerTy()); + + // emit a ISD::ADD which emits the final + // stack location to place the parameter + PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff); + + // emit ISD::STORE whichs stores the + // parameter value to a stack Location + MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0)); + } + } + + // Transform all store nodes into one single node because + // all store nodes ar independent of each other. + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, + &MemOpChains[0], MemOpChains.size()); + + // Build a sequence of copy-to-reg nodes chained together with token + // chain and flag operands which copy the outgoing args into registers. + // The InFlag in necessary since all emited instructions must be + // stuck together. + SDOperand InFlag; + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + // If the callee is a GlobalAddress node (quite common, every direct + // call is) turn it into a TargetGlobalAddress node so that legalize + // doesn't hack it. + if (GlobalAddressSDNode *G = dyn_cast(Callee)) { + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy()); + } else + if (ExternalSymbolSDNode *S = dyn_cast(Callee)) + Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy()); + + // MipsJmpLink = #chain, #target_address, #opt_in_flags... + // = Chain, Callee, Reg#1, Reg#2, ... + // + // Returns a chain & a flag for retval copy to use. + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + // Add argument registers to the end of the list so that they are + // known live into the call. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) + Ops.push_back(DAG.getRegister(RegsToPass[i].first, + RegsToPass[i].second.getValueType())); + + if (InFlag.Val) + Ops.push_back(InFlag); + + Chain = DAG.getNode(MipsISD::JmpLink, NodeTys, &Ops[0], Ops.size()); + InFlag = Chain.getValue(1); + + // Create the CALLSEQ_END node. + NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + Ops.clear(); + Ops.push_back(Chain); + Ops.push_back(DAG.getConstant(NumBytes, getPointerTy())); + Ops.push_back(InFlag); + Chain = DAG.getNode(ISD::CALLSEQ_END, NodeTys, &Ops[0], Ops.size()); + InFlag = Chain.getValue(1); + + // Handle result values, copying them out of physregs into vregs that we + // return. + return SDOperand(LowerCallResult(Chain, InFlag, Op.Val, CC, DAG), Op.ResNo); + } + + /// LowerCallResult - Lower the result values of an ISD::CALL into the + /// appropriate copies out of appropriate physical registers. This assumes that + /// Chain/InFlag are the input chain/flag to use, and that TheCall is the call + /// being lowered. Returns a SDNode with the same number of values as the + /// ISD::CALL. + SDNode *MipsTargetLowering:: + LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode *TheCall, + unsigned CallingConv, SelectionDAG &DAG) { + + // Assign locations to each value returned by this call. + SmallVector RVLocs; + CCState CCInfo(CallingConv, getTargetMachine(), RVLocs); + CCInfo.AnalyzeCallResult(TheCall, RetCC_Mips); + SmallVector ResultVals; + + // returns void + if (!RVLocs.size()) + return Chain.Val; + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + Chain = DAG.getCopyFromReg(Chain, RVLocs[i].getLocReg(), + RVLocs[i].getValVT(), InFlag).getValue(1); + InFlag = Chain.getValue(2); + ResultVals.push_back(Chain.getValue(0)); + } + + // Merge everything together with a MERGE_VALUES node. + ResultVals.push_back(Chain); + return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(), + &ResultVals[0], ResultVals.size()).Val; + } + + //===----------------------------------------------------------------------===// + // FORMAL_ARGUMENTS Calling Convention Implementation + //===----------------------------------------------------------------------===// + + /// Mips custom FORMAL_ARGUMENTS implementation + SDOperand MipsTargetLowering:: + LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) + { + unsigned CC = cast(Op.getOperand(1))->getValue(); + switch(CC) + { + default: + assert(0 && "Unsupported calling convention"); + case CallingConv::C: + return LowerCCCArguments(Op, DAG); + } + } + + /// LowerCCCArguments - transform physical registers into + /// virtual registers and generate load operations for + /// arguments places on the stack. + /// TODO: isVarArg, sret + SDOperand MipsTargetLowering:: + LowerCCCArguments(SDOperand Op, SelectionDAG &DAG) + { + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + SDOperand Root = Op.getOperand(0); + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(MF.getFunction()->getCallingConv(), + getTargetMachine(), ArgLocs); + CCInfo.AnalyzeFormalArguments(Op.Val, CC_Mips); + SmallVector ArgValues; + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + + CCValAssign &VA = ArgLocs[i]; + + // Arguments stored on registers + if (VA.isRegLoc()) { + MVT::ValueType RegVT = VA.getLocVT(); + TargetRegisterClass *RC; + + if (RegVT == MVT::i32) + RC = Mips::CPURegsRegisterClass; + else + assert(0 && "support only Mips::CPURegsRegisterClass"); + + unsigned Reg = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg(), RC); + + // Transform the arguments stored on + // physical registers into virtual ones + SDOperand ArgValue = DAG.getCopyFromReg(Root, Reg, RegVT); + + // If this is an 8 or 16-bit value, it is really passed promoted + // to 32 bits. Insert an assert[sz]ext to capture this, then + // truncate to the right size. + if (VA.getLocInfo() == CCValAssign::SExt) + ArgValue = DAG.getNode(ISD::AssertSext, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + else if (VA.getLocInfo() == CCValAssign::ZExt) + ArgValue = DAG.getNode(ISD::AssertZext, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + + if (VA.getLocInfo() != CCValAssign::Full) + ArgValue = DAG.getNode(ISD::TRUNCATE, VA.getValVT(), ArgValue); + + ArgValues.push_back(ArgValue); + + } else { + // sanity check + assert(VA.isMemLoc()); + + // Create the frame index object for this incoming parameter... + int FI = MFI->CreateFixedObject(MVT::getSizeInBits(VA.getValVT())/8, + VA.getLocMemOffset()); + + // Create load nodes to retrieve arguments from the stack + SDOperand FIN = DAG.getFrameIndex(FI, getPointerTy()); + ArgValues.push_back(DAG.getLoad(VA.getValVT(), Root, FIN, NULL, 0)); + } + } + ArgValues.push_back(Root); + + ReturnAddrIndex = 0; + + // Return the new list of results. + return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(), + &ArgValues[0], ArgValues.size()).getValue(Op.ResNo); + } + + //===----------------------------------------------------------------------===// + // Return Value Calling Convention Implementation + //===----------------------------------------------------------------------===// + + SDOperand MipsTargetLowering:: + LowerRET(SDOperand Op, SelectionDAG &DAG) + { + // CCValAssign - represent the assignment of + // the return value to a location + SmallVector RVLocs; + unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv(); + + // CCState - Info about the registers and stack slot. + CCState CCInfo(CC, getTargetMachine(), RVLocs); + + // Analize return values of ISD::RET + CCInfo.AnalyzeReturn(Op.Val, RetCC_Mips); + + // If this is the first return lowered for this function, add + // the regs to the liveout set for the function. + if (DAG.getMachineFunction().liveout_empty()) { + for (unsigned i = 0; i != RVLocs.size(); ++i) + DAG.getMachineFunction().addLiveOut(RVLocs[i].getLocReg()); + } + + // The chain is always operand #0 + SDOperand Chain = Op.getOperand(0); + SDOperand Flag; + + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + + // ISD::RET => ret chain, (regnum1,val1), ... + // So i*2+1 index only the regnums + Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), + Op.getOperand(i*2+1), Flag); + + // guarantee that all emitted copies are + // stuck together, avoiding something bad + Flag = Chain.getValue(1); + } + + // Return on Mips is always a "jr $ra" + if (Flag.Val) + return DAG.getNode(MipsISD::Ret, MVT::Other, + Chain, DAG.getRegister(Mips::RA, MVT::i32), Flag); + else // Return Void + return DAG.getNode(MipsISD::Ret, MVT::Other, + Chain, DAG.getRegister(Mips::RA, MVT::i32)); + } Index: llvm/lib/Target/Mips/MipsISelLowering.h diff -c /dev/null llvm/lib/Target/Mips/MipsISelLowering.h:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsISelLowering.h Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,83 ---- + //===-- MipsISelLowering.h - Mips DAG Lowering Interface --------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file defines the interfaces that Mips uses to lower LLVM code into a + // selection DAG. + // + //===----------------------------------------------------------------------===// + + #ifndef MipsISELLOWERING_H + #define MipsISELLOWERING_H + + #include "llvm/CodeGen/SelectionDAG.h" + #include "llvm/Target/TargetLowering.h" + #include "Mips.h" + #include "MipsSubtarget.h" + + namespace llvm { + namespace MipsISD { + enum NodeType { + // Start the numbering from where ISD NodeType finishes. + FIRST_NUMBER = ISD::BUILTIN_OP_END+Mips::INSTRUCTION_LIST_END, + + // Jump and link (call) + JmpLink, + + // Get the Higher 16 bits from a 32-bit immediate + // No relation with Mips Hi register + Hi, + + // Get the Lower 16 bits from a 32-bit immediate + // No relation with Mips Lo register + Lo, + + // Return + Ret + }; + } + + //===--------------------------------------------------------------------===// + // TargetLowering Implementation + //===--------------------------------------------------------------------===// + class MipsTargetLowering : public TargetLowering + { + // FrameIndex for return slot. + int ReturnAddrIndex; + + // const MipsSubtarget &MipsSubTarget; + public: + + MipsTargetLowering(MipsTargetMachine &TM); + + /// LowerOperation - Provide custom lowering hooks for some operations. + virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); + + /// getTargetNodeName - This method returns the name of a target specific + // DAG node. + virtual const char *getTargetNodeName(unsigned Opcode) const; + + private: + // Lower Operand helpers + SDOperand LowerCCCArguments(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC); + SDNode *LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode*TheCall, + unsigned CallingConv, SelectionDAG &DAG); + SDOperand getReturnAddressFrameIndex(SelectionDAG &DAG); + + // Lower Operand specifics + SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG); + + }; + } + + #endif // MipsISELLOWERING_H Index: llvm/lib/Target/Mips/MipsInstrFormats.td diff -c /dev/null llvm/lib/Target/Mips/MipsInstrFormats.td:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsInstrFormats.td Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,96 ---- + //===- MipsRegisterInfo.td - Mips Register defs -----------------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// + // Describe MIPS instructions format + // + // All the possible Mips fields are: + // + // opcode - operation code. + // rs - src reg. + // rt - dst reg (on a 2 regs instr) or src reg (on a 3 reg instr). + // rd - dst reg, only used on 3 regs instr. + // shamt - only used on shift instructions, contains the shift amount. + // funct - combined with opcode field give us an operation code. + // + //===----------------------------------------------------------------------===// + + // Generic Mips Format + class MipsInst pattern>: + Instruction + { + field bits<32> Inst; + + let Namespace = "Mips"; + + bits<6> opcode; + + // Top 5 bits are the 'opcode' field + let Inst{31-26} = opcode; + + dag OperandList = ops; + let AsmString = asmstr; + let Pattern = pattern; + } + + + //===----------------------------------------------------------------------===// + // Format R instruction class in Mips : <|opcode|rs|rt|rd|shamt|funct|> + //===----------------------------------------------------------------------===// + + class FR op, bits<6> _funct, dag ops, string asmstr, list pattern>: + MipsInst + { + bits<5> rd; + bits<5> rs; + bits<5> rt; + bits<5> shamt; + bits<6> funct; + + let opcode = op; + let funct = _funct; + + let Inst{25-21} = rs; + let Inst{20-16} = rt; + let Inst{15-11} = rd; + let Inst{10-6} = shamt; + let Inst{5-0} = funct; + } + + //===----------------------------------------------------------------------===// + // Format I instruction class in Mips : <|opcode|rs|rt|immediate|> + //===----------------------------------------------------------------------===// + + class FI op, dag ops, string asmstr, list pattern>: + MipsInst + { + bits<5> rt; + bits<5> rs; + bits<16> imm16; + + let opcode = op; + + let Inst{25-21} = rs; + let Inst{20-16} = rt; + let Inst{15-0} = imm16; + } + + //===----------------------------------------------------------------------===// + // Format J instruction class in Mips : <|opcode|address|> + //===----------------------------------------------------------------------===// + + class FJ op, dag ops, string asmstr, list pattern>: + MipsInst + { + bits<26> addr; + + let opcode = op; + + let Inst{25-0} = addr; + } Index: llvm/lib/Target/Mips/MipsInstrInfo.cpp diff -c /dev/null llvm/lib/Target/Mips/MipsInstrInfo.cpp:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsInstrInfo.cpp Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,114 ---- + //===- MipsInstrInfo.cpp - Mips Instruction Information ---------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file contains the Mips implementation of the TargetInstrInfo class. + // + //===----------------------------------------------------------------------===// + + #include "Mips.h" + #include "MipsInstrInfo.h" + #include "llvm/CodeGen/MachineInstrBuilder.h" + #include "MipsGenInstrInfo.inc" + + using namespace llvm; + + // TODO: Add the subtarget support on this constructor + MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm) + : TargetInstrInfo(MipsInsts, sizeof(MipsInsts)/sizeof(MipsInsts[0])), + TM(tm), RI(*this) {} + + static bool isZeroImm(const MachineOperand &op) { + return op.isImmediate() && op.getImmedValue() == 0; + } + + /// Return true if the instruction is a register to register move and + /// leave the source and dest operands in the passed parameters. + bool MipsInstrInfo:: + isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg) const + { + // addu $dst, $src, $zero || addu $dst, $zero, $src + // or $dst, $src, $zero || or $dst, $zero, $src + if ((MI.getOpcode() == Mips::ADDu) || (MI.getOpcode() == Mips::OR)) + { + if (MI.getOperand(1).getReg() == Mips::ZERO) { + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(2).getReg(); + return true; + } else if (MI.getOperand(2).getReg() == Mips::ZERO) { + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(1).getReg(); + return true; + } + } + + // addiu $dst, $src, 0 + if (MI.getOpcode() == Mips::ADDiu) + { + if ((MI.getOperand(1).isRegister()) && (isZeroImm(MI.getOperand(2)))) { + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(1).getReg(); + return true; + } + } + return false; + } + + /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// load from a stack slot, return the virtual or physical register number of + /// the destination along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than loading from the stack slot. + unsigned MipsInstrInfo:: + isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const + { + // TODO: add lhu, lbu ??? + if (MI->getOpcode() == Mips::LW) + { + if ((MI->getOperand(2).isFrameIndex()) && // is a stack slot + (MI->getOperand(1).isImmediate()) && // the imm is zero + (isZeroImm(MI->getOperand(1)))) + { + FrameIndex = MI->getOperand(2).getFrameIndex(); + return MI->getOperand(0).getReg(); + } + } + + return 0; + } + + /// isStoreToStackSlot - If the specified machine instruction is a direct + /// store to a stack slot, return the virtual or physical register number of + /// the source reg along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than storing to the stack slot. + unsigned MipsInstrInfo:: + isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const + { + // TODO: add sb, sh ??? + if (MI->getOpcode() == Mips::SW) { + if ((MI->getOperand(0).isFrameIndex()) && // is a stack slot + (MI->getOperand(1).isImmediate()) && // the imm is zero + (isZeroImm(MI->getOperand(1)))) + { + FrameIndex = MI->getOperand(0).getFrameIndex(); + return MI->getOperand(2).getReg(); + } + } + return 0; + } + + unsigned MipsInstrInfo:: + InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, const std::vector &Cond) + const + { + // TODO: add Mips::J here. + assert(0 && "Cant handle any kind of branches!"); + return 1; + } Index: llvm/lib/Target/Mips/MipsInstrInfo.h diff -c /dev/null llvm/lib/Target/Mips/MipsInstrInfo.h:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsInstrInfo.h Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,63 ---- + //===- MipsInstrInfo.h - Mips Instruction Information -----------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file contains the Mips implementation of the TargetInstrInfo class. + // + //===----------------------------------------------------------------------===// + + #ifndef MIPSINSTRUCTIONINFO_H + #define MIPSINSTRUCTIONINFO_H + + #include "Mips.h" + #include "llvm/Target/TargetInstrInfo.h" + #include "MipsRegisterInfo.h" + + namespace llvm { + + class MipsInstrInfo : public TargetInstrInfo + { + MipsTargetMachine &TM; + const MipsRegisterInfo RI; + public: + MipsInstrInfo(MipsTargetMachine &TM); + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + virtual const MRegisterInfo &getRegisterInfo() const { return RI; } + + /// Return true if the instruction is a register to register move and + /// leave the source and dest operands in the passed parameters. + /// + virtual bool isMoveInstr(const MachineInstr &MI, + unsigned &SrcReg, unsigned &DstReg) const; + + /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// load from a stack slot, return the virtual or physical register number of + /// the destination along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than loading from the stack slot. + virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const; + + /// isStoreToStackSlot - If the specified machine instruction is a direct + /// store to a stack slot, return the virtual or physical register number of + /// the source reg along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than storing to the stack slot. + virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const; + + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const std::vector &Cond) const; + }; + + } + + #endif Index: llvm/lib/Target/Mips/MipsInstrInfo.td diff -c /dev/null llvm/lib/Target/Mips/MipsInstrInfo.td:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsInstrInfo.td Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,468 ---- + //===- MipsInstrInfo.td - Mips Register defs --------------------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// + // Instruction format superclass + //===----------------------------------------------------------------------===// + + include "MipsInstrFormats.td" + + //===----------------------------------------------------------------------===// + // Mips profiles and nodes + //===----------------------------------------------------------------------===// + + // Call + def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; + def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain, + SDNPOutFlag]>; + + // Hi and Lo nodes are created to let easy manipulation of 16-bit when + // handling 32-bit immediates. They are used on MipsISelLowering to + // lower stuff like GlobalAddress, ExternalSymbol, ... + // This two nodes have nothing to do with Mips Registers Hi and Lo. + def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>; + def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; + + // Return + def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; + def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, + SDNPOptInFlag]>; + + // These are target-independent nodes, but have target-specific formats. + def SDT_MipsCallSeq : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; + def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeq, + [SDNPHasChain, SDNPOutFlag]>; + def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeq, + [SDNPHasChain, SDNPOutFlag]>; + + // Instruction operand types + def brtarget : Operand; + def calltarget : Operand; + def uimm16 : Operand; + def simm16 : Operand; + def shamt : Operand; + + // Address operand + def mem : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops simm16, CPURegs); + } + + //===----------------------------------------------------------------------===// + // Mips Patterns and Transformations + //===----------------------------------------------------------------------===// + + // Transformation Function - get the lower 16 bits. + def LO16 : SDNodeXFormgetValue() & 0xFFFF); + }]>; + + // Transformation Function - get the higher 16 bits. + def HI16 : SDNodeXFormgetValue() >> 16); + }]>; + + // Node immediate fits as 16-bit sign extended on target immediate. + // e.g. addi, andi + def immSExt16 : PatLeaf<(imm), [{ + if (N->getValueType(0) == MVT::i32) + return (int32_t)N->getValue() == (short)N->getValue(); + else + return (int64_t)N->getValue() == (short)N->getValue(); + }]>; + + // Node immediate fits as 16-bit zero extended on target immediate. + // The LO16 param means that only the lower 16 bits of the node + // immediate are caught. + // e.g. addiu, sltiu + def immZExt16 : PatLeaf<(imm), [{ + return (uint64_t)N->getValue() == (unsigned short)N->getValue(); + }], LO16>; + + // Node immediate must have only it's 16 high bits set. + // The HI16 param means that only the higher 16 bits of the node + // immediate are caught. + // e.g. lui + def imm16ShiftedZExt : PatLeaf<(imm), [{ + return (N->getValue() & ~uint64_t(0xFFFF0000)) == 0; + }], HI16>; + + // shamt field must fit in 5 bits. + def immZExt5 : PatLeaf<(imm), [{ + return N->getValue() == ((N->getValue()) & 0x1f) ; + }]>; + + // Mips Address Mode! SDNode frameindex could possibily be a match + // since load and store instructions from stack used it. + def addr : ComplexPattern; + + //===----------------------------------------------------------------------===// + // Instructions specific format + //===----------------------------------------------------------------------===// + + // Arithmetic 3 register operands + let isCommutable = 1 in + class ArithR< bits<6> op, bits<6> func, string instr_asm, SDNode OpNode>: + FR< op, + func, + (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))] >; + + let isCommutable = 1 in + class ArithOverflowR< bits<6> op, bits<6> func, string instr_asm>: + FR< op, + func, + (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + []>; + + // Arithmetic 2 register operands + let isCommutable = 1 in + class ArithI op, string instr_asm, SDNode OpNode, + Operand Od, PatLeaf imm_type> : + FI< op, + (ops CPURegs:$dst, CPURegs:$b, Od:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))] >; + + // Arithmetic Multiply ADD/SUB + let rd=0 in + class MArithR func, string instr_asm> : + FR< 0x1c, + func, + (ops CPURegs:$rs, CPURegs:$rt), + !strconcat(instr_asm, " $rs, $rt"), + []>; + + // Logical + class LogicR func, string instr_asm, SDNode OpNode>: + FR< 0x00, + func, + (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))] >; + + class LogicI op, string instr_asm, SDNode OpNode>: + FI< op, + (ops CPURegs:$dst, CPURegs:$b, uimm16:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, immSExt16:$c))]>; + + class LogicNOR op, bits<6> func, string instr_asm>: + FR< op, + func, + (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))] >; + + // Shifts + let rt = 0 in + class LogicR_shift_imm func, string instr_asm, SDNode OpNode>: + FR< 0x00, + func, + (ops CPURegs:$dst, CPURegs:$b, shamt:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))] >; + + class LogicR_shift_reg func, string instr_asm, SDNode OpNode>: + FR< 0x00, + func, + (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))] >; + + // Load Upper Imediate + class LoadUpper op, string instr_asm>: + FI< op, + (ops CPURegs:$dst, uimm16:$imm), + !strconcat(instr_asm, " $dst, $imm"), + [(set CPURegs:$dst, imm16ShiftedZExt:$imm)]>; + + // Memory Load/Store + let isLoad = 1 in + class LoadM op, string instr_asm, PatFrag OpNode>: + FI< op, + (ops CPURegs:$dst, mem:$addr), + !strconcat(instr_asm, " $dst, $addr"), + [(set CPURegs:$dst, (OpNode addr:$addr))]>; + + let isStore = 1 in + class StoreM op, string instr_asm, PatFrag OpNode>: + FI< op, + (ops CPURegs:$dst, mem:$addr), + !strconcat(instr_asm, " $dst, $addr"), + [(OpNode CPURegs:$dst, addr:$addr)]>; + + // Conditional Branch + let isBranch = 1, noResults=1, isTerminator=1 in + class CBranch op, string instr_asm, PatFrag cond_op>: + FI< op, + (ops CPURegs:$a, CPURegs:$b, brtarget:$offset), + !strconcat(instr_asm, " $a, $b, $offset"), + [(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)]>; + + class SetCC_R op, bits<6> func, string instr_asm, + PatFrag cond_op>: + FR< op, + func, + (ops CPURegs:$dst, CPURegs:$b, CPURegs:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))]>; + + class SetCC_I op, string instr_asm, PatFrag cond_op, + Operand Od, PatLeaf imm_type>: + FI< op, + (ops CPURegs:$dst, CPURegs:$b, Od:$c), + !strconcat(instr_asm, " $dst, $b, $c"), + [(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))]>; + + // Unconditional branch + let hasCtrlDep=1, noResults=1, isTerminator=1 in + class JumpFJ op, string instr_asm>: + FJ< op, + (ops brtarget:$target), + !strconcat(instr_asm, " $target"), + [(br bb:$target)]>; + + let hasCtrlDep=1, noResults=1, isTerminator=1, rd=0 in + class JumpFR op, bits<6> func, string instr_asm>: + FR< op, + func, + (ops CPURegs:$target), + !strconcat(instr_asm, " $target"), + []>; + + // Jump and Link (Call) + let isCall=1 in + class JumpLink op, string instr_asm>: + FJ< op, + (ops calltarget:$target), + !strconcat(instr_asm, " $target"), + [(MipsJmpLink imm:$target)]>; + + let isCall=1 in + class JumpLinkReg op, bits<6> func, string instr_asm>: + FR< op, + func, + (ops CPURegs:$rd, CPURegs:$rs), + !strconcat(instr_asm, " $rs, $rd"), + []>; + + // Mul, Div + class MulDiv func, string instr_asm>: + FR< 0x00, + func, + (ops CPURegs:$a, CPURegs:$b), + !strconcat(instr_asm, " $a, $b"), + []>; + + // Move from Hi/Lo + class MoveFromTo func, string instr_asm>: + FR< 0x00, + func, + (ops CPURegs:$dst), + !strconcat(instr_asm, " $dst"), + []>; + + // Count Leading Ones/Zeros in Word + class CountLeading func, string instr_asm>: + FR< 0x1c, + func, + (ops CPURegs:$dst, CPURegs:$src), + !strconcat(instr_asm, " $dst, $src"), + []>; + + + //===----------------------------------------------------------------------===// + // Pseudo instructions + //===----------------------------------------------------------------------===// + + class Pseudo pattern>: + MipsInst; + + // As stack alignment is always done with addiu, we need a 16-bit immediate + def ADJCALLSTACKDOWN : Pseudo<(ops uimm16:$amt), + "!ADJCALLSTACKDOWN $amt", + [(callseq_start imm:$amt)]>, Imp<[SP],[SP]>; + def ADJCALLSTACKUP : Pseudo<(ops uimm16:$amt), + "!ADJCALLSTACKUP $amt", + [(callseq_end imm:$amt)]>, Imp<[SP],[SP]>; + + def IMPLICIT_DEF_CPURegs : Pseudo<(ops CPURegs:$dst), + "!IMPLICIT_DEF $dst", + [(set CPURegs:$dst, (undef))]>; + + //===----------------------------------------------------------------------===// + // Instruction definition + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// + // Mips32 I + //===----------------------------------------------------------------------===// + + // Arithmetic + def ADDi : ArithI<0x08, "addi", add, simm16, immZExt16>; + def ADDiu : ArithI<0x09, "addiu", add, uimm16, immSExt16>; + def MUL : ArithR<0x1c, 0x02, "mul", mul>; + def ADDu : ArithR<0x00, 0x21, "addu", add>; + def SUBu : ArithR<0x00, 0x23, "subu", sub>; + def ADD : ArithOverflowR<0x00, 0x20, "add">; + def SUB : ArithOverflowR<0x00, 0x22, "sub">; + def MADD : MArithR<0x00, "madd">; + def MADDU : MArithR<0x01, "maddu">; + def MSUB : MArithR<0x04, "msub">; + def MSUBU : MArithR<0x05, "msubu">; + + // Logical + def AND : LogicR<0x24, "and", and>; + def OR : LogicR<0x25, "or", or>; + def XOR : LogicR<0x26, "xor", xor>; + def ANDi : LogicI<0x0c, "andi", and>; + def ORi : LogicI<0x0d, "ori", or>; + def XORi : LogicI<0x0e, "xori", xor>; + def NOR : LogicNOR<0x00, 0x27, "nor">; + + // Shifts + def SLL : LogicR_shift_imm<0x00, "sll", shl>; + def SRL : LogicR_shift_imm<0x02, "srl", srl>; + def SRA : LogicR_shift_imm<0x03, "sra", sra>; + def SLLV : LogicR_shift_reg<0x04, "sllv", shl>; + def SRLV : LogicR_shift_reg<0x06, "srlv", srl>; + def SRAV : LogicR_shift_reg<0x07, "srav", sra>; + + // Load Upper Immediate + def LUi : LoadUpper<0x0f, "lui">; + + // Load/Store + def LB : LoadM<0x20, "lb", sextloadi8>; + def LBu : LoadM<0x24, "lbu", zextloadi8>; + def LH : LoadM<0x21, "lh", sextloadi16>; + def LHu : LoadM<0x25, "lhu", zextloadi16>; + def LW : LoadM<0x23, "lw", load>; + def SB : StoreM<0x28, "sb", truncstorei8>; + def SH : StoreM<0x29, "sh", truncstorei16>; + def SW : StoreM<0x2b, "sw", store>; + + // Conditional Branch + def BEQ : CBranch<0x04, "beq", seteq>; + def BNE : CBranch<0x05, "bne", setne>; + def SLT : SetCC_R<0x00, 0x2a, "slt", setlt>; + def SLTu : SetCC_R<0x00, 0x2b, "sltu", setult>; + def SLTi : SetCC_I<0x0a, "slti", setlt, simm16, immSExt16>; + def SLTiu : SetCC_I<0x0b, "sltiu", setult, uimm16, immZExt16>; + + // Unconditional jump + def J : JumpFJ<0x02, "j">; + def JR : JumpFR<0x00, 0x08, "jr">; + + // Jump and Link (Call) + def JAL : JumpLink<0x03, "jal">; + def JALR : JumpLinkReg<0x00, 0x09, "jalr">; + + // MulDiv and Move From Hi/Lo operations, have + // their correpondent SDNodes created on ISelDAG. + // Special Mul, Div operations + def MULT : MulDiv<0x18, "mult">; + def MULTu : MulDiv<0x19, "multu">; + def DIV : MulDiv<0x1a, "div">; + def DIVu : MulDiv<0x1b, "divu">; + + // Move From Hi/Lo + def MFHI : MoveFromTo<0x10, "mfhi">; + def MFLO : MoveFromTo<0x12, "mflo">; + def MTHI : MoveFromTo<0x11, "mthi">; + def MTLO : MoveFromTo<0x13, "mtlo">; + + // Count Leading + def CLO : CountLeading<0x21, "clo">; + def CLZ : CountLeading<0x20, "clz">; + + // No operation + let addr=0 in + def NOOP : FJ<0, (ops), "nop", []>; + + // Ret instruction - as mips does not have "ret" a + // jr $ra must be generated. + let isReturn=1, isTerminator=1, hasDelaySlot=1, noResults=1, + isBarrier=1, hasCtrlDep=1, rs=0, rt=0, shamt=0 in + { + def RET : FR <0x00, 0x02, (ops CPURegs:$target), + "jr $target", [(MipsRet CPURegs:$target)]>; + } + + //===----------------------------------------------------------------------===// + // Arbitrary patterns that map to one or more instructions + //===----------------------------------------------------------------------===// + + // Small immediates + def : Pat<(i32 immSExt16:$in), + (ORi ZERO, imm:$in)>; + + // Arbitrary immediates + def : Pat<(i32 imm:$imm), + (ORi (LUi (HI16 imm:$imm)), (LO16 imm:$imm))>; + + // Call + def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)), + (JAL tglobaladdr:$dst)>; + def : Pat<(MipsJmpLink (i32 texternalsym:$dst)), + (JAL texternalsym:$dst)>; + + // GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable + def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; + def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>; + + // When extracting the address from GlobalAddress we + // need something of the form "addiu $reg, %lo(addr)" + def : Pat<(add CPURegs:$a, (MipsLo tglobaladdr:$in)), + (ADDiu CPURegs:$a, tglobaladdr:$in)>; + + // Mips does not have not, so we increase the operation + def : Pat<(not CPURegs:$in), + (NOR CPURegs:$in, CPURegs:$in)>; + + // extended load and stores + def : Pat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>; + def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>; + def : Pat<(truncstorei1 CPURegs:$src, addr:$addr), + (SB CPURegs:$src, addr:$src)>; + + // Conditional branch patterns. + // cond branches patterns, 2 register operands signed. + def : Pat<(brcond (setlt CPURegs:$lhs, CPURegs:$rhs), bb:$dst), + (BNE (SLT CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; + def : Pat<(brcond (setle CPURegs:$lhs, CPURegs:$rhs), bb:$dst), + (BEQ (SLT CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>; + def : Pat<(brcond (setgt CPURegs:$lhs, CPURegs:$rhs), bb:$dst), + (BNE (SLT CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>; + def : Pat<(brcond (setge CPURegs:$lhs, CPURegs:$rhs), bb:$dst), + (BEQ (SLT CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; + + // cond branches patterns, 2 register operands unsigned. + def : Pat<(brcond (setult CPURegs:$lhs, CPURegs:$rhs), bb:$dst), + (BNE (SLTu CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; + def : Pat<(brcond (setule CPURegs:$lhs, CPURegs:$rhs), bb:$dst), + (BEQ (SLTu CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>; + def : Pat<(brcond (setugt CPURegs:$lhs, CPURegs:$rhs), bb:$dst), + (BNE (SLTu CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>; + def : Pat<(brcond (setuge CPURegs:$lhs, CPURegs:$rhs), bb:$dst), + (BEQ (SLTu CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; + + // cond branches patterns, reg/imm operands signed. + def : Pat<(brcond (setult CPURegs:$lhs, immSExt16:$rhs), bb:$dst), + (BNE (SLTi CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; + def : Pat<(brcond (setuge CPURegs:$lhs, immSExt16:$rhs), bb:$dst), + (BEQ (SLTi CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; + + // cond branches patterns, reg/imm operands unsigned. + def : Pat<(brcond (setult CPURegs:$lhs, immZExt16:$rhs), bb:$dst), + (BNE (SLTiu CPURegs:$lhs, immZExt16:$rhs), ZERO, bb:$dst)>; + def : Pat<(brcond (setuge CPURegs:$lhs, immZExt16:$rhs), bb:$dst), + (BEQ (SLTiu CPURegs:$lhs, immZExt16:$rhs), ZERO, bb:$dst)>; Index: llvm/lib/Target/Mips/MipsRegisterInfo.cpp diff -c /dev/null llvm/lib/Target/Mips/MipsRegisterInfo.cpp:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsRegisterInfo.cpp Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,288 ---- + //===- MipsRegisterInfo.cpp - MIPS Register Information -== -----*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file contains the MIPS implementation of the MRegisterInfo class. + // + //===----------------------------------------------------------------------===// + + #define DEBUG_TYPE "mips-reg-info" + + #include "Mips.h" + #include "MipsRegisterInfo.h" + #include "llvm/Constants.h" + #include "llvm/Type.h" + #include "llvm/Function.h" + #include "llvm/CodeGen/ValueTypes.h" + #include "llvm/CodeGen/MachineInstrBuilder.h" + #include "llvm/CodeGen/MachineFunction.h" + #include "llvm/CodeGen/MachineFrameInfo.h" + #include "llvm/CodeGen/MachineLocation.h" + #include "llvm/Target/TargetFrameInfo.h" + #include "llvm/Target/TargetMachine.h" + #include "llvm/Target/TargetOptions.h" + #include "llvm/Target/TargetInstrInfo.h" + #include "llvm/Support/CommandLine.h" + #include "llvm/Support/Debug.h" + #include "llvm/ADT/BitVector.h" + #include "llvm/ADT/STLExtras.h" + //#include "MipsSubtarget.h" + + using namespace llvm; + + // TODO: add subtarget support + MipsRegisterInfo::MipsRegisterInfo(const TargetInstrInfo &tii) + : MipsGenRegisterInfo(Mips::ADJCALLSTACKDOWN, Mips::ADJCALLSTACKUP), + TII(tii) {} + + void MipsRegisterInfo:: + storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned SrcReg, int FI, + const TargetRegisterClass *RC) const + { + if (RC == Mips::CPURegsRegisterClass) + BuildMI(MBB, I, TII.get(Mips::SW)).addFrameIndex(FI) + .addImm(0).addReg(SrcReg, false, false, true); + else + assert(0 && "Can't store this register to stack slot"); + } + + void MipsRegisterInfo:: + loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, int FI, + const TargetRegisterClass *RC) const + { + if (RC == Mips::CPURegsRegisterClass) + BuildMI(MBB, I, TII.get(Mips::LW), DestReg).addImm(0).addFrameIndex(FI); + else + assert(0 && "Can't load this register from stack slot"); + } + + void MipsRegisterInfo:: + copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *RC) const + { + if (RC == Mips::CPURegsRegisterClass) + BuildMI(MBB, I, TII.get(Mips::ADDu), DestReg).addReg(Mips::ZERO) + .addReg(SrcReg); + else + assert (0 && "Can't copy this register"); + } + + void MipsRegisterInfo::reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, + const MachineInstr *Orig) const + { + MachineInstr *MI = Orig->clone(); + MI->getOperand(0).setReg(DestReg); + MBB.insert(I, MI); + } + + MachineInstr *MipsRegisterInfo:: + foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FI) const + { + MachineInstr *NewMI = NULL; + + switch (MI->getOpcode()) + { + case Mips::ADDu: + if ((MI->getOperand(0).isRegister()) && + (MI->getOperand(1).isRegister()) && + (MI->getOperand(1).getReg() == Mips::ZERO) && + (MI->getOperand(2).isRegister())) + { + if (OpNum == 0) // COPY -> STORE + NewMI = BuildMI(TII.get(Mips::SW)).addFrameIndex(FI) + .addImm(0).addReg(MI->getOperand(2).getReg()); + else // COPY -> LOAD + NewMI = BuildMI(TII.get(Mips::LW), MI->getOperand(0) + .getReg()).addImm(0).addFrameIndex(FI); + } + break; + } + + if (NewMI) + NewMI->copyKillDeadInfo(MI); + return NewMI; + } + + /// Mips Callee Saved Registers + const unsigned* MipsRegisterInfo:: + getCalleeSavedRegs() const + { + // Mips calle-save register range is $16-$26(s0-s7) + static const unsigned CalleeSavedRegs[] = { + Mips::S0, Mips::S1, Mips::S2, Mips::S3, + Mips::S4, Mips::S5, Mips::S6, Mips::S7, 0 + }; + return CalleeSavedRegs; + } + + /// Mips Callee Saved Register Classes + const TargetRegisterClass* const* + MipsRegisterInfo::getCalleeSavedRegClasses() const + { + static const TargetRegisterClass * const CalleeSavedRegClasses[] = { + &Mips::CPURegsRegClass, &Mips::CPURegsRegClass, + &Mips::CPURegsRegClass, &Mips::CPURegsRegClass, + &Mips::CPURegsRegClass, &Mips::CPURegsRegClass, + &Mips::CPURegsRegClass, &Mips::CPURegsRegClass, 0 + }; + return CalleeSavedRegClasses; + } + + BitVector MipsRegisterInfo:: + getReservedRegs(const MachineFunction &MF) const + { + BitVector Reserved(getNumRegs()); + Reserved.set(Mips::ZERO); + Reserved.set(Mips::AT); + Reserved.set(Mips::K0); + Reserved.set(Mips::K1); + Reserved.set(Mips::GP); + Reserved.set(Mips::SP); + Reserved.set(Mips::FP); + Reserved.set(Mips::RA); + return Reserved; + } + + //===----------------------------------------------------------------------===// + // Stack Frame Processing methods + //===----------------------------------------------------------------------===// + + // True if target has frame pointer + bool MipsRegisterInfo:: + hasFP(const MachineFunction &MF) const { + return false; + } + + // This function eliminate ADJCALLSTACKDOWN, + // ADJCALLSTACKUP pseudo instructions + void MipsRegisterInfo:: + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. + MBB.erase(I); + } + + // FrameIndex represent objects inside a abstract stack. + // We must replace FrameIndex with an stack/frame pointer + // direct reference. + void MipsRegisterInfo:: + eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, + RegScavenger *RS) const + { + unsigned i = 0; + MachineInstr &MI = *II; + MachineFunction &MF = *MI.getParent()->getParent(); + + while (!MI.getOperand(i).isFrameIndex()) { + ++i; + assert(i < MI.getNumOperands() && + "Instr doesn't have FrameIndex operand!"); + } + + // FrameInfo addressable stack objects are accessed + // using neg. offsets, so we must add with the stack + // size to obtain $sp relative address. + int FrameIndex = MI.getOperand(i).getFrameIndex(); + int stackSize = MF.getFrameInfo()->getStackSize(); + int spOffset = MF.getFrameInfo()->getObjectOffset(FrameIndex); + + #ifndef NDEBUG + DOUT << "\n<--------->\n"; + MI.print(DOUT); + DOUT << "FrameIndex : " << FrameIndex << "\n"; + DOUT << "spOffset : " << spOffset << "\n"; + DOUT << "stackSize : " << stackSize << "\n"; + #endif + + // If the FrameIndex points to a positive SPOffset this + // means we are inside the callee and getting the arguments + // from the caller stack + int Offset = (-(stackSize)) + spOffset; + + #ifndef NDEBUG + DOUT << "Offset : " << Offset << "\n"; + DOUT << "<--------->\n"; + #endif + + MI.getOperand(i-1).ChangeToImmediate(Offset); + MI.getOperand(i).ChangeToRegister(Mips::SP,false); + } + + void MipsRegisterInfo:: + emitPrologue(MachineFunction &MF) const + { + MachineBasicBlock &MBB = MF.front(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + + // Get the number of bytes to allocate from the FrameInfo + int NumBytes = (int) MFI->getStackSize(); + + // Do we need to allocate space on the stack? + if (NumBytes == 0) return; + + // FIXME: is Stack Align needed here ?? (maybe it's done before...) + unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); + NumBytes = -((NumBytes+Align-1)/Align*Align); + + // Update frame info to pretend that this is part of the stack... + MFI->setStackSize(NumBytes); + + // adjust stack : addi sp, sp, (-imm) + BuildMI(MBB, MBB.begin(), TII.get(Mips::ADDi), Mips::SP) + .addReg(Mips::SP).addImm(NumBytes); + } + + void MipsRegisterInfo:: + emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const + { + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + MachineFrameInfo *MFI = MF.getFrameInfo(); + + // Get the number of bytes from FrameInfo + int NumBytes = (int) MFI->getStackSize(); + + // adjust stack : insert addi sp, sp, (imm) + if (NumBytes) { + BuildMI(MBB, MBBI, TII.get(Mips::ADDi), Mips::SP) + .addReg(Mips::SP).addImm(-NumBytes); + } + } + + void MipsRegisterInfo:: + processFunctionBeforeFrameFinalized(MachineFunction &MF) const {} + + unsigned MipsRegisterInfo:: + getRARegister() const { + return Mips::RA; + } + + unsigned MipsRegisterInfo:: + getFrameRegister(MachineFunction &MF) const { + assert(0 && "What is the frame register"); + return Mips::FP; + } + + unsigned MipsRegisterInfo:: + getEHExceptionRegister() const { + assert(0 && "What is the exception register"); + return 0; + } + + unsigned MipsRegisterInfo:: + getEHHandlerRegister() const { + assert(0 && "What is the exception handler register"); + return 0; + } + + #include "MipsGenRegisterInfo.inc" + Index: llvm/lib/Target/Mips/MipsRegisterInfo.h diff -c /dev/null llvm/lib/Target/Mips/MipsRegisterInfo.h:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsRegisterInfo.h Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,83 ---- + //===- MipsRegisterInfo.h - Mips Register Information Impl ------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file contains the Mips implementation of the MRegisterInfo class. + // + //===----------------------------------------------------------------------===// + + #ifndef MIPSREGISTERINFO_H + #define MIPSREGISTERINFO_H + + #include "llvm/Target/MRegisterInfo.h" + #include "MipsGenRegisterInfo.h.inc" + + namespace llvm { + + class TargetInstrInfo; + class Type; + + struct MipsRegisterInfo : public MipsGenRegisterInfo { + const TargetInstrInfo &TII; + + MipsRegisterInfo(const TargetInstrInfo &tii); + + /// Code Generation virtual methods... + void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, int FrameIndex, + const TargetRegisterClass *RC) const; + + void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const; + + void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + unsigned DestReg, const MachineInstr *Orig) const; + + MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, + int FrameIndex) const; + + void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *RC) const; + + + const unsigned *getCalleeSavedRegs() const; + + const TargetRegisterClass* const* getCalleeSavedRegClasses() const; + + BitVector getReservedRegs(const MachineFunction &MF) const; + + bool hasFP(const MachineFunction &MF) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + void eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, RegScavenger *RS = NULL) const; + + void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; + + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + // Debug information queries. + unsigned getRARegister() const; + unsigned getFrameRegister(MachineFunction &MF) const; + + // Exception handling queries. + unsigned getEHExceptionRegister() const; + unsigned getEHHandlerRegister() const; + }; + + } // end namespace llvm + + #endif Index: llvm/lib/Target/Mips/MipsRegisterInfo.td diff -c /dev/null llvm/lib/Target/Mips/MipsRegisterInfo.td:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsRegisterInfo.td Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,80 ---- + //===- MipsRegisterInfo.td - Mips Register defs -----------------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// + // Declarations that describe the MIPS register file + //===----------------------------------------------------------------------===// + + // We have banks of 32 registers each. + class MipsReg : Register { + field bits<5> Num; + let Namespace = "Mips"; + } + + // Mips CPU Registers + class MipsGPRReg num, string n> : MipsReg { + let Num = num; + } + + // CPU GPR Registers + def ZERO : MipsGPRReg< 0, "ZERO">, DwarfRegNum<0>; + def AT : MipsGPRReg< 1, "AT">, DwarfRegNum<1>; + def V0 : MipsGPRReg< 2, "2">, DwarfRegNum<2>; + def V1 : MipsGPRReg< 3, "3">, DwarfRegNum<3>; + def A0 : MipsGPRReg< 4, "4">, DwarfRegNum<5>; + def A1 : MipsGPRReg< 5, "5">, DwarfRegNum<5>; + def A2 : MipsGPRReg< 6, "6">, DwarfRegNum<6>; + def A3 : MipsGPRReg< 7, "7">, DwarfRegNum<7>; + def T0 : MipsGPRReg< 8, "8">, DwarfRegNum<8>; + def T1 : MipsGPRReg< 9, "9">, DwarfRegNum<9>; + def T2 : MipsGPRReg< 10, "10">, DwarfRegNum<10>; + def T3 : MipsGPRReg< 11, "11">, DwarfRegNum<11>; + def T4 : MipsGPRReg< 12, "12">, DwarfRegNum<12>; + def T5 : MipsGPRReg< 13, "13">, DwarfRegNum<13>; + def T6 : MipsGPRReg< 14, "14">, DwarfRegNum<14>; + def T7 : MipsGPRReg< 15, "15">, DwarfRegNum<15>; + def S0 : MipsGPRReg< 16, "16">, DwarfRegNum<16>; + def S1 : MipsGPRReg< 17, "17">, DwarfRegNum<17>; + def S2 : MipsGPRReg< 18, "18">, DwarfRegNum<18>; + def S3 : MipsGPRReg< 19, "19">, DwarfRegNum<19>; + def S4 : MipsGPRReg< 20, "20">, DwarfRegNum<20>; + def S5 : MipsGPRReg< 21, "21">, DwarfRegNum<21>; + def S6 : MipsGPRReg< 22, "22">, DwarfRegNum<22>; + def S7 : MipsGPRReg< 23, "23">, DwarfRegNum<23>; + def T8 : MipsGPRReg< 24, "24">, DwarfRegNum<24>; + def T9 : MipsGPRReg< 25, "25">, DwarfRegNum<25>; + def K0 : MipsGPRReg< 26, "26">, DwarfRegNum<26>; + def K1 : MipsGPRReg< 27, "27">, DwarfRegNum<27>; + def GP : MipsGPRReg< 28, "GP">, DwarfRegNum<28>; + def SP : MipsGPRReg< 29, "SP">, DwarfRegNum<29>; + def FP : MipsGPRReg< 30, "FP">, DwarfRegNum<30>; + def RA : MipsGPRReg< 31, "RA">, DwarfRegNum<31>; + + // CPU Registers Class + def CPURegs : RegisterClass<"Mips", [i32], 32, + // Return Values and Arguments + [V0, V1, A0, A1, A2, A3, + // Not preserved across procedure calls + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, + // Callee save + S0, S1, S2, S3, S4, S5, S6, S7, + // Reserved + ZERO, AT, K0, K1, GP, SP, FP, RA]> + { + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + CPURegsClass::iterator + CPURegsClass::allocation_order_end(const MachineFunction &MF) const { + // The last 8 registers on the list above are reserved + return end()-8; + } + }]; + } Index: llvm/lib/Target/Mips/MipsSubtarget.cpp diff -c /dev/null llvm/lib/Target/Mips/MipsSubtarget.cpp:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsSubtarget.cpp Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,26 ---- + //===- MipsSubtarget.cpp - Mips Subtarget Information -----------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file implements the Mips specific subclass of TargetSubtarget. + // + //===----------------------------------------------------------------------===// + + #include "MipsSubtarget.h" + #include "Mips.h" + #include "MipsGenSubtarget.inc" + using namespace llvm; + + MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M, + const std::string &FS) : isR3000(false) + { + std::string CPU = "generic"; + + // Parse features string. + ParseSubtargetFeatures(FS, CPU); + } Index: llvm/lib/Target/Mips/MipsSubtarget.h diff -c /dev/null llvm/lib/Target/Mips/MipsSubtarget.h:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsSubtarget.h Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,43 ---- + //=====-- MipsSubtarget.h - Define Subtarget for the Mips -----*- C++ -*--====// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file declares the Mips specific subclass of TargetSubtarget. + // + //===----------------------------------------------------------------------===// + + #ifndef MIPSSUBTARGET_H + #define MIPSSUBTARGET_H + + #include "llvm/Target/TargetSubtarget.h" + #include "llvm/Target/TargetMachine.h" + + #include + + namespace llvm { + class Module; + + class MipsSubtarget : public TargetSubtarget { + protected: + bool isR3000; + public: + /// This constructor initializes the data members to match that + /// of the specified module. + /// + MipsSubtarget(const TargetMachine &TM, const Module &M, + const std::string &FS); + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); + + bool IsR3000() const { return isR3000; } + }; + } // End llvm namespace + + #endif Index: llvm/lib/Target/Mips/MipsTargetAsmInfo.cpp diff -c /dev/null llvm/lib/Target/Mips/MipsTargetAsmInfo.cpp:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsTargetAsmInfo.cpp Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,22 ---- + //===-- MipsTargetAsmInfo.cpp - Mips asm properties -------------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file contains the declarations of the MipsTargetAsmInfo properties. + // + //===----------------------------------------------------------------------===// + + #include "MipsTargetAsmInfo.h" + + using namespace llvm; + + MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM) { + Data16bitsDirective = "\t.half\t"; + Data32bitsDirective = "\t.word\t"; + CommentString = "#"; + } Index: llvm/lib/Target/Mips/MipsTargetAsmInfo.h diff -c /dev/null llvm/lib/Target/Mips/MipsTargetAsmInfo.h:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsTargetAsmInfo.h Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,30 ---- + //=====-- MipsTargetAsmInfo.h - Mips asm properties -----------*- C++ -*--====// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file contains the declaration of the MipsTargetAsmInfo class. + // + //===----------------------------------------------------------------------===// + + #ifndef MIPSTARGETASMINFO_H + #define MIPSTARGETASMINFO_H + + #include "llvm/Target/TargetAsmInfo.h" + + namespace llvm { + + // Forward declaration. + class MipsTargetMachine; + + struct MipsTargetAsmInfo : public TargetAsmInfo { + MipsTargetAsmInfo(const MipsTargetMachine &TM); + }; + + } // namespace llvm + + #endif Index: llvm/lib/Target/Mips/MipsTargetMachine.cpp diff -c /dev/null llvm/lib/Target/Mips/MipsTargetMachine.cpp:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsTargetMachine.cpp Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,81 ---- + //===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // Implements the info about Mips target spec. + // + //===----------------------------------------------------------------------===// + + #include "Mips.h" + #include "MipsTargetAsmInfo.h" + #include "MipsTargetMachine.h" + #include "llvm/Module.h" + #include "llvm/PassManager.h" + #include "llvm/Target/TargetMachineRegistry.h" + using namespace llvm; + + namespace { + // Register the target. + RegisterTarget X("mips", " Mips"); + } + + const TargetAsmInfo *MipsTargetMachine:: + createTargetAsmInfo() const + { + return new MipsTargetAsmInfo(*this); + } + + // DataLayout --> Big-endian, 32-bit pointer/ABI/alignment + // FrameInfo --> StackGrowsDown, 8 bytes aligned, LOA : -4 (Ra : 0) + MipsTargetMachine:: + MipsTargetMachine(const Module &M, const std::string &FS): + Subtarget(*this, M, FS), DataLayout("E-p:32:32:32"), + InstrInfo(*this), FrameInfo(TargetFrameInfo::StackGrowsDown, 8, -4), + TLInfo(*this) {} + + // return 0 and must specify -march to gen MIPS code. + unsigned MipsTargetMachine:: + getModuleMatchQuality(const Module &M) + { + // We strongly match "mips-*". + std::string TT = M.getTargetTriple(); + if (TT.size() >= 5 && std::string(TT.begin(), TT.begin()+5) == "mips-") + return 20; + + return 0; + } + + // Install an instruction selector pass using + // the ISelDag to gen Mips code. + bool MipsTargetMachine:: + addInstSelector(FunctionPassManager &PM, bool Fast) + { + PM.add(createMipsISelDag(*this)); + return false; + } + + // Implemented by targets that want to run passes immediately before + // machine code is emitted. return true if -print-machineinstrs should + // print out the code after the passes. + // TODO: Delay slot must be implemented here. + bool MipsTargetMachine:: + addPreEmitPass(FunctionPassManager &PM, bool Fast) + { + return false; + } + + // Implements the AssemblyEmitter for the target. Must return + // true if AssemblyEmitter is supported + bool MipsTargetMachine:: + addAssemblyEmitter(FunctionPassManager &PM, bool Fast, + std::ostream &Out) + { + // Output assembly language. + PM.add(createMipsCodePrinterPass(Out, *this)); + return false; + } Index: llvm/lib/Target/Mips/MipsTargetMachine.h diff -c /dev/null llvm/lib/Target/Mips/MipsTargetMachine.h:1.1 *** /dev/null Wed Jun 6 02:43:11 2007 --- llvm/lib/Target/Mips/MipsTargetMachine.h Wed Jun 6 02:42:06 2007 *************** *** 0 **** --- 1,65 ---- + //===-- MipsTargetMachine.h - Define TargetMachine for Mips -00--*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by Bruno Cardoso Lopes and is distributed under the + // University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file declares the Mips specific subclass of TargetMachine. + // + //===----------------------------------------------------------------------===// + + #ifndef MIPSTARGETMACHINE_H + #define MIPSTARGETMACHINE_H + + #include "MipsSubtarget.h" + #include "MipsInstrInfo.h" + #include "MipsISelLowering.h" + #include "llvm/Target/TargetMachine.h" + #include "llvm/Target/TargetData.h" + #include "llvm/Target/TargetFrameInfo.h" + + namespace llvm { + class MipsTargetMachine : public LLVMTargetMachine { + MipsSubtarget Subtarget; + const TargetData DataLayout; // Calculates type size & alignment + MipsInstrInfo InstrInfo; + TargetFrameInfo FrameInfo; + MipsTargetLowering TLInfo; + + protected: + virtual const TargetAsmInfo *createTargetAsmInfo() const; + + public: + MipsTargetMachine(const Module &M, const std::string &FS); + + virtual const MipsInstrInfo *getInstrInfo() const + { return &InstrInfo; } + virtual const TargetFrameInfo *getFrameInfo() const + { return &FrameInfo; } + virtual const TargetSubtarget *getSubtargetImpl() const + { return &Subtarget; } + virtual const TargetData *getTargetData() const + { return &DataLayout;} + + virtual const MRegisterInfo *getRegisterInfo() const { + return &InstrInfo.getRegisterInfo(); + } + + virtual MipsTargetLowering *getTargetLowering() const { + return const_cast(&TLInfo); + } + + static unsigned getModuleMatchQuality(const Module &M); + + // Pass Pipeline Configuration + virtual bool addInstSelector(FunctionPassManager &PM, bool Fast); + virtual bool addPreEmitPass(FunctionPassManager &PM, bool Fast); + virtual bool addAssemblyEmitter(FunctionPassManager &PM, bool Fast, + std::ostream &Out); + }; + } // End llvm namespace + + #endif From baldrick at free.fr Wed Jun 6 05:00:12 2007 From: baldrick at free.fr (Duncan Sands) Date: Wed, 6 Jun 2007 05:00:12 -0500 Subject: [llvm-commits] CVS: llvm/test/CodeGen/Generic/2007-06-06-CriticalEdgeLandingPad.ll Message-ID: <200706061000.l56A0Ce0020080@zion.cs.uiuc.edu> Changes in directory llvm/test/CodeGen/Generic: 2007-06-06-CriticalEdgeLandingPad.ll added (r1.1) --- Log message: "Simplified" testcase for PR1422: http://llvm.org/PR1422 . --- Diffs of the changes: (+2864 -0) 2007-06-06-CriticalEdgeLandingPad.ll | 2864 +++++++++++++++++++++++++++++++++++ 1 files changed, 2864 insertions(+) Index: llvm/test/CodeGen/Generic/2007-06-06-CriticalEdgeLandingPad.ll diff -c /dev/null llvm/test/CodeGen/Generic/2007-06-06-CriticalEdgeLandingPad.ll:1.1 *** /dev/null Wed Jun 6 05:00:03 2007 --- llvm/test/CodeGen/Generic/2007-06-06-CriticalEdgeLandingPad.ll Wed Jun 6 04:59:53 2007 *************** *** 0 **** --- 1,2864 ---- + ; RUN: llvm-as < %s | llc -enable-eh -asm-verbose -o - | grep {Llabel137.*Region start} + ; PR1422 + + target triple = "i686-pc-linux-gnu" + %struct.exception = type { i8, i8, i32, i8*, i8*, i32, i8* } + %struct.string___XUB = type { i32, i32 } + %struct.string___XUP = type { i8*, %struct.string___XUB* } + %struct.system__secondary_stack__mark_id = type { i8*, i32 } + @weekS.154 = internal constant [28 x i8] c"SSUNSMONSTUESWEDSTHUSFRISSAT" ; <[28 x i8]*> [#uses=1] + @weekN.179 = internal constant [8 x i8] c"\01\05\09\0D\11\15\19\1D" ; <[8 x i8]*> [#uses=1] + @C.28.862 = internal constant %struct.string___XUB { i32 1, i32 85 } ; <%struct.string___XUB*> [#uses=1] + @C.29.865 = internal constant %struct.string___XUB { i32 1, i32 7 } ; <%struct.string___XUB*> [#uses=1] + @C.30.904 = internal constant %struct.string___XUB { i32 1, i32 30 } ; <%struct.string___XUB*> [#uses=1] + @C.32.910 = internal constant %struct.string___XUB { i32 1, i32 28 } ; <%struct.string___XUB*> [#uses=1] + @C.35.915 = internal constant %struct.string___XUB { i32 1, i32 24 } ; <%struct.string___XUB*> [#uses=1] + @C.36.923 = internal constant %struct.string___XUB { i32 1, i32 29 } ; <%struct.string___XUB*> [#uses=1] + @C.98.1466 = internal constant %struct.string___XUB { i32 1, i32 31 } ; <%struct.string___XUB*> [#uses=1] + @C.101.1473 = internal constant %struct.string___XUB { i32 1, i32 46 } ; <%struct.string___XUB*> [#uses=1] + @C.104.1478 = internal constant %struct.string___XUB { i32 1, i32 25 } ; <%struct.string___XUB*> [#uses=1] + @C.124.1606 = internal constant %struct.string___XUB { i32 1, i32 18 } ; <%struct.string___XUB*> [#uses=1] + @C.143.1720 = internal constant [2 x i32] [ i32 1, i32 2 ] ; <[2 x i32]*> [#uses=1] + @C.146.1725 = internal constant %struct.string___XUB { i32 1, i32 37 } ; <%struct.string___XUB*> [#uses=1] + @C.170.1990 = internal constant %struct.string___XUB { i32 1, i32 19 } ; <%struct.string___XUB*> [#uses=1] + @C.178.2066 = internal constant %struct.string___XUB { i32 1, i32 27 } ; <%struct.string___XUB*> [#uses=1] + @.str = internal constant [13 x i8] c"c36104b.adb\00\00" ; <[13 x i8]*> [#uses=1] + @.str1 = internal constant [85 x i8] c"CONSTRAINT_ERROR IS RAISED OR NOT IN DYNAMIC DISCRETE_RANGES WITH EXPLICIT TYPE_MARKS" ; <[85 x i8]*> [#uses=1] + @.str2 = internal constant [7 x i8] c"C36104B" ; <[7 x i8]*> [#uses=1] + @constraint_error = external global %struct.exception ; <%struct.exception*> [#uses=18] + @__gnat_others_value = external constant i32 ; [#uses=37] + @.str3 = internal constant [30 x i8] c"CONSTRAINT_ERROR NOT RAISED 1 " ; <[30 x i8]*> [#uses=1] + @system__soft_links__abort_undefer = external global void ()* ; [#uses=30] + @.str4 = internal constant [28 x i8] c"UNHANDLED EXCEPTION RAISED 1" ; <[28 x i8]*> [#uses=1] + @.str5 = internal constant [24 x i8] c"WRONG EXCEPTION RAISED 1" ; <[24 x i8]*> [#uses=1] + @.str6 = internal constant [29 x i8] c"CONSTRAINT_ERROR NOT RAISED 3" ; <[29 x i8]*> [#uses=1] + @.str7 = internal constant [24 x i8] c"WRONG EXCEPTION RAISED 3" ; <[24 x i8]*> [#uses=1] + @.str10 = internal constant [24 x i8] c"WRONG EXCEPTION RAISED 4" ; <[24 x i8]*> [#uses=1] + @.str11 = internal constant [30 x i8] c"CONSTRAINT_ERROR NOT RAISED 7 " ; <[30 x i8]*> [#uses=1] + @.str12 = internal constant [28 x i8] c"UNHANDLED EXCEPTION RAISED 7" ; <[28 x i8]*> [#uses=1] + @.str13 = internal constant [24 x i8] c"WRONG EXCEPTION RAISED 7" ; <[24 x i8]*> [#uses=1] + @.str14 = internal constant [30 x i8] c"CONSTRAINT_ERROR NOT RAISED 8 " ; <[30 x i8]*> [#uses=1] + @.str15 = internal constant [28 x i8] c"UNHANDLED EXCEPTION RAISED 8" ; <[28 x i8]*> [#uses=1] + @.str16 = internal constant [24 x i8] c"WRONG EXCEPTION RAISED 8" ; <[24 x i8]*> [#uses=1] + @.str17 = internal constant [30 x i8] c"CONSTRAINT_ERROR NOT RAISED 9 " ; <[30 x i8]*> [#uses=1] + @.str18 = internal constant [24 x i8] c"WRONG EXCEPTION RAISED 9" ; <[24 x i8]*> [#uses=1] + @.str19 = internal constant [31 x i8] c"CONSTRAINT_ERROR NOT RAISED 10 " ; <[31 x i8]*> [#uses=1] + @.str20 = internal constant [46 x i8] c"DID NOT RAISE CONSTRAINT_ERROR AT PROPER PLACE" ; <[46 x i8]*> [#uses=1] + @.str21 = internal constant [25 x i8] c"WRONG EXCEPTION RAISED 10" ; <[25 x i8]*> [#uses=1] + @.str22 = internal constant [31 x i8] c"CONSTRAINT_ERROR NOT RAISED 11 " ; <[31 x i8]*> [#uses=1] + @.str23 = internal constant [25 x i8] c"WRONG EXCEPTION RAISED 11" ; <[25 x i8]*> [#uses=1] + @.str24 = internal constant [30 x i8] c"'FIRST OF NULL ARRAY INCORRECT" ; <[30 x i8]*> [#uses=1] + @.str25 = internal constant [18 x i8] c"EXCEPTION RAISED 1" ; <[18 x i8]*> [#uses=1] + @.str26 = internal constant [18 x i8] c"EXCEPTION RAISED 3" ; <[18 x i8]*> [#uses=1] + @.str27 = internal constant [31 x i8] c"'LENGTH OF NULL ARRAY INCORRECT" ; <[31 x i8]*> [#uses=1] + @.str28 = internal constant [18 x i8] c"EXCEPTION RAISED 5" ; <[18 x i8]*> [#uses=1] + @.str29 = internal constant [37 x i8] c"EVALUATION OF EXPRESSION IS INCORRECT" ; <[37 x i8]*> [#uses=1] + @.str30 = internal constant [18 x i8] c"EXCEPTION RAISED 7" ; <[18 x i8]*> [#uses=1] + @.str32 = internal constant [18 x i8] c"EXCEPTION RAISED 9" ; <[18 x i8]*> [#uses=1] + @.str33 = internal constant [19 x i8] c"EXCEPTION RAISED 10" ; <[19 x i8]*> [#uses=1] + @.str34 = internal constant [19 x i8] c"EXCEPTION RAISED 12" ; <[19 x i8]*> [#uses=1] + @.str35 = internal constant [27 x i8] c"INCORRECT 'IN' EVALUATION 1" ; <[27 x i8]*> [#uses=1] + @.str36 = internal constant [27 x i8] c"INCORRECT 'IN' EVALUATION 2" ; <[27 x i8]*> [#uses=1] + @.str37 = internal constant [29 x i8] c"INCORRECT 'NOT IN' EVALUATION" ; <[29 x i8]*> [#uses=1] + @.str38 = internal constant [19 x i8] c"EXCEPTION RAISED 52" ; <[19 x i8]*> [#uses=1] + + define void @_ada_c36104b() { + entry: + %tmp9 = alloca %struct.system__secondary_stack__mark_id, align 8 ; <%struct.system__secondary_stack__mark_id*> [#uses=3] + %tmp12 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp15 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp31 = alloca %struct.system__secondary_stack__mark_id, align 8 ; <%struct.system__secondary_stack__mark_id*> [#uses=3] + %tmp34 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp37 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp46 = alloca %struct.system__secondary_stack__mark_id, align 8 ; <%struct.system__secondary_stack__mark_id*> [#uses=3] + %tmp49 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp52 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp55 = alloca %struct.system__secondary_stack__mark_id, align 8 ; <%struct.system__secondary_stack__mark_id*> [#uses=3] + %tmp58 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp61 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp63 = alloca %struct.system__secondary_stack__mark_id, align 8 ; <%struct.system__secondary_stack__mark_id*> [#uses=3] + %tmp66 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp69 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp72 = alloca %struct.system__secondary_stack__mark_id, align 8 ; <%struct.system__secondary_stack__mark_id*> [#uses=3] + %tmp75 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp78 = alloca %struct.string___XUP, align 8 ; <%struct.string___XUP*> [#uses=3] + %tmp123 = call i32 @report__ident_int( i32 0 ) ; [#uses=3] + %tmp125 = icmp ugt i32 %tmp123, 6 ; [#uses=1] + br i1 %tmp125, label %cond_true, label %cond_next136 + + cond_true: ; preds = %entry + call void @__gnat_rcheck_10( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 50 ) + unreachable + + cond_next136: ; preds = %entry + %tmp137138 = trunc i32 %tmp123 to i8 ; [#uses=21] + %tmp139 = icmp ugt i8 %tmp137138, 6 ; [#uses=1] + br i1 %tmp139, label %bb, label %bb144 + + bb: ; preds = %cond_next136 + call void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 50 ) + unreachable + + bb144: ; preds = %cond_next136 + %tmp150 = call i32 @report__ident_int( i32 1 ) ; [#uses=4] + %tmp154 = icmp ugt i32 %tmp150, 6 ; [#uses=1] + br i1 %tmp154, label %cond_true157, label %cond_next169 + + cond_true157: ; preds = %bb144 + call void @__gnat_rcheck_10( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 51 ) + unreachable + + cond_next169: ; preds = %bb144 + %tmp170171 = trunc i32 %tmp150 to i8 ; [#uses=34] + %tmp172 = icmp ugt i8 %tmp170171, 6 ; [#uses=1] + br i1 %tmp172, label %bb175, label %bb178 + + bb175: ; preds = %cond_next169 + call void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 51 ) + unreachable + + bb178: ; preds = %cond_next169 + %tmp184 = call i32 @report__ident_int( i32 2 ) ; [#uses=3] + %tmp188 = icmp ugt i32 %tmp184, 6 ; [#uses=1] + br i1 %tmp188, label %cond_true191, label %cond_next203 + + cond_true191: ; preds = %bb178 + call void @__gnat_rcheck_10( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 52 ) + unreachable + + cond_next203: ; preds = %bb178 + %tmp204205 = trunc i32 %tmp184 to i8 ; [#uses=30] + %tmp206 = icmp ugt i8 %tmp204205, 6 ; [#uses=3] + br i1 %tmp206, label %bb209, label %bb212 + + bb209: ; preds = %cond_next203 + call void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 52 ) + unreachable + + bb212: ; preds = %cond_next203 + %tmp218 = call i32 @report__ident_int( i32 3 ) ; [#uses=4] + %tmp222 = icmp ugt i32 %tmp218, 6 ; [#uses=1] + br i1 %tmp222, label %cond_true225, label %cond_next237 + + cond_true225: ; preds = %bb212 + call void @__gnat_rcheck_10( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 53 ) + unreachable + + cond_next237: ; preds = %bb212 + %tmp238239 = trunc i32 %tmp218 to i8 ; [#uses=34] + %tmp240 = icmp ugt i8 %tmp238239, 6 ; [#uses=2] + br i1 %tmp240, label %bb243, label %bb246 + + bb243: ; preds = %cond_next237 + call void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 53 ) + unreachable + + bb246: ; preds = %cond_next237 + %tmp252 = call i32 @report__ident_int( i32 4 ) ; [#uses=3] + %tmp256 = icmp ugt i32 %tmp252, 6 ; [#uses=1] + br i1 %tmp256, label %cond_true259, label %cond_next271 + + cond_true259: ; preds = %bb246 + call void @__gnat_rcheck_10( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 54 ) + unreachable + + cond_next271: ; preds = %bb246 + %tmp272273 = trunc i32 %tmp252 to i8 ; [#uses=27] + %tmp274 = icmp ugt i8 %tmp272273, 6 ; [#uses=4] + br i1 %tmp274, label %bb277, label %bb280 + + bb277: ; preds = %cond_next271 + call void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 54 ) + unreachable + + bb280: ; preds = %cond_next271 + %tmp286 = call i32 @report__ident_int( i32 5 ) ; [#uses=3] + %tmp290 = icmp ugt i32 %tmp286, 6 ; [#uses=1] + br i1 %tmp290, label %cond_true293, label %cond_next305 + + cond_true293: ; preds = %bb280 + call void @__gnat_rcheck_10( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 55 ) + unreachable + + cond_next305: ; preds = %bb280 + %tmp306307 = trunc i32 %tmp286 to i8 ; [#uses=16] + %tmp308 = icmp ugt i8 %tmp306307, 6 ; [#uses=1] + br i1 %tmp308, label %bb311, label %bb314 + + bb311: ; preds = %cond_next305 + call void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 55 ) + unreachable + + bb314: ; preds = %cond_next305 + %tmp320 = call i32 @report__ident_int( i32 6 ) ; [#uses=2] + %tmp324 = icmp ugt i32 %tmp320, 6 ; [#uses=1] + br i1 %tmp324, label %cond_true327, label %cond_next339 + + cond_true327: ; preds = %bb314 + call void @__gnat_rcheck_10( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 56 ) + unreachable + + cond_next339: ; preds = %bb314 + %tmp340341 = trunc i32 %tmp320 to i8 ; [#uses=4] + %tmp342 = icmp ugt i8 %tmp340341, 6 ; [#uses=1] + br i1 %tmp342, label %bb345, label %bb348 + + bb345: ; preds = %cond_next339 + call void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 56 ) + unreachable + + bb348: ; preds = %cond_next339 + %tmp364 = icmp ult i8 %tmp272273, %tmp204205 ; [#uses=2] + br i1 %tmp364, label %cond_next383, label %cond_true367 + + cond_true367: ; preds = %bb348 + %tmp370 = icmp ult i8 %tmp204205, %tmp170171 ; [#uses=1] + %tmp374 = icmp ugt i8 %tmp272273, %tmp306307 ; [#uses=1] + %tmp378 = or i1 %tmp374, %tmp370 ; [#uses=1] + br i1 %tmp378, label %cond_true381, label %cond_next383 + + cond_true381: ; preds = %cond_true367 + call void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 59 ) + unreachable + + cond_next383: ; preds = %cond_true367, %bb348 + %tmp384 = call i32 @report__ident_int( i32 -5 ) ; [#uses=15] + %tmp388 = add i32 %tmp384, 10 ; [#uses=1] + %tmp389 = icmp ugt i32 %tmp388, 20 ; [#uses=1] + br i1 %tmp389, label %cond_true392, label %cond_next393 + + cond_true392: ; preds = %cond_next383 + call void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 63 ) + unreachable + + cond_next393: ; preds = %cond_next383 + %tmp394 = call i32 @report__ident_int( i32 5 ) ; [#uses=18] + %tmp398 = add i32 %tmp394, 10 ; [#uses=1] + %tmp399 = icmp ugt i32 %tmp398, 20 ; [#uses=1] + br i1 %tmp399, label %cond_true402, label %cond_next403 + + cond_true402: ; preds = %cond_next393 + call void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 64 ) + unreachable + + cond_next403: ; preds = %cond_next393 + %tmp416 = icmp slt i32 %tmp394, %tmp384 ; [#uses=1] + br i1 %tmp416, label %cond_next437, label %cond_true419 + + cond_true419: ; preds = %cond_next403 + %tmp423 = icmp slt i32 %tmp384, -10 ; [#uses=1] + %tmp428 = icmp sgt i32 %tmp394, 10 ; [#uses=1] + %tmp432 = or i1 %tmp428, %tmp423 ; [#uses=1] + br i1 %tmp432, label %cond_true435, label %cond_next437 + + cond_true435: ; preds = %cond_true419 + call void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 63 ) + unreachable + + cond_next437: ; preds = %cond_true419, %cond_next403 + call void @report__test( i64 or (i64 zext (i32 ptrtoint ([7 x i8]* @.str2 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.29.865 to i32) to i64), i64 32)), i64 or (i64 zext (i32 ptrtoint ([85 x i8]* @.str1 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.28.862 to i32) to i64), i64 32)) ) + %tmp453 = icmp sgt i32 %tmp384, 0 ; [#uses=1] + %tmp458 = icmp slt i32 %tmp394, 6 ; [#uses=1] + %tmp462 = or i1 %tmp458, %tmp453 ; [#uses=3] + br i1 %tmp462, label %cond_true465, label %cond_next467 + + cond_true465: ; preds = %cond_next437 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 80 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind + + unwind: ; preds = %cleanup798, %unwind783, %cond_true465 + %eh_ptr = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid8065921 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp8085923 = icmp eq i32 %eh_select, %eh_typeid8065921 ; [#uses=1] + br i1 %tmp8085923, label %eh_then809, label %eh_else823 + + cond_next467: ; preds = %cond_next437 + invoke void @system__secondary_stack__ss_mark( %struct.system__secondary_stack__mark_id* %tmp9 sret ) + to label %invcont472 unwind label %unwind468 + + unwind468: ; preds = %cleanup, %unwind480, %cond_next467 + %eh_ptr469 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select471 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr469, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid5928 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp7815929 = icmp eq i32 %eh_select471, %eh_typeid5928 ; [#uses=1] + br i1 %tmp7815929, label %eh_then, label %cleanup805 + + invcont472: ; preds = %cond_next467 + %tmp475 = getelementptr %struct.system__secondary_stack__mark_id* %tmp9, i32 0, i32 0 ; [#uses=1] + %tmp476 = load i8** %tmp475 ; [#uses=2] + %tmp478 = getelementptr %struct.system__secondary_stack__mark_id* %tmp9, i32 0, i32 1 ; [#uses=1] + %tmp479 = load i32* %tmp478 ; [#uses=2] + %tmp485 = invoke i32 @report__ident_int( i32 1 ) + to label %invcont484 unwind label %unwind480 ; [#uses=2] + + unwind480: ; preds = %invcont734, %invcont717, %cond_next665, %cond_true663, %cond_next639, %cond_true637, %cond_next613, %cond_true611, %cond_next587, %cond_true585, %cond_next561, %cond_true559, %cond_next535, %cond_true533, %cond_next509, %cond_true507, %invcont472 + %eh_ptr481 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select483 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr481, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=2] + %tmp7685575 = ptrtoint i8* %tmp476 to i32 ; [#uses=1] + %tmp76855755576 = zext i32 %tmp7685575 to i64 ; [#uses=1] + %tmp7715572 = zext i32 %tmp479 to i64 ; [#uses=1] + %tmp77155725573 = shl i64 %tmp7715572, 32 ; [#uses=1] + %tmp77155725573.ins = or i64 %tmp77155725573, %tmp76855755576 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp77155725573.ins ) + to label %cleanup779 unwind label %unwind468 + + invcont484: ; preds = %invcont472 + %tmp492 = icmp slt i32 %tmp485, %tmp384 ; [#uses=1] + %tmp500 = icmp sgt i32 %tmp485, %tmp394 ; [#uses=1] + %tmp504 = or i1 %tmp492, %tmp500 ; [#uses=1] + br i1 %tmp504, label %cond_true507, label %cond_next509 + + cond_true507: ; preds = %invcont484 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 86 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind480 + + cond_next509: ; preds = %invcont484 + %tmp511 = invoke i32 @report__ident_int( i32 1 ) + to label %invcont510 unwind label %unwind480 ; [#uses=3] + + invcont510: ; preds = %cond_next509 + %tmp518 = icmp slt i32 %tmp511, %tmp384 ; [#uses=1] + %tmp526 = icmp sgt i32 %tmp511, %tmp394 ; [#uses=1] + %tmp530 = or i1 %tmp518, %tmp526 ; [#uses=1] + br i1 %tmp530, label %cond_true533, label %cond_next535 + + cond_true533: ; preds = %invcont510 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 86 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind480 + + cond_next535: ; preds = %invcont510 + %tmp537 = invoke i32 @report__ident_int( i32 1 ) + to label %invcont536 unwind label %unwind480 ; [#uses=2] + + invcont536: ; preds = %cond_next535 + %tmp544 = icmp slt i32 %tmp537, %tmp384 ; [#uses=1] + %tmp552 = icmp sgt i32 %tmp537, %tmp394 ; [#uses=1] + %tmp556 = or i1 %tmp544, %tmp552 ; [#uses=1] + br i1 %tmp556, label %cond_true559, label %cond_next561 + + cond_true559: ; preds = %invcont536 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 86 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind480 + + cond_next561: ; preds = %invcont536 + %tmp563 = invoke i32 @report__ident_int( i32 1 ) + to label %invcont562 unwind label %unwind480 ; [#uses=2] + + invcont562: ; preds = %cond_next561 + %tmp570 = icmp slt i32 %tmp563, %tmp384 ; [#uses=1] + %tmp578 = icmp sgt i32 %tmp563, %tmp394 ; [#uses=1] + %tmp582 = or i1 %tmp570, %tmp578 ; [#uses=1] + br i1 %tmp582, label %cond_true585, label %cond_next587 + + cond_true585: ; preds = %invcont562 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 86 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind480 + + cond_next587: ; preds = %invcont562 + %tmp589 = invoke i32 @report__ident_int( i32 1 ) + to label %invcont588 unwind label %unwind480 ; [#uses=2] + + invcont588: ; preds = %cond_next587 + %tmp596 = icmp slt i32 %tmp589, %tmp384 ; [#uses=1] + %tmp604 = icmp sgt i32 %tmp589, %tmp394 ; [#uses=1] + %tmp608 = or i1 %tmp596, %tmp604 ; [#uses=1] + br i1 %tmp608, label %cond_true611, label %cond_next613 + + cond_true611: ; preds = %invcont588 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 86 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind480 + + cond_next613: ; preds = %invcont588 + %tmp615 = invoke i32 @report__ident_int( i32 1 ) + to label %invcont614 unwind label %unwind480 ; [#uses=2] + + invcont614: ; preds = %cond_next613 + %tmp622 = icmp slt i32 %tmp615, %tmp384 ; [#uses=1] + %tmp630 = icmp sgt i32 %tmp615, %tmp394 ; [#uses=1] + %tmp634 = or i1 %tmp622, %tmp630 ; [#uses=1] + br i1 %tmp634, label %cond_true637, label %cond_next639 + + cond_true637: ; preds = %invcont614 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 86 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind480 + + cond_next639: ; preds = %invcont614 + %tmp641 = invoke i32 @report__ident_int( i32 1 ) + to label %invcont640 unwind label %unwind480 ; [#uses=2] + + invcont640: ; preds = %cond_next639 + %tmp648 = icmp slt i32 %tmp641, %tmp384 ; [#uses=1] + %tmp656 = icmp sgt i32 %tmp641, %tmp394 ; [#uses=1] + %tmp660 = or i1 %tmp648, %tmp656 ; [#uses=1] + br i1 %tmp660, label %cond_true663, label %cond_next665 + + cond_true663: ; preds = %invcont640 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 86 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind480 + + cond_next665: ; preds = %invcont640 + invoke void @system__img_int__image_integer( %struct.string___XUP* %tmp12 sret , i32 %tmp511 ) + to label %invcont717 unwind label %unwind480 + + invcont717: ; preds = %cond_next665 + %tmp719 = getelementptr %struct.string___XUP* %tmp12, i32 0, i32 0 ; [#uses=1] + %tmp720 = load i8** %tmp719 ; [#uses=1] + %tmp7205888 = ptrtoint i8* %tmp720 to i32 ; [#uses=1] + %tmp72058885889 = zext i32 %tmp7205888 to i64 ; [#uses=1] + %tmp722 = getelementptr %struct.string___XUP* %tmp12, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp723 = load %struct.string___XUB** %tmp722 ; <%struct.string___XUB*> [#uses=1] + %tmp7235884 = ptrtoint %struct.string___XUB* %tmp723 to i32 ; [#uses=1] + %tmp72358845885 = zext i32 %tmp7235884 to i64 ; [#uses=1] + %tmp723588458855886 = shl i64 %tmp72358845885, 32 ; [#uses=1] + %tmp723588458855886.ins = or i64 %tmp723588458855886, %tmp72058885889 ; [#uses=1] + invoke void @system__string_ops__str_concat( %struct.string___XUP* %tmp15 sret , i64 or (i64 zext (i32 ptrtoint ([30 x i8]* @.str3 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.30.904 to i32) to i64), i64 32)), i64 %tmp723588458855886.ins ) + to label %invcont734 unwind label %unwind480 + + invcont734: ; preds = %invcont717 + %tmp736 = getelementptr %struct.string___XUP* %tmp15, i32 0, i32 0 ; [#uses=1] + %tmp737 = load i8** %tmp736 ; [#uses=1] + %tmp7375876 = ptrtoint i8* %tmp737 to i32 ; [#uses=1] + %tmp73758765877 = zext i32 %tmp7375876 to i64 ; [#uses=1] + %tmp739 = getelementptr %struct.string___XUP* %tmp15, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp740 = load %struct.string___XUB** %tmp739 ; <%struct.string___XUB*> [#uses=1] + %tmp7405872 = ptrtoint %struct.string___XUB* %tmp740 to i32 ; [#uses=1] + %tmp74058725873 = zext i32 %tmp7405872 to i64 ; [#uses=1] + %tmp740587258735874 = shl i64 %tmp74058725873, 32 ; [#uses=1] + %tmp740587258735874.ins = or i64 %tmp740587258735874, %tmp73758765877 ; [#uses=1] + invoke void @report__failed( i64 %tmp740587258735874.ins ) + to label %cleanup unwind label %unwind480 + + cleanup: ; preds = %invcont734 + %tmp7515581 = ptrtoint i8* %tmp476 to i32 ; [#uses=1] + %tmp75155815582 = zext i32 %tmp7515581 to i64 ; [#uses=1] + %tmp7545578 = zext i32 %tmp479 to i64 ; [#uses=1] + %tmp75455785579 = shl i64 %tmp7545578, 32 ; [#uses=1] + %tmp75455785579.ins = or i64 %tmp75455785579, %tmp75155815582 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp75455785579.ins ) + to label %cond_true856 unwind label %unwind468 + + cleanup779: ; preds = %unwind480 + %eh_typeid = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp781 = icmp eq i32 %eh_select483, %eh_typeid ; [#uses=1] + br i1 %tmp781, label %eh_then, label %cleanup805 + + eh_then: ; preds = %cleanup779, %unwind468 + %eh_exception.35924.0 = phi i8* [ %eh_ptr469, %unwind468 ], [ %eh_ptr481, %cleanup779 ] ; [#uses=3] + invoke void @__gnat_begin_handler( i8* %eh_exception.35924.0 ) + to label %invcont787 unwind label %unwind783 + + unwind783: ; preds = %invcont789, %invcont787, %eh_then + %eh_ptr784 = call i8* @llvm.eh.exception( ) ; [#uses=2] + %eh_select786 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr784, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=1] + invoke void @__gnat_end_handler( i8* %eh_exception.35924.0 ) + to label %cleanup805 unwind label %unwind + + invcont787: ; preds = %eh_then + %tmp788 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp788( ) + to label %invcont789 unwind label %unwind783 + + invcont789: ; preds = %invcont787 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([28 x i8]* @.str4 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.32.910 to i32) to i64), i64 32)) ) + to label %cleanup798 unwind label %unwind783 + + cleanup798: ; preds = %invcont789 + invoke void @__gnat_end_handler( i8* %eh_exception.35924.0 ) + to label %cond_true856 unwind label %unwind + + cleanup805: ; preds = %unwind783, %cleanup779, %unwind468 + %eh_selector.0 = phi i32 [ %eh_select471, %unwind468 ], [ %eh_select483, %cleanup779 ], [ %eh_select786, %unwind783 ] ; [#uses=2] + %eh_exception.0 = phi i8* [ %eh_ptr469, %unwind468 ], [ %eh_ptr481, %cleanup779 ], [ %eh_ptr784, %unwind783 ] ; [#uses=2] + %eh_typeid806 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp808 = icmp eq i32 %eh_selector.0, %eh_typeid806 ; [#uses=1] + br i1 %tmp808, label %eh_then809, label %eh_else823 + + eh_then809: ; preds = %cleanup805, %unwind + %eh_exception.05914.0 = phi i8* [ %eh_ptr, %unwind ], [ %eh_exception.0, %cleanup805 ] ; [#uses=3] + invoke void @__gnat_begin_handler( i8* %eh_exception.05914.0 ) + to label %invcont815 unwind label %unwind813 + + unwind813: ; preds = %invcont815, %eh_then809 + %eh_ptr814 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_exception.05914.0 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr814 ) ; :0 [#uses=0] + unreachable + + invcont815: ; preds = %eh_then809 + %tmp816 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp816( ) + to label %cleanup819 unwind label %unwind813 + + cleanup819: ; preds = %invcont815 + call void @__gnat_end_handler( i8* %eh_exception.05914.0 ) + %tmp8595931 = icmp ult i8 %tmp170171, %tmp204205 ; [#uses=1] + %tmp8635932 = icmp ugt i8 %tmp170171, %tmp272273 ; [#uses=1] + %tmp8675933 = or i1 %tmp8635932, %tmp8595931 ; [#uses=1] + br i1 %tmp8675933, label %cond_true870, label %bb887 + + eh_else823: ; preds = %cleanup805, %unwind + %eh_selector.05912.1 = phi i32 [ %eh_select, %unwind ], [ %eh_selector.0, %cleanup805 ] ; [#uses=1] + %eh_exception.05914.1 = phi i8* [ %eh_ptr, %unwind ], [ %eh_exception.0, %cleanup805 ] ; [#uses=4] + %eh_typeid824 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp826 = icmp eq i32 %eh_selector.05912.1, %eh_typeid824 ; [#uses=1] + br i1 %tmp826, label %eh_then827, label %Unwind + + eh_then827: ; preds = %eh_else823 + invoke void @__gnat_begin_handler( i8* %eh_exception.05914.1 ) + to label %invcont833 unwind label %unwind831 + + unwind831: ; preds = %invcont835, %invcont833, %eh_then827 + %eh_ptr832 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_exception.05914.1 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr832 ) ; :1 [#uses=0] + unreachable + + invcont833: ; preds = %eh_then827 + %tmp834 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp834( ) + to label %invcont835 unwind label %unwind831 + + invcont835: ; preds = %invcont833 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([24 x i8]* @.str5 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.35.915 to i32) to i64), i64 32)) ) + to label %cleanup844 unwind label %unwind831 + + cleanup844: ; preds = %invcont835 + call void @__gnat_end_handler( i8* %eh_exception.05914.1 ) + br label %cond_true856 + + cond_true856: ; preds = %cleanup844, %cleanup798, %cleanup + %tmp859 = icmp ult i8 %tmp170171, %tmp204205 ; [#uses=1] + %tmp863 = icmp ugt i8 %tmp170171, %tmp272273 ; [#uses=1] + %tmp867 = or i1 %tmp863, %tmp859 ; [#uses=1] + br i1 %tmp867, label %cond_true870, label %bb887 + + cond_true870: ; preds = %cond_true856, %cleanup819 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 103 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind871 + + unwind871: ; preds = %cond_next905, %bb887, %cond_true870 + %sat.3 = phi i8 [ %tmp340341, %cond_true870 ], [ %sat.1, %bb887 ], [ %sat.0, %cond_next905 ] ; [#uses=2] + %eh_ptr872 = call i8* @llvm.eh.exception( ) ; [#uses=8] + %eh_select874 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr872, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid915 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp917 = icmp eq i32 %eh_select874, %eh_typeid915 ; [#uses=1] + br i1 %tmp917, label %eh_then918, label %eh_else932 + + bb887: ; preds = %cond_next901, %cond_true856, %cleanup819 + %indvar = phi i8 [ %indvar.next10, %cond_next901 ], [ 0, %cond_true856 ], [ 0, %cleanup819 ] ; [#uses=2] + %sat.1 = phi i8 [ %sat.0, %cond_next901 ], [ %tmp340341, %cond_true856 ], [ %tmp340341, %cleanup819 ] ; [#uses=2] + %tmp889 = invoke i8 @report__equal( i32 2, i32 2 ) + to label %invcont888 unwind label %unwind871 ; [#uses=1] + + invcont888: ; preds = %bb887 + %i.4 = add i8 %indvar, %tmp170171 ; [#uses=1] + %tmp890 = icmp eq i8 %tmp889, 0 ; [#uses=1] + %sat.0 = select i1 %tmp890, i8 %sat.1, i8 6 ; [#uses=3] + %tmp897 = icmp eq i8 %i.4, %tmp170171 ; [#uses=1] + br i1 %tmp897, label %cond_next905, label %cond_next901 + + cond_next901: ; preds = %invcont888 + %indvar.next10 = add i8 %indvar, 1 ; [#uses=1] + br label %bb887 + + cond_next905: ; preds = %invcont888 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([29 x i8]* @.str6 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.36.923 to i32) to i64), i64 32)) ) + to label %finally913 unwind label %unwind871 + + eh_then918: ; preds = %unwind871 + invoke void @__gnat_begin_handler( i8* %eh_ptr872 ) + to label %invcont924 unwind label %unwind922 + + unwind922: ; preds = %invcont924, %eh_then918 + %eh_ptr923 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_ptr872 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr923 ) ; :2 [#uses=0] + unreachable + + invcont924: ; preds = %eh_then918 + %tmp925 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp925( ) + to label %cleanup928 unwind label %unwind922 + + cleanup928: ; preds = %invcont924 + call void @__gnat_end_handler( i8* %eh_ptr872 ) + br i1 %tmp462, label %cond_true973, label %UnifiedReturnBlock35 + + eh_else932: ; preds = %unwind871 + %eh_typeid933 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp935 = icmp eq i32 %eh_select874, %eh_typeid933 ; [#uses=1] + br i1 %tmp935, label %eh_then936, label %Unwind + + eh_then936: ; preds = %eh_else932 + invoke void @__gnat_begin_handler( i8* %eh_ptr872 ) + to label %invcont942 unwind label %unwind940 + + unwind940: ; preds = %invcont944, %invcont942, %eh_then936 + %eh_ptr941 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_ptr872 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr941 ) ; :3 [#uses=0] + unreachable + + invcont942: ; preds = %eh_then936 + %tmp943 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp943( ) + to label %invcont944 unwind label %unwind940 + + invcont944: ; preds = %invcont942 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([24 x i8]* @.str7 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.35.915 to i32) to i64), i64 32)) ) + to label %cleanup953 unwind label %unwind940 + + cleanup953: ; preds = %invcont944 + call void @__gnat_end_handler( i8* %eh_ptr872 ) + br label %finally913 + + finally913: ; preds = %cleanup953, %cond_next905 + %sat.4 = phi i8 [ %sat.3, %cleanup953 ], [ %sat.0, %cond_next905 ] ; [#uses=1] + br i1 %tmp462, label %cond_true973, label %UnifiedReturnBlock35 + + cond_true973: ; preds = %finally913, %cleanup928 + %sat.45934.0 = phi i8 [ %sat.3, %cleanup928 ], [ %sat.4, %finally913 ] ; [#uses=9] + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 119 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind974 + + unwind974: ; preds = %cond_true973 + %eh_ptr975 = call i8* @llvm.eh.exception( ) ; [#uses=8] + %eh_select977 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr975, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid13135959 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp13155961 = icmp eq i32 %eh_select977, %eh_typeid13135959 ; [#uses=1] + br i1 %tmp13155961, label %eh_then1316, label %eh_else1330 + + eh_then1316: ; preds = %unwind974 + invoke void @__gnat_begin_handler( i8* %eh_ptr975 ) + to label %invcont1322 unwind label %unwind1320 + + unwind1320: ; preds = %invcont1322, %eh_then1316 + %eh_ptr1321 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_ptr975 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr1321 ) ; :4 [#uses=0] + unreachable + + invcont1322: ; preds = %eh_then1316 + %tmp1323 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp1323( ) + to label %cleanup1326 unwind label %unwind1320 + + cleanup1326: ; preds = %invcont1322 + call void @__gnat_end_handler( i8* %eh_ptr975 ) + br label %finally1311 + + eh_else1330: ; preds = %unwind974 + %eh_typeid1331 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp1333 = icmp eq i32 %eh_select977, %eh_typeid1331 ; [#uses=1] + br i1 %tmp1333, label %eh_then1334, label %Unwind + + eh_then1334: ; preds = %eh_else1330 + invoke void @__gnat_begin_handler( i8* %eh_ptr975 ) + to label %invcont1340 unwind label %unwind1338 + + unwind1338: ; preds = %invcont1342, %invcont1340, %eh_then1334 + %eh_ptr1339 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_ptr975 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr1339 ) ; :5 [#uses=0] + unreachable + + invcont1340: ; preds = %eh_then1334 + %tmp1341 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp1341( ) + to label %invcont1342 unwind label %unwind1338 + + invcont1342: ; preds = %invcont1340 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([24 x i8]* @.str10 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.35.915 to i32) to i64), i64 32)) ) + to label %cleanup1351 unwind label %unwind1338 + + cleanup1351: ; preds = %invcont1342 + call void @__gnat_end_handler( i8* %eh_ptr975 ) + br label %finally1311 + + finally1311: ; preds = %cleanup1351, %cleanup1326 + %tmp1356 = call i8* @llvm.stacksave( ) ; [#uses=6] + %tmp13571358 = and i32 %tmp184, 255 ; [#uses=11] + %tmp13831384 = and i32 %tmp252, 255 ; [#uses=5] + %tmp1387 = add i32 %tmp13571358, -1 ; [#uses=2] + %tmp1388 = icmp sge i32 %tmp13831384, %tmp1387 ; [#uses=1] + %max1389 = select i1 %tmp1388, i32 %tmp13831384, i32 %tmp1387 ; [#uses=1] + %tmp1392 = sub i32 %max1389, %tmp13571358 ; [#uses=1] + %tmp1393 = add i32 %tmp1392, 1 ; [#uses=2] + %tmp1394 = icmp sgt i32 %tmp1393, -1 ; [#uses=1] + %max1395 = select i1 %tmp1394, i32 %tmp1393, i32 0 ; [#uses=5] + %tmp1397 = alloca i8, i32 %max1395 ; [#uses=2] + %tmp1401 = icmp ult i8 %tmp238239, %tmp170171 ; [#uses=2] + br i1 %tmp1401, label %cond_next1425, label %cond_true1404 + + cond_true1404: ; preds = %finally1311 + %tmp1407 = icmp ult i8 %tmp170171, %tmp204205 ; [#uses=1] + %tmp1411 = icmp ugt i8 %tmp238239, %tmp272273 ; [#uses=1] + %tmp1415 = or i1 %tmp1411, %tmp1407 ; [#uses=1] + br i1 %tmp1415, label %cond_true1418, label %cond_next1425 + + cond_true1418: ; preds = %cond_true1404 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 144 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind1419 + + unwind1419: ; preds = %cleanup1702, %cleanup1686, %unwind1676, %cond_next1548, %cond_true1546, %cond_true1418 + %eh_ptr1420 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select1422 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr1420, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid17215981 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp17235983 = icmp eq i32 %eh_select1422, %eh_typeid17215981 ; [#uses=1] + br i1 %tmp17235983, label %eh_then1724, label %eh_else1742 + + cond_next1425: ; preds = %cond_true1404, %finally1311 + %tmp14281429 = and i32 %tmp150, 255 ; [#uses=3] + %tmp14841485 = and i32 %tmp218, 255 ; [#uses=3] + %tmp1488 = add i32 %tmp14281429, -1 ; [#uses=2] + %tmp1489 = icmp sge i32 %tmp14841485, %tmp1488 ; [#uses=1] + %max1490 = select i1 %tmp1489, i32 %tmp14841485, i32 %tmp1488 ; [#uses=1] + %tmp1493 = sub i32 %max1490, %tmp14281429 ; [#uses=1] + %tmp1494 = add i32 %tmp1493, 1 ; [#uses=2] + %tmp1495 = icmp sgt i32 %tmp1494, -1 ; [#uses=1] + %max1496 = select i1 %tmp1495, i32 %tmp1494, i32 0 ; [#uses=1] + %tmp1497 = alloca i8, i32 %max1496 ; [#uses=3] + %tmp1504 = icmp ugt i8 %tmp170171, %tmp238239 ; [#uses=1] + br i1 %tmp1504, label %cond_next1526, label %bb1509 + + bb1509: ; preds = %cond_next1425 + store i8 %tmp238239, i8* %tmp1497 + %tmp1518 = icmp eq i8 %tmp238239, %tmp170171 ; [#uses=1] + br i1 %tmp1518, label %cond_next1526, label %cond_next1522.preheader + + cond_next1522.preheader: ; preds = %bb1509 + %J64b.55984.8 = add i8 %tmp170171, 1 ; [#uses=1] + br label %cond_next1522 + + cond_next1522: ; preds = %cond_next1522, %cond_next1522.preheader + %indvar6241 = phi i8 [ 0, %cond_next1522.preheader ], [ %indvar.next, %cond_next1522 ] ; [#uses=2] + %tmp1524 = add i8 %J64b.55984.8, %indvar6241 ; [#uses=2] + %tmp151015115988 = zext i8 %tmp1524 to i32 ; [#uses=1] + %tmp15135989 = sub i32 %tmp151015115988, %tmp14281429 ; [#uses=1] + %tmp15145990 = getelementptr i8* %tmp1497, i32 %tmp15135989 ; [#uses=1] + store i8 %tmp238239, i8* %tmp15145990 + %tmp15185992 = icmp eq i8 %tmp238239, %tmp1524 ; [#uses=1] + %indvar.next = add i8 %indvar6241, 1 ; [#uses=1] + br i1 %tmp15185992, label %cond_next1526, label %cond_next1522 + + cond_next1526: ; preds = %cond_next1522, %bb1509, %cond_next1425 + %tmp15271528 = zext i8 %tmp272273 to i64 ; [#uses=1] + %tmp15291530 = zext i8 %tmp204205 to i64 ; [#uses=1] + %tmp1531 = sub i64 %tmp15271528, %tmp15291530 ; [#uses=1] + %tmp1532 = add i64 %tmp1531, 1 ; [#uses=2] + %tmp1533 = icmp sgt i64 %tmp1532, -1 ; [#uses=1] + %max1534 = select i1 %tmp1533, i64 %tmp1532, i64 0 ; [#uses=1] + %tmp15351536 = zext i8 %tmp238239 to i64 ; [#uses=1] + %tmp15371538 = zext i8 %tmp170171 to i64 ; [#uses=1] + %tmp1539 = sub i64 %tmp15351536, %tmp15371538 ; [#uses=1] + %tmp1540 = add i64 %tmp1539, 1 ; [#uses=2] + %tmp1541 = icmp sgt i64 %tmp1540, -1 ; [#uses=1] + %max1542 = select i1 %tmp1541, i64 %tmp1540, i64 0 ; [#uses=1] + %tmp1543 = icmp eq i64 %max1534, %max1542 ; [#uses=1] + br i1 %tmp1543, label %cond_next1548, label %cond_true1546 + + cond_true1546: ; preds = %cond_next1526 + invoke void @__gnat_rcheck_07( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 144 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind1419 + + cond_next1548: ; preds = %cond_next1526 + call void @llvm.memcpy.i32( i8* %tmp1397, i8* %tmp1497, i32 %max1395, i32 1 ) + invoke void @system__secondary_stack__ss_mark( %struct.system__secondary_stack__mark_id* %tmp31 sret ) + to label %invcont1552 unwind label %unwind1419 + + invcont1552: ; preds = %cond_next1548 + %tmp1555 = getelementptr %struct.system__secondary_stack__mark_id* %tmp31, i32 0, i32 0 ; [#uses=1] + %tmp1556 = load i8** %tmp1555 ; [#uses=3] + %tmp1558 = getelementptr %struct.system__secondary_stack__mark_id* %tmp31, i32 0, i32 1 ; [#uses=1] + %tmp1559 = load i32* %tmp1558 ; [#uses=3] + %tmp1562 = icmp ult i8 %tmp238239, %tmp204205 ; [#uses=1] + %tmp1566 = icmp ugt i8 %tmp238239, %tmp272273 ; [#uses=1] + %tmp1570 = or i1 %tmp1566, %tmp1562 ; [#uses=1] + br i1 %tmp1570, label %cond_true1573, label %cond_next1591 + + cond_true1573: ; preds = %invcont1552 + invoke void @__gnat_rcheck_05( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 148 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind1574 + + unwind1574: ; preds = %invcont1638, %invcont1621, %bb1607, %bb1605, %cond_true1573 + %eh_ptr1575 = call i8* @llvm.eh.exception( ) ; [#uses=5] + %eh_select1577 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr1575, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid1652 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp1654 = icmp eq i32 %eh_select1577, %eh_typeid1652 ; [#uses=1] + br i1 %tmp1654, label %eh_then1655, label %cleanup1686 + + cond_next1591: ; preds = %invcont1552 + %tmp1595 = sub i32 %tmp14841485, %tmp13571358 ; [#uses=1] + %tmp1596 = getelementptr i8* %tmp1397, i32 %tmp1595 ; [#uses=1] + %tmp1597 = load i8* %tmp1596 ; [#uses=2] + %tmp1599 = icmp ugt i8 %tmp1597, 6 ; [#uses=1] + br i1 %tmp1599, label %bb1605, label %bb1607 + + bb1605: ; preds = %cond_next1591 + invoke void @__gnat_rcheck_06( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 148 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind1574 + + bb1607: ; preds = %cond_next1591 + %tmp16151616 = zext i8 %tmp1597 to i32 ; [#uses=1] + invoke void @system__img_enum__image_enumeration_8( %struct.string___XUP* %tmp34 sret , i32 %tmp16151616, i64 or (i64 zext (i32 ptrtoint ([28 x i8]* @weekS.154 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.32.910 to i32) to i64), i64 32)), i8* getelementptr ([8 x i8]* @weekN.179, i32 0, i32 0) ) + to label %invcont1621 unwind label %unwind1574 + + invcont1621: ; preds = %bb1607 + %tmp1623 = getelementptr %struct.string___XUP* %tmp34, i32 0, i32 0 ; [#uses=1] + %tmp1624 = load i8** %tmp1623 ; [#uses=1] + %tmp16245815 = ptrtoint i8* %tmp1624 to i32 ; [#uses=1] + %tmp162458155816 = zext i32 %tmp16245815 to i64 ; [#uses=1] + %tmp1626 = getelementptr %struct.string___XUP* %tmp34, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp1627 = load %struct.string___XUB** %tmp1626 ; <%struct.string___XUB*> [#uses=1] + %tmp16275811 = ptrtoint %struct.string___XUB* %tmp1627 to i32 ; [#uses=1] + %tmp162758115812 = zext i32 %tmp16275811 to i64 ; [#uses=1] + %tmp1627581158125813 = shl i64 %tmp162758115812, 32 ; [#uses=1] + %tmp1627581158125813.ins = or i64 %tmp1627581158125813, %tmp162458155816 ; [#uses=1] + invoke void @system__string_ops__str_concat( %struct.string___XUP* %tmp37 sret , i64 or (i64 zext (i32 ptrtoint ([30 x i8]* @.str11 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.30.904 to i32) to i64), i64 32)), i64 %tmp1627581158125813.ins ) + to label %invcont1638 unwind label %unwind1574 + + invcont1638: ; preds = %invcont1621 + %tmp1640 = getelementptr %struct.string___XUP* %tmp37, i32 0, i32 0 ; [#uses=1] + %tmp1641 = load i8** %tmp1640 ; [#uses=1] + %tmp16415803 = ptrtoint i8* %tmp1641 to i32 ; [#uses=1] + %tmp164158035804 = zext i32 %tmp16415803 to i64 ; [#uses=1] + %tmp1643 = getelementptr %struct.string___XUP* %tmp37, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp1644 = load %struct.string___XUB** %tmp1643 ; <%struct.string___XUB*> [#uses=1] + %tmp16445799 = ptrtoint %struct.string___XUB* %tmp1644 to i32 ; [#uses=1] + %tmp164457995800 = zext i32 %tmp16445799 to i64 ; [#uses=1] + %tmp1644579958005801 = shl i64 %tmp164457995800, 32 ; [#uses=1] + %tmp1644579958005801.ins = or i64 %tmp1644579958005801, %tmp164158035804 ; [#uses=1] + invoke void @report__failed( i64 %tmp1644579958005801.ins ) + to label %cleanup1702 unwind label %unwind1574 + + eh_then1655: ; preds = %unwind1574 + invoke void @__gnat_begin_handler( i8* %eh_ptr1575 ) + to label %invcont1663 unwind label %unwind1659 + + unwind1659: ; preds = %invcont1665, %invcont1663, %eh_then1655 + %eh_ptr1660 = call i8* @llvm.eh.exception( ) ; [#uses=2] + %eh_select1662 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr1660, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=1] + invoke void @__gnat_end_handler( i8* %eh_ptr1575 ) + to label %cleanup1686 unwind label %unwind1676 + + invcont1663: ; preds = %eh_then1655 + %tmp1664 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp1664( ) + to label %invcont1665 unwind label %unwind1659 + + invcont1665: ; preds = %invcont1663 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([28 x i8]* @.str12 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.32.910 to i32) to i64), i64 32)) ) + to label %cleanup1674 unwind label %unwind1659 + + cleanup1674: ; preds = %invcont1665 + invoke void @__gnat_end_handler( i8* %eh_ptr1575 ) + to label %cleanup1702 unwind label %unwind1676 + + unwind1676: ; preds = %cleanup1674, %unwind1659 + %eh_ptr1677 = call i8* @llvm.eh.exception( ) ; [#uses=2] + %eh_select1679 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr1677, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=1] + %tmp169255575995 = ptrtoint i8* %tmp1556 to i32 ; [#uses=1] + %tmp1692555755585996 = zext i32 %tmp169255575995 to i64 ; [#uses=1] + %tmp169555545997 = zext i32 %tmp1559 to i64 ; [#uses=1] + %tmp1695555455555998 = shl i64 %tmp169555545997, 32 ; [#uses=1] + %tmp169555545555.ins5999 = or i64 %tmp1695555455555998, %tmp1692555755585996 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp169555545555.ins5999 ) + to label %cleanup1720 unwind label %unwind1419 + + cleanup1686: ; preds = %unwind1659, %unwind1574 + %eh_selector.18 = phi i32 [ %eh_select1577, %unwind1574 ], [ %eh_select1662, %unwind1659 ] ; [#uses=1] + %eh_exception.18 = phi i8* [ %eh_ptr1575, %unwind1574 ], [ %eh_ptr1660, %unwind1659 ] ; [#uses=1] + %tmp16925557 = ptrtoint i8* %tmp1556 to i32 ; [#uses=1] + %tmp169255575558 = zext i32 %tmp16925557 to i64 ; [#uses=1] + %tmp16955554 = zext i32 %tmp1559 to i64 ; [#uses=1] + %tmp169555545555 = shl i64 %tmp16955554, 32 ; [#uses=1] + %tmp169555545555.ins = or i64 %tmp169555545555, %tmp169255575558 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp169555545555.ins ) + to label %cleanup1720 unwind label %unwind1419 + + cleanup1702: ; preds = %cleanup1674, %invcont1638 + %tmp17095551 = ptrtoint i8* %tmp1556 to i32 ; [#uses=1] + %tmp170955515552 = zext i32 %tmp17095551 to i64 ; [#uses=1] + %tmp17125548 = zext i32 %tmp1559 to i64 ; [#uses=1] + %tmp171255485549 = shl i64 %tmp17125548, 32 ; [#uses=1] + %tmp171255485549.ins = or i64 %tmp171255485549, %tmp170955515552 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp171255485549.ins ) + to label %cleanup1773 unwind label %unwind1419 + + cleanup1720: ; preds = %cleanup1686, %unwind1676 + %eh_selector.185993.1 = phi i32 [ %eh_select1679, %unwind1676 ], [ %eh_selector.18, %cleanup1686 ] ; [#uses=2] + %eh_exception.185994.1 = phi i8* [ %eh_ptr1677, %unwind1676 ], [ %eh_exception.18, %cleanup1686 ] ; [#uses=2] + %eh_typeid1721 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp1723 = icmp eq i32 %eh_selector.185993.1, %eh_typeid1721 ; [#uses=1] + br i1 %tmp1723, label %eh_then1724, label %eh_else1742 + + eh_then1724: ; preds = %cleanup1720, %unwind1419 + %eh_exception.135974.0 = phi i8* [ %eh_ptr1420, %unwind1419 ], [ %eh_exception.185994.1, %cleanup1720 ] ; [#uses=3] + invoke void @__gnat_begin_handler( i8* %eh_exception.135974.0 ) + to label %invcont1730 unwind label %unwind1728 + + unwind1728: ; preds = %invcont1730, %eh_then1724 + %eh_ptr1729 = call i8* @llvm.eh.exception( ) ; [#uses=1] + invoke void @__gnat_end_handler( i8* %eh_exception.135974.0 ) + to label %cleanup1771 unwind label %unwind1736 + + invcont1730: ; preds = %eh_then1724 + %tmp1731 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp1731( ) + to label %cleanup1734 unwind label %unwind1728 + + cleanup1734: ; preds = %invcont1730 + invoke void @__gnat_end_handler( i8* %eh_exception.135974.0 ) + to label %cleanup1773 unwind label %unwind1736 + + unwind1736: ; preds = %cleanup1763, %unwind1750, %cleanup1734, %unwind1728 + %eh_ptr1737 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @llvm.stackrestore( i8* %tmp1356 ) + call void @llvm.stackrestore( i8* %tmp1356 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr1737 ) ; :6 [#uses=0] + unreachable + + eh_else1742: ; preds = %cleanup1720, %unwind1419 + %eh_selector.135972.1 = phi i32 [ %eh_select1422, %unwind1419 ], [ %eh_selector.185993.1, %cleanup1720 ] ; [#uses=1] + %eh_exception.135974.1 = phi i8* [ %eh_ptr1420, %unwind1419 ], [ %eh_exception.185994.1, %cleanup1720 ] ; [#uses=4] + %eh_typeid1743 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp1745 = icmp eq i32 %eh_selector.135972.1, %eh_typeid1743 ; [#uses=1] + br i1 %tmp1745, label %eh_then1746, label %cleanup1771 + + eh_then1746: ; preds = %eh_else1742 + invoke void @__gnat_begin_handler( i8* %eh_exception.135974.1 ) + to label %invcont1752 unwind label %unwind1750 + + unwind1750: ; preds = %invcont1754, %invcont1752, %eh_then1746 + %eh_ptr1751 = call i8* @llvm.eh.exception( ) ; [#uses=1] + invoke void @__gnat_end_handler( i8* %eh_exception.135974.1 ) + to label %cleanup1771 unwind label %unwind1736 + + invcont1752: ; preds = %eh_then1746 + %tmp1753 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp1753( ) + to label %invcont1754 unwind label %unwind1750 + + invcont1754: ; preds = %invcont1752 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([24 x i8]* @.str13 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.35.915 to i32) to i64), i64 32)) ) + to label %cleanup1763 unwind label %unwind1750 + + cleanup1763: ; preds = %invcont1754 + invoke void @__gnat_end_handler( i8* %eh_exception.135974.1 ) + to label %cleanup1773 unwind label %unwind1736 + + cleanup1771: ; preds = %unwind1750, %eh_else1742, %unwind1728 + %eh_exception.20 = phi i8* [ %eh_ptr1729, %unwind1728 ], [ %eh_exception.135974.1, %eh_else1742 ], [ %eh_ptr1751, %unwind1750 ] ; [#uses=1] + call void @llvm.stackrestore( i8* %tmp1356 ) + call void @llvm.stackrestore( i8* %tmp1356 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_exception.20 ) ; :7 [#uses=0] + unreachable + + cleanup1773: ; preds = %cleanup1763, %cleanup1734, %cleanup1702 + call void @llvm.stackrestore( i8* %tmp1356 ) + call void @llvm.stackrestore( i8* %tmp1356 ) + %tmp1780 = call i8* @llvm.stacksave( ) ; [#uses=6] + %tmp17811782 = and i32 %tmp150, 255 ; [#uses=4] + %tmp18071808 = and i32 %tmp286, 255 ; [#uses=2] + %tmp1811 = add i32 %tmp17811782, -1 ; [#uses=2] + %tmp1812 = icmp sge i32 %tmp18071808, %tmp1811 ; [#uses=1] + %max1813 = select i1 %tmp1812, i32 %tmp18071808, i32 %tmp1811 ; [#uses=1] + %tmp1816 = sub i32 %max1813, %tmp17811782 ; [#uses=1] + %tmp1817 = add i32 %tmp1816, 1 ; [#uses=2] + %tmp1818 = icmp sgt i32 %tmp1817, -1 ; [#uses=1] + %max1819 = select i1 %tmp1818, i32 %tmp1817, i32 0 ; [#uses=3] + %tmp1821 = alloca i8, i32 %max1819 ; [#uses=2] + %tmp1863 = alloca i8, i32 %max1819 ; [#uses=3] + %tmp1870 = icmp ugt i8 %tmp170171, %tmp306307 ; [#uses=1] + br i1 %tmp1870, label %cond_next1900, label %bb1875 + + bb1875: ; preds = %cleanup1773 + store i8 %tmp238239, i8* %tmp1863 + %tmp1884 = icmp eq i8 %tmp306307, %tmp170171 ; [#uses=1] + br i1 %tmp1884, label %cond_next1900, label %cond_next1888.preheader + + cond_next1888.preheader: ; preds = %bb1875 + %J77b.26000.2 = add i8 %tmp170171, 1 ; [#uses=1] + br label %cond_next1888 + + cond_next1888: ; preds = %cond_next1888, %cond_next1888.preheader + %indvar6245 = phi i8 [ 0, %cond_next1888.preheader ], [ %indvar.next14, %cond_next1888 ] ; [#uses=2] + %tmp1890 = add i8 %J77b.26000.2, %indvar6245 ; [#uses=2] + %tmp187618776004 = zext i8 %tmp1890 to i32 ; [#uses=1] + %tmp18796005 = sub i32 %tmp187618776004, %tmp17811782 ; [#uses=1] + %tmp18806006 = getelementptr i8* %tmp1863, i32 %tmp18796005 ; [#uses=1] + store i8 %tmp238239, i8* %tmp18806006 + %tmp18846008 = icmp eq i8 %tmp306307, %tmp1890 ; [#uses=1] + %indvar.next14 = add i8 %indvar6245, 1 ; [#uses=1] + br i1 %tmp18846008, label %cond_next1900, label %cond_next1888 + + unwind1895: ; preds = %cleanup2300, %cleanup2284, %unwind2274, %cond_next2149, %cond_true1946 + %eh_ptr1896 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select1898 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr1896, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid23196018 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp23216020 = icmp eq i32 %eh_select1898, %eh_typeid23196018 ; [#uses=1] + br i1 %tmp23216020, label %eh_then2322, label %eh_else2340 + + cond_next1900: ; preds = %cond_next1888, %bb1875, %cleanup1773 + call void @llvm.memcpy.i32( i8* %tmp1821, i8* %tmp1863, i32 %max1819, i32 1 ) + ret void + + cond_true1909: ; No predecessors! + %tmp1912 = icmp ult i8 %tmp170171, %tmp204205 ; [#uses=1] + %tmp1916 = icmp ugt i8 %tmp238239, %tmp272273 ; [#uses=1] + %tmp1920 = or i1 %tmp1916, %tmp1912 ; [#uses=0] + ret void + + cond_true1923: ; No predecessors! + ret void + + cond_next1926: ; No predecessors! + %tmp1929.not = icmp uge i8 %tmp238239, %tmp170171 ; [#uses=1] + %tmp1939 = icmp ugt i8 %tmp238239, %tmp306307 ; [#uses=2] + %bothcond = and i1 %tmp1939, %tmp1929.not ; [#uses=0] + ret void + + cond_true1946: ; No predecessors! + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 162 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind1895 + + cond_next2149: ; No predecessors! + invoke void @system__secondary_stack__ss_mark( %struct.system__secondary_stack__mark_id* %tmp46 sret ) + to label %invcont2150 unwind label %unwind1895 + + invcont2150: ; preds = %cond_next2149 + %tmp2153 = getelementptr %struct.system__secondary_stack__mark_id* %tmp46, i32 0, i32 0 ; [#uses=1] + %tmp2154 = load i8** %tmp2153 ; [#uses=3] + %tmp2156 = getelementptr %struct.system__secondary_stack__mark_id* %tmp46, i32 0, i32 1 ; [#uses=1] + %tmp2157 = load i32* %tmp2156 ; [#uses=3] + %tmp2168 = or i1 %tmp1939, %tmp1401 ; [#uses=1] + br i1 %tmp2168, label %cond_true2171, label %cond_next2189 + + cond_true2171: ; preds = %invcont2150 + invoke void @__gnat_rcheck_05( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 165 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind2172 + + unwind2172: ; preds = %invcont2236, %invcont2219, %bb2205, %bb2203, %cond_true2171 + %eh_ptr2173 = call i8* @llvm.eh.exception( ) ; [#uses=5] + %eh_select2175 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr2173, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid2250 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp2252 = icmp eq i32 %eh_select2175, %eh_typeid2250 ; [#uses=1] + br i1 %tmp2252, label %eh_then2253, label %cleanup2284 + + cond_next2189: ; preds = %invcont2150 + %tmp21902191 = and i32 %tmp218, 255 ; [#uses=1] + %tmp2193 = sub i32 %tmp21902191, %tmp17811782 ; [#uses=1] + %tmp2194 = getelementptr i8* %tmp1821, i32 %tmp2193 ; [#uses=1] + %tmp2195 = load i8* %tmp2194 ; [#uses=2] + %tmp2197 = icmp ugt i8 %tmp2195, 6 ; [#uses=1] + br i1 %tmp2197, label %bb2203, label %bb2205 + + bb2203: ; preds = %cond_next2189 + invoke void @__gnat_rcheck_06( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 165 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind2172 + + bb2205: ; preds = %cond_next2189 + %tmp22132214 = zext i8 %tmp2195 to i32 ; [#uses=1] + invoke void @system__img_enum__image_enumeration_8( %struct.string___XUP* %tmp49 sret , i32 %tmp22132214, i64 or (i64 zext (i32 ptrtoint ([28 x i8]* @weekS.154 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.32.910 to i32) to i64), i64 32)), i8* getelementptr ([8 x i8]* @weekN.179, i32 0, i32 0) ) + to label %invcont2219 unwind label %unwind2172 + + invcont2219: ; preds = %bb2205 + %tmp2221 = getelementptr %struct.string___XUP* %tmp49, i32 0, i32 0 ; [#uses=1] + %tmp2222 = load i8** %tmp2221 ; [#uses=1] + %tmp22225781 = ptrtoint i8* %tmp2222 to i32 ; [#uses=1] + %tmp222257815782 = zext i32 %tmp22225781 to i64 ; [#uses=1] + %tmp2224 = getelementptr %struct.string___XUP* %tmp49, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp2225 = load %struct.string___XUB** %tmp2224 ; <%struct.string___XUB*> [#uses=1] + %tmp22255777 = ptrtoint %struct.string___XUB* %tmp2225 to i32 ; [#uses=1] + %tmp222557775778 = zext i32 %tmp22255777 to i64 ; [#uses=1] + %tmp2225577757785779 = shl i64 %tmp222557775778, 32 ; [#uses=1] + %tmp2225577757785779.ins = or i64 %tmp2225577757785779, %tmp222257815782 ; [#uses=1] + invoke void @system__string_ops__str_concat( %struct.string___XUP* %tmp52 sret , i64 or (i64 zext (i32 ptrtoint ([30 x i8]* @.str14 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.30.904 to i32) to i64), i64 32)), i64 %tmp2225577757785779.ins ) + to label %invcont2236 unwind label %unwind2172 + + invcont2236: ; preds = %invcont2219 + %tmp2238 = getelementptr %struct.string___XUP* %tmp52, i32 0, i32 0 ; [#uses=1] + %tmp2239 = load i8** %tmp2238 ; [#uses=1] + %tmp22395769 = ptrtoint i8* %tmp2239 to i32 ; [#uses=1] + %tmp223957695770 = zext i32 %tmp22395769 to i64 ; [#uses=1] + %tmp2241 = getelementptr %struct.string___XUP* %tmp52, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp2242 = load %struct.string___XUB** %tmp2241 ; <%struct.string___XUB*> [#uses=1] + %tmp22425765 = ptrtoint %struct.string___XUB* %tmp2242 to i32 ; [#uses=1] + %tmp224257655766 = zext i32 %tmp22425765 to i64 ; [#uses=1] + %tmp2242576557665767 = shl i64 %tmp224257655766, 32 ; [#uses=1] + %tmp2242576557665767.ins = or i64 %tmp2242576557665767, %tmp223957695770 ; [#uses=1] + invoke void @report__failed( i64 %tmp2242576557665767.ins ) + to label %cleanup2300 unwind label %unwind2172 + + eh_then2253: ; preds = %unwind2172 + invoke void @__gnat_begin_handler( i8* %eh_ptr2173 ) + to label %invcont2261 unwind label %unwind2257 + + unwind2257: ; preds = %invcont2263, %invcont2261, %eh_then2253 + %eh_ptr2258 = call i8* @llvm.eh.exception( ) ; [#uses=2] + %eh_select2260 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr2258, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=1] + invoke void @__gnat_end_handler( i8* %eh_ptr2173 ) + to label %cleanup2284 unwind label %unwind2274 + + invcont2261: ; preds = %eh_then2253 + %tmp2262 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp2262( ) + to label %invcont2263 unwind label %unwind2257 + + invcont2263: ; preds = %invcont2261 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([28 x i8]* @.str15 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.32.910 to i32) to i64), i64 32)) ) + to label %cleanup2272 unwind label %unwind2257 + + cleanup2272: ; preds = %invcont2263 + invoke void @__gnat_end_handler( i8* %eh_ptr2173 ) + to label %cleanup2300 unwind label %unwind2274 + + unwind2274: ; preds = %cleanup2272, %unwind2257 + %eh_ptr2275 = call i8* @llvm.eh.exception( ) ; [#uses=2] + %eh_select2277 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr2275, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=1] + %tmp229055456023 = ptrtoint i8* %tmp2154 to i32 ; [#uses=1] + %tmp2290554555466024 = zext i32 %tmp229055456023 to i64 ; [#uses=1] + %tmp229355426025 = zext i32 %tmp2157 to i64 ; [#uses=1] + %tmp2293554255436026 = shl i64 %tmp229355426025, 32 ; [#uses=1] + %tmp229355425543.ins6027 = or i64 %tmp2293554255436026, %tmp2290554555466024 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp229355425543.ins6027 ) + to label %cleanup2318 unwind label %unwind1895 + + cleanup2284: ; preds = %unwind2257, %unwind2172 + %eh_selector.24 = phi i32 [ %eh_select2175, %unwind2172 ], [ %eh_select2260, %unwind2257 ] ; [#uses=1] + %eh_exception.26 = phi i8* [ %eh_ptr2173, %unwind2172 ], [ %eh_ptr2258, %unwind2257 ] ; [#uses=1] + %tmp22905545 = ptrtoint i8* %tmp2154 to i32 ; [#uses=1] + %tmp229055455546 = zext i32 %tmp22905545 to i64 ; [#uses=1] + %tmp22935542 = zext i32 %tmp2157 to i64 ; [#uses=1] + %tmp229355425543 = shl i64 %tmp22935542, 32 ; [#uses=1] + %tmp229355425543.ins = or i64 %tmp229355425543, %tmp229055455546 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp229355425543.ins ) + to label %cleanup2318 unwind label %unwind1895 + + cleanup2300: ; preds = %cleanup2272, %invcont2236 + %tmp23075539 = ptrtoint i8* %tmp2154 to i32 ; [#uses=1] + %tmp230755395540 = zext i32 %tmp23075539 to i64 ; [#uses=1] + %tmp23105536 = zext i32 %tmp2157 to i64 ; [#uses=1] + %tmp231055365537 = shl i64 %tmp23105536, 32 ; [#uses=1] + %tmp231055365537.ins = or i64 %tmp231055365537, %tmp230755395540 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp231055365537.ins ) + to label %cleanup2371 unwind label %unwind1895 + + cleanup2318: ; preds = %cleanup2284, %unwind2274 + %eh_selector.246021.1 = phi i32 [ %eh_select2277, %unwind2274 ], [ %eh_selector.24, %cleanup2284 ] ; [#uses=2] + %eh_exception.266022.1 = phi i8* [ %eh_ptr2275, %unwind2274 ], [ %eh_exception.26, %cleanup2284 ] ; [#uses=2] + %eh_typeid2319 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp2321 = icmp eq i32 %eh_selector.246021.1, %eh_typeid2319 ; [#uses=1] + br i1 %tmp2321, label %eh_then2322, label %eh_else2340 + + eh_then2322: ; preds = %cleanup2318, %unwind1895 + %eh_exception.216011.0 = phi i8* [ %eh_ptr1896, %unwind1895 ], [ %eh_exception.266022.1, %cleanup2318 ] ; [#uses=3] + invoke void @__gnat_begin_handler( i8* %eh_exception.216011.0 ) + to label %invcont2328 unwind label %unwind2326 + + unwind2326: ; preds = %invcont2328, %eh_then2322 + %eh_ptr2327 = call i8* @llvm.eh.exception( ) ; [#uses=1] + invoke void @__gnat_end_handler( i8* %eh_exception.216011.0 ) + to label %cleanup2369 unwind label %unwind2334 + + invcont2328: ; preds = %eh_then2322 + %tmp2329 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp2329( ) + to label %cleanup2332 unwind label %unwind2326 + + cleanup2332: ; preds = %invcont2328 + invoke void @__gnat_end_handler( i8* %eh_exception.216011.0 ) + to label %cleanup2371 unwind label %unwind2334 + + unwind2334: ; preds = %cleanup2361, %unwind2348, %cleanup2332, %unwind2326 + %eh_ptr2335 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @llvm.stackrestore( i8* %tmp1780 ) + call void @llvm.stackrestore( i8* %tmp1780 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr2335 ) ; :8 [#uses=0] + unreachable + + eh_else2340: ; preds = %cleanup2318, %unwind1895 + %eh_selector.196009.1 = phi i32 [ %eh_select1898, %unwind1895 ], [ %eh_selector.246021.1, %cleanup2318 ] ; [#uses=1] + %eh_exception.216011.1 = phi i8* [ %eh_ptr1896, %unwind1895 ], [ %eh_exception.266022.1, %cleanup2318 ] ; [#uses=4] + %eh_typeid2341 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp2343 = icmp eq i32 %eh_selector.196009.1, %eh_typeid2341 ; [#uses=1] + br i1 %tmp2343, label %eh_then2344, label %cleanup2369 + + eh_then2344: ; preds = %eh_else2340 + invoke void @__gnat_begin_handler( i8* %eh_exception.216011.1 ) + to label %invcont2350 unwind label %unwind2348 + + unwind2348: ; preds = %invcont2352, %invcont2350, %eh_then2344 + %eh_ptr2349 = call i8* @llvm.eh.exception( ) ; [#uses=1] + invoke void @__gnat_end_handler( i8* %eh_exception.216011.1 ) + to label %cleanup2369 unwind label %unwind2334 + + invcont2350: ; preds = %eh_then2344 + %tmp2351 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp2351( ) + to label %invcont2352 unwind label %unwind2348 + + invcont2352: ; preds = %invcont2350 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([24 x i8]* @.str16 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.35.915 to i32) to i64), i64 32)) ) + to label %cleanup2361 unwind label %unwind2348 + + cleanup2361: ; preds = %invcont2352 + invoke void @__gnat_end_handler( i8* %eh_exception.216011.1 ) + to label %cleanup2371 unwind label %unwind2334 + + cleanup2369: ; preds = %unwind2348, %eh_else2340, %unwind2326 + %eh_exception.28 = phi i8* [ %eh_ptr2327, %unwind2326 ], [ %eh_exception.216011.1, %eh_else2340 ], [ %eh_ptr2349, %unwind2348 ] ; [#uses=1] + call void @llvm.stackrestore( i8* %tmp1780 ) + call void @llvm.stackrestore( i8* %tmp1780 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_exception.28 ) ; :9 [#uses=0] + unreachable + + cleanup2371: ; preds = %cleanup2361, %cleanup2332, %cleanup2300 + call void @llvm.stackrestore( i8* %tmp1780 ) + call void @llvm.stackrestore( i8* %tmp1780 ) + invoke void @system__secondary_stack__ss_mark( %struct.system__secondary_stack__mark_id* %tmp55 sret ) + to label %invcont2382 unwind label %unwind2378 + + unwind2378: ; preds = %cleanup2371 + %eh_ptr2379 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select2381 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr2379, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid26496037 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp26516039 = icmp eq i32 %eh_select2381, %eh_typeid26496037 ; [#uses=1] + br i1 %tmp26516039, label %eh_then2652, label %eh_else2666 + + invcont2382: ; preds = %cleanup2371 + %tmp2385 = getelementptr %struct.system__secondary_stack__mark_id* %tmp55, i32 0, i32 0 ; [#uses=1] + %tmp2386 = load i8** %tmp2385 ; [#uses=2] + %tmp2388 = getelementptr %struct.system__secondary_stack__mark_id* %tmp55, i32 0, i32 1 ; [#uses=1] + %tmp2389 = load i32* %tmp2388 ; [#uses=2] + %tmp2390 = call i8* @llvm.stacksave( ) ; [#uses=3] + %tmp2393 = icmp ult i8 %tmp306307, %tmp170171 ; [#uses=1] + br i1 %tmp2393, label %cond_next2417, label %cond_true2396 + + cond_true2396: ; preds = %invcont2382 + %tmp2399 = icmp ult i8 %tmp170171, %tmp204205 ; [#uses=1] + %tmp2403 = icmp ugt i8 %tmp306307, %tmp272273 ; [#uses=1] + %tmp2407 = or i1 %tmp2403, %tmp2399 ; [#uses=1] + br i1 %tmp2407, label %cond_true2410, label %cond_next2417 + + cond_true2410: ; preds = %cond_true2396 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 177 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind2411 + + unwind2411: ; preds = %invcont2591, %invcont2574, %bb2560, %bb2558, %bb2524, %bb2506, %cond_true2410 + %eh_ptr2412 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select2414 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr2412, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=2] + %tmp26315527 = ptrtoint i8* %tmp2386 to i32 ; [#uses=1] + %tmp263155275528 = zext i32 %tmp26315527 to i64 ; [#uses=1] + %tmp26345524 = zext i32 %tmp2389 to i64 ; [#uses=1] + %tmp263455245525 = shl i64 %tmp26345524, 32 ; [#uses=1] + %tmp263455245525.ins = or i64 %tmp263455245525, %tmp263155275528 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp263455245525.ins ) + to label %cleanup2644 unwind label %unwind2618 + + cond_next2417: ; preds = %cond_true2396, %invcont2382 + %tmp2493 = icmp ugt i8 %tmp170171, %tmp238239 ; [#uses=1] + %tmp2500 = icmp ugt i8 %tmp238239, %tmp306307 ; [#uses=1] + %bothcond5903 = or i1 %tmp2500, %tmp2493 ; [#uses=1] + br i1 %bothcond5903, label %bb2506, label %cond_next2515 + + bb2506: ; preds = %cond_next2417 + invoke void @__gnat_rcheck_05( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 180 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind2411 + + cond_next2515: ; preds = %cond_next2417 + br i1 %tmp240, label %bb2524, label %bb2526 + + bb2524: ; preds = %cond_next2515 + invoke void @__gnat_rcheck_06( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 180 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind2411 + + bb2526: ; preds = %cond_next2515 + br i1 %tmp274, label %bb2558, label %bb2560 + + bb2558: ; preds = %bb2526 + invoke void @__gnat_rcheck_06( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 182 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind2411 + + bb2560: ; preds = %bb2526 + invoke void @system__img_enum__image_enumeration_8( %struct.string___XUP* %tmp58 sret , i32 %tmp13831384, i64 or (i64 zext (i32 ptrtoint ([28 x i8]* @weekS.154 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.32.910 to i32) to i64), i64 32)), i8* getelementptr ([8 x i8]* @weekN.179, i32 0, i32 0) ) + to label %invcont2574 unwind label %unwind2411 + + invcont2574: ; preds = %bb2560 + %tmp2576 = getelementptr %struct.string___XUP* %tmp58, i32 0, i32 0 ; [#uses=1] + %tmp2577 = load i8** %tmp2576 ; [#uses=1] + %tmp25775747 = ptrtoint i8* %tmp2577 to i32 ; [#uses=1] + %tmp257757475748 = zext i32 %tmp25775747 to i64 ; [#uses=1] + %tmp2579 = getelementptr %struct.string___XUP* %tmp58, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp2580 = load %struct.string___XUB** %tmp2579 ; <%struct.string___XUB*> [#uses=1] + %tmp25805743 = ptrtoint %struct.string___XUB* %tmp2580 to i32 ; [#uses=1] + %tmp258057435744 = zext i32 %tmp25805743 to i64 ; [#uses=1] + %tmp2580574357445745 = shl i64 %tmp258057435744, 32 ; [#uses=1] + %tmp2580574357445745.ins = or i64 %tmp2580574357445745, %tmp257757475748 ; [#uses=1] + invoke void @system__string_ops__str_concat( %struct.string___XUP* %tmp61 sret , i64 or (i64 zext (i32 ptrtoint ([30 x i8]* @.str17 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.30.904 to i32) to i64), i64 32)), i64 %tmp2580574357445745.ins ) + to label %invcont2591 unwind label %unwind2411 + + invcont2591: ; preds = %invcont2574 + %tmp2593 = getelementptr %struct.string___XUP* %tmp61, i32 0, i32 0 ; [#uses=1] + %tmp2594 = load i8** %tmp2593 ; [#uses=1] + %tmp25945735 = ptrtoint i8* %tmp2594 to i32 ; [#uses=1] + %tmp259457355736 = zext i32 %tmp25945735 to i64 ; [#uses=1] + %tmp2596 = getelementptr %struct.string___XUP* %tmp61, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp2597 = load %struct.string___XUB** %tmp2596 ; <%struct.string___XUB*> [#uses=1] + %tmp25975731 = ptrtoint %struct.string___XUB* %tmp2597 to i32 ; [#uses=1] + %tmp259757315732 = zext i32 %tmp25975731 to i64 ; [#uses=1] + %tmp2597573157325733 = shl i64 %tmp259757315732, 32 ; [#uses=1] + %tmp2597573157325733.ins = or i64 %tmp2597573157325733, %tmp259457355736 ; [#uses=1] + invoke void @report__failed( i64 %tmp2597573157325733.ins ) + to label %cleanup2604 unwind label %unwind2411 + + cleanup2604: ; preds = %invcont2591 + %tmp26105533 = ptrtoint i8* %tmp2386 to i32 ; [#uses=1] + %tmp261055335534 = zext i32 %tmp26105533 to i64 ; [#uses=1] + %tmp26135530 = zext i32 %tmp2389 to i64 ; [#uses=1] + %tmp261355305531 = shl i64 %tmp26135530, 32 ; [#uses=1] + %tmp261355305531.ins = or i64 %tmp261355305531, %tmp261055335534 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp261355305531.ins ) + to label %cleanup2642 unwind label %unwind2618 + + unwind2618: ; preds = %cleanup2604, %unwind2411 + %eh_ptr2619 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select2621 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr2619, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=2] + call void @llvm.stackrestore( i8* %tmp2390 ) + %eh_typeid26493 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp26514 = icmp eq i32 %eh_select2621, %eh_typeid26493 ; [#uses=1] + br i1 %tmp26514, label %eh_then2652, label %eh_else2666 + + cleanup2642: ; preds = %cleanup2604 + call void @llvm.stackrestore( i8* %tmp2390 ) + %tmp26946042 = icmp ult i8 %tmp238239, %tmp137138 ; [#uses=1] + br i1 %tmp26946042, label %cond_next2718, label %cond_true2697 + + cleanup2644: ; preds = %unwind2411 + call void @llvm.stackrestore( i8* %tmp2390 ) + %eh_typeid2649 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp2651 = icmp eq i32 %eh_select2414, %eh_typeid2649 ; [#uses=1] + br i1 %tmp2651, label %eh_then2652, label %eh_else2666 + + eh_then2652: ; preds = %cleanup2644, %unwind2618, %unwind2378 + %eh_exception.296030.0 = phi i8* [ %eh_ptr2379, %unwind2378 ], [ %eh_ptr2619, %unwind2618 ], [ %eh_ptr2412, %cleanup2644 ] ; [#uses=3] + invoke void @__gnat_begin_handler( i8* %eh_exception.296030.0 ) + to label %invcont2658 unwind label %unwind2656 + + unwind2656: ; preds = %invcont2658, %eh_then2652 + %eh_ptr2657 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_exception.296030.0 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr2657 ) ; :10 [#uses=0] + unreachable + + invcont2658: ; preds = %eh_then2652 + %tmp2659 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp2659( ) + to label %cleanup2662 unwind label %unwind2656 + + cleanup2662: ; preds = %invcont2658 + call void @__gnat_end_handler( i8* %eh_exception.296030.0 ) + %tmp26946043 = icmp ult i8 %tmp238239, %tmp137138 ; [#uses=1] + br i1 %tmp26946043, label %cond_next2718, label %cond_true2697 + + eh_else2666: ; preds = %cleanup2644, %unwind2618, %unwind2378 + %eh_selector.256028.1 = phi i32 [ %eh_select2381, %unwind2378 ], [ %eh_select2621, %unwind2618 ], [ %eh_select2414, %cleanup2644 ] ; [#uses=1] + %eh_exception.296030.1 = phi i8* [ %eh_ptr2379, %unwind2378 ], [ %eh_ptr2619, %unwind2618 ], [ %eh_ptr2412, %cleanup2644 ] ; [#uses=4] + %eh_typeid2667 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp2669 = icmp eq i32 %eh_selector.256028.1, %eh_typeid2667 ; [#uses=1] + br i1 %tmp2669, label %eh_then2670, label %Unwind + + eh_then2670: ; preds = %eh_else2666 + invoke void @__gnat_begin_handler( i8* %eh_exception.296030.1 ) + to label %invcont2676 unwind label %unwind2674 + + unwind2674: ; preds = %invcont2678, %invcont2676, %eh_then2670 + %eh_ptr2675 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_exception.296030.1 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr2675 ) ; :11 [#uses=0] + unreachable + + invcont2676: ; preds = %eh_then2670 + %tmp2677 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp2677( ) + to label %invcont2678 unwind label %unwind2674 + + invcont2678: ; preds = %invcont2676 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([24 x i8]* @.str18 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.35.915 to i32) to i64), i64 32)) ) + to label %cleanup2687 unwind label %unwind2674 + + cleanup2687: ; preds = %invcont2678 + call void @__gnat_end_handler( i8* %eh_exception.296030.1 ) + %tmp2694 = icmp ult i8 %tmp238239, %tmp137138 ; [#uses=1] + br i1 %tmp2694, label %cond_next2718, label %cond_true2697 + + cond_true2697: ; preds = %cleanup2687, %cleanup2662, %cleanup2642 + %tmp2700 = icmp ult i8 %tmp137138, %tmp204205 ; [#uses=1] + %tmp2704 = icmp ugt i8 %tmp238239, %tmp272273 ; [#uses=1] + %tmp2708 = or i1 %tmp2704, %tmp2700 ; [#uses=1] + br i1 %tmp2708, label %cond_true2711, label %cond_next2718 + + cond_true2711: ; preds = %cond_true2697 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 192 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind2712 + + unwind2712: ; preds = %cleanup2990, %unwind2975, %cond_true2711 + %eh_ptr2713 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select2715 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr2713, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid29996053 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp30016055 = icmp eq i32 %eh_select2715, %eh_typeid29996053 ; [#uses=1] + br i1 %tmp30016055, label %eh_then3002, label %eh_else3016 + + cond_next2718: ; preds = %cond_true2697, %cleanup2687, %cleanup2662, %cleanup2642 + invoke void @system__secondary_stack__ss_mark( %struct.system__secondary_stack__mark_id* %tmp63 sret ) + to label %invcont2766 unwind label %unwind2762 + + unwind2762: ; preds = %cond_next2718 + %eh_ptr2763 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select2765 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr2763, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid29686060 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp29706061 = icmp eq i32 %eh_select2765, %eh_typeid29686060 ; [#uses=1] + br i1 %tmp29706061, label %eh_then2971, label %cleanup2998 + + invcont2766: ; preds = %cond_next2718 + %tmp2769 = getelementptr %struct.system__secondary_stack__mark_id* %tmp63, i32 0, i32 0 ; [#uses=1] + %tmp2770 = load i8** %tmp2769 ; [#uses=2] + %tmp2772 = getelementptr %struct.system__secondary_stack__mark_id* %tmp63, i32 0, i32 1 ; [#uses=1] + %tmp2773 = load i32* %tmp2772 ; [#uses=2] + %tmp2774 = call i8* @llvm.stacksave( ) ; [#uses=3] + %tmp2808 = icmp ugt i8 %tmp137138, %tmp204205 ; [#uses=1] + %tmp2815 = icmp ult i8 %tmp238239, %tmp204205 ; [#uses=1] + %bothcond5904 = or i1 %tmp2815, %tmp2808 ; [#uses=1] + br i1 %bothcond5904, label %bb2821, label %cond_next2834 + + bb2821: ; preds = %invcont2766 + invoke void @__gnat_rcheck_05( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 198 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind2822 + + unwind2822: ; preds = %invcont2910, %invcont2893, %bb2879, %bb2877, %bb2843, %bb2821 + %eh_ptr2823 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select2825 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr2823, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=2] + %tmp29295521 = ptrtoint i8* %tmp2770 to i32 ; [#uses=1] + %tmp292955215522 = zext i32 %tmp29295521 to i64 ; [#uses=1] + %tmp29325518 = zext i32 %tmp2773 to i64 ; [#uses=1] + %tmp293255185519 = shl i64 %tmp29325518, 32 ; [#uses=1] + %tmp293255185519.ins = or i64 %tmp293255185519, %tmp292955215522 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp293255185519.ins ) + to label %cleanup2963 unwind label %unwind2937 + + cond_next2834: ; preds = %invcont2766 + br i1 %tmp206, label %bb2843, label %bb2845 + + bb2843: ; preds = %cond_next2834 + invoke void @__gnat_rcheck_06( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 198 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind2822 + + bb2845: ; preds = %cond_next2834 + br i1 %tmp274, label %bb2877, label %bb2879 + + bb2877: ; preds = %bb2845 + invoke void @__gnat_rcheck_06( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 200 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind2822 + + bb2879: ; preds = %bb2845 + invoke void @system__img_enum__image_enumeration_8( %struct.string___XUP* %tmp66 sret , i32 %tmp13831384, i64 or (i64 zext (i32 ptrtoint ([28 x i8]* @weekS.154 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.32.910 to i32) to i64), i64 32)), i8* getelementptr ([8 x i8]* @weekN.179, i32 0, i32 0) ) + to label %invcont2893 unwind label %unwind2822 + + invcont2893: ; preds = %bb2879 + %tmp2895 = getelementptr %struct.string___XUP* %tmp66, i32 0, i32 0 ; [#uses=1] + %tmp2896 = load i8** %tmp2895 ; [#uses=1] + %tmp28965718 = ptrtoint i8* %tmp2896 to i32 ; [#uses=1] + %tmp289657185719 = zext i32 %tmp28965718 to i64 ; [#uses=1] + %tmp2898 = getelementptr %struct.string___XUP* %tmp66, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp2899 = load %struct.string___XUB** %tmp2898 ; <%struct.string___XUB*> [#uses=1] + %tmp28995714 = ptrtoint %struct.string___XUB* %tmp2899 to i32 ; [#uses=1] + %tmp289957145715 = zext i32 %tmp28995714 to i64 ; [#uses=1] + %tmp2899571457155716 = shl i64 %tmp289957145715, 32 ; [#uses=1] + %tmp2899571457155716.ins = or i64 %tmp2899571457155716, %tmp289657185719 ; [#uses=1] + invoke void @system__string_ops__str_concat( %struct.string___XUP* %tmp69 sret , i64 or (i64 zext (i32 ptrtoint ([31 x i8]* @.str19 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.98.1466 to i32) to i64), i64 32)), i64 %tmp2899571457155716.ins ) + to label %invcont2910 unwind label %unwind2822 + + invcont2910: ; preds = %invcont2893 + %tmp2912 = getelementptr %struct.string___XUP* %tmp69, i32 0, i32 0 ; [#uses=1] + %tmp2913 = load i8** %tmp2912 ; [#uses=1] + %tmp29135706 = ptrtoint i8* %tmp2913 to i32 ; [#uses=1] + %tmp291357065707 = zext i32 %tmp29135706 to i64 ; [#uses=1] + %tmp2915 = getelementptr %struct.string___XUP* %tmp69, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp2916 = load %struct.string___XUB** %tmp2915 ; <%struct.string___XUB*> [#uses=1] + %tmp29165702 = ptrtoint %struct.string___XUB* %tmp2916 to i32 ; [#uses=1] + %tmp291657025703 = zext i32 %tmp29165702 to i64 ; [#uses=1] + %tmp2916570257035704 = shl i64 %tmp291657025703, 32 ; [#uses=1] + %tmp2916570257035704.ins = or i64 %tmp2916570257035704, %tmp291357065707 ; [#uses=1] + invoke void @report__failed( i64 %tmp2916570257035704.ins ) + to label %cleanup2943 unwind label %unwind2822 + + unwind2937: ; preds = %cleanup2943, %unwind2822 + %eh_ptr2938 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select2940 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr2938, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=2] + call void @llvm.stackrestore( i8* %tmp2774 ) + %eh_typeid29685 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp29706 = icmp eq i32 %eh_select2940, %eh_typeid29685 ; [#uses=1] + br i1 %tmp29706, label %eh_then2971, label %cleanup2998 + + cleanup2943: ; preds = %invcont2910 + %tmp29505515 = ptrtoint i8* %tmp2770 to i32 ; [#uses=1] + %tmp295055155516 = zext i32 %tmp29505515 to i64 ; [#uses=1] + %tmp29535512 = zext i32 %tmp2773 to i64 ; [#uses=1] + %tmp295355125513 = shl i64 %tmp29535512, 32 ; [#uses=1] + %tmp295355125513.ins = or i64 %tmp295355125513, %tmp295055155516 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp295355125513.ins ) + to label %cleanup2961 unwind label %unwind2937 + + cleanup2961: ; preds = %cleanup2943 + call void @llvm.stackrestore( i8* %tmp2774 ) + %tmp3044.not6066 = icmp uge i8 %tmp272273, %tmp170171 ; [#uses=1] + %tmp30506067 = icmp ult i8 %tmp170171, %tmp204205 ; [#uses=1] + %bothcond59056068 = and i1 %tmp3044.not6066, %tmp30506067 ; [#uses=1] + br i1 %bothcond59056068, label %cond_true3061, label %cond_next3068 + + cleanup2963: ; preds = %unwind2822 + call void @llvm.stackrestore( i8* %tmp2774 ) + %eh_typeid2968 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp2970 = icmp eq i32 %eh_select2825, %eh_typeid2968 ; [#uses=1] + br i1 %tmp2970, label %eh_then2971, label %cleanup2998 + + eh_then2971: ; preds = %cleanup2963, %unwind2937, %unwind2762 + %eh_exception.356056.0 = phi i8* [ %eh_ptr2763, %unwind2762 ], [ %eh_ptr2938, %unwind2937 ], [ %eh_ptr2823, %cleanup2963 ] ; [#uses=3] + invoke void @__gnat_begin_handler( i8* %eh_exception.356056.0 ) + to label %invcont2979 unwind label %unwind2975 + + unwind2975: ; preds = %invcont2981, %invcont2979, %eh_then2971 + %eh_ptr2976 = call i8* @llvm.eh.exception( ) ; [#uses=2] + %eh_select2978 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr2976, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=1] + invoke void @__gnat_end_handler( i8* %eh_exception.356056.0 ) + to label %cleanup2998 unwind label %unwind2712 + + invcont2979: ; preds = %eh_then2971 + %tmp2980 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp2980( ) + to label %invcont2981 unwind label %unwind2975 + + invcont2981: ; preds = %invcont2979 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([46 x i8]* @.str20 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.101.1473 to i32) to i64), i64 32)) ) + to label %cleanup2990 unwind label %unwind2975 + + cleanup2990: ; preds = %invcont2981 + invoke void @__gnat_end_handler( i8* %eh_exception.356056.0 ) + to label %finally2997 unwind label %unwind2712 + + cleanup2998: ; preds = %unwind2975, %cleanup2963, %unwind2937, %unwind2762 + %eh_selector.29 = phi i32 [ %eh_select2765, %unwind2762 ], [ %eh_select2940, %unwind2937 ], [ %eh_select2825, %cleanup2963 ], [ %eh_select2978, %unwind2975 ] ; [#uses=2] + %eh_exception.33 = phi i8* [ %eh_ptr2763, %unwind2762 ], [ %eh_ptr2938, %unwind2937 ], [ %eh_ptr2823, %cleanup2963 ], [ %eh_ptr2976, %unwind2975 ] ; [#uses=2] + %eh_typeid2999 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp3001 = icmp eq i32 %eh_selector.29, %eh_typeid2999 ; [#uses=1] + br i1 %tmp3001, label %eh_then3002, label %eh_else3016 + + eh_then3002: ; preds = %cleanup2998, %unwind2712 + %eh_exception.336046.0 = phi i8* [ %eh_ptr2713, %unwind2712 ], [ %eh_exception.33, %cleanup2998 ] ; [#uses=3] + invoke void @__gnat_begin_handler( i8* %eh_exception.336046.0 ) + to label %invcont3008 unwind label %unwind3006 + + unwind3006: ; preds = %invcont3008, %eh_then3002 + %eh_ptr3007 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_exception.336046.0 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr3007 ) ; :12 [#uses=0] + unreachable + + invcont3008: ; preds = %eh_then3002 + %tmp3009 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp3009( ) + to label %cleanup3012 unwind label %unwind3006 + + cleanup3012: ; preds = %invcont3008 + call void @__gnat_end_handler( i8* %eh_exception.336046.0 ) + %tmp3044.not6069 = icmp uge i8 %tmp272273, %tmp170171 ; [#uses=1] + %tmp30506070 = icmp ult i8 %tmp170171, %tmp204205 ; [#uses=1] + %bothcond59056071 = and i1 %tmp3044.not6069, %tmp30506070 ; [#uses=1] + br i1 %bothcond59056071, label %cond_true3061, label %cond_next3068 + + eh_else3016: ; preds = %cleanup2998, %unwind2712 + %eh_selector.296044.1 = phi i32 [ %eh_select2715, %unwind2712 ], [ %eh_selector.29, %cleanup2998 ] ; [#uses=1] + %eh_exception.336046.1 = phi i8* [ %eh_ptr2713, %unwind2712 ], [ %eh_exception.33, %cleanup2998 ] ; [#uses=4] + %eh_typeid3017 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp3019 = icmp eq i32 %eh_selector.296044.1, %eh_typeid3017 ; [#uses=1] + br i1 %tmp3019, label %eh_then3020, label %Unwind + + eh_then3020: ; preds = %eh_else3016 + invoke void @__gnat_begin_handler( i8* %eh_exception.336046.1 ) + to label %invcont3026 unwind label %unwind3024 + + unwind3024: ; preds = %invcont3028, %invcont3026, %eh_then3020 + %eh_ptr3025 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_exception.336046.1 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr3025 ) ; :13 [#uses=0] + unreachable + + invcont3026: ; preds = %eh_then3020 + %tmp3027 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp3027( ) + to label %invcont3028 unwind label %unwind3024 + + invcont3028: ; preds = %invcont3026 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([25 x i8]* @.str21 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.104.1478 to i32) to i64), i64 32)) ) + to label %cleanup3037 unwind label %unwind3024 + + cleanup3037: ; preds = %invcont3028 + call void @__gnat_end_handler( i8* %eh_exception.336046.1 ) + br label %finally2997 + + finally2997: ; preds = %cleanup3037, %cleanup2990 + %tmp3044.not = icmp uge i8 %tmp272273, %tmp170171 ; [#uses=1] + %tmp3050 = icmp ult i8 %tmp170171, %tmp204205 ; [#uses=1] + %bothcond5905 = and i1 %tmp3044.not, %tmp3050 ; [#uses=1] + br i1 %bothcond5905, label %cond_true3061, label %cond_next3068 + + cond_true3061: ; preds = %finally2997, %cleanup3012, %cleanup2961 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 214 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3062 + + unwind3062: ; preds = %cleanup3340, %unwind3325, %cond_true3061 + %eh_ptr3063 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select3065 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr3063, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid33496081 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp33516083 = icmp eq i32 %eh_select3065, %eh_typeid33496081 ; [#uses=1] + br i1 %tmp33516083, label %eh_then3352, label %eh_else3366 + + cond_next3068: ; preds = %finally2997, %cleanup3012, %cleanup2961 + invoke void @system__secondary_stack__ss_mark( %struct.system__secondary_stack__mark_id* %tmp72 sret ) + to label %invcont3116 unwind label %unwind3112 + + unwind3112: ; preds = %cond_next3068 + %eh_ptr3113 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select3115 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr3113, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=2] + %eh_typeid33186088 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp33206089 = icmp eq i32 %eh_select3115, %eh_typeid33186088 ; [#uses=1] + br i1 %tmp33206089, label %eh_then3321, label %cleanup3348 + + invcont3116: ; preds = %cond_next3068 + %tmp3119 = getelementptr %struct.system__secondary_stack__mark_id* %tmp72, i32 0, i32 0 ; [#uses=1] + %tmp3120 = load i8** %tmp3119 ; [#uses=2] + %tmp3122 = getelementptr %struct.system__secondary_stack__mark_id* %tmp72, i32 0, i32 1 ; [#uses=1] + %tmp3123 = load i32* %tmp3122 ; [#uses=2] + %tmp3124 = call i8* @llvm.stacksave( ) ; [#uses=3] + %tmp3158 = icmp ugt i8 %tmp170171, %tmp204205 ; [#uses=1] + %bothcond5906 = or i1 %tmp364, %tmp3158 ; [#uses=1] + br i1 %bothcond5906, label %bb3171, label %cond_next3184 + + bb3171: ; preds = %invcont3116 + invoke void @__gnat_rcheck_05( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 220 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3172 + + unwind3172: ; preds = %invcont3260, %invcont3243, %bb3229, %bb3227, %bb3193, %bb3171 + %eh_ptr3173 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select3175 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr3173, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=2] + %tmp32795509 = ptrtoint i8* %tmp3120 to i32 ; [#uses=1] + %tmp327955095510 = zext i32 %tmp32795509 to i64 ; [#uses=1] + %tmp32825506 = zext i32 %tmp3123 to i64 ; [#uses=1] + %tmp328255065507 = shl i64 %tmp32825506, 32 ; [#uses=1] + %tmp328255065507.ins = or i64 %tmp328255065507, %tmp327955095510 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp328255065507.ins ) + to label %cleanup3313 unwind label %unwind3287 + + cond_next3184: ; preds = %invcont3116 + br i1 %tmp206, label %bb3193, label %bb3195 + + bb3193: ; preds = %cond_next3184 + invoke void @__gnat_rcheck_06( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 220 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3172 + + bb3195: ; preds = %cond_next3184 + br i1 %tmp274, label %bb3227, label %bb3229 + + bb3227: ; preds = %bb3195 + invoke void @__gnat_rcheck_06( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 222 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3172 + + bb3229: ; preds = %bb3195 + invoke void @system__img_enum__image_enumeration_8( %struct.string___XUP* %tmp75 sret , i32 %tmp13831384, i64 or (i64 zext (i32 ptrtoint ([28 x i8]* @weekS.154 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.32.910 to i32) to i64), i64 32)), i8* getelementptr ([8 x i8]* @weekN.179, i32 0, i32 0) ) + to label %invcont3243 unwind label %unwind3172 + + invcont3243: ; preds = %bb3229 + %tmp3245 = getelementptr %struct.string___XUP* %tmp75, i32 0, i32 0 ; [#uses=1] + %tmp3246 = load i8** %tmp3245 ; [#uses=1] + %tmp32465684 = ptrtoint i8* %tmp3246 to i32 ; [#uses=1] + %tmp324656845685 = zext i32 %tmp32465684 to i64 ; [#uses=1] + %tmp3248 = getelementptr %struct.string___XUP* %tmp75, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp3249 = load %struct.string___XUB** %tmp3248 ; <%struct.string___XUB*> [#uses=1] + %tmp32495680 = ptrtoint %struct.string___XUB* %tmp3249 to i32 ; [#uses=1] + %tmp324956805681 = zext i32 %tmp32495680 to i64 ; [#uses=1] + %tmp3249568056815682 = shl i64 %tmp324956805681, 32 ; [#uses=1] + %tmp3249568056815682.ins = or i64 %tmp3249568056815682, %tmp324656845685 ; [#uses=1] + invoke void @system__string_ops__str_concat( %struct.string___XUP* %tmp78 sret , i64 or (i64 zext (i32 ptrtoint ([31 x i8]* @.str22 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.98.1466 to i32) to i64), i64 32)), i64 %tmp3249568056815682.ins ) + to label %invcont3260 unwind label %unwind3172 + + invcont3260: ; preds = %invcont3243 + %tmp3262 = getelementptr %struct.string___XUP* %tmp78, i32 0, i32 0 ; [#uses=1] + %tmp3263 = load i8** %tmp3262 ; [#uses=1] + %tmp32635672 = ptrtoint i8* %tmp3263 to i32 ; [#uses=1] + %tmp326356725673 = zext i32 %tmp32635672 to i64 ; [#uses=1] + %tmp3265 = getelementptr %struct.string___XUP* %tmp78, i32 0, i32 1 ; <%struct.string___XUB**> [#uses=1] + %tmp3266 = load %struct.string___XUB** %tmp3265 ; <%struct.string___XUB*> [#uses=1] + %tmp32665668 = ptrtoint %struct.string___XUB* %tmp3266 to i32 ; [#uses=1] + %tmp326656685669 = zext i32 %tmp32665668 to i64 ; [#uses=1] + %tmp3266566856695670 = shl i64 %tmp326656685669, 32 ; [#uses=1] + %tmp3266566856695670.ins = or i64 %tmp3266566856695670, %tmp326356725673 ; [#uses=1] + invoke void @report__failed( i64 %tmp3266566856695670.ins ) + to label %cleanup3293 unwind label %unwind3172 + + unwind3287: ; preds = %cleanup3293, %unwind3172 + %eh_ptr3288 = call i8* @llvm.eh.exception( ) ; [#uses=3] + %eh_select3290 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr3288, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=2] + call void @llvm.stackrestore( i8* %tmp3124 ) + %eh_typeid33187 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp33208 = icmp eq i32 %eh_select3290, %eh_typeid33187 ; [#uses=1] + br i1 %tmp33208, label %eh_then3321, label %cleanup3348 + + cleanup3293: ; preds = %invcont3260 + %tmp33005503 = ptrtoint i8* %tmp3120 to i32 ; [#uses=1] + %tmp330055035504 = zext i32 %tmp33005503 to i64 ; [#uses=1] + %tmp33035500 = zext i32 %tmp3123 to i64 ; [#uses=1] + %tmp330355005501 = shl i64 %tmp33035500, 32 ; [#uses=1] + %tmp330355005501.ins = or i64 %tmp330355005501, %tmp330055035504 ; [#uses=1] + invoke void @system__secondary_stack__ss_release( i64 %tmp330355005501.ins ) + to label %cleanup3311 unwind label %unwind3287 + + cleanup3311: ; preds = %cleanup3293 + call void @llvm.stackrestore( i8* %tmp3124 ) + br label %finally3347 + + cleanup3313: ; preds = %unwind3172 + call void @llvm.stackrestore( i8* %tmp3124 ) + %eh_typeid3318 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp3320 = icmp eq i32 %eh_select3175, %eh_typeid3318 ; [#uses=1] + br i1 %tmp3320, label %eh_then3321, label %cleanup3348 + + eh_then3321: ; preds = %cleanup3313, %unwind3287, %unwind3112 + %eh_exception.416084.0 = phi i8* [ %eh_ptr3113, %unwind3112 ], [ %eh_ptr3288, %unwind3287 ], [ %eh_ptr3173, %cleanup3313 ] ; [#uses=3] + invoke void @__gnat_begin_handler( i8* %eh_exception.416084.0 ) + to label %invcont3329 unwind label %unwind3325 + + unwind3325: ; preds = %invcont3331, %invcont3329, %eh_then3321 + %eh_ptr3326 = call i8* @llvm.eh.exception( ) ; [#uses=2] + %eh_select3328 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr3326, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), %struct.exception* @constraint_error, i32* @__gnat_others_value ) ; [#uses=1] + invoke void @__gnat_end_handler( i8* %eh_exception.416084.0 ) + to label %cleanup3348 unwind label %unwind3062 + + invcont3329: ; preds = %eh_then3321 + %tmp3330 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp3330( ) + to label %invcont3331 unwind label %unwind3325 + + invcont3331: ; preds = %invcont3329 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([46 x i8]* @.str20 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.101.1473 to i32) to i64), i64 32)) ) + to label %cleanup3340 unwind label %unwind3325 + + cleanup3340: ; preds = %invcont3331 + invoke void @__gnat_end_handler( i8* %eh_exception.416084.0 ) + to label %finally3347 unwind label %unwind3062 + + cleanup3348: ; preds = %unwind3325, %cleanup3313, %unwind3287, %unwind3112 + %eh_selector.35 = phi i32 [ %eh_select3115, %unwind3112 ], [ %eh_select3290, %unwind3287 ], [ %eh_select3175, %cleanup3313 ], [ %eh_select3328, %unwind3325 ] ; [#uses=2] + %eh_exception.39 = phi i8* [ %eh_ptr3113, %unwind3112 ], [ %eh_ptr3288, %unwind3287 ], [ %eh_ptr3173, %cleanup3313 ], [ %eh_ptr3326, %unwind3325 ] ; [#uses=2] + %eh_typeid3349 = call i32 @llvm.eh.typeid.for( i8* getelementptr (%struct.exception* @constraint_error, i32 0, i32 0) ) ; [#uses=1] + %tmp3351 = icmp eq i32 %eh_selector.35, %eh_typeid3349 ; [#uses=1] + br i1 %tmp3351, label %eh_then3352, label %eh_else3366 + + eh_then3352: ; preds = %cleanup3348, %unwind3062 + %eh_exception.396074.0 = phi i8* [ %eh_ptr3063, %unwind3062 ], [ %eh_exception.39, %cleanup3348 ] ; [#uses=3] + invoke void @__gnat_begin_handler( i8* %eh_exception.396074.0 ) + to label %invcont3358 unwind label %unwind3356 + + unwind3356: ; preds = %invcont3358, %eh_then3352 + %eh_ptr3357 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_exception.396074.0 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr3357 ) ; :14 [#uses=0] + unreachable + + invcont3358: ; preds = %eh_then3352 + %tmp3359 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp3359( ) + to label %cleanup3362 unwind label %unwind3356 + + cleanup3362: ; preds = %invcont3358 + call void @__gnat_end_handler( i8* %eh_exception.396074.0 ) + br label %finally3347 + + eh_else3366: ; preds = %cleanup3348, %unwind3062 + %eh_selector.356072.1 = phi i32 [ %eh_select3065, %unwind3062 ], [ %eh_selector.35, %cleanup3348 ] ; [#uses=1] + %eh_exception.396074.1 = phi i8* [ %eh_ptr3063, %unwind3062 ], [ %eh_exception.39, %cleanup3348 ] ; [#uses=4] + %eh_typeid3367 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp3369 = icmp eq i32 %eh_selector.356072.1, %eh_typeid3367 ; [#uses=1] + br i1 %tmp3369, label %eh_then3370, label %Unwind + + eh_then3370: ; preds = %eh_else3366 + invoke void @__gnat_begin_handler( i8* %eh_exception.396074.1 ) + to label %invcont3376 unwind label %unwind3374 + + unwind3374: ; preds = %invcont3378, %invcont3376, %eh_then3370 + %eh_ptr3375 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_exception.396074.1 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr3375 ) ; :15 [#uses=0] + unreachable + + invcont3376: ; preds = %eh_then3370 + %tmp3377 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp3377( ) + to label %invcont3378 unwind label %unwind3374 + + invcont3378: ; preds = %invcont3376 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([25 x i8]* @.str23 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.104.1478 to i32) to i64), i64 32)) ) + to label %cleanup3387 unwind label %unwind3374 + + cleanup3387: ; preds = %invcont3378 + call void @__gnat_end_handler( i8* %eh_exception.396074.1 ) + br label %finally3347 + + finally3347: ; preds = %cleanup3387, %cleanup3362, %cleanup3340, %cleanup3311 + %tmp3392 = call i8* @llvm.stacksave( ) ; [#uses=2] + %tmp3398 = invoke i32 @report__ident_int( i32 -5 ) + to label %invcont3397 unwind label %unwind3393 ; [#uses=4] + + unwind3393: ; preds = %cond_true3555, %cond_true3543, %cond_next3451, %cond_true3448, %cond_true3420, %finally3347 + %eh_ptr3394 = call i8* @llvm.eh.exception( ) ; [#uses=5] + %eh_select3396 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr3394, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=1] + call void @llvm.stackrestore( i8* %tmp3392 ) + %eh_typeid3571 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp3573 = icmp eq i32 %eh_select3396, %eh_typeid3571 ; [#uses=1] + br i1 %tmp3573, label %eh_then3574, label %Unwind + + invcont3397: ; preds = %finally3347 + %tmp3405 = icmp slt i32 %tmp3398, %tmp384 ; [#uses=2] + %tmp3413 = icmp sgt i32 %tmp3398, %tmp394 ; [#uses=1] + %tmp3417 = or i1 %tmp3405, %tmp3413 ; [#uses=1] + br i1 %tmp3417, label %cond_true3420, label %cond_next3422 + + cond_true3420: ; preds = %invcont3397 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 238 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3393 + + cond_next3422: ; preds = %invcont3397 + %tmp3426 = icmp slt i32 %tmp3398, -5 ; [#uses=1] + br i1 %tmp3426, label %cond_true3429, label %cond_next3451 + + cond_true3429: ; preds = %cond_next3422 + %tmp3441 = icmp slt i32 %tmp394, -6 ; [#uses=1] + %tmp3445 = or i1 %tmp3405, %tmp3441 ; [#uses=1] + br i1 %tmp3445, label %cond_true3448, label %cond_next3451 + + cond_true3448: ; preds = %cond_true3429 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 238 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3393 + + cond_next3451: ; preds = %cond_true3429, %cond_next3422 + %tmp3521 = invoke i32 @report__ident_int( i32 -5 ) + to label %invcont3520 unwind label %unwind3393 ; [#uses=3] + + invcont3520: ; preds = %cond_next3451 + %tmp3528 = icmp slt i32 %tmp3521, %tmp384 ; [#uses=1] + %tmp3536 = icmp sgt i32 %tmp3521, %tmp394 ; [#uses=1] + %tmp3540 = or i1 %tmp3528, %tmp3536 ; [#uses=1] + br i1 %tmp3540, label %cond_true3543, label %cond_next3545 + + cond_true3543: ; preds = %invcont3520 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 241 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3393 + + cond_next3545: ; preds = %invcont3520 + %tmp3552 = icmp eq i32 %tmp3398, %tmp3521 ; [#uses=1] + br i1 %tmp3552, label %cleanup3565, label %cond_true3555 + + cond_true3555: ; preds = %cond_next3545 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([30 x i8]* @.str24 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.30.904 to i32) to i64), i64 32)) ) + to label %cleanup3565 unwind label %unwind3393 + + cleanup3565: ; preds = %cond_true3555, %cond_next3545 + call void @llvm.stackrestore( i8* %tmp3392 ) + %tmp36006095 = icmp ult i8 %tmp137138, %sat.45934.0 ; [#uses=1] + br i1 %tmp36006095, label %cond_next3624, label %cond_true3603 + + eh_then3574: ; preds = %unwind3393 + invoke void @__gnat_begin_handler( i8* %eh_ptr3394 ) + to label %invcont3580 unwind label %unwind3578 + + unwind3578: ; preds = %invcont3582, %invcont3580, %eh_then3574 + %eh_ptr3579 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_ptr3394 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr3579 ) ; :16 [#uses=0] + unreachable + + invcont3580: ; preds = %eh_then3574 + %tmp3581 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp3581( ) + to label %invcont3582 unwind label %unwind3578 + + invcont3582: ; preds = %invcont3580 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([18 x i8]* @.str25 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.124.1606 to i32) to i64), i64 32)) ) + to label %cleanup3591 unwind label %unwind3578 + + cleanup3591: ; preds = %invcont3582 + call void @__gnat_end_handler( i8* %eh_ptr3394 ) + %tmp3600 = icmp ult i8 %tmp137138, %sat.45934.0 ; [#uses=1] + br i1 %tmp3600, label %cond_next3624, label %cond_true3603 + + cond_true3603: ; preds = %cleanup3591, %cleanup3565 + %tmp3606 = icmp ult i8 %sat.45934.0, %tmp204205 ; [#uses=1] + %tmp3610 = icmp ugt i8 %tmp137138, %tmp272273 ; [#uses=1] + %tmp3614 = or i1 %tmp3606, %tmp3610 ; [#uses=1] + br i1 %tmp3614, label %cond_true3617, label %cond_next3624 + + cond_true3617: ; preds = %cond_true3603 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 250 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3618 + + unwind3618: ; preds = %bb3743, %cond_true3729, %bb3689, %cond_true3675, %bb3635, %cond_true3617 + %wed.3 = phi i8 [ %tmp238239, %cond_true3617 ], [ %wed.1, %bb3743 ], [ %tmp238239, %bb3689 ], [ %tmp238239, %bb3635 ], [ %tmp238239, %cond_true3675 ], [ %tmp238239, %cond_true3729 ] ; [#uses=1] + %tue.3 = phi i8 [ %tmp204205, %cond_true3617 ], [ %tue.2, %bb3743 ], [ %tue.2, %bb3689 ], [ %tue.1, %bb3635 ], [ %tue.2, %cond_true3675 ], [ %tue.2, %cond_true3729 ] ; [#uses=1] + %mon.3 = phi i8 [ %tmp170171, %cond_true3617 ], [ %mon.2, %bb3743 ], [ %mon.1, %bb3689 ], [ %tmp170171, %bb3635 ], [ %tmp170171, %cond_true3675 ], [ %mon.2, %cond_true3729 ] ; [#uses=1] + %eh_ptr3619 = call i8* @llvm.eh.exception( ) ; [#uses=5] + %eh_select3621 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr3619, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=1] + %eh_typeid3854 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp3856 = icmp eq i32 %eh_select3621, %eh_typeid3854 ; [#uses=1] + br i1 %tmp3856, label %eh_then3857, label %Unwind + + cond_next3624: ; preds = %cond_true3603, %cleanup3591, %cleanup3565 + %tmp3629 = icmp ugt i8 %sat.45934.0, %tmp137138 ; [#uses=1] + br i1 %tmp3629, label %cond_next3653, label %bb3635 + + bb3635: ; preds = %cond_next3649, %cond_next3624 + %indvar6258 = phi i8 [ %indvar.next16, %cond_next3649 ], [ 0, %cond_next3624 ] ; [#uses=2] + %tue.1 = phi i8 [ %tue.0, %cond_next3649 ], [ %tmp204205, %cond_next3624 ] ; [#uses=2] + %tmp3637 = invoke i8 @report__equal( i32 2, i32 2 ) + to label %invcont3636 unwind label %unwind3618 ; [#uses=1] + + invcont3636: ; preds = %bb3635 + %i3633.4 = add i8 %indvar6258, %sat.45934.0 ; [#uses=1] + %tmp3638 = icmp eq i8 %tmp3637, 0 ; [#uses=1] + %tue.0 = select i1 %tmp3638, i8 %tue.1, i8 2 ; [#uses=2] + %tmp3645 = icmp eq i8 %i3633.4, %tmp137138 ; [#uses=1] + br i1 %tmp3645, label %cond_next3653, label %cond_next3649 + + cond_next3649: ; preds = %invcont3636 + %indvar.next16 = add i8 %indvar6258, 1 ; [#uses=1] + br label %bb3635 + + cond_next3653: ; preds = %invcont3636, %cond_next3624 + %tue.2 = phi i8 [ %tmp204205, %cond_next3624 ], [ %tue.0, %invcont3636 ] ; [#uses=6] + %tmp3658 = icmp ult i8 %tmp238239, %tmp306307 ; [#uses=1] + br i1 %tmp3658, label %cond_next3678, label %cond_true3661 + + cond_true3661: ; preds = %cond_next3653 + %tmp3664 = icmp ult i8 %tmp306307, %tmp204205 ; [#uses=1] + %tmp3668 = icmp ugt i8 %tmp238239, %tmp272273 ; [#uses=1] + %tmp3672 = or i1 %tmp3664, %tmp3668 ; [#uses=1] + br i1 %tmp3672, label %cond_true3675, label %cond_next3678 + + cond_true3675: ; preds = %cond_true3661 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 257 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3618 + + cond_next3678: ; preds = %cond_true3661, %cond_next3653 + %tmp3683 = icmp ugt i8 %tmp306307, %tmp238239 ; [#uses=1] + br i1 %tmp3683, label %cond_next3707, label %bb3689 + + bb3689: ; preds = %cond_next3703, %cond_next3678 + %indvar6261 = phi i8 [ %indvar.next18, %cond_next3703 ], [ 0, %cond_next3678 ] ; [#uses=2] + %mon.1 = phi i8 [ %mon.0, %cond_next3703 ], [ %tmp170171, %cond_next3678 ] ; [#uses=2] + %tmp3691 = invoke i8 @report__equal( i32 2, i32 2 ) + to label %invcont3690 unwind label %unwind3618 ; [#uses=1] + + invcont3690: ; preds = %bb3689 + %i3687.4 = add i8 %indvar6261, %tmp306307 ; [#uses=1] + %tmp3692 = icmp eq i8 %tmp3691, 0 ; [#uses=1] + %mon.0 = select i1 %tmp3692, i8 %mon.1, i8 1 ; [#uses=2] + %tmp3699 = icmp eq i8 %i3687.4, %tmp238239 ; [#uses=1] + br i1 %tmp3699, label %cond_next3707, label %cond_next3703 + + cond_next3703: ; preds = %invcont3690 + %indvar.next18 = add i8 %indvar6261, 1 ; [#uses=1] + br label %bb3689 + + cond_next3707: ; preds = %invcont3690, %cond_next3678 + %mon.2 = phi i8 [ %tmp170171, %cond_next3678 ], [ %mon.0, %invcont3690 ] ; [#uses=8] + %tmp3712 = icmp ult i8 %tmp137138, %mon.2 ; [#uses=1] + br i1 %tmp3712, label %cond_next3732, label %cond_true3715 + + cond_true3715: ; preds = %cond_next3707 + %tmp3718 = icmp ult i8 %mon.2, %tmp204205 ; [#uses=1] + %tmp3722 = icmp ugt i8 %tmp137138, %tmp272273 ; [#uses=1] + %tmp3726 = or i1 %tmp3718, %tmp3722 ; [#uses=1] + br i1 %tmp3726, label %cond_true3729, label %cond_next3732 + + cond_true3729: ; preds = %cond_true3715 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 264 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3618 + + cond_next3732: ; preds = %cond_true3715, %cond_next3707 + %tmp3737 = icmp ugt i8 %mon.2, %tmp137138 ; [#uses=1] + br i1 %tmp3737, label %finally3852, label %bb3743 + + bb3743: ; preds = %cond_next3757, %cond_next3732 + %indvar6265 = phi i8 [ %indvar.next20, %cond_next3757 ], [ 0, %cond_next3732 ] ; [#uses=2] + %wed.1 = phi i8 [ %wed.0, %cond_next3757 ], [ %tmp238239, %cond_next3732 ] ; [#uses=2] + %tmp3745 = invoke i8 @report__equal( i32 3, i32 3 ) + to label %invcont3744 unwind label %unwind3618 ; [#uses=1] + + invcont3744: ; preds = %bb3743 + %i3741.4 = add i8 %indvar6265, %mon.2 ; [#uses=1] + %tmp3746 = icmp eq i8 %tmp3745, 0 ; [#uses=1] + %wed.0 = select i1 %tmp3746, i8 %wed.1, i8 3 ; [#uses=2] + %tmp3753 = icmp eq i8 %i3741.4, %tmp137138 ; [#uses=1] + br i1 %tmp3753, label %finally3852, label %cond_next3757 + + cond_next3757: ; preds = %invcont3744 + %indvar.next20 = add i8 %indvar6265, 1 ; [#uses=1] + br label %bb3743 + + eh_then3857: ; preds = %unwind3618 + invoke void @__gnat_begin_handler( i8* %eh_ptr3619 ) + to label %invcont3863 unwind label %unwind3861 + + unwind3861: ; preds = %invcont3865, %invcont3863, %eh_then3857 + %eh_ptr3862 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_ptr3619 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr3862 ) ; :17 [#uses=0] + unreachable + + invcont3863: ; preds = %eh_then3857 + %tmp3864 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp3864( ) + to label %invcont3865 unwind label %unwind3861 + + invcont3865: ; preds = %invcont3863 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([18 x i8]* @.str26 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.124.1606 to i32) to i64), i64 32)) ) + to label %cleanup3874 unwind label %unwind3861 + + cleanup3874: ; preds = %invcont3865 + call void @__gnat_end_handler( i8* %eh_ptr3619 ) + br label %finally3852 + + finally3852: ; preds = %cleanup3874, %invcont3744, %cond_next3732 + %wed.4 = phi i8 [ %wed.3, %cleanup3874 ], [ %tmp238239, %cond_next3732 ], [ %wed.0, %invcont3744 ] ; [#uses=4] + %tue.4 = phi i8 [ %tue.3, %cleanup3874 ], [ %tue.2, %cond_next3732 ], [ %tue.2, %invcont3744 ] ; [#uses=13] + %mon.4 = phi i8 [ %mon.3, %cleanup3874 ], [ %mon.2, %cond_next3732 ], [ %mon.2, %invcont3744 ] ; [#uses=18] + %tmp3885 = invoke i32 @report__ident_int( i32 -5 ) + to label %invcont3884 unwind label %unwind3880 ; [#uses=4] + + unwind3880: ; preds = %cond_true4138, %invcont4122, %cond_next4120, %cond_true4117, %cond_true4027, %cond_next3938, %cond_true3935, %cond_true3907, %finally3852 + %eh_ptr3881 = call i8* @llvm.eh.exception( ) ; [#uses=5] + %eh_select3883 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr3881, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=1] + %eh_typeid4149 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp4151 = icmp eq i32 %eh_select3883, %eh_typeid4149 ; [#uses=1] + br i1 %tmp4151, label %eh_then4152, label %Unwind + + invcont3884: ; preds = %finally3852 + %tmp3892 = icmp slt i32 %tmp3885, %tmp384 ; [#uses=2] + %tmp3900 = icmp sgt i32 %tmp3885, %tmp394 ; [#uses=1] + %tmp3904 = or i1 %tmp3892, %tmp3900 ; [#uses=1] + br i1 %tmp3904, label %cond_true3907, label %cond_next3909 + + cond_true3907: ; preds = %invcont3884 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 312 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3880 + + cond_next3909: ; preds = %invcont3884 + %tmp3913 = icmp slt i32 %tmp3885, -5 ; [#uses=1] + br i1 %tmp3913, label %cond_true3916, label %cond_next3938 + + cond_true3916: ; preds = %cond_next3909 + %tmp3928 = icmp slt i32 %tmp394, -6 ; [#uses=1] + %tmp3932 = or i1 %tmp3892, %tmp3928 ; [#uses=1] + br i1 %tmp3932, label %cond_true3935, label %cond_next3938 + + cond_true3935: ; preds = %cond_true3916 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 312 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3880 + + cond_next3938: ; preds = %cond_true3916, %cond_next3909 + %tmp4005 = invoke i32 @report__ident_int( i32 -5 ) + to label %invcont4004 unwind label %unwind3880 ; [#uses=6] + + invcont4004: ; preds = %cond_next3938 + %tmp4012 = icmp slt i32 %tmp4005, %tmp384 ; [#uses=2] + %tmp4020 = icmp sgt i32 %tmp4005, %tmp394 ; [#uses=1] + %tmp4024 = or i1 %tmp4012, %tmp4020 ; [#uses=1] + br i1 %tmp4024, label %cond_true4027, label %cond_next4029 + + cond_true4027: ; preds = %invcont4004 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 313 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3880 + + cond_next4029: ; preds = %invcont4004 + %tmp4071 = icmp sgt i32 %tmp4005, -6 ; [#uses=1] + %tmp4078 = add i32 %tmp4005, 1073741823 ; [#uses=1] + %iftmp.132.0 = select i1 %tmp4071, i32 %tmp4078, i32 1073741818 ; [#uses=1] + %tmp4085 = sub i32 %iftmp.132.0, %tmp4005 ; [#uses=1] + %tmp4086 = shl i32 %tmp4085, 2 ; [#uses=2] + %tmp4087 = add i32 %tmp4086, 4 ; [#uses=1] + %tmp4088 = icmp sgt i32 %tmp4087, -1 ; [#uses=1] + %tmp4087.op = add i32 %tmp4086, 7 ; [#uses=1] + %tmp4087.op.op = and i32 %tmp4087.op, -4 ; [#uses=1] + %tmp4091 = select i1 %tmp4088, i32 %tmp4087.op.op, i32 0 ; [#uses=1] + %tmp4095 = icmp slt i32 %tmp4005, -5 ; [#uses=1] + br i1 %tmp4095, label %cond_true4098, label %cond_next4120 + + cond_true4098: ; preds = %cond_next4029 + %tmp4110 = icmp slt i32 %tmp394, -6 ; [#uses=1] + %tmp4114 = or i1 %tmp4012, %tmp4110 ; [#uses=1] + br i1 %tmp4114, label %cond_true4117, label %cond_next4120 + + cond_true4117: ; preds = %cond_true4098 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 313 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind3880 + + cond_next4120: ; preds = %cond_true4098, %cond_next4029 + %tmp4123 = invoke i8* @__gnat_malloc( i32 %tmp4091 ) + to label %invcont4122 unwind label %unwind3880 ; [#uses=0] + + invcont4122: ; preds = %cond_next4120 + %tmp41254128 = sext i32 %tmp3885 to i64 ; [#uses=1] + %tmp4129 = sub i64 -5, %tmp41254128 ; [#uses=2] + %tmp4134 = invoke i32 @report__ident_int( i32 0 ) + to label %invcont4133 unwind label %unwind3880 ; [#uses=1] + + invcont4133: ; preds = %invcont4122 + %tmp4130 = icmp sgt i64 %tmp4129, -1 ; [#uses=1] + %tmp4129.cast = trunc i64 %tmp4129 to i32 ; [#uses=1] + %max41314132 = select i1 %tmp4130, i32 %tmp4129.cast, i32 0 ; [#uses=1] + %tmp4135 = icmp eq i32 %max41314132, %tmp4134 ; [#uses=1] + br i1 %tmp4135, label %finally4147, label %cond_true4138 + + cond_true4138: ; preds = %invcont4133 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([31 x i8]* @.str27 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.98.1466 to i32) to i64), i64 32)) ) + to label %finally4147 unwind label %unwind3880 + + eh_then4152: ; preds = %unwind3880 + invoke void @__gnat_begin_handler( i8* %eh_ptr3881 ) + to label %invcont4158 unwind label %unwind4156 + + unwind4156: ; preds = %invcont4160, %invcont4158, %eh_then4152 + %eh_ptr4157 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_ptr3881 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr4157 ) ; :18 [#uses=0] + unreachable + + invcont4158: ; preds = %eh_then4152 + %tmp4159 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp4159( ) + to label %invcont4160 unwind label %unwind4156 + + invcont4160: ; preds = %invcont4158 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([18 x i8]* @.str28 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.124.1606 to i32) to i64), i64 32)) ) + to label %cleanup4169 unwind label %unwind4156 + + cleanup4169: ; preds = %invcont4160 + call void @__gnat_end_handler( i8* %eh_ptr3881 ) + br label %finally4147 + + finally4147: ; preds = %cleanup4169, %cond_true4138, %invcont4133 + %tmp4174 = call i8* @llvm.stacksave( ) ; [#uses=3] + %tmp4180 = invoke i32 @report__ident_int( i32 4 ) + to label %invcont4179 unwind label %unwind4175 ; [#uses=6] + + unwind4175: ; preds = %cond_true4292, %cond_true4187, %finally4147 + %eh_ptr4176 = call i8* @llvm.eh.exception( ) ; [#uses=5] + %eh_select4178 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr4176, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=1] + %eh_typeid4304 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp4306 = icmp eq i32 %eh_select4178, %eh_typeid4304 ; [#uses=1] + br i1 %tmp4306, label %eh_then4307, label %cleanup4334 + + invcont4179: ; preds = %finally4147 + %tmp4184 = icmp slt i32 %tmp4180, 1 ; [#uses=1] + br i1 %tmp4184, label %cond_true4187, label %cond_next4189 + + cond_true4187: ; preds = %invcont4179 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 329 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind4175 + + cond_next4189: ; preds = %invcont4179 + %tmp4231 = icmp sgt i32 %tmp4180, 2 ; [#uses=2] + %tmp4238 = add i32 %tmp4180, 1073741823 ; [#uses=1] + %iftmp.138.0 = select i1 %tmp4231, i32 %tmp4238, i32 2 ; [#uses=1] + %tmp4245 = sub i32 %iftmp.138.0, %tmp4180 ; [#uses=1] + %tmp4246 = shl i32 %tmp4245, 2 ; [#uses=2] + %tmp4247 = add i32 %tmp4246, 4 ; [#uses=1] + %tmp4248 = icmp sgt i32 %tmp4247, -1 ; [#uses=1] + %tmp4247.op = add i32 %tmp4246, 7 ; [#uses=1] + %tmp4247.op.op = and i32 %tmp4247.op, -4 ; [#uses=1] + %tmp4251 = select i1 %tmp4248, i32 %tmp4247.op.op, i32 0 ; [#uses=1] + %tmp4253 = alloca i8, i32 %tmp4251 ; [#uses=2] + %tmp42534254 = bitcast i8* %tmp4253 to i32* ; [#uses=1] + br i1 %tmp4231, label %bb4276, label %cond_next4266.preheader + + cond_next4266.preheader: ; preds = %cond_next4189 + %J152b.36147.3 = add i32 %tmp4180, 1 ; [#uses=1] + br label %cond_next4266 + + cond_next4266: ; preds = %cond_next4266, %cond_next4266.preheader + %indvar6268 = phi i32 [ 0, %cond_next4266.preheader ], [ %indvar.next22, %cond_next4266 ] ; [#uses=3] + %tmp4273 = getelementptr i32* %tmp42534254, i32 %indvar6268 ; [#uses=1] + store i32 5, i32* %tmp4273 + %tmp4275 = add i32 %J152b.36147.3, %indvar6268 ; [#uses=1] + %tmp42626151 = icmp sgt i32 %tmp4275, 2 ; [#uses=1] + %indvar.next22 = add i32 %indvar6268, 1 ; [#uses=1] + br i1 %tmp42626151, label %bb4276, label %cond_next4266 + + bb4276: ; preds = %cond_next4266, %cond_next4189 + %tmp4280 = sub i32 2, %tmp4180 ; [#uses=1] + %tmp4281 = icmp eq i32 %tmp4280, 1 ; [#uses=1] + br i1 %tmp4281, label %cond_true4284, label %cleanup4336 + + cond_true4284: ; preds = %bb4276 + %tmp4288 = call i32 (i8*, i8*, i32, ...)* @memcmp( i8* %tmp4253, i8* bitcast ([2 x i32]* @C.143.1720 to i8*), i32 8 ) ; [#uses=1] + %tmp4289 = icmp eq i32 %tmp4288, 0 ; [#uses=1] + br i1 %tmp4289, label %cond_true4292, label %cleanup4336 + + cond_true4292: ; preds = %cond_true4284 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([37 x i8]* @.str29 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.146.1725 to i32) to i64), i64 32)) ) + to label %cleanup4336 unwind label %unwind4175 + + eh_then4307: ; preds = %unwind4175 + invoke void @__gnat_begin_handler( i8* %eh_ptr4176 ) + to label %invcont4313 unwind label %unwind4311 + + unwind4311: ; preds = %invcont4315, %invcont4313, %eh_then4307 + %eh_ptr4312 = call i8* @llvm.eh.exception( ) ; [#uses=1] + invoke void @__gnat_end_handler( i8* %eh_ptr4176 ) + to label %cleanup4334 unwind label %unwind4326 + + invcont4313: ; preds = %eh_then4307 + %tmp4314 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp4314( ) + to label %invcont4315 unwind label %unwind4311 + + invcont4315: ; preds = %invcont4313 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([18 x i8]* @.str30 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.124.1606 to i32) to i64), i64 32)) ) + to label %cleanup4324 unwind label %unwind4311 + + cleanup4324: ; preds = %invcont4315 + invoke void @__gnat_end_handler( i8* %eh_ptr4176 ) + to label %cleanup4336 unwind label %unwind4326 + + unwind4326: ; preds = %cleanup4324, %unwind4311 + %eh_ptr4327 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @llvm.stackrestore( i8* %tmp4174 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr4327 ) ; :19 [#uses=0] + unreachable + + cleanup4334: ; preds = %unwind4311, %unwind4175 + %eh_exception.50 = phi i8* [ %eh_ptr4176, %unwind4175 ], [ %eh_ptr4312, %unwind4311 ] ; [#uses=1] + call void @llvm.stackrestore( i8* %tmp4174 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_exception.50 ) ; :20 [#uses=0] + unreachable + + cleanup4336: ; preds = %cleanup4324, %cond_true4292, %cond_true4284, %bb4276 + call void @llvm.stackrestore( i8* %tmp4174 ) + %tmp4338 = call i8* @llvm.stacksave( ) ; [#uses=6] + %tmp4379 = alloca i8, i32 %max1395 ; [#uses=9] + %tmp4421 = alloca i8, i32 %max1395 ; [#uses=3] + %tmp4428 = icmp ugt i8 %tmp204205, %tmp272273 ; [#uses=1] + br i1 %tmp4428, label %cond_next4458, label %bb4433 + + bb4433: ; preds = %cleanup4336 + store i8 %wed.4, i8* %tmp4421 + %tmp4442 = icmp eq i8 %tmp272273, %tmp204205 ; [#uses=1] + br i1 %tmp4442, label %cond_next4458, label %cond_next4446.preheader + + cond_next4446.preheader: ; preds = %bb4433 + %J161b.26152.2 = add i8 %tmp204205, 1 ; [#uses=1] + br label %cond_next4446 + + cond_next4446: ; preds = %cond_next4446, %cond_next4446.preheader + %indvar6271 = phi i8 [ 0, %cond_next4446.preheader ], [ %indvar.next24, %cond_next4446 ] ; [#uses=2] + %tmp4448 = add i8 %J161b.26152.2, %indvar6271 ; [#uses=2] + %tmp443444356156 = zext i8 %tmp4448 to i32 ; [#uses=1] + %tmp44376157 = sub i32 %tmp443444356156, %tmp13571358 ; [#uses=1] + %tmp44386158 = getelementptr i8* %tmp4421, i32 %tmp44376157 ; [#uses=1] + store i8 %wed.4, i8* %tmp44386158 + %tmp44426160 = icmp eq i8 %tmp272273, %tmp4448 ; [#uses=1] + %indvar.next24 = add i8 %indvar6271, 1 ; [#uses=1] + br i1 %tmp44426160, label %cond_next4458, label %cond_next4446 + + unwind4453: ; preds = %cond_true4609, %cond_true4504, %cond_true4481 + %eh_ptr4454 = call i8* @llvm.eh.exception( ) ; [#uses=4] + %eh_select4456 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr4454, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=1] + %eh_typeid4710 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp4712 = icmp eq i32 %eh_select4456, %eh_typeid4710 ; [#uses=1] + br i1 %tmp4712, label %eh_then4713, label %cleanup4740 + + cond_next4458: ; preds = %cond_next4446, %bb4433, %cleanup4336 + call void @llvm.memcpy.i32( i8* %tmp4379, i8* %tmp4421, i32 %max1395, i32 1 ) + %tmp4464 = icmp ult i8 %tmp137138, %mon.4 ; [#uses=2] + br i1 %tmp4464, label %cond_next4484, label %cond_true4467 + + cond_true4467: ; preds = %cond_next4458 + %tmp4470 = icmp ult i8 %mon.4, %tmp204205 ; [#uses=1] + %tmp4474 = icmp ugt i8 %tmp137138, %tmp272273 ; [#uses=1] + %tmp4478 = or i1 %tmp4470, %tmp4474 ; [#uses=1] + br i1 %tmp4478, label %cond_true4481, label %cond_next4484 + + cond_true4481: ; preds = %cond_true4467 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 340 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind4453 + + cond_next4484: ; preds = %cond_true4467, %cond_next4458 + %tmp4487 = icmp ult i8 %mon.4, %tue.4 ; [#uses=2] + br i1 %tmp4487, label %cond_next4507, label %cond_true4490 + + cond_true4490: ; preds = %cond_next4484 + %tmp4493 = icmp ult i8 %tue.4, %tmp204205 ; [#uses=1] + %tmp4497 = icmp ugt i8 %mon.4, %tmp272273 ; [#uses=1] + %tmp4501 = or i1 %tmp4497, %tmp4493 ; [#uses=1] + br i1 %tmp4501, label %cond_true4504, label %cond_next4507 + + cond_true4504: ; preds = %cond_true4490 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 340 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind4453 + + cond_next4507: ; preds = %cond_true4490, %cond_next4484 + %tmp45904591 = zext i8 %mon.4 to i64 ; [#uses=3] + %tmp45924593 = zext i8 %tue.4 to i64 ; [#uses=1] + %tmp4594 = sub i64 %tmp45904591, %tmp45924593 ; [#uses=1] + %tmp4595 = add i64 %tmp4594, 1 ; [#uses=2] + %tmp4596 = icmp sgt i64 %tmp4595, -1 ; [#uses=1] + %max4597 = select i1 %tmp4596, i64 %tmp4595, i64 0 ; [#uses=1] + %tmp45984599 = zext i8 %tmp137138 to i64 ; [#uses=1] + %tmp4602 = sub i64 %tmp45984599, %tmp45904591 ; [#uses=1] + %tmp4603 = add i64 %tmp4602, 1 ; [#uses=3] + %tmp4604 = icmp sgt i64 %tmp4603, -1 ; [#uses=2] + %max4605 = select i1 %tmp4604, i64 %tmp4603, i64 0 ; [#uses=1] + %tmp4606 = icmp eq i64 %max4597, %max4605 ; [#uses=1] + br i1 %tmp4606, label %cond_next4611, label %cond_true4609 + + cond_true4609: ; preds = %cond_next4507 + invoke void @__gnat_rcheck_07( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 340 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind4453 + + cond_next4611: ; preds = %cond_next4507 + %tmp46124613 = zext i8 %tue.4 to i32 ; [#uses=1] + %tmp4616 = sub i32 %tmp46124613, %tmp13571358 ; [#uses=2] + %tmp46244625 = zext i8 %mon.4 to i32 ; [#uses=1] + %tmp4628 = sub i32 %tmp46244625, %tmp13571358 ; [#uses=3] + %tmp4636 = icmp slt i32 %tmp4628, %tmp4616 ; [#uses=1] + %tmp4677 = icmp ugt i8 %tue.4, %mon.4 ; [#uses=2] + br i1 %tmp4636, label %cond_false4673, label %cond_true4639 + + cond_true4639: ; preds = %cond_next4611 + br i1 %tmp4677, label %cleanup4742, label %bb4648.preheader + + bb4648.preheader: ; preds = %cond_true4639 + %tmp46556217 = getelementptr i8* %tmp4379, i32 %tmp4628 ; [#uses=1] + %tmp46566218 = load i8* %tmp46556217 ; [#uses=1] + %tmp46596220 = getelementptr i8* %tmp4379, i32 %tmp4616 ; [#uses=1] + store i8 %tmp46566218, i8* %tmp46596220 + %tmp46646223 = icmp eq i8 %tue.4, %mon.4 ; [#uses=1] + br i1 %tmp46646223, label %cleanup4742, label %cond_next4668.preheader + + cond_next4668.preheader: ; preds = %bb4648.preheader + %tmp46616222.in = add i8 %mon.4, 1 ; [#uses=1] + %L174b.26213 = add i8 %tue.4, 1 ; [#uses=1] + %tmp.27 = sub i8 %mon.4, %tue.4 ; [#uses=1] + br label %cond_next4668 + + cond_next4668: ; preds = %cond_next4668, %cond_next4668.preheader + %indvar6275 = phi i8 [ 0, %cond_next4668.preheader ], [ %indvar.next26, %cond_next4668 ] ; [#uses=3] + %tmp46616222 = add i8 %tmp46616222.in, %indvar6275 ; [#uses=1] + %tmp4670 = add i8 %L174b.26213, %indvar6275 ; [#uses=1] + %tmp46494650 = zext i8 %tmp4670 to i32 ; [#uses=1] + %tmp46514652 = zext i8 %tmp46616222 to i32 ; [#uses=1] + %tmp4654 = sub i32 %tmp46514652, %tmp13571358 ; [#uses=1] + %tmp4655 = getelementptr i8* %tmp4379, i32 %tmp4654 ; [#uses=1] + %tmp4656 = load i8* %tmp4655 ; [#uses=1] + %tmp4658 = sub i32 %tmp46494650, %tmp13571358 ; [#uses=1] + %tmp4659 = getelementptr i8* %tmp4379, i32 %tmp4658 ; [#uses=1] + store i8 %tmp4656, i8* %tmp4659 + %indvar.next26 = add i8 %indvar6275, 1 ; [#uses=2] + %exitcond28 = icmp eq i8 %indvar.next26, %tmp.27 ; [#uses=1] + br i1 %exitcond28, label %cleanup4742, label %cond_next4668 + + cond_false4673: ; preds = %cond_next4611 + br i1 %tmp4677, label %cleanup4742, label %bb4682.preheader + + bb4682.preheader: ; preds = %cond_false4673 + %tmp468546866228 = and i32 %tmp123, 255 ; [#uses=1] + %tmp46886229 = sub i32 %tmp468546866228, %tmp13571358 ; [#uses=1] + %tmp46896230 = getelementptr i8* %tmp4379, i32 %tmp46886229 ; [#uses=1] + %tmp46906231 = load i8* %tmp46896230 ; [#uses=1] + %tmp46936233 = getelementptr i8* %tmp4379, i32 %tmp4628 ; [#uses=1] + store i8 %tmp46906231, i8* %tmp46936233 + %tmp46986236 = icmp eq i8 %mon.4, %tue.4 ; [#uses=1] + br i1 %tmp46986236, label %cleanup4742, label %cond_next4702.preheader + + cond_next4702.preheader: ; preds = %bb4682.preheader + %tmp46956235.in = add i8 %tmp137138, -1 ; [#uses=1] + %L172b.26226 = add i8 %mon.4, -1 ; [#uses=1] + %tmp.32 = sub i8 %mon.4, %tue.4 ; [#uses=1] + br label %cond_next4702 + + cond_next4702: ; preds = %cond_next4702, %cond_next4702.preheader + %indvar6278 = phi i8 [ 0, %cond_next4702.preheader ], [ %indvar.next30, %cond_next4702 ] ; [#uses=3] + %tmp46956235 = sub i8 %tmp46956235.in, %indvar6278 ; [#uses=1] + %tmp4704 = sub i8 %L172b.26226, %indvar6278 ; [#uses=1] + %tmp46834684 = zext i8 %tmp4704 to i32 ; [#uses=1] + %tmp46854686 = zext i8 %tmp46956235 to i32 ; [#uses=1] + %tmp4688 = sub i32 %tmp46854686, %tmp13571358 ; [#uses=1] + %tmp4689 = getelementptr i8* %tmp4379, i32 %tmp4688 ; [#uses=1] + %tmp4690 = load i8* %tmp4689 ; [#uses=1] + %tmp4692 = sub i32 %tmp46834684, %tmp13571358 ; [#uses=1] + %tmp4693 = getelementptr i8* %tmp4379, i32 %tmp4692 ; [#uses=1] + store i8 %tmp4690, i8* %tmp4693 + %indvar.next30 = add i8 %indvar6278, 1 ; [#uses=2] + %exitcond33 = icmp eq i8 %indvar.next30, %tmp.32 ; [#uses=1] + br i1 %exitcond33, label %cleanup4742, label %cond_next4702 + + eh_then4713: ; preds = %unwind4453 + invoke void @__gnat_begin_handler( i8* %eh_ptr4454 ) + to label %invcont4719 unwind label %unwind4717 + + unwind4717: ; preds = %invcont4719, %eh_then4713 + %eh_ptr4718 = call i8* @llvm.eh.exception( ) ; [#uses=1] + invoke void @__gnat_end_handler( i8* %eh_ptr4454 ) + to label %cleanup4740 unwind label %unwind4732 + + invcont4719: ; preds = %eh_then4713 + %tmp4720 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp4720( ) + to label %UnifiedReturnBlock35 unwind label %unwind4717 + + unwind4732: ; preds = %unwind4717 + %eh_ptr4733 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @llvm.stackrestore( i8* %tmp4338 ) + call void @llvm.stackrestore( i8* %tmp4338 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr4733 ) ; :21 [#uses=0] + unreachable + + cleanup4740: ; preds = %unwind4717, %unwind4453 + %eh_exception.53 = phi i8* [ %eh_ptr4454, %unwind4453 ], [ %eh_ptr4718, %unwind4717 ] ; [#uses=1] + call void @llvm.stackrestore( i8* %tmp4338 ) + call void @llvm.stackrestore( i8* %tmp4338 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_exception.53 ) ; :22 [#uses=0] + unreachable + + cleanup4742: ; preds = %cond_next4702, %bb4682.preheader, %cond_false4673, %cond_next4668, %bb4648.preheader, %cond_true4639 + call void @llvm.stackrestore( i8* %tmp4338 ) + call void @llvm.stackrestore( i8* %tmp4338 ) + %tmp4749 = call i8* @llvm.stacksave( ) ; [#uses=2] + br i1 %tmp4464, label %cond_next4776, label %UnifiedReturnBlock35 + + unwind4770: ; preds = %cond_next4776 + %eh_ptr4771 = call i8* @llvm.eh.exception( ) ; [#uses=5] + %eh_select4773 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr4771, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=1] + call void @llvm.stackrestore( i8* %tmp4749 ) + %eh_typeid4874 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp4876 = icmp eq i32 %eh_select4773, %eh_typeid4874 ; [#uses=1] + br i1 %tmp4876, label %eh_then4877, label %Unwind + + cond_next4776: ; preds = %cleanup4742 + %tmp4856.cast = trunc i64 %tmp4603 to i32 ; [#uses=1] + %max48584859 = select i1 %tmp4604, i32 %tmp4856.cast, i32 0 ; [#uses=1] + %tmp4861 = invoke i8 @report__equal( i32 %max48584859, i32 0 ) + to label %invcont4860 unwind label %unwind4770 ; [#uses=1] + + invcont4860: ; preds = %cond_next4776 + %tmp4862 = icmp eq i8 %tmp4861, 0 ; [#uses=1] + %tue.8 = select i1 %tmp4862, i8 %tue.4, i8 2 ; [#uses=3] + call void @llvm.stackrestore( i8* %tmp4749 ) + %tmp49016170 = icmp ult i8 %mon.4, %tue.8 ; [#uses=1] + br i1 %tmp49016170, label %cond_next4925, label %cond_true4904 + + eh_then4877: ; preds = %unwind4770 + invoke void @__gnat_begin_handler( i8* %eh_ptr4771 ) + to label %invcont4883 unwind label %unwind4881 + + unwind4881: ; preds = %invcont4885, %invcont4883, %eh_then4877 + %eh_ptr4882 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_ptr4771 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr4882 ) ; :23 [#uses=0] + unreachable + + invcont4883: ; preds = %eh_then4877 + %tmp4884 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp4884( ) + to label %invcont4885 unwind label %unwind4881 + + invcont4885: ; preds = %invcont4883 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([18 x i8]* @.str32 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.124.1606 to i32) to i64), i64 32)) ) + to label %cleanup4894 unwind label %unwind4881 + + cleanup4894: ; preds = %invcont4885 + call void @__gnat_end_handler( i8* %eh_ptr4771 ) + br i1 %tmp4487, label %cond_next4925, label %cond_true4904 + + cond_true4904: ; preds = %cleanup4894, %invcont4860 + %tue.96161.0 = phi i8 [ %tue.8, %invcont4860 ], [ %tue.4, %cleanup4894 ] ; [#uses=3] + %tmp4907 = icmp ult i8 %tue.96161.0, %tmp204205 ; [#uses=1] + %tmp4911 = icmp ugt i8 %mon.4, %tmp272273 ; [#uses=1] + %tmp4915 = or i1 %tmp4907, %tmp4911 ; [#uses=1] + br i1 %tmp4915, label %cond_true4918, label %cond_next4925 + + cond_true4918: ; preds = %cond_true4904 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 361 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind4919 + + unwind4919: ; preds = %cond_next4925, %cond_true4918 + %tue.96161.2 = phi i8 [ %tue.96161.0, %cond_true4918 ], [ %tue.96161.1, %cond_next4925 ] ; [#uses=1] + %eh_ptr4920 = call i8* @llvm.eh.exception( ) ; [#uses=5] + %eh_select4922 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr4920, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=1] + %eh_typeid4987 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp4989 = icmp eq i32 %eh_select4922, %eh_typeid4987 ; [#uses=1] + br i1 %tmp4989, label %eh_then4990, label %Unwind + + cond_next4925: ; preds = %cond_true4904, %cleanup4894, %invcont4860 + %tue.96161.1 = phi i8 [ %tue.8, %invcont4860 ], [ %tue.4, %cleanup4894 ], [ %tue.96161.0, %cond_true4904 ] ; [#uses=6] + %tmp49714972 = zext i8 %tue.96161.1 to i64 ; [#uses=1] + %tmp4973 = sub i64 %tmp45904591, %tmp49714972 ; [#uses=1] + %tmp4974 = add i64 %tmp4973, 1 ; [#uses=2] + %tmp4975 = icmp sgt i64 %tmp4974, -1 ; [#uses=1] + %tmp4974.cast = trunc i64 %tmp4974 to i32 ; [#uses=1] + %max49764977 = select i1 %tmp4975, i32 %tmp4974.cast, i32 0 ; [#uses=1] + %tmp4979 = invoke i8 @report__equal( i32 %max49764977, i32 0 ) + to label %invcont4978 unwind label %unwind4919 ; [#uses=1] + + invcont4978: ; preds = %cond_next4925 + %tmp4980 = icmp eq i8 %tmp4979, 0 ; [#uses=1] + br i1 %tmp4980, label %finally4985, label %cond_true4983 + + cond_true4983: ; preds = %invcont4978 + %tmp50146178 = icmp ugt i8 %tue.96161.1, 1 ; [#uses=1] + br i1 %tmp50146178, label %cond_next5038, label %cond_true5017 + + eh_then4990: ; preds = %unwind4919 + invoke void @__gnat_begin_handler( i8* %eh_ptr4920 ) + to label %invcont4996 unwind label %unwind4994 + + unwind4994: ; preds = %invcont4998, %invcont4996, %eh_then4990 + %eh_ptr4995 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_ptr4920 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr4995 ) ; :24 [#uses=0] + unreachable + + invcont4996: ; preds = %eh_then4990 + %tmp4997 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp4997( ) + to label %invcont4998 unwind label %unwind4994 + + invcont4998: ; preds = %invcont4996 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([19 x i8]* @.str33 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.170.1990 to i32) to i64), i64 32)) ) + to label %cleanup5007 unwind label %unwind4994 + + cleanup5007: ; preds = %invcont4998 + call void @__gnat_end_handler( i8* %eh_ptr4920 ) + br label %finally4985 + + finally4985: ; preds = %cleanup5007, %invcont4978 + %tue.96161.3 = phi i8 [ %tue.96161.2, %cleanup5007 ], [ %tue.96161.1, %invcont4978 ] ; [#uses=3] + %tmp5014 = icmp ult i8 %mon.4, %tue.96161.3 ; [#uses=1] + br i1 %tmp5014, label %cond_next5038, label %cond_true5017 + + cond_true5017: ; preds = %finally4985, %cond_true4983 + %tue.96161.4 = phi i8 [ %tue.96161.1, %cond_true4983 ], [ %tue.96161.3, %finally4985 ] ; [#uses=3] + %mon.86171.0 = phi i8 [ 1, %cond_true4983 ], [ %mon.4, %finally4985 ] ; [#uses=3] + %tmp5020 = icmp ult i8 %tue.96161.4, %tmp204205 ; [#uses=1] + %tmp5024 = icmp ugt i8 %mon.86171.0, %tmp272273 ; [#uses=1] + %tmp5028 = or i1 %tmp5024, %tmp5020 ; [#uses=1] + br i1 %tmp5028, label %cond_true5031, label %cond_next5038 + + cond_true5031: ; preds = %cond_true5017 + invoke void @__gnat_rcheck_12( i8* getelementptr ([13 x i8]* @.str, i32 0, i32 0), i32 375 ) + to label %UnifiedUnreachableBlock34 unwind label %unwind5032 + + unwind5032: ; preds = %cond_next5038, %cond_true5031 + %tue.96161.6 = phi i8 [ %tue.96161.4, %cond_true5031 ], [ %tue.96161.5, %cond_next5038 ] ; [#uses=1] + %mon.86171.2 = phi i8 [ %mon.86171.0, %cond_true5031 ], [ %mon.86171.1, %cond_next5038 ] ; [#uses=1] + %eh_ptr5033 = call i8* @llvm.eh.exception( ) ; [#uses=5] + %eh_select5035 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr5033, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=1] + %eh_typeid5100 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp5102 = icmp eq i32 %eh_select5035, %eh_typeid5100 ; [#uses=1] + br i1 %tmp5102, label %eh_then5103, label %Unwind + + cond_next5038: ; preds = %cond_true5017, %finally4985, %cond_true4983 + %tue.96161.5 = phi i8 [ %tue.96161.1, %cond_true4983 ], [ %tue.96161.3, %finally4985 ], [ %tue.96161.4, %cond_true5017 ] ; [#uses=4] + %mon.86171.1 = phi i8 [ 1, %cond_true4983 ], [ %mon.4, %finally4985 ], [ %mon.86171.0, %cond_true5017 ] ; [#uses=4] + %tmp50825083 = zext i8 %mon.86171.1 to i64 ; [#uses=1] + %tmp50845085 = zext i8 %tue.96161.5 to i64 ; [#uses=1] + %tmp5086 = sub i64 %tmp50825083, %tmp50845085 ; [#uses=1] + %tmp5087 = add i64 %tmp5086, 1 ; [#uses=2] + %tmp5088 = icmp sgt i64 %tmp5087, -1 ; [#uses=1] + %tmp5087.cast = trunc i64 %tmp5087 to i32 ; [#uses=1] + %max50895090 = select i1 %tmp5088, i32 %tmp5087.cast, i32 0 ; [#uses=1] + %tmp5092 = invoke i8 @report__equal( i32 %max50895090, i32 0 ) + to label %invcont5091 unwind label %unwind5032 ; [#uses=1] + + invcont5091: ; preds = %cond_next5038 + %tmp5093 = icmp eq i8 %tmp5092, 0 ; [#uses=1] + br i1 %tmp5093, label %finally5098, label %cond_true5096 + + cond_true5096: ; preds = %invcont5091 + br label %finally5098 + + eh_then5103: ; preds = %unwind5032 + invoke void @__gnat_begin_handler( i8* %eh_ptr5033 ) + to label %invcont5109 unwind label %unwind5107 + + unwind5107: ; preds = %invcont5111, %invcont5109, %eh_then5103 + %eh_ptr5108 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_ptr5033 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr5108 ) ; :25 [#uses=0] + unreachable + + invcont5109: ; preds = %eh_then5103 + %tmp5110 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp5110( ) + to label %invcont5111 unwind label %unwind5107 + + invcont5111: ; preds = %invcont5109 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([19 x i8]* @.str34 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.170.1990 to i32) to i64), i64 32)) ) + to label %cleanup5120 unwind label %unwind5107 + + cleanup5120: ; preds = %invcont5111 + call void @__gnat_end_handler( i8* %eh_ptr5033 ) + br label %finally5098 + + finally5098: ; preds = %cleanup5120, %cond_true5096, %invcont5091 + %tue.96161.7 = phi i8 [ %tue.96161.6, %cleanup5120 ], [ %tue.96161.5, %cond_true5096 ], [ %tue.96161.5, %invcont5091 ] ; [#uses=1] + %mon.86171.3 = phi i8 [ %mon.86171.2, %cleanup5120 ], [ %mon.86171.1, %cond_true5096 ], [ %mon.86171.1, %invcont5091 ] ; [#uses=2] + %wed.6 = phi i8 [ %wed.4, %cleanup5120 ], [ 3, %cond_true5096 ], [ %wed.4, %invcont5091 ] ; [#uses=5] + %not.tmp5135 = icmp uge i8 %tmp137138, %sat.45934.0 ; [#uses=1] + %tmp5151 = icmp uge i8 %sat.45934.0, %tmp306307 ; [#uses=1] + %tmp5155 = icmp ule i8 %sat.45934.0, %wed.6 ; [#uses=1] + %tmp5159 = and i1 %tmp5155, %tmp5151 ; [#uses=1] + %tmp5177 = icmp ult i8 %wed.6, %tmp272273 ; [#uses=1] + %tmp5184 = icmp ugt i8 %wed.6, %tue.96161.7 ; [#uses=1] + %bothcond5907 = or i1 %tmp5177, %tmp5184 ; [#uses=2] + %not.bothcond5907 = xor i1 %bothcond5907, true ; [#uses=1] + %tmp5198 = icmp uge i8 %tmp272273, %mon.86171.3 ; [#uses=1] + %tmp5202 = icmp ule i8 %tmp272273, %tmp137138 ; [#uses=1] + %tmp5206 = and i1 %tmp5198, %tmp5202 ; [#uses=1] + %not.bothcond5908 = icmp uge i8 %tmp306307, %sat.45934.0 ; [#uses=1] + %tmp5244 = icmp uge i8 %wed.6, %tmp306307 ; [#uses=1] + %tmp5248 = icmp ule i8 %wed.6, %mon.86171.3 ; [#uses=1] + %tmp5252 = and i1 %tmp5244, %tmp5248 ; [#uses=1] + %tmp5164 = or i1 %not.tmp5135, %not.bothcond5908 ; [#uses=1] + %tmp5194 = or i1 %tmp5164, %tmp5206 ; [#uses=1] + %tmp5210 = or i1 %tmp5194, %tmp5159 ; [#uses=1] + %tmp5240 = or i1 %tmp5210, %not.bothcond5907 ; [#uses=1] + %tmp5256 = or i1 %tmp5240, %tmp5252 ; [#uses=1] + br i1 %tmp5256, label %cond_true5259, label %cond_next5271 + + cond_true5259: ; preds = %finally5098 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([27 x i8]* @.str35 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.178.2066 to i32) to i64), i64 32)) ) + to label %cond_next5271 unwind label %unwind5266 + + unwind5266: ; preds = %cond_true5462, %invcont5429, %cond_next5401, %cond_true5393, %cond_next5374, %bb5359, %cond_next5347, %invcont5330, %invcont5305, %invcont5303, %invcont5294, %bb5293, %cond_next5281, %cond_next5271, %cond_true5259 + %eh_ptr5267 = call i8* @llvm.eh.exception( ) ; [#uses=5] + %eh_select5269 = call i32 (i8*, i8*, ...)* @llvm.eh.selector( i8* %eh_ptr5267, i8* bitcast (i32 (...)* @__gnat_eh_personality to i8*), i32* @__gnat_others_value ) ; [#uses=1] + %eh_typeid5473 = call i32 @llvm.eh.typeid.for( i8* bitcast (i32* @__gnat_others_value to i8*) ) ; [#uses=1] + %tmp5475 = icmp eq i32 %eh_select5269, %eh_typeid5473 ; [#uses=1] + br i1 %tmp5475, label %eh_then5476, label %Unwind + + cond_next5271: ; preds = %cond_true5259, %finally5098 + %tmp5273 = invoke i32 @report__ident_int( i32 0 ) + to label %invcont5272 unwind label %unwind5266 ; [#uses=2] + + invcont5272: ; preds = %cond_next5271 + %tmp5277 = icmp slt i32 %tmp5273, 10 ; [#uses=1] + br i1 %tmp5277, label %bb5292, label %cond_next5281 + + cond_next5281: ; preds = %invcont5272 + %tmp5283 = invoke i32 @report__ident_int( i32 -10 ) + to label %invcont5282 unwind label %unwind5266 ; [#uses=1] + + invcont5282: ; preds = %cond_next5281 + %tmp5287 = icmp sgt i32 %tmp5273, %tmp5283 ; [#uses=1] + br i1 %tmp5287, label %bb5292, label %bb5293 + + bb5292: ; preds = %invcont5282, %invcont5272 + br label %bb5293 + + bb5293: ; preds = %bb5292, %invcont5282 + %iftmp.179.0 = phi i1 [ false, %bb5292 ], [ true, %invcont5282 ] ; [#uses=1] + %tmp5295 = invoke i32 @report__ident_int( i32 10 ) + to label %invcont5294 unwind label %unwind5266 ; [#uses=1] + + invcont5294: ; preds = %bb5293 + %tmp5296 = icmp slt i32 %tmp5295, 1 ; [#uses=1] + %tmp5304 = invoke i32 @report__ident_int( i32 0 ) + to label %invcont5303 unwind label %unwind5266 ; [#uses=2] + + invcont5303: ; preds = %invcont5294 + %tmp5306 = invoke i32 @report__ident_int( i32 -10 ) + to label %invcont5305 unwind label %unwind5266 ; [#uses=1] + + invcont5305: ; preds = %invcont5303 + %tmp5331 = invoke i32 @report__ident_int( i32 -20 ) + to label %invcont5330 unwind label %unwind5266 ; [#uses=1] + + invcont5330: ; preds = %invcont5305 + %tmp5310 = icmp slt i32 %tmp5304, %tmp5306 ; [#uses=1] + %tmp5318 = icmp sgt i32 %tmp5304, -11 ; [#uses=1] + %bothcond5909 = or i1 %tmp5310, %tmp5318 ; [#uses=1] + %not.bothcond5909 = xor i1 %bothcond5909, true ; [#uses=1] + %tmp5332 = icmp sgt i32 %tmp5331, -1 ; [#uses=1] + %tmp5339 = invoke i32 @report__ident_int( i32 0 ) + to label %invcont5338 unwind label %unwind5266 ; [#uses=2] + + invcont5338: ; preds = %invcont5330 + %tmp5343 = icmp slt i32 %tmp5339, 6 ; [#uses=1] + br i1 %tmp5343, label %bb5358, label %cond_next5347 + + cond_next5347: ; preds = %invcont5338 + %tmp5349 = invoke i32 @report__ident_int( i32 5 ) + to label %invcont5348 unwind label %unwind5266 ; [#uses=1] + + invcont5348: ; preds = %cond_next5347 + %tmp5353 = icmp sgt i32 %tmp5339, %tmp5349 ; [#uses=1] + br i1 %tmp5353, label %bb5358, label %bb5359 + + bb5358: ; preds = %invcont5348, %invcont5338 + br label %bb5359 + + bb5359: ; preds = %bb5358, %invcont5348 + %iftmp.181.0 = phi i1 [ false, %bb5358 ], [ true, %invcont5348 ] ; [#uses=1] + %tmp5366 = invoke i32 @report__ident_int( i32 0 ) + to label %invcont5365 unwind label %unwind5266 ; [#uses=2] + + invcont5365: ; preds = %bb5359 + %tmp5370 = icmp slt i32 %tmp5366, 7 ; [#uses=1] + br i1 %tmp5370, label %bb5385, label %cond_next5374 + + cond_next5374: ; preds = %invcont5365 + %tmp5376 = invoke i32 @report__ident_int( i32 3 ) + to label %invcont5375 unwind label %unwind5266 ; [#uses=1] + + invcont5375: ; preds = %cond_next5374 + %tmp5380 = icmp sgt i32 %tmp5366, %tmp5376 ; [#uses=1] + br i1 %tmp5380, label %bb5385, label %bb5386 + + bb5385: ; preds = %invcont5375, %invcont5365 + br label %bb5386 + + bb5386: ; preds = %bb5385, %invcont5375 + %iftmp.182.0 = phi i1 [ false, %bb5385 ], [ true, %invcont5375 ] ; [#uses=1] + %tmp5301 = or i1 %tmp5296, %iftmp.179.0 ; [#uses=1] + %tmp5328 = or i1 %tmp5301, %not.bothcond5909 ; [#uses=1] + %tmp5336 = or i1 %tmp5328, %tmp5332 ; [#uses=1] + %tmp5363 = or i1 %tmp5336, %iftmp.181.0 ; [#uses=1] + %tmp5390 = or i1 %tmp5363, %iftmp.182.0 ; [#uses=1] + br i1 %tmp5390, label %cond_true5393, label %cond_next5401 + + cond_true5393: ; preds = %bb5386 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([27 x i8]* @.str36 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.178.2066 to i32) to i64), i64 32)) ) + to label %cond_next5401 unwind label %unwind5266 + + cond_next5401: ; preds = %cond_true5393, %bb5386 + %tmp5430 = invoke i32 @report__ident_int( i32 0 ) + to label %invcont5429 unwind label %unwind5266 ; [#uses=2] + + invcont5429: ; preds = %cond_next5401 + %tmp5432 = invoke i32 @report__ident_int( i32 4 ) + to label %invcont5431 unwind label %unwind5266 ; [#uses=1] + + invcont5431: ; preds = %invcont5429 + %tmp5436 = icmp slt i32 %tmp5430, %tmp5432 ; [#uses=1] + %tmp5444 = icmp sgt i32 %tmp5430, -4 ; [#uses=1] + %bothcond5911 = or i1 %tmp5436, %tmp5444 ; [#uses=1] + %tmp5457 = and i1 %bothcond5911, %bothcond5907 ; [#uses=1] + br i1 %tmp5457, label %finally5471, label %cond_true5462 + + cond_true5462: ; preds = %invcont5431 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([29 x i8]* @.str37 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.36.923 to i32) to i64), i64 32)) ) + to label %finally5471 unwind label %unwind5266 + + eh_then5476: ; preds = %unwind5266 + invoke void @__gnat_begin_handler( i8* %eh_ptr5267 ) + to label %invcont5482 unwind label %unwind5480 + + unwind5480: ; preds = %invcont5484, %invcont5482, %eh_then5476 + %eh_ptr5481 = call i8* @llvm.eh.exception( ) ; [#uses=1] + call void @__gnat_end_handler( i8* %eh_ptr5267 ) + call i32 (...)* @_Unwind_Resume( i8* %eh_ptr5481 ) ; :26 [#uses=0] + unreachable + + invcont5482: ; preds = %eh_then5476 + %tmp5483 = load void ()** @system__soft_links__abort_undefer ; [#uses=1] + invoke void %tmp5483( ) + to label %invcont5484 unwind label %unwind5480 + + invcont5484: ; preds = %invcont5482 + invoke void @report__failed( i64 or (i64 zext (i32 ptrtoint ([19 x i8]* @.str38 to i32) to i64), i64 shl (i64 zext (i32 ptrtoint (%struct.string___XUB* @C.170.1990 to i32) to i64), i64 32)) ) + to label %cleanup5493 unwind label %unwind5480 + + cleanup5493: ; preds = %invcont5484 + call void @__gnat_end_handler( i8* %eh_ptr5267 ) + call void @report__result( ) + ret void + + finally5471: ; preds = %cond_true5462, %invcont5431 + call void @report__result( ) + ret void + + Unwind: ; preds = %unwind5266, %unwind5032, %unwind4919, %unwind4770, %unwind3880, %unwind3618, %unwind3393, %eh_else3366, %eh_else3016, %eh_else2666, %eh_else1330, %eh_else932, %eh_else823 + %eh_exception.2 = phi i8* [ %eh_exception.05914.1, %eh_else823 ], [ %eh_ptr872, %eh_else932 ], [ %eh_ptr975, %eh_else1330 ], [ %eh_exception.296030.1, %eh_else2666 ], [ %eh_exception.336046.1, %eh_else3016 ], [ %eh_exception.396074.1, %eh_else3366 ], [ %eh_ptr3394, %unwind3393 ], [ %eh_ptr3619, %unwind3618 ], [ %eh_ptr3881, %unwind3880 ], [ %eh_ptr4771, %unwind4770 ], [ %eh_ptr4920, %unwind4919 ], [ %eh_ptr5033, %unwind5032 ], [ %eh_ptr5267, %unwind5266 ] ; [#uses=1] + call i32 (...)* @_Unwind_Resume( i8* %eh_exception.2 ) ; :27 [#uses=0] + unreachable + + UnifiedUnreachableBlock34: ; preds = %cond_true5031, %cond_true4918, %cond_true4609, %cond_true4504, %cond_true4481, %cond_true4187, %cond_true4117, %cond_true4027, %cond_true3935, %cond_true3907, %cond_true3729, %cond_true3675, %cond_true3617, %cond_true3543, %cond_true3448, %cond_true3420, %bb3227, %bb3193, %bb3171, %cond_true3061, %bb2877, %bb2843, %bb2821, %cond_true2711, %bb2558, %bb2524, %bb2506, %cond_true2410, %bb2203, %cond_true2171, %cond_true1946, %bb1605, %cond_true1573, %cond_true1546, %cond_true1418, %cond_true973, %cond_true870, %cond_true663, %cond_true637, %cond_true611, %cond_true585, %cond_true559, %cond_true533, %cond_true507, %cond_true465 + unreachable + + UnifiedReturnBlock35: ; preds = %cleanup4742, %invcont4719, %finally913, %cleanup928 + ret void + } + + declare i32 @report__ident_int(i32) + + declare void @__gnat_rcheck_10(i8*, i32) + + declare void @__gnat_rcheck_12(i8*, i32) + + declare void @report__test(i64, i64) + + declare i8* @llvm.eh.exception() + + declare i32 @llvm.eh.selector(i8*, i8*, ...) + + declare i32 @llvm.eh.typeid.for(i8*) + + declare i32 @__gnat_eh_personality(...) + + declare i32 @_Unwind_Resume(...) + + declare void @system__secondary_stack__ss_mark(%struct.system__secondary_stack__mark_id* sret ) + + declare void @system__img_int__image_integer(%struct.string___XUP* sret , i32) + + declare void @system__string_ops__str_concat(%struct.string___XUP* sret , i64, i64) + + declare void @report__failed(i64) + + declare void @system__secondary_stack__ss_release(i64) + + declare void @__gnat_begin_handler(i8*) + + declare void @__gnat_end_handler(i8*) + + declare i8 @report__equal(i32, i32) + + declare i8* @llvm.stacksave() + + declare void @__gnat_rcheck_07(i8*, i32) + + declare i8* @__gnat_malloc(i32) + + declare void @llvm.stackrestore(i8*) + + declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) + + declare void @__gnat_rcheck_05(i8*, i32) + + declare void @__gnat_rcheck_06(i8*, i32) + + declare void @system__img_enum__image_enumeration_8(%struct.string___XUP* sret , i32, i64, i8*) + + declare i32 @memcmp(i8*, i8*, i32, ...) + + declare void @report__result() From baldrick at free.fr Wed Jun 6 05:05:40 2007 From: baldrick at free.fr (Duncan Sands) Date: Wed, 6 Jun 2007 05:05:40 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Message-ID: <200706061005.l56A5eX0020185@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAGISel.cpp updated: 1.456 -> 1.457 --- Log message: Additional fix for PR1422: http://llvm.org/PR1422 : make sure the landing pad label is placed in the correct machine basic block - do not rely on the eh.exception intrinsic being in the landing pad: the loop optimizers can move it out. --- Diffs of the changes: (+26 -15) SelectionDAGISel.cpp | 41 ++++++++++++++++++++++++++--------------- 1 files changed, 26 insertions(+), 15 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.456 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.457 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.456 Sat Jun 2 11:53:42 2007 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Wed Jun 6 05:05:18 2007 @@ -1337,12 +1337,10 @@ void SelectionDAGLowering::visitInvoke(InvokeInst &I, bool AsTerminator) { // Retrieve successors. MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)]; - MachineBasicBlock *LandingPad = FuncInfo.MBBMap[I.getSuccessor(1)]; - + if (!AsTerminator) { - // Mark landing pad so that it doesn't get deleted in branch folding. - LandingPad->setIsLandingPad(); - + MachineBasicBlock *LandingPad = FuncInfo.MBBMap[I.getSuccessor(1)]; + LowerCallTo(I, I.getCalledValue()->getType(), I.getCallingConv(), false, @@ -2577,16 +2575,10 @@ MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); if (MMI) { - // Add a label to mark the beginning of the landing pad. Deletion of the - // landing pad can thus be detected via the MachineModuleInfo. - unsigned LabelID = MMI->addLandingPad(CurMBB); - DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, DAG.getEntryNode(), - DAG.getConstant(LabelID, MVT::i32))); - // Mark exception register as live in. unsigned Reg = TLI.getExceptionAddressRegister(); if (Reg) CurMBB->addLiveIn(Reg); - + // Insert the EXCEPTIONADDR instruction. SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other); SDOperand Ops[1]; @@ -2626,7 +2618,7 @@ MMI->addFilterTypeInfo(CurMBB, TyInfo); else MMI->addCatchTypeInfo(CurMBB, TyInfo); - + // Mark exception selector register as live in. unsigned Reg = TLI.getExceptionSelectorRegister(); if (Reg) CurMBB->addLiveIn(Reg); @@ -2788,7 +2780,7 @@ Args.push_back(Entry); } - if (ExceptionHandling) { + if (ExceptionHandling && MMI) { // Insert a label before the invoke call to mark the try range. This can be // used to detect deletion of the invoke via the MachineModuleInfo. BeginLabel = MMI->NextLabelID(); @@ -2805,7 +2797,7 @@ setValue(&I, Result.first); DAG.setRoot(Result.second); - if (ExceptionHandling) { + if (ExceptionHandling && MMI) { // Insert a label at the end of the invoke call to mark the try range. This // can be used to detect deletion of the invoke via the MachineModuleInfo. EndLabel = MMI->NextLabelID(); @@ -4387,6 +4379,13 @@ FunctionLoweringInfo FuncInfo(TLI, Fn, MF); for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) + if (InvokeInst *Invoke = dyn_cast(I->getTerminator())) { + // Mark landing pad. + MachineBasicBlock *LandingPad = FuncInfo.MBBMap[Invoke->getSuccessor(1)]; + LandingPad->setIsLandingPad(); + } + + for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) SelectBasicBlock(I, MF, FuncInfo); // Add function live-ins to entry block live-in set. @@ -4523,6 +4522,18 @@ BB = FuncInfo.MBBMap[LLVMBB]; SDL.setCurrentBasicBlock(BB); + if (ExceptionHandling && BB->isLandingPad()) { + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + + if (MMI) { + // Add a label to mark the beginning of the landing pad. Deletion of the + // landing pad can thus be detected via the MachineModuleInfo. + unsigned LabelID = MMI->addLandingPad(BB); + DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, DAG.getEntryNode(), + DAG.getConstant(LabelID, MVT::i32))); + } + } + // Lower all of the non-terminator instructions. for (BasicBlock::iterator I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I) From evan.cheng at apple.com Wed Jun 6 05:14:17 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 6 Jun 2007 05:14:17 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/TargetInstrInfo.h Message-ID: <200706061014.l56AEHRu020422@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: TargetInstrInfo.h updated: 1.125 -> 1.126 --- Log message: Add a machine instruction flag indicating the instruction can clobber condition code / register(s) used to predicate instructions. --- Diffs of the changes: (+6 -0) TargetInstrInfo.h | 6 ++++++ 1 files changed, 6 insertions(+) Index: llvm/include/llvm/Target/TargetInstrInfo.h diff -u llvm/include/llvm/Target/TargetInstrInfo.h:1.125 llvm/include/llvm/Target/TargetInstrInfo.h:1.126 --- llvm/include/llvm/Target/TargetInstrInfo.h:1.125 Tue May 29 13:30:54 2007 +++ llvm/include/llvm/Target/TargetInstrInfo.h Wed Jun 6 05:13:55 2007 @@ -82,6 +82,9 @@ // at any time, e.g. constant generation, load from constant pool. const unsigned M_REMATERIALIZIBLE = 1 << 13; +// M_CLOBBERS_PRED - Set if this instruction may clobbers the condition code +// register and / or registers that are used to predicate instructions. +const unsigned M_CLOBBERS_PRED = 1 << 14; // Machine operand flags // M_LOOK_UP_PTR_REG_CLASS - Set if this operand is a pointer value and it @@ -211,6 +214,9 @@ bool isPredicable(MachineOpCode Opcode) const { return get(Opcode).Flags & M_PREDICABLE; } + bool clobbersPredicate(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_CLOBBERS_PRED; + } bool isReMaterializable(MachineOpCode Opcode) const { return get(Opcode).Flags & M_REMATERIALIZIBLE; } From evan.cheng at apple.com Wed Jun 6 05:15:17 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 6 Jun 2007 05:15:17 -0500 Subject: [llvm-commits] CVS: llvm/utils/TableGen/CodeGenInstruction.h CodeGenTarget.cpp InstrInfoEmitter.cpp Message-ID: <200706061015.l56AFHXj020466@zion.cs.uiuc.edu> Changes in directory llvm/utils/TableGen: CodeGenInstruction.h updated: 1.27 -> 1.28 CodeGenTarget.cpp updated: 1.90 -> 1.91 InstrInfoEmitter.cpp updated: 1.59 -> 1.60 --- Log message: Add clobbersPred - instruction that clobbers condition code / register which are used to predicate instructions. --- Diffs of the changes: (+3 -0) CodeGenInstruction.h | 1 + CodeGenTarget.cpp | 1 + InstrInfoEmitter.cpp | 1 + 3 files changed, 3 insertions(+) Index: llvm/utils/TableGen/CodeGenInstruction.h diff -u llvm/utils/TableGen/CodeGenInstruction.h:1.27 llvm/utils/TableGen/CodeGenInstruction.h:1.28 --- llvm/utils/TableGen/CodeGenInstruction.h:1.27 Wed May 16 15:45:24 2007 +++ llvm/utils/TableGen/CodeGenInstruction.h Wed Jun 6 05:14:55 2007 @@ -97,6 +97,7 @@ bool hasVariableNumberOfOperands; bool hasCtrlDep; bool noResults; + bool clobbersPred; /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar", /// where $foo is a whole operand and $foo.bar refers to a suboperand. Index: llvm/utils/TableGen/CodeGenTarget.cpp diff -u llvm/utils/TableGen/CodeGenTarget.cpp:1.90 llvm/utils/TableGen/CodeGenTarget.cpp:1.91 --- llvm/utils/TableGen/CodeGenTarget.cpp:1.90 Mon Jun 4 11:11:03 2007 +++ llvm/utils/TableGen/CodeGenTarget.cpp Wed Jun 6 05:14:55 2007 @@ -360,6 +360,7 @@ usesCustomDAGSchedInserter = R->getValueAsBit("usesCustomDAGSchedInserter"); hasCtrlDep = R->getValueAsBit("hasCtrlDep"); noResults = R->getValueAsBit("noResults"); + clobbersPred = R->getValueAsBit("clobbersPred"); hasVariableNumberOfOperands = false; DagInit *DI; Index: llvm/utils/TableGen/InstrInfoEmitter.cpp diff -u llvm/utils/TableGen/InstrInfoEmitter.cpp:1.59 llvm/utils/TableGen/InstrInfoEmitter.cpp:1.60 --- llvm/utils/TableGen/InstrInfoEmitter.cpp:1.59 Wed May 16 15:45:24 2007 +++ llvm/utils/TableGen/InstrInfoEmitter.cpp Wed Jun 6 05:14:55 2007 @@ -241,6 +241,7 @@ if (Inst.isCommutable) OS << "|M_COMMUTABLE"; if (Inst.isTerminator) OS << "|M_TERMINATOR_FLAG"; if (Inst.isReMaterializable) OS << "|M_REMATERIALIZIBLE"; + if (Inst.clobbersPred) OS << "|M_CLOBBERS_PRED"; if (Inst.usesCustomDAGSchedInserter) OS << "|M_USES_CUSTOM_DAG_SCHED_INSERTION"; if (Inst.hasVariableNumberOfOperands) From evan.cheng at apple.com Wed Jun 6 05:15:50 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 6 Jun 2007 05:15:50 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Target.td Message-ID: <200706061015.l56AFoE9020491@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target: Target.td updated: 1.101 -> 1.102 --- Log message: Added clobbersPred. --- Diffs of the changes: (+1 -0) Target.td | 1 + 1 files changed, 1 insertion(+) Index: llvm/lib/Target/Target.td diff -u llvm/lib/Target/Target.td:1.101 llvm/lib/Target/Target.td:1.102 --- llvm/lib/Target/Target.td:1.101 Wed May 16 15:47:01 2007 +++ llvm/lib/Target/Target.td Wed Jun 6 05:15:28 2007 @@ -188,6 +188,7 @@ bit usesCustomDAGSchedInserter = 0; // Pseudo instr needing special help. bit hasCtrlDep = 0; // Does this instruction r/w ctrl-flow chains? bit noResults = 0; // Does this instruction produce no results? + bit clobbersPred = 0; // Does it clobbers condition code / predicate? InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling. From evan.cheng at apple.com Wed Jun 6 05:16:39 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 6 Jun 2007 05:16:39 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706061016.l56AGdb7020524@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.32 -> 1.33 --- Log message: Lots of bug fixes. --- Diffs of the changes: (+76 -40) IfConversion.cpp | 116 ++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 76 insertions(+), 40 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.32 llvm/lib/CodeGen/IfConversion.cpp:1.33 --- llvm/lib/CodeGen/IfConversion.cpp:1.32 Tue Jun 5 21:08:52 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Wed Jun 6 05:16:17 2007 @@ -41,7 +41,7 @@ ICTriangle, // BB is entry of a triangle sub-CFG. ICDiamond, // BB is entry of a diamond sub-CFG. ICChild, // BB is part of the sub-CFG that'll be predicated. - ICDead // BB has been converted and merged, it's now dead. + ICDead // BB cannot be if-converted again. }; /// BBInfo - One per MachineBasicBlock, this is used to cache the result @@ -54,8 +54,8 @@ /// Kind - Type of block. See BBICKind. /// NonPredSize - Number of non-predicated instructions. /// IsAnalyzable - True if AnalyzeBranch() returns false. - /// ModifyPredicate - FIXME: Not used right now. True if BB would modify - /// the predicate (e.g. has cmp, call, etc.) + /// ModifyPredicate - True if BB would modify the predicate (e.g. has + /// cmp, call, etc.) /// BB - Corresponding MachineBasicBlock. /// TrueBB / FalseBB- See AnalyzeBranch(). /// BrCond - Conditions for end of block conditional branches. @@ -96,6 +96,7 @@ private: bool ReverseBranchCondition(BBInfo &BBI); + bool BlockModifyPredicate(MachineBasicBlock *BB) const; void StructuralAnalysis(MachineBasicBlock *BB); bool FeasibilityAnalysis(BBInfo &BBI, std::vector &Cond, @@ -112,6 +113,11 @@ bool IgnoreTerm = false); void MergeBlocks(BBInfo &TrueBBI, BBInfo &FalseBBI); + // blockFallsThrough - Block ends without a terminator. + bool blockFallsThrough(BBInfo &BBI) const { + return BBI.IsAnalyzable && BBI.TrueBB == NULL; + } + // IfcvtCandidateCmp - Used to sort if-conversion candidates. static bool IfcvtCandidateCmp(BBInfo* C1, BBInfo* C2){ // Favor diamond over triangle, etc. @@ -161,7 +167,9 @@ case ICSimpleFalse: { bool isRev = BBI.Kind == ICSimpleFalse; DOUT << "Ifcvt (Simple" << (BBI.Kind == ICSimpleFalse ? " false" : "") - << "): BB#" << BBI.BB->getNumber() << " "; + << "): BB#" << BBI.BB->getNumber() << " (" + << ((BBI.Kind == ICSimpleFalse) + ? BBI.FalseBB->getNumber() : BBI.TrueBB->getNumber()) << ") "; RetVal = IfConvertSimple(BBI); DOUT << (RetVal ? "succeeded!" : "failed!") << "\n"; if (RetVal) @@ -170,13 +178,19 @@ break; } case ICTriangle: - DOUT << "Ifcvt (Triangle): BB#" << BBI.BB->getNumber() << " "; + DOUT << "Ifcvt (Triangle): BB#" << BBI.BB->getNumber() << " (T:" + << BBI.TrueBB->getNumber() << ",F:" << BBI.FalseBB->getNumber() + << ") "; RetVal = IfConvertTriangle(BBI); DOUT << (RetVal ? "succeeded!" : "failed!") << "\n"; if (RetVal) NumTriangle++; break; case ICDiamond: - DOUT << "Ifcvt (Diamond): BB#" << BBI.BB->getNumber() << " "; + DOUT << "Ifcvt (Diamond): BB#" << BBI.BB->getNumber() << " (T:" + << BBI.TrueBB->getNumber() << ",F:" << BBI.FalseBB->getNumber(); + if (BBI.TailBB) + DOUT << "," << BBI.TailBB->getNumber() ; + DOUT << ") "; RetVal = IfConvertDiamond(BBI); DOUT << (RetVal ? "succeeded!" : "failed!") << "\n"; if (RetVal) NumDiamonds++; @@ -217,6 +231,17 @@ return false; } +/// BlockModifyPredicate - Returns true if any instruction in the block may +/// clobber the condition code or register(s) used to predicate instructions, +/// e.g. call, cmp. +bool IfConverter::BlockModifyPredicate(MachineBasicBlock *BB) const { + for (MachineBasicBlock::const_reverse_iterator I = BB->rbegin(), + E = BB->rend(); I != E; ++I) + if (I->getInstrDescriptor()->Flags & M_CLOBBERS_PRED) + return true; + return false; +} + /// StructuralAnalysis - Analyze the structure of the sub-CFG starting from /// the specified block. Record its successors and whether it looks like an /// if-conversion candidate. @@ -231,6 +256,7 @@ return; // Already analyzed. BBI.BB = BB; BBI.NonPredSize = std::distance(BB->begin(), BB->end()); + BBI.ModifyPredicate = BlockModifyPredicate(BB); } // Look for 'root' of a simple (non-nested) triangle or diamond. @@ -254,7 +280,13 @@ StructuralAnalysis(BBI.FalseBB); BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; - + + // If both paths are dead, then forget about it. + if (TrueBBI.Kind == ICDead && FalseBBI.Kind == ICDead) { + BBI.Kind = ICDead; + return; + } + // Look for more opportunities to if-convert a triangle. Try to restructure // the CFG to form a triangle with the 'false' path. std::vector RevCond(BBI.BrCond); @@ -337,11 +369,12 @@ } } else if (FalseBBI.BrCond.size() == 0 && FalseBBI.BB->pred_size() == 1) { // Try the other path... + bool TryTriangle = FalseBBI.TrueBB && FalseBBI.TrueBB == BBI.TrueBB && + FalseBBI.BB->pred_size() == 1; std::vector RevCond(BBI.BrCond); if (!TII->ReverseBranchCondition(RevCond) && FeasibilityAnalysis(FalseBBI, RevCond)) { - if (FalseBBI.TrueBB && FalseBBI.TrueBB == BBI.TrueBB && - FalseBBI.BB->pred_size() == 1) { + if (TryTriangle) { // Reverse 'true' and 'false' paths. ReverseBranchCondition(BBI); BBI.Kind = ICTriangle; @@ -486,17 +519,13 @@ /// IfConvertSimple - If convert a simple (split, no rejoin) sub-CFG. /// bool IfConverter::IfConvertSimple(BBInfo &BBI) { - bool ReverseCond = BBI.Kind == ICSimpleFalse; - - BBI.Kind = ICNotClassfied; - BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; BBInfo *CvtBBI = &TrueBBI; BBInfo *NextBBI = &FalseBBI; std::vector Cond(BBI.BrCond); - if (ReverseCond) { + if (BBI.Kind == ICSimpleFalse) { std::swap(CvtBBI, NextBBI); TII->ReverseBranchCondition(Cond); } @@ -517,23 +546,27 @@ MergeBlocks(BBI, *CvtBBI); bool IterIfcvt = true; if (!isNextBlock(BBI.BB, NextBBI->BB)) { - // Now ifcvt'd block will look like this: - // BB: - // ... - // t, f = cmp - // if t op - // b BBf - // - // We cannot further ifcvt this block because the unconditional branch will - // have to be predicated on the new condition, that will not be available - // if cmp executes. InsertUncondBranch(BBI.BB, NextBBI->BB, TII); + if (BBI.ModifyPredicate) + // Now ifcvt'd block will look like this: + // BB: + // ... + // t, f = cmp + // if t op + // b BBf + // + // We cannot further ifcvt this block because the unconditional branch will + // have to be predicated on the new condition, that will not be available + // if cmp executes. + IterIfcvt = false; } std::copy(Cond.begin(), Cond.end(), std::back_inserter(BBI.Predicate)); // Update block info. BB can be iteratively if-converted. if (IterIfcvt) BBI.Kind = ICReAnalyze; + else + BBI.Kind = ICDead; ReTryPreds(BBI.BB); CvtBBI->Kind = ICDead; @@ -544,8 +577,6 @@ /// IfConvertTriangle - If convert a triangle sub-CFG. /// bool IfConverter::IfConvertTriangle(BBInfo &BBI) { - BBI.Kind = ICNotClassfied; - BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; // Predicate the 'true' block after removing its branch. @@ -571,17 +602,18 @@ FalseBBDead = true; } else if (!isNextBlock(TrueBBI.BB, FalseBBI.BB)) { InsertUncondBranch(TrueBBI.BB, FalseBBI.BB, TII); - // Now ifcvt'd block will look like this: - // BB: - // ... - // t, f = cmp - // if t op - // b BBf - // - // We cannot further ifcvt this block because the unconditional branch will - // have to be predicated on the new condition, that will not be available - // if cmp executes. - IterIfcvt = false; + if (BBI.ModifyPredicate || TrueBBI.ModifyPredicate) + // Now ifcvt'd block will look like this: + // BB: + // ... + // t, f = cmp + // if t op + // b BBf + // + // We cannot further ifcvt this block because the unconditional branch will + // have to be predicated on the new condition, that will not be available + // if cmp executes. + IterIfcvt = false; } // Now merge the entry of the triangle with the true block. @@ -593,6 +625,8 @@ // Update block info. BB can be iteratively if-converted. if (IterIfcvt) BBI.Kind = ICReAnalyze; + else + BBI.Kind = ICDead; ReTryPreds(BBI.BB); TrueBBI.Kind = ICDead; if (FalseBBDead) @@ -605,8 +639,6 @@ /// IfConvertDiamond - If convert a diamond sub-CFG. /// bool IfConverter::IfConvertDiamond(BBInfo &BBI) { - BBI.Kind = ICNotClassfied; - BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; @@ -714,6 +746,7 @@ } // Update block info. + BBI.Kind = ICDead; TrueBBI.Kind = ICDead; FalseBBI.Kind = ICDead; @@ -785,7 +818,10 @@ // Transfer preds / succs and update size. TransferPreds(ToBBI.BB, FromBBI.BB); - TransferSuccs(ToBBI.BB, FromBBI.BB); + if (!blockFallsThrough(FromBBI.BB)) + TransferSuccs(ToBBI.BB, FromBBI.BB); ToBBI.NonPredSize += FromBBI.NonPredSize; FromBBI.NonPredSize = 0; + + ToBBI.ModifyPredicate |= FromBBI.ModifyPredicate; } From evan.cheng at apple.com Wed Jun 6 05:17:27 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 6 Jun 2007 05:17:27 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/ARM/ARMInstrInfo.td ARMInstrThumb.td ARMInstrVFP.td Message-ID: <200706061017.l56AHRha020566@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/ARM: ARMInstrInfo.td updated: 1.109 -> 1.110 ARMInstrThumb.td updated: 1.28 -> 1.29 ARMInstrVFP.td updated: 1.7 -> 1.8 --- Log message: Mark these instructions clobbersPred. They modify the condition code register. --- Diffs of the changes: (+19 -9) ARMInstrInfo.td | 25 +++++++++++++++++-------- ARMInstrThumb.td | 1 + ARMInstrVFP.td | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) Index: llvm/lib/Target/ARM/ARMInstrInfo.td diff -u llvm/lib/Target/ARM/ARMInstrInfo.td:1.109 llvm/lib/Target/ARM/ARMInstrInfo.td:1.110 --- llvm/lib/Target/ARM/ARMInstrInfo.td:1.109 Fri Jun 1 15:51:29 2007 +++ llvm/lib/Target/ARM/ARMInstrInfo.td Wed Jun 6 05:17:05 2007 @@ -612,7 +612,7 @@ "ldm${p}${addr:submode} $addr, $dst1", []>; -let isCall = 1, noResults = 1, +let isCall = 1, noResults = 1, clobbersPred = 1, Defs = [R0, R1, R2, R3, R12, LR, D0, D1, D2, D3, D4, D5, D6, D7] in { def BL : AXI<(ops i32imm:$func, variable_ops), @@ -806,12 +806,14 @@ // These aren't really mov instructions, but we have to define them this way // due to flag operands. +let clobbersPred = 1 in { def MOVsrl_flag : AI1<(ops GPR:$dst, GPR:$src), "mov", "s $dst, $src, lsr #1", [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>; def MOVsra_flag : AI1<(ops GPR:$dst, GPR:$src), "mov", "s $dst, $src, asr #1", [(set GPR:$dst, (ARMsra_flag GPR:$src))]>; +} def MOVrx : AI1<(ops GPR:$dst, GPR:$src), "mov", " $dst, $src, rrx", [(set GPR:$dst, (ARMrrx GPR:$src))]>; @@ -860,17 +862,22 @@ // defm ADD : AI1_bin_irs<"add", "" , BinOpFrag<(add node:$LHS, node:$RHS)>>; -defm ADDS : AI1_bin_irs<"add", "s", BinOpFrag<(addc node:$LHS, node:$RHS)>>; defm ADC : AI1_bin_irs<"adc", "" , BinOpFrag<(adde node:$LHS, node:$RHS)>>; defm SUB : AI1_bin_irs<"sub", "" , BinOpFrag<(sub node:$LHS, node:$RHS)>>; -defm SUBS : AI1_bin_irs<"sub", "s", BinOpFrag<(subc node:$LHS, node:$RHS)>>; defm SBC : AI1_bin_irs<"sbc", "" , BinOpFrag<(sube node:$LHS, node:$RHS)>>; +let clobbersPred = 1 in { +defm ADDS : AI1_bin_irs<"add", "s", BinOpFrag<(addc node:$LHS, node:$RHS)>>; +defm SUBS : AI1_bin_irs<"sub", "s", BinOpFrag<(subc node:$LHS, node:$RHS)>>; +} + // These don't define reg/reg forms, because they are handled above. defm RSB : AI1_bin_is <"rsb", "" , BinOpFrag<(sub node:$RHS, node:$LHS)>>; -defm RSBS : AI1_bin_is <"rsb", "s", BinOpFrag<(subc node:$RHS, node:$LHS)>>; defm RSC : AI1_bin_is <"rsc", "" , BinOpFrag<(sube node:$RHS, node:$LHS)>>; +let clobbersPred = 1 in +defm RSBS : AI1_bin_is <"rsb", "s", BinOpFrag<(subc node:$RHS, node:$LHS)>>; + // (sub X, imm) gets canonicalized to (add X, -imm). Match this form. def : ARMPat<(add GPR:$src, so_imm_neg:$imm), (SUBri GPR:$src, so_imm_neg:$imm)>; @@ -1094,18 +1101,20 @@ // Comparison Instructions... // +let clobbersPred = 1 in { defm CMP : AI1_bin0_irs<"cmp", BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>; defm CMN : AI1_bin0_irs<"cmn", BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>; -def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm), - (CMNri GPR:$src, so_imm_neg:$imm)>; - // Note that TST/TEQ don't set all the same flags that CMP does! defm TST : AI1_bin0_irs<"tst", BinOpFrag<(ARMcmpNZ (and node:$LHS, node:$RHS), 0)>>; defm TEQ : AI1_bin0_irs<"teq", BinOpFrag<(ARMcmpNZ (xor node:$LHS, node:$RHS), 0)>>; defm CMPnz : AI1_bin0_irs<"cmp", BinOpFrag<(ARMcmpNZ node:$LHS, node:$RHS)>>; defm CMNnz : AI1_bin0_irs<"cmn", BinOpFrag<(ARMcmpNZ node:$LHS,(ineg node:$RHS))>>; +} + +def : ARMPat<(ARMcmp GPR:$src, so_imm_neg:$imm), + (CMNri GPR:$src, so_imm_neg:$imm)>; def : ARMPat<(ARMcmpNZ GPR:$src, so_imm_neg:$imm), (CMNri GPR:$src, so_imm_neg:$imm)>; @@ -1148,7 +1157,7 @@ // // __aeabi_read_tp preserves the registers r1-r3. -let isCall = 1, +let isCall = 1, clobbersPred = 1, Defs = [R0, R12, LR] in { def TPsoft : AXI<(ops), "bl __aeabi_read_tp", Index: llvm/lib/Target/ARM/ARMInstrThumb.td diff -u llvm/lib/Target/ARM/ARMInstrThumb.td:1.28 llvm/lib/Target/ARM/ARMInstrThumb.td:1.29 --- llvm/lib/Target/ARM/ARMInstrThumb.td:1.28 Wed May 16 16:53:43 2007 +++ llvm/lib/Target/ARM/ARMInstrThumb.td Wed Jun 6 05:17:05 2007 @@ -33,6 +33,7 @@ string asm, string cstr, list pattern> // FIXME: Set all opcodes to 0 for now. : InstARM<0, am, sz, IndexModeNone, cstr> { + let clobbersPred = 1; let OperandList = ops; let AsmString = asm; let Pattern = pattern; Index: llvm/lib/Target/ARM/ARMInstrVFP.td diff -u llvm/lib/Target/ARM/ARMInstrVFP.td:1.7 llvm/lib/Target/ARM/ARMInstrVFP.td:1.8 --- llvm/lib/Target/ARM/ARMInstrVFP.td:1.7 Tue May 29 18:34:19 2007 +++ llvm/lib/Target/ARM/ARMInstrVFP.td Wed Jun 6 05:17:05 2007 @@ -277,7 +277,7 @@ // FMSRR: GPR -> SPR - +let clobbersPred = 1 in def FMSTAT : ASI<(ops), "fmstat", "", [(arm_fmstat)]>; // FMXR: GPR -> VFP Sstem reg From nicholas at mxc.ca Wed Jun 6 06:26:42 2007 From: nicholas at mxc.ca (Nick Lewycky) Date: Wed, 6 Jun 2007 06:26:42 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/ScalarEvolution.cpp Message-ID: <200706061126.l56BQgZu021761@zion.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: ScalarEvolution.cpp updated: 1.117 -> 1.118 --- Log message: Optimize this test. Firstly, only Instructions may use other Instructions. Secondly, checking whether removal succeeded tells you whether it was in the map to begin with. --- Diffs of the changes: (+2 -2) ScalarEvolution.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/Analysis/ScalarEvolution.cpp diff -u llvm/lib/Analysis/ScalarEvolution.cpp:1.117 llvm/lib/Analysis/ScalarEvolution.cpp:1.118 --- llvm/lib/Analysis/ScalarEvolution.cpp:1.117 Tue Jun 5 23:12:20 2007 +++ llvm/lib/Analysis/ScalarEvolution.cpp Wed Jun 6 06:26:20 2007 @@ -1210,8 +1210,8 @@ for (Instruction::use_iterator UI = II->use_begin(), UE = II->use_end(); UI != UE; ++UI) { - Instruction *Inst = dyn_cast(*UI); - if (Inst && hasSCEV(Inst) && Scalars.erase(Inst)) { + Instruction *Inst = cast(*UI); + if (Scalars.erase(Inst)) { if (PHINode *PN = dyn_cast(II)) ConstantEvolutionLoopExitValue.erase(PN); Worklist.push_back(Inst); From nicholas at mxc.ca Wed Jun 6 07:19:21 2007 From: nicholas at mxc.ca (Nick Lewycky) Date: Wed, 06 Jun 2007 08:19:21 -0400 Subject: [llvm-commits] CVS: llvm/lib/Analysis/ScalarEvolution.cpp In-Reply-To: <7731079E-CD1B-4975-A68C-1FA2CA686925@apple.com> References: <200706060412.l564CgV9003861@zion.cs.uiuc.edu> <7731079E-CD1B-4975-A68C-1FA2CA686925@apple.com> Message-ID: <4666A649.5050903@mxc.ca> Chris Lattner wrote: > The only thing that can use Instructions are other intstructions. As > such, you can change the dyn_cast into cast > and there is no need to check for null in the next line. Fixed. Thanks Chris! Nick From baldrick at free.fr Wed Jun 6 10:37:56 2007 From: baldrick at free.fr (Duncan Sands) Date: Wed, 6 Jun 2007 10:37:56 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/DwarfWriter.cpp Message-ID: <200706061537.l56FbulM027892@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: DwarfWriter.cpp updated: 1.150 -> 1.151 --- Log message: Fold the exception actions table harder: if two typeid lists start the same, only output one copy of the common part. --- Diffs of the changes: (+68 -56) DwarfWriter.cpp | 124 ++++++++++++++++++++++++++++++-------------------------- 1 files changed, 68 insertions(+), 56 deletions(-) Index: llvm/lib/CodeGen/DwarfWriter.cpp diff -u llvm/lib/CodeGen/DwarfWriter.cpp:1.150 llvm/lib/CodeGen/DwarfWriter.cpp:1.151 --- llvm/lib/CodeGen/DwarfWriter.cpp:1.150 Sat Jun 2 11:53:42 2007 +++ llvm/lib/CodeGen/DwarfWriter.cpp Wed Jun 6 10:37:31 2007 @@ -2894,36 +2894,32 @@ O << UsedDirective << EHFrameInfo.FnName << ".eh\n\n"; } - /// EquivPads - Whether two landing pads have equivalent actions. - static bool EquivPads(const LandingPadInfo *L, const LandingPadInfo *R) { - const std::vector &LIds = L->TypeIds; - const std::vector &RIds = R->TypeIds; + /// SharedTypeIds - How many leading type ids two landing pads have in common. + static unsigned SharedTypeIds(const LandingPadInfo *L, + const LandingPadInfo *R) { + const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds; unsigned LSize = LIds.size(), RSize = RIds.size(); + unsigned MinSize = LSize < RSize ? LSize : RSize; + unsigned Count = 0; - if (LSize != RSize) - return false; + for (; Count != MinSize; ++Count) + if (LIds[Count] != RIds[Count]) + return Count; - for (unsigned i = 0; i != LSize; ++i) - if (LIds[i] != RIds[i]) - return false; - - return true; + return Count; } - /// PadLT - An order on landing pads, with EquivPads as order equivalence. + /// PadLT - Order landing pads lexicographically by type id. static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { - const std::vector &LIds = L->TypeIds; - const std::vector &RIds = R->TypeIds; + const std::vector &LIds = L->TypeIds, &RIds = R->TypeIds; unsigned LSize = LIds.size(), RSize = RIds.size(); + unsigned MinSize = LSize < RSize ? LSize : RSize; - if (LSize != RSize) - return LSize < RSize; - - for (unsigned i = 0; i != LSize; ++i) + for (unsigned i = 0; i != MinSize; ++i) if (LIds[i] != RIds[i]) return LIds[i] < RIds[i]; - return false; // Equivalent + return LSize < RSize; } /// EmitExceptionTable - Emit landpads and actions. @@ -2960,6 +2956,12 @@ typedef DenseMap PadMapType; + struct ActionEntry { + int TypeID; + int NextAction; + struct ActionEntry *Previous; + }; + void EmitExceptionTable() { // Map all labels and get rid of any dead landing pads. MMI->TidyLandingPads(); @@ -2977,7 +2979,10 @@ std::sort(LandingPads.begin(), LandingPads.end(), PadLT); // Gather first action index for each landing pad site. - SmallVector Actions; + SmallVector FirstActions; + + // The actions table. + SmallVector Actions; // Compute sizes for exception table. unsigned SizeSites = 0; @@ -2985,38 +2990,55 @@ // Look at each landing pad site to compute size. We need the size of each // landing pad site info and the size of the landing pad's actions. - signed FirstAction = 0; + int FirstAction = 0; for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { - const LandingPadInfo *LandingPad = LandingPads[i]; + const LandingPadInfo *LP = LandingPads[i]; + const std::vector &TypeIds = LP->TypeIds; + const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0; unsigned SizeSiteActions = 0; - if (!i || !EquivPads(LandingPad, LandingPads[i-1])) { - const std::vector &TypeIds = LandingPad->TypeIds; + if (NumShared < TypeIds.size()) { unsigned SizeAction = 0; + ActionEntry *PrevAction = 0; - if (TypeIds.empty()) { - FirstAction = 0; - } else { - // Gather the action sizes - for (unsigned j = 0, M = TypeIds.size(); j != M; ++j) { - int TypeID = TypeIds[j]; - unsigned SizeTypeID = Asm->SizeSLEB128(TypeID); - signed Action = j ? -(SizeAction + SizeTypeID) : 0; - SizeAction = SizeTypeID + Asm->SizeSLEB128(Action); - SizeSiteActions += SizeAction; + if (NumShared) { + const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size(); + assert(Actions.size()); + PrevAction = &Actions.back(); + SizeAction = Asm->SizeSLEB128(PrevAction->NextAction) + + Asm->SizeSLEB128(PrevAction->TypeID); + for (unsigned j = NumShared; j != SizePrevIds; ++j) { + SizeAction -= Asm->SizeSLEB128(PrevAction->TypeID); + SizeAction += -PrevAction->NextAction; + PrevAction = PrevAction->Previous; } + } - // Record the first action of the landing pad site. - FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; + // Compute the actions. + for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) { + int TypeID = TypeIds[I]; + unsigned SizeTypeID = Asm->SizeSLEB128(TypeID); + + int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; + SizeAction = SizeTypeID + Asm->SizeSLEB128(NextAction); + SizeSiteActions += SizeAction; + + ActionEntry Action = {TypeID, NextAction, PrevAction}; + Actions.push_back(Action); + + PrevAction = &Actions.back(); } - } // else re-use previous FirstAction - Actions.push_back(FirstAction); + // Record the first action of the landing pad site. + FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; + } // else identical - re-use previous FirstAction + + FirstActions.push_back(FirstAction); // Compute this sites contribution to size. SizeActions += SizeSiteActions; - unsigned M = LandingPad->BeginLabels.size(); + unsigned M = LP->BeginLabels.size(); SizeSites += M*(sizeof(int32_t) + // Site start. sizeof(int32_t) + // Site length. sizeof(int32_t) + // Landing pad. @@ -3111,29 +3133,19 @@ } Asm->EOL("Landing pad"); - Asm->EmitULEB128Bytes(Actions[P.PadIndex]); + Asm->EmitULEB128Bytes(FirstActions[P.PadIndex]); Asm->EOL("Action"); } } // Emit the actions. - for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { - if (!i || Actions[i] != Actions[i-1]) { - const LandingPadInfo *LandingPad = LandingPads[i]; - const std::vector &TypeIds = LandingPad->TypeIds; - unsigned SizeAction = 0; + for (unsigned I = 0, N = Actions.size(); I != N; ++I) { + ActionEntry &Action = Actions[I]; - for (unsigned j = 0, M = TypeIds.size(); j < M; ++j) { - int TypeID = TypeIds[j]; - unsigned SizeTypeID = Asm->SizeSLEB128(TypeID); - Asm->EmitSLEB128Bytes(TypeID); - Asm->EOL("TypeInfo index"); - signed Action = j ? -(SizeAction + SizeTypeID) : 0; - SizeAction = SizeTypeID + Asm->SizeSLEB128(Action); - Asm->EmitSLEB128Bytes(Action); - Asm->EOL("Next action"); - } - } + Asm->EmitSLEB128Bytes(Action.TypeID); + Asm->EOL("TypeInfo index"); + Asm->EmitSLEB128Bytes(Action.NextAction); + Asm->EOL("Next action"); } // Emit the type ids. From resistor at mac.com Wed Jun 6 11:22:22 2007 From: resistor at mac.com (Owen Anderson) Date: Wed, 6 Jun 2007 11:22:22 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706061622.l56GMMCG028986@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.33 -> 1.34 --- Log message: Quick patch to fix the build, based on what it appears Evan meant to write. Evan, please check that this is in fact correct. --- Diffs of the changes: (+1 -1) IfConversion.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.33 llvm/lib/CodeGen/IfConversion.cpp:1.34 --- llvm/lib/CodeGen/IfConversion.cpp:1.33 Wed Jun 6 05:16:17 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Wed Jun 6 11:22:00 2007 @@ -818,7 +818,7 @@ // Transfer preds / succs and update size. TransferPreds(ToBBI.BB, FromBBI.BB); - if (!blockFallsThrough(FromBBI.BB)) + if (!blockFallsThrough(FromBBI)) TransferSuccs(ToBBI.BB, FromBBI.BB); ToBBI.NonPredSize += FromBBI.NonPredSize; FromBBI.NonPredSize = 0; From lattner at apple.com Wed Jun 6 12:03:32 2007 From: lattner at apple.com (lattner at apple.com) Date: Wed, 6 Jun 2007 10:03:32 -0700 (PDT) Subject: [llvm-commits] [128183] Unbreak build Message-ID: <20070606170332.A80827243750@src> Revision: 128183 Author: lattner Date: 2007-06-06 10:03:32 -0700 (Wed, 06 Jun 2007) Log Message: ----------- Unbreak build Modified Paths: -------------- apple-local/branches/llvm/gcc/llvm-backend.cpp Modified: apple-local/branches/llvm/gcc/llvm-backend.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-06 15:53:19 UTC (rev 128182) +++ apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-06 17:03:32 UTC (rev 128183) @@ -476,7 +476,7 @@ } // Add llvm.noinline -#ifdef 0 +#if 0 if (!AttributeNoinlineFunctions.empty()) { const Type *SBP= PointerType::get(Type::Int8Ty); ArrayType *AT = ArrayType::get(SBP, AttributeNoinlineFunctions.size()); From lauro.venancio at gmail.com Wed Jun 6 12:09:06 2007 From: lauro.venancio at gmail.com (Lauro Ramos Venancio) Date: Wed, 6 Jun 2007 12:09:06 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200706061709.l56H96j6030478@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.768 -> 1.769 --- Log message: Fix PR1499: http://llvm.org/PR1499 . --- Diffs of the changes: (+4 -0) InstructionCombining.cpp | 4 ++++ 1 files changed, 4 insertions(+) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.768 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.769 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.768 Tue May 22 20:17:04 2007 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Wed Jun 6 12:08:48 2007 @@ -1346,6 +1346,10 @@ // Signed shift right. APInt DemandedMaskIn(DemandedMask.shl(ShiftAmt)); + // If any of the "high bits" are demanded, we should set the sign bit as + // demanded. + if (DemandedMask.countLeadingZeros() <= ShiftAmt) + DemandedMaskIn.set(BitWidth-1); if (SimplifyDemandedBits(I->getOperand(0), DemandedMaskIn, RHSKnownZero, RHSKnownOne, Depth+1)) From lauro.venancio at gmail.com Wed Jun 6 12:10:20 2007 From: lauro.venancio at gmail.com (Lauro Ramos Venancio) Date: Wed, 6 Jun 2007 12:10:20 -0500 Subject: [llvm-commits] CVS: llvm/test/Transforms/InstCombine/2007-06-06-AshrSignBit.ll Message-ID: <200706061710.l56HAKB5030522@zion.cs.uiuc.edu> Changes in directory llvm/test/Transforms/InstCombine: 2007-06-06-AshrSignBit.ll added (r1.1) --- Log message: Add a test for PR1499: http://llvm.org/PR1499 . --- Diffs of the changes: (+22 -0) 2007-06-06-AshrSignBit.ll | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+) Index: llvm/test/Transforms/InstCombine/2007-06-06-AshrSignBit.ll diff -c /dev/null llvm/test/Transforms/InstCombine/2007-06-06-AshrSignBit.ll:1.1 *** /dev/null Wed Jun 6 12:10:12 2007 --- llvm/test/Transforms/InstCombine/2007-06-06-AshrSignBit.ll Wed Jun 6 12:10:02 2007 *************** *** 0 **** --- 1,22 ---- + ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {ashr} + ; PR1499 + + define void @av_cmp_q_cond_true(i32* %retval, i32* %tmp9, i64* %tmp10) { + newFuncRoot: + br label %cond_true + + return.exitStub: ; preds = %cond_true + ret void + + cond_true: ; preds = %newFuncRoot + %tmp30 = load i64* %tmp10 ; [#uses=1] + %.cast = zext i32 63 to i64 ; [#uses=1] + %tmp31 = ashr i64 %tmp30, %.cast ; [#uses=1] + %tmp3132 = trunc i64 %tmp31 to i32 ; [#uses=1] + %tmp33 = or i32 %tmp3132, 1 ; [#uses=1] + store i32 %tmp33, i32* %tmp9 + %tmp34 = load i32* %tmp9 ; [#uses=1] + store i32 %tmp34, i32* %retval + br label %return.exitStub + } + From clattner at apple.com Wed Jun 6 12:49:54 2007 From: clattner at apple.com (Chris Lattner) Date: Wed, 6 Jun 2007 10:49:54 -0700 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp In-Reply-To: <200706061709.l56H96j6030478@zion.cs.uiuc.edu> References: <200706061709.l56H96j6030478@zion.cs.uiuc.edu> Message-ID: <78505634-9B2E-43BA-B42A-F42F7AC23C29@apple.com> > > Fix PR1499: http://llvm.org/PR1499 . Very nice, thanks again Lauro! -Chris > > --- > Diffs of the changes: (+4 -0) > > InstructionCombining.cpp | 4 ++++ > 1 files changed, 4 insertions(+) > > > Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp > diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.768 > llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.769 > --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.768 Tue > May 22 20:17:04 2007 > +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Wed Jun 6 > 12:08:48 2007 > @@ -1346,6 +1346,10 @@ > > // Signed shift right. > APInt DemandedMaskIn(DemandedMask.shl(ShiftAmt)); > + // If any of the "high bits" are demanded, we should set the > sign bit as > + // demanded. > + if (DemandedMask.countLeadingZeros() <= ShiftAmt) > + DemandedMaskIn.set(BitWidth-1); > if (SimplifyDemandedBits(I->getOperand(0), > DemandedMaskIn, > RHSKnownZero, RHSKnownOne, Depth+1)) > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From clattner at apple.com Wed Jun 6 12:51:44 2007 From: clattner at apple.com (Chris Lattner) Date: Wed, 6 Jun 2007 10:51:44 -0700 Subject: [llvm-commits] CVS: llvm/lib/Analysis/ScalarEvolution.cpp In-Reply-To: <4666A649.5050903@mxc.ca> References: <200706060412.l564CgV9003861@zion.cs.uiuc.edu> <7731079E-CD1B-4975-A68C-1FA2CA686925@apple.com> <4666A649.5050903@mxc.ca> Message-ID: <60FDB371-10E3-477C-9557-3BB8448F00D8@apple.com> On Jun 6, 2007, at 5:19 AM, Nick Lewycky wrote: > Chris Lattner wrote: >> The only thing that can use Instructions are other intstructions. As >> such, you can change the dyn_cast into cast >> and there is no need to check for null in the next line. > > Fixed. Thanks Chris! Even better fix, thanks Nick, -Chris From sabre at nondot.org Wed Jun 6 13:28:31 2007 From: sabre at nondot.org (Chris Lattner) Date: Wed, 6 Jun 2007 13:28:31 -0500 Subject: [llvm-commits] CVS: llvm/docs/LangRef.html Message-ID: <200706061828.l56ISVPM032479@zion.cs.uiuc.edu> Changes in directory llvm/docs: LangRef.html updated: 1.250 -> 1.251 --- Log message: update to match latest changes --- Diffs of the changes: (+4 -4) LangRef.html | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) Index: llvm/docs/LangRef.html diff -u llvm/docs/LangRef.html:1.250 llvm/docs/LangRef.html:1.251 --- llvm/docs/LangRef.html:1.250 Tue Jun 5 00:28:25 2007 +++ llvm/docs/LangRef.html Wed Jun 6 13:28:13 2007 @@ -1428,9 +1428,9 @@
-%X = global i32 17
-%Y = global i32 42
-%Z = global [2 x i32*] [ i32* %X, i32* %Y ]
+ at X = global i32 17
+ at Y = global i32 42
+ at Z = global [2 x i32*] [ i32* @X, i32* @Y ]
 
@@ -4830,7 +4830,7 @@ Chris Lattner
The LLVM Compiler Infrastructure
- Last modified: $Date: 2007/06/05 05:28:25 $ + Last modified: $Date: 2007/06/06 18:28:13 $ From sabre at nondot.org Wed Jun 6 13:47:50 2007 From: sabre at nondot.org (Chris Lattner) Date: Wed, 6 Jun 2007 13:47:50 -0500 Subject: [llvm-commits] CVS: llvm-www/ProjectsWithLLVM/index.html Message-ID: <200706061847.l56Ilo8t000539@zion.cs.uiuc.edu> Changes in directory llvm-www/ProjectsWithLLVM: index.html updated: 1.35 -> 1.36 --- Log message: Add the adobe Hydra language --- Diffs of the changes: (+29 -0) index.html | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+) Index: llvm-www/ProjectsWithLLVM/index.html diff -u llvm-www/ProjectsWithLLVM/index.html:1.35 llvm-www/ProjectsWithLLVM/index.html:1.36 --- llvm-www/ProjectsWithLLVM/index.html:1.35 Mon Apr 23 10:39:59 2007 +++ llvm-www/ProjectsWithLLVM/index.html Wed Jun 6 13:47:31 2007 @@ -35,6 +35,7 @@
    +
  • Adobe Inc "Hydra" Language
  • Calysto Static Checker
  • Improvements on SSA-Based Register Allocation
  • LENS Project
  • @@ -58,6 +59,34 @@ + + +
    +By Adobe Inc. +
    + +
    + +

    +Efficient use of the computational resources available for image processing is +a goal of the Adobe Image Foundation project. Our language, "Hydra", is used +to describe single- and multi-stage image processing kernels, which are then +compiled and run on a target machine within a larger application. Similarly +to how its namesake had many heads, our Hydra can be run on the GPU or +alternately on the host CPU(s). AIF uses LLVM for our CPU path.

    + +

    +The first Adobe application to use our system is the soon-to-ship After +Effects CS3. We welcome you to try out our public beta found at +labs.adobe.com. +

    +
    + + + From sabre at nondot.org Wed Jun 6 13:49:47 2007 From: sabre at nondot.org (Chris Lattner) Date: Wed, 6 Jun 2007 13:49:47 -0500 Subject: [llvm-commits] CVS: llvm-www/Users.html Message-ID: <200706061849.l56InlN2000642@zion.cs.uiuc.edu> Changes in directory llvm-www: Users.html updated: 1.17 -> 1.18 --- Log message: add adobe --- Diffs of the changes: (+7 -1) Users.html | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletion(-) Index: llvm-www/Users.html diff -u llvm-www/Users.html:1.17 llvm-www/Users.html:1.18 --- llvm-www/Users.html:1.17 Thu Apr 26 16:01:00 2007 +++ llvm-www/Users.html Wed Jun 6 13:49:29 2007 @@ -20,6 +20,12 @@ Company Description + + + Adobe Inc. + Optimizer and JIT codegen for the Hydra Language. + @@ -246,6 +252,6 @@ src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!">
    LLVM Development List
    - Last modified: $Date: 2007/04/26 21:01:00 $ + Last modified: $Date: 2007/06/06 18:49:29 $ From sabre at nondot.org Wed Jun 6 15:07:37 2007 From: sabre at nondot.org (Chris Lattner) Date: Wed, 6 Jun 2007 15:07:37 -0500 Subject: [llvm-commits] CVS: llvm-www/Users.html Message-ID: <200706062007.l56K7bbs002770@zion.cs.uiuc.edu> Changes in directory llvm-www: Users.html updated: 1.18 -> 1.19 --- Log message: Fix adobe's name --- Diffs of the changes: (+2 -2) Users.html | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm-www/Users.html diff -u llvm-www/Users.html:1.18 llvm-www/Users.html:1.19 --- llvm-www/Users.html:1.18 Wed Jun 6 13:49:29 2007 +++ llvm-www/Users.html Wed Jun 6 15:07:02 2007 @@ -22,7 +22,7 @@ - Adobe Inc. + Adobe Systems Incorporated Optimizer and JIT codegen for the Hydra Language. @@ -252,6 +252,6 @@ src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!">
    LLVM Development List
    - Last modified: $Date: 2007/06/06 18:49:29 $ + Last modified: $Date: 2007/06/06 20:07:02 $ From sabre at nondot.org Wed Jun 6 15:07:37 2007 From: sabre at nondot.org (Chris Lattner) Date: Wed, 6 Jun 2007 15:07:37 -0500 Subject: [llvm-commits] CVS: llvm-www/ProjectsWithLLVM/index.html Message-ID: <200706062007.l56K7bug002771@zion.cs.uiuc.edu> Changes in directory llvm-www/ProjectsWithLLVM: index.html updated: 1.36 -> 1.37 --- Log message: Fix adobe's name --- Diffs of the changes: (+3 -3) index.html | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) Index: llvm-www/ProjectsWithLLVM/index.html diff -u llvm-www/ProjectsWithLLVM/index.html:1.36 llvm-www/ProjectsWithLLVM/index.html:1.37 --- llvm-www/ProjectsWithLLVM/index.html:1.36 Wed Jun 6 13:47:31 2007 +++ llvm-www/ProjectsWithLLVM/index.html Wed Jun 6 15:07:02 2007 @@ -35,7 +35,7 @@
      -
    • Adobe Inc "Hydra" Language
    • +
    • Adobe "Hydra" Language
    • Calysto Static Checker
    • Improvements on SSA-Based Register Allocation
    • LENS Project
    • @@ -59,13 +59,13 @@
      -By Adobe Inc. +By Adobe Systems Incorporated
      From dpatel at apple.com Wed Jun 6 15:08:33 2007 From: dpatel at apple.com (Devang Patel) Date: Wed, 6 Jun 2007 15:08:33 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp Message-ID: <200706062008.l56K8X4L002800@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Dominators.cpp updated: 1.105 -> 1.106 --- Log message: Add new dominator tree node into dominator tree node map. --- Diffs of the changes: (+6 -2) Dominators.cpp | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) Index: llvm/lib/VMCore/Dominators.cpp diff -u llvm/lib/VMCore/Dominators.cpp:1.105 llvm/lib/VMCore/Dominators.cpp:1.106 --- llvm/lib/VMCore/Dominators.cpp:1.105 Mon Jun 4 12:38:00 2007 +++ llvm/lib/VMCore/Dominators.cpp Wed Jun 6 15:08:11 2007 @@ -289,7 +289,9 @@ // Add a new tree node for this BasicBlock, and link it as a child of // IDomNode - BBNode = IDomNode->addChild(new DomTreeNode(I, IDomNode)); + DomTreeNode *C = new DomTreeNode(I, IDomNode); + DomTreeNodes[I] = C; + BBNode = IDomNode->addChild(C); } } @@ -338,7 +340,9 @@ // Add a new tree node for this BasicBlock, and link it as a child of // IDomNode - return BBNode = IDomNode->addChild(new DomTreeNode(BB, IDomNode)); + DomTreeNode *C = new DomTreeNode(BB, IDomNode); + DomTreeNodes[BB] = C; + return BBNode = IDomNode->addChild(C); } static std::ostream &operator<<(std::ostream &o, From sabre at nondot.org Wed Jun 6 15:17:17 2007 From: sabre at nondot.org (Chris Lattner) Date: Wed, 6 Jun 2007 15:17:17 -0500 Subject: [llvm-commits] CVS: llvm-www/Users.html Message-ID: <200706062017.l56KHH4R003130@zion.cs.uiuc.edu> Changes in directory llvm-www: Users.html updated: 1.19 -> 1.20 --- Log message: inc'ity inc inc --- Diffs of the changes: (+2 -2) Users.html | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm-www/Users.html diff -u llvm-www/Users.html:1.19 llvm-www/Users.html:1.20 --- llvm-www/Users.html:1.19 Wed Jun 6 15:07:02 2007 +++ llvm-www/Users.html Wed Jun 6 15:16:55 2007 @@ -35,7 +35,7 @@ - Apple Computer + Apple Inc. OpenGL Engine @@ -252,6 +252,6 @@ src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!">
      LLVM Development List
      - Last modified: $Date: 2007/06/06 20:07:02 $ + Last modified: $Date: 2007/06/06 20:16:55 $ From lattner at apple.com Wed Jun 6 15:41:08 2007 From: lattner at apple.com (lattner at apple.com) Date: Wed, 6 Jun 2007 13:41:08 -0700 (PDT) Subject: [llvm-commits] [128186] Use attribute directly instead of flag. Message-ID: <20070606204108.9F4D672BFA98@src> Revision: 128186 Author: lattner Date: 2007-06-06 13:41:07 -0700 (Wed, 06 Jun 2007) Log Message: ----------- Use attribute directly instead of flag. Removing ifdef since I'm using the attribute now. Modified Paths: -------------- apple-local/branches/llvm/gcc/llvm-backend.cpp apple-local/branches/llvm/gcc/llvm-convert.cpp apple-local/branches/llvm/gcc/tree-inline.c Modified: apple-local/branches/llvm/gcc/llvm-backend.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-06 19:47:00 UTC (rev 128185) +++ apple-local/branches/llvm/gcc/llvm-backend.cpp 2007-06-06 20:41:07 UTC (rev 128186) @@ -476,7 +476,6 @@ } // Add llvm.noinline -#if 0 if (!AttributeNoinlineFunctions.empty()) { const Type *SBP= PointerType::get(Type::Int8Ty); ArrayType *AT = ArrayType::get(SBP, AttributeNoinlineFunctions.size()); @@ -489,7 +488,6 @@ // Clear vector AttributeNoinlineFunctions.clear(); } -#endif // Finish off the per-function pass. if (PerFunctionPasses) Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp =================================================================== --- apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-06-06 19:47:00 UTC (rev 128185) +++ apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-06-06 20:41:07 UTC (rev 128186) @@ -595,7 +595,7 @@ } // Handle noinline Functions - if (DECL_UNINLINABLE (FnDecl)) { + if (lookup_attribute ("noinline", DECL_ATTRIBUTES (FnDecl))) { const Type *SBP= PointerType::get(Type::Int8Ty); AttributeNoinlineFunctions.push_back(ConstantExpr::getBitCast(Fn,SBP)); } Modified: apple-local/branches/llvm/gcc/tree-inline.c =================================================================== --- apple-local/branches/llvm/gcc/tree-inline.c 2007-06-06 19:47:00 UTC (rev 128185) +++ apple-local/branches/llvm/gcc/tree-inline.c 2007-06-06 20:41:07 UTC (rev 128186) @@ -1220,15 +1220,8 @@ inlinable = false; } - /* APPLE LOCAL begin LLVM */ - #ifndef ENABLE_LLVM - /* LLVM uses the uninlinable flag to know when the noinline attribute - was used. This code will cause all functions that this inliner decides - not to inline to appear to have been marked noinline. */ /* Squirrel away the result so that we don't have to check again. */ DECL_UNINLINABLE (fn) = !inlinable; - #endif - /* APPLE LOCAL end LLVM */ return inlinable; } From tonic at nondot.org Wed Jun 6 15:47:05 2007 From: tonic at nondot.org (Tanya Lattner) Date: Wed, 6 Jun 2007 15:47:05 -0500 Subject: [llvm-commits] CVS: llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr 2003-11-18-MemberInitializationCasting.cpp.tr 2005-07-21-VirtualBaseAccess.cpp Message-ID: <200706062047.l56Kl5mu004414@zion.cs.uiuc.edu> Changes in directory llvm/test/C++Frontend: 2003-11-09-ConstructorTypeSafety.cpp.tr updated: 1.4 -> 1.5 2003-11-18-MemberInitializationCasting.cpp.tr updated: 1.4 -> 1.5 2005-07-21-VirtualBaseAccess.cpp updated: 1.3 -> 1.4 --- Log message: Revert changes for noinline. --- Diffs of the changes: (+3 -3) 2003-11-09-ConstructorTypeSafety.cpp.tr | 2 +- 2003-11-18-MemberInitializationCasting.cpp.tr | 2 +- 2005-07-21-VirtualBaseAccess.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) Index: llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr diff -u llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr:1.4 llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr:1.5 --- llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr:1.4 Wed Jun 6 00:53:50 2007 +++ llvm/test/C++Frontend/2003-11-09-ConstructorTypeSafety.cpp.tr Wed Jun 6 15:46:40 2007 @@ -1,6 +1,6 @@ // The code generated for this testcase should be completely typesafe! // RUN: %llvmgcc -xc++ -S -o - %s | llvm-as | opt -die | llvm-dis | \ -// RUN: grep -v llvm.noinline | notcast +// RUN: notcast struct contained { unsigned X; Index: llvm/test/C++Frontend/2003-11-18-MemberInitializationCasting.cpp.tr diff -u llvm/test/C++Frontend/2003-11-18-MemberInitializationCasting.cpp.tr:1.4 llvm/test/C++Frontend/2003-11-18-MemberInitializationCasting.cpp.tr:1.5 --- llvm/test/C++Frontend/2003-11-18-MemberInitializationCasting.cpp.tr:1.4 Wed Jun 6 00:53:50 2007 +++ llvm/test/C++Frontend/2003-11-18-MemberInitializationCasting.cpp.tr Wed Jun 6 15:46:40 2007 @@ -1,4 +1,4 @@ -// RUN: %llvmgcc -xc++ -S -o - %s | llvm-as | opt -die | llvm-dis | grep -v llvm.noinline | notcast +// RUN: %llvmgcc -xc++ -S -o - %s | llvm-as | opt -die | llvm-dis | notcast struct A { A() : i(0) {} Index: llvm/test/C++Frontend/2005-07-21-VirtualBaseAccess.cpp diff -u llvm/test/C++Frontend/2005-07-21-VirtualBaseAccess.cpp:1.3 llvm/test/C++Frontend/2005-07-21-VirtualBaseAccess.cpp:1.4 --- llvm/test/C++Frontend/2005-07-21-VirtualBaseAccess.cpp:1.3 Wed Jun 6 00:53:50 2007 +++ llvm/test/C++Frontend/2005-07-21-VirtualBaseAccess.cpp Wed Jun 6 15:46:40 2007 @@ -1,4 +1,4 @@ -// RUN: %llvmgxx -xc++ %s -c -o - | opt -die | llvm-dis | grep -v llvm.noinline | not grep cast +// RUN: %llvmgxx -xc++ %s -c -o - | opt -die | llvm-dis | not grep cast void foo(int*); From tonic at nondot.org Wed Jun 6 15:47:05 2007 From: tonic at nondot.org (Tanya Lattner) Date: Wed, 6 Jun 2007 15:47:05 -0500 Subject: [llvm-commits] CVS: llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr Message-ID: <200706062047.l56Kl5cO004419@zion.cs.uiuc.edu> Changes in directory llvm/test/CFrontend: 2003-07-22-ArrayAccessTypeSafety.c.tr updated: 1.7 -> 1.8 --- Log message: Revert changes for noinline. --- Diffs of the changes: (+1 -1) 2003-07-22-ArrayAccessTypeSafety.c.tr | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr diff -u llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr:1.7 llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr:1.8 --- llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr:1.7 Wed Jun 6 00:53:50 2007 +++ llvm/test/CFrontend/2003-07-22-ArrayAccessTypeSafety.c.tr Wed Jun 6 15:46:40 2007 @@ -1,4 +1,4 @@ -/* RUN: %llvmgcc -xc %s -S -o - | grep -v alloca | grep -v llvm.noinline | not grep bitcast +/* RUN: %llvmgcc -xc %s -S -o - | grep -v alloca | not grep bitcast */ void test(int* array, long long N) { From sabre at nondot.org Wed Jun 6 15:51:36 2007 From: sabre at nondot.org (Chris Lattner) Date: Wed, 6 Jun 2007 15:51:36 -0500 Subject: [llvm-commits] CVS: llvm/tools/llvm-ld/Optimize.cpp Message-ID: <200706062051.l56Kpa2H004631@zion.cs.uiuc.edu> Changes in directory llvm/tools/llvm-ld: Optimize.cpp updated: 1.19 -> 1.20 --- Log message: if internalize is disabled, don't run the pass at all! --- Diffs of the changes: (+2 -1) Optimize.cpp | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-) Index: llvm/tools/llvm-ld/Optimize.cpp diff -u llvm/tools/llvm-ld/Optimize.cpp:1.19 llvm/tools/llvm-ld/Optimize.cpp:1.20 --- llvm/tools/llvm-ld/Optimize.cpp:1.19 Thu Apr 5 11:50:20 2007 +++ llvm/tools/llvm-ld/Optimize.cpp Wed Jun 6 15:51:14 2007 @@ -122,7 +122,8 @@ // Now that composite has been compiled, scan through the module, looking // for a main function. If main is defined, mark all other functions // internal. - addPass(Passes, createInternalizePass(!DisableInternalize)); + if (!DisableInternalize) + addPass(Passes, createInternalizePass(true)); // Propagate constants at call sites into the functions they call. This // opens opportunities for globalopt (and inlining) by substituting function From sabre at nondot.org Wed Jun 6 15:52:03 2007 From: sabre at nondot.org (Chris Lattner) Date: Wed, 6 Jun 2007 15:52:03 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/Internalize.cpp Message-ID: <200706062052.l56Kq3mx004672@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: Internalize.cpp updated: 1.49 -> 1.50 --- Log message: simplify this code and fix PR1493: http://llvm.org/PR1493 , now that llvm-gcc3 is dead. --- Diffs of the changes: (+2 -17) Internalize.cpp | 19 ++----------------- 1 files changed, 2 insertions(+), 17 deletions(-) Index: llvm/lib/Transforms/IPO/Internalize.cpp diff -u llvm/lib/Transforms/IPO/Internalize.cpp:1.49 llvm/lib/Transforms/IPO/Internalize.cpp:1.50 --- llvm/lib/Transforms/IPO/Internalize.cpp:1.49 Sun May 6 08:37:16 2007 +++ llvm/lib/Transforms/IPO/Internalize.cpp Wed Jun 6 15:51:41 2007 @@ -128,29 +128,14 @@ ExternalNames.insert("llvm.dbg.compile_units"); ExternalNames.insert("llvm.dbg.global_variables"); ExternalNames.insert("llvm.dbg.subprograms"); + ExternalNames.insert("llvm.global_ctors"); + ExternalNames.insert("llvm.global_dtors"); // Mark all global variables with initializers as internal as well. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (!I->isDeclaration() && !I->hasInternalLinkage() && !ExternalNames.count(I->getName())) { - // Special case handling of the global ctor and dtor list. When we - // internalize it, we mark it constant, which allows elimination of - // the list if it's empty. - // - if (I->hasAppendingLinkage() && (I->getName() == "llvm.global_ctors" || - I->getName() == "llvm.global_dtors")) { - // If the global ctors/dtors list has no uses, do not internalize it, as - // there is no __main in this program, so the asmprinter should handle - // it. - if (I->use_empty()) continue; - - // Otherwise, also mark the list constant, as we know that it will not - // be mutated any longer, and the makes simple IPO xforms automatically - // better. - I->setConstant(true); - } - I->setLinkage(GlobalValue::InternalLinkage); Changed = true; ++NumGlobals; From tonic at nondot.org Wed Jun 6 15:52:37 2007 From: tonic at nondot.org (Tanya Lattner) Date: Wed, 6 Jun 2007 15:52:37 -0500 Subject: [llvm-commits] CVS: llvm/test/CFrontend/2007-06-05-NoInlineAttribute.c Message-ID: <200706062052.l56KqbMq004752@zion.cs.uiuc.edu> Changes in directory llvm/test/CFrontend: 2007-06-05-NoInlineAttribute.c added (r1.1) --- Log message: Test case for noinline attribute. --- Diffs of the changes: (+13 -0) 2007-06-05-NoInlineAttribute.c | 13 +++++++++++++ 1 files changed, 13 insertions(+) Index: llvm/test/CFrontend/2007-06-05-NoInlineAttribute.c diff -c /dev/null llvm/test/CFrontend/2007-06-05-NoInlineAttribute.c:1.1 *** /dev/null Wed Jun 6 15:52:27 2007 --- llvm/test/CFrontend/2007-06-05-NoInlineAttribute.c Wed Jun 6 15:52:16 2007 *************** *** 0 **** --- 1,13 ---- + // RUN: %llvmgxx -c -emit-llvm %s -o - | llvm-dis | grep llvm.noinline + + int bar(int x, int y); __attribute__((noinline)) + + int bar(int x, int y) + { + return x + y; + } + + int foo(int a, int b) { + return bar(b, a); + } + From tonic at nondot.org Wed Jun 6 16:01:07 2007 From: tonic at nondot.org (Tanya Lattner) Date: Wed, 6 Jun 2007 16:01:07 -0500 Subject: [llvm-commits] CVS: llvm/test/CFrontend/2007-06-05-NoInlineAttribute.c Message-ID: <200706062101.l56L17xt005090@zion.cs.uiuc.edu> Changes in directory llvm/test/CFrontend: 2007-06-05-NoInlineAttribute.c updated: 1.1 -> 1.2 --- Log message: Really use attribute. --- Diffs of the changes: (+2 -2) 2007-06-05-NoInlineAttribute.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/test/CFrontend/2007-06-05-NoInlineAttribute.c diff -u llvm/test/CFrontend/2007-06-05-NoInlineAttribute.c:1.1 llvm/test/CFrontend/2007-06-05-NoInlineAttribute.c:1.2 --- llvm/test/CFrontend/2007-06-05-NoInlineAttribute.c:1.1 Wed Jun 6 15:52:16 2007 +++ llvm/test/CFrontend/2007-06-05-NoInlineAttribute.c Wed Jun 6 16:00:46 2007 @@ -1,8 +1,8 @@ // RUN: %llvmgxx -c -emit-llvm %s -o - | llvm-dis | grep llvm.noinline -int bar(int x, int y); __attribute__((noinline)) +static int bar(int x, int y) __attribute__((noinline)); -int bar(int x, int y) +static int bar(int x, int y) { return x + y; } From tonic at nondot.org Wed Jun 6 16:59:50 2007 From: tonic at nondot.org (Tanya Lattner) Date: Wed, 6 Jun 2007 16:59:50 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/InlineSimple.cpp Message-ID: <200706062159.l56Lxoi5006920@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: InlineSimple.cpp updated: 1.83 -> 1.84 --- Log message: Instruct the inliner to obey the noinline attribute. Add test case. --- Diffs of the changes: (+43 -1) InlineSimple.cpp | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 43 insertions(+), 1 deletion(-) Index: llvm/lib/Transforms/IPO/InlineSimple.cpp diff -u llvm/lib/Transforms/IPO/InlineSimple.cpp:1.83 llvm/lib/Transforms/IPO/InlineSimple.cpp:1.84 --- llvm/lib/Transforms/IPO/InlineSimple.cpp:1.83 Sun May 6 18:13:56 2007 +++ llvm/lib/Transforms/IPO/InlineSimple.cpp Wed Jun 6 16:59:26 2007 @@ -15,11 +15,14 @@ #include "llvm/CallingConv.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" -#include "llvm/Function.h" +#include "llvm/Module.h" #include "llvm/Type.h" +#include "llvm/Analysis/CallGraph.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Compiler.h" #include "llvm/Transforms/IPO.h" +#include + using namespace llvm; namespace { @@ -53,10 +56,12 @@ class VISIBILITY_HIDDEN SimpleInliner : public Inliner { std::map CachedFunctionInfo; + std::set NeverInline; // Functions that are never inlined public: SimpleInliner() : Inliner(&ID) {} static char ID; // Pass identification, replacement for typeid int getInlineCost(CallSite CS); + virtual bool doInitialization(CallGraph &CG); }; char SimpleInliner::ID = 0; RegisterPass X("inline", "Function Integration/Inlining"); @@ -191,6 +196,9 @@ // Don't inline a directly recursive call. if (Caller == Callee) return 2000000000; + // Don't inline functions marked noinline + if (NeverInline.count(Callee)) return 2000000000; + // InlineCost - This value measures how good of an inline candidate this call // site is to inline. A lower inline cost make is more likely for the call to // be inlined. This value may go negative. @@ -274,3 +282,37 @@ return InlineCost; } +// doInitialization - Initializes the vector of functions that have been +// annotated with the noinline attribute. +bool SimpleInliner::doInitialization(CallGraph &CG) { + + Module &M = CG.getModule(); + + // Get llvm.noinline + GlobalVariable *GV = M.getNamedGlobal("llvm.noinline"); + + if(GV == 0) + return false; + + const ConstantArray *InitList = dyn_cast(GV->getInitializer()); + + if(InitList == 0) + return false; + + // Iterate over each element and add to the NeverInline set + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + + // Get Source + const Constant *Elt = InitList->getOperand(i); + + if (const ConstantExpr *CE = dyn_cast(Elt)) + if (CE->getOpcode() == Instruction::BitCast) + Elt = CE->getOperand(0); + + // Insert into set of functions to never inline + if(const Function *f = dyn_cast(Elt)) + NeverInline.insert(f); + } + + return false; +} From tonic at nondot.org Wed Jun 6 16:59:49 2007 From: tonic at nondot.org (Tanya Lattner) Date: Wed, 6 Jun 2007 16:59:49 -0500 Subject: [llvm-commits] CVS: llvm/test/Transforms/Inline/2007-06-06-NoInline.ll Message-ID: <200706062159.l56Lxn4f006917@zion.cs.uiuc.edu> Changes in directory llvm/test/Transforms/Inline: 2007-06-06-NoInline.ll added (r1.1) --- Log message: Instruct the inliner to obey the noinline attribute. Add test case. --- Diffs of the changes: (+46 -0) 2007-06-06-NoInline.ll | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 46 insertions(+) Index: llvm/test/Transforms/Inline/2007-06-06-NoInline.ll diff -c /dev/null llvm/test/Transforms/Inline/2007-06-06-NoInline.ll:1.1 *** /dev/null Wed Jun 6 16:59:36 2007 --- llvm/test/Transforms/Inline/2007-06-06-NoInline.ll Wed Jun 6 16:59:26 2007 *************** *** 0 **** --- 1,46 ---- + ; RUN: llvm-as < %s | opt -inline -f - | llvm-dis | grep "define internal i32 @bar" + @llvm.noinline = appending global [1 x i8*] [ i8* bitcast (i32 (i32, i32)* @bar to i8*) ], section "llvm.metadata" ; <[1 x i8*]*> [#uses=0] + + define internal i32 @bar(i32 %x, i32 %y) { + entry: + %x_addr = alloca i32 ; [#uses=2] + %y_addr = alloca i32 ; [#uses=2] + %retval = alloca i32, align 4 ; [#uses=2] + %tmp = alloca i32, align 4 ; [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i32 %x, i32* %x_addr + store i32 %y, i32* %y_addr + %tmp1 = load i32* %x_addr ; [#uses=1] + %tmp2 = load i32* %y_addr ; [#uses=1] + %tmp3 = add i32 %tmp1, %tmp2 ; [#uses=1] + store i32 %tmp3, i32* %tmp + %tmp4 = load i32* %tmp ; [#uses=1] + store i32 %tmp4, i32* %retval + br label %return + + return: ; preds = %entry + %retval5 = load i32* %retval ; [#uses=1] + ret i32 %retval5 + } + + define i32 @foo(i32 %a, i32 %b) { + entry: + %a_addr = alloca i32 ; [#uses=2] + %b_addr = alloca i32 ; [#uses=2] + %retval = alloca i32, align 4 ; [#uses=2] + %tmp = alloca i32, align 4 ; [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i32 %a, i32* %a_addr + store i32 %b, i32* %b_addr + %tmp1 = load i32* %b_addr ; [#uses=1] + %tmp2 = load i32* %a_addr ; [#uses=1] + %tmp3 = call i32 @bar( i32 %tmp1, i32 %tmp2 ) ; [#uses=1] + store i32 %tmp3, i32* %tmp + %tmp4 = load i32* %tmp ; [#uses=1] + store i32 %tmp4, i32* %retval + br label %return + + return: ; preds = %entry + %retval5 = load i32* %retval ; [#uses=1] + ret i32 %retval5 + } From lauro.venancio at gmail.com Wed Jun 6 17:01:34 2007 From: lauro.venancio at gmail.com (Lauro Ramos Venancio) Date: Wed, 6 Jun 2007 17:01:34 -0500 Subject: [llvm-commits] CVS: llvm/lib/Linker/LinkModules.cpp Message-ID: <200706062201.l56M1Yn8007052@zion.cs.uiuc.edu> Changes in directory llvm/lib/Linker: LinkModules.cpp updated: 1.140 -> 1.141 --- Log message: Propagate alignment, section name and visibility when linking "appending global values". Fix noinline linkage. --- Diffs of the changes: (+15 -0) LinkModules.cpp | 15 +++++++++++++++ 1 files changed, 15 insertions(+) Index: llvm/lib/Linker/LinkModules.cpp diff -u llvm/lib/Linker/LinkModules.cpp:1.140 llvm/lib/Linker/LinkModules.cpp:1.141 --- llvm/lib/Linker/LinkModules.cpp:1.140 Sun Apr 29 15:56:48 2007 +++ llvm/lib/Linker/LinkModules.cpp Wed Jun 6 17:01:12 2007 @@ -827,6 +827,18 @@ return Error(ErrorMsg, "Appending variables linked with different const'ness!"); + if (G1->getAlignment() != G2->getAlignment()) + return Error(ErrorMsg, + "Appending variables with different alignment need to be linked!"); + + if (G1->getVisibility() != G2->getVisibility()) + return Error(ErrorMsg, + "Appending variables with different visibility need to be linked!"); + + if (G1->getSection() != G2->getSection()) + return Error(ErrorMsg, + "Appending variables with different section name need to be linked!"); + unsigned NewSize = T1->getNumElements() + T2->getNumElements(); ArrayType *NewType = ArrayType::get(T1->getElementType(), NewSize); @@ -837,6 +849,9 @@ new GlobalVariable(NewType, G1->isConstant(), G1->getLinkage(), /*init*/0, First->first, M, G1->isThreadLocal()); + // Propagate alignment, visibility and section info. + CopyGVAttributes(NG, G1); + // Merge the initializer... Inits.reserve(NewSize); if (ConstantArray *I = dyn_cast(G1->getInitializer())) { From lauro.venancio at gmail.com Wed Jun 6 18:11:18 2007 From: lauro.venancio at gmail.com (Lauro Ramos Venancio) Date: Wed, 6 Jun 2007 18:11:18 -0500 Subject: [llvm-commits] CVS: llvm/tools/bugpoint/ExecutionDriver.cpp ToolRunner.cpp Message-ID: <200706062311.l56NBIOn008586@zion.cs.uiuc.edu> Changes in directory llvm/tools/bugpoint: ExecutionDriver.cpp updated: 1.69 -> 1.70 ToolRunner.cpp updated: 1.62 -> 1.63 --- Log message: Fix bugpoint to run -llc-safe with -Xlinker. --- Diffs of the changes: (+3 -1) ExecutionDriver.cpp | 2 +- ToolRunner.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) Index: llvm/tools/bugpoint/ExecutionDriver.cpp diff -u llvm/tools/bugpoint/ExecutionDriver.cpp:1.69 llvm/tools/bugpoint/ExecutionDriver.cpp:1.70 --- llvm/tools/bugpoint/ExecutionDriver.cpp:1.69 Fri Feb 16 13:11:07 2007 +++ llvm/tools/bugpoint/ExecutionDriver.cpp Wed Jun 6 18:10:56 2007 @@ -260,7 +260,7 @@ // as the GCCArgs. int RetVal = 0; if (InterpreterSel == RunLLC || InterpreterSel == RunCBE || - InterpreterSel == CBE_bug) + InterpreterSel == CBE_bug || InterpreterSel == LLC_Safe) RetVal = AI->ExecuteProgram(BytecodeFile, InputArgv, InputFile, OutputFile, AdditionalLinkerArgs, SharedObjs, Timeout, MemoryLimit); Index: llvm/tools/bugpoint/ToolRunner.cpp diff -u llvm/tools/bugpoint/ToolRunner.cpp:1.62 llvm/tools/bugpoint/ToolRunner.cpp:1.63 --- llvm/tools/bugpoint/ToolRunner.cpp:1.62 Thu May 3 13:36:15 2007 +++ llvm/tools/bugpoint/ToolRunner.cpp Wed Jun 6 18:10:56 2007 @@ -555,6 +555,8 @@ GCCArgs.push_back(fileType == AsmFile ? "assembler" : "c"); GCCArgs.push_back("-fno-strict-aliasing"); GCCArgs.push_back(InputFile.c_str()); // Specify the input filename. + GCCArgs.push_back("-x"); + GCCArgs.push_back("none"); #if defined(sparc) || defined(__sparc__) || defined(__sparcv9) GCCArgs.push_back("-G"); // Compile a shared library, `-G' for Sparc #elif defined(__APPLE__) From evan.cheng at apple.com Wed Jun 6 20:38:16 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 6 Jun 2007 20:38:16 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/ARM/ARMInstrInfo.cpp Message-ID: <200706070138.l571cGnr012780@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/ARM: ARMInstrInfo.cpp updated: 1.32 -> 1.33 --- Log message: Stupid cut-n-paste bug caused me soooo much grief. Why wasn't there a compilation warning? I blame it on the FE folks. --- Diffs of the changes: (+1 -1) ARMInstrInfo.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Target/ARM/ARMInstrInfo.cpp diff -u llvm/lib/Target/ARM/ARMInstrInfo.cpp:1.32 llvm/lib/Target/ARM/ARMInstrInfo.cpp:1.33 --- llvm/lib/Target/ARM/ARMInstrInfo.cpp:1.32 Tue May 29 13:42:18 2007 +++ llvm/lib/Target/ARM/ARMInstrInfo.cpp Wed Jun 6 20:37:54 2007 @@ -476,7 +476,7 @@ return CC2 == ARMCC::LO || CC2 == ARMCC::EQ; case ARMCC::GE: return CC2 == ARMCC::GT || CC2 == ARMCC::EQ; - case ARMCC::LE: return "le"; + case ARMCC::LE: return CC2 == ARMCC::LT || CC2 == ARMCC::EQ; } } From evan.cheng at apple.com Wed Jun 6 21:12:37 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 6 Jun 2007 21:12:37 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706070212.l572Cbt4013379@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.34 -> 1.35 --- Log message: Lots of bug fixes. Now finally in a reasonable state. --- Diffs of the changes: (+104 -78) IfConversion.cpp | 182 +++++++++++++++++++++++++++++++------------------------ 1 files changed, 104 insertions(+), 78 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.34 llvm/lib/CodeGen/IfConversion.cpp:1.35 --- llvm/lib/CodeGen/IfConversion.cpp:1.34 Wed Jun 6 11:22:00 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Wed Jun 6 21:12:15 2007 @@ -64,6 +64,7 @@ BBICKind Kind; unsigned NonPredSize; bool IsAnalyzable; + bool hasFallThrough; bool ModifyPredicate; MachineBasicBlock *BB; MachineBasicBlock *TrueBB; @@ -72,7 +73,8 @@ std::vector BrCond; std::vector Predicate; BBInfo() : Kind(ICNotAnalyzed), NonPredSize(0), - IsAnalyzable(false), ModifyPredicate(false), + IsAnalyzable(false), hasFallThrough(false), + ModifyPredicate(false), BB(0), TrueBB(0), FalseBB(0), TailBB(0) {} }; @@ -97,6 +99,8 @@ private: bool ReverseBranchCondition(BBInfo &BBI); bool BlockModifyPredicate(MachineBasicBlock *BB) const; + bool ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI) const; + bool ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI) const; void StructuralAnalysis(MachineBasicBlock *BB); bool FeasibilityAnalysis(BBInfo &BBI, std::vector &Cond, @@ -113,8 +117,8 @@ bool IgnoreTerm = false); void MergeBlocks(BBInfo &TrueBBI, BBInfo &FalseBBI); - // blockFallsThrough - Block ends without a terminator. - bool blockFallsThrough(BBInfo &BBI) const { + // blockAlwaysFallThrough - Block ends without a terminator. + bool blockAlwaysFallThrough(BBInfo &BBI) const { return BBI.IsAnalyzable && BBI.TrueBB == NULL; } @@ -242,6 +246,32 @@ return false; } +/// ValidTriangle - Returns true if the 'true' and 'false' blocks paths (along +/// with their common predecessor) forms a valid triangle shape for ifcvt. +bool IfConverter::ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI) const { + if (TrueBBI.BB->pred_size() != 1) + return false; + + MachineBasicBlock *TTBB = TrueBBI.TrueBB; + if (!TTBB && blockAlwaysFallThrough(TrueBBI)) { + MachineFunction::iterator I = TrueBBI.BB; + if (++I == TrueBBI.BB->getParent()->end()) + return false; + TTBB = I; + } + return TTBB && TTBB == FalseBBI.BB; +} + +/// ValidDiamond - Returns true if the 'true' and 'false' blocks paths (along +/// with their common predecessor) forms a valid diamond shape for ifcvt. +bool IfConverter::ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI) const { + return (TrueBBI.TrueBB == FalseBBI.TrueBB && + TrueBBI.BB->pred_size() == 1 && + FalseBBI.BB->pred_size() == 1 && + !(TrueBBI.ModifyPredicate && FalseBBI.ModifyPredicate) && + !TrueBBI.FalseBB && !FalseBBI.FalseBB); +} + /// StructuralAnalysis - Analyze the structure of the sub-CFG starting from /// the specified block. Record its successors and whether it looks like an /// if-conversion candidate. @@ -263,6 +293,8 @@ BBI.Kind = ICNotClassfied; BBI.IsAnalyzable = !TII->AnalyzeBranch(*BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond); + BBI.hasFallThrough = BBI.IsAnalyzable && BBI.FalseBB == NULL; + // Unanalyable or ends with fallthrough or unconditional branch. if (!BBI.IsAnalyzable || BBI.BrCond.size() == 0) return; // Do not ifcvt if either path is a back edge to the entry block. @@ -316,16 +348,7 @@ FalseBBI.Kind = ICChild; } } - } else if (TrueBBI.TrueBB == FalseBBI.TrueBB && CanRevCond && - TrueBBI.BB->pred_size() == 1 && - FalseBBI.BB->pred_size() == 1 && - // Check the 'true' and 'false' blocks if either isn't ended with - // a branch. If the block does not fallthrough to another block - // then we need to add a branch to its successor. - !(TrueBBI.ModifyPredicate && - !TrueBBI.TrueBB && TrueBBI.BB->succ_size()) && - !(FalseBBI.ModifyPredicate && - !FalseBBI.TrueBB && FalseBBI.BB->succ_size()) && + } else if (CanRevCond && ValidDiamond(TrueBBI, FalseBBI) && FeasibilityAnalysis(TrueBBI, BBI.BrCond) && FeasibilityAnalysis(FalseBBI, RevCond)) { // Diamond: @@ -341,9 +364,9 @@ BBI.TailBB = TrueBBI.TrueBB; } else { // FIXME: Consider duplicating if BB is small. - bool TryTriangle = TrueBBI.TrueBB && TrueBBI.TrueBB == BBI.FalseBB && - TrueBBI.BB->pred_size() == 1; - bool TrySimple = TrueBBI.BrCond.size() == 0 && TrueBBI.BB->pred_size() == 1; + bool TryTriangle = ValidTriangle(TrueBBI, FalseBBI); + bool TrySimple = !blockAlwaysFallThrough(TrueBBI) && + TrueBBI.BrCond.size() == 0 && TrueBBI.BB->pred_size() == 1; if ((TryTriangle || TrySimple) && FeasibilityAnalysis(TrueBBI, BBI.BrCond)) { if (TryTriangle) { @@ -369,19 +392,21 @@ } } else if (FalseBBI.BrCond.size() == 0 && FalseBBI.BB->pred_size() == 1) { // Try the other path... - bool TryTriangle = FalseBBI.TrueBB && FalseBBI.TrueBB == BBI.TrueBB && - FalseBBI.BB->pred_size() == 1; - std::vector RevCond(BBI.BrCond); - if (!TII->ReverseBranchCondition(RevCond) && - FeasibilityAnalysis(FalseBBI, RevCond)) { - if (TryTriangle) { - // Reverse 'true' and 'false' paths. - ReverseBranchCondition(BBI); - BBI.Kind = ICTriangle; - FalseBBI.Kind = ICChild; - } else { - BBI.Kind = ICSimpleFalse; - FalseBBI.Kind = ICChild; + bool TryTriangle = ValidTriangle(FalseBBI, TrueBBI); + bool TrySimple = !blockAlwaysFallThrough(FalseBBI); + if (TryTriangle || TrySimple) { + std::vector RevCond(BBI.BrCond); + if (!TII->ReverseBranchCondition(RevCond) && + FeasibilityAnalysis(FalseBBI, RevCond)) { + if (TryTriangle) { + // Reverse 'true' and 'false' paths. + ReverseBranchCondition(BBI); + BBI.Kind = ICTriangle; + FalseBBI.Kind = ICChild; + } else { + BBI.Kind = ICSimpleFalse; + FalseBBI.Kind = ICChild; + } } } } @@ -418,7 +443,6 @@ I != E; ++I) { if (IgnoreTerm && TII->isTerminatorInstr(I->getOpcode())) continue; - // TODO: check if instruction clobbers predicate. if (!I->isPredicable()) return false; } @@ -531,22 +555,16 @@ } PredicateBlock(*CvtBBI, Cond); - // If the 'true' block ends without a branch, add a conditional branch - // to its successor unless that happens to be the 'false' block. - if (CvtBBI->IsAnalyzable && CvtBBI->TrueBB == NULL) { - assert(CvtBBI->BB->succ_size() == 1 && "Unexpected!"); - MachineBasicBlock *SuccBB = *CvtBBI->BB->succ_begin(); - if (SuccBB != NextBBI->BB) - TII->InsertBranch(*CvtBBI->BB, SuccBB, NULL, Cond); - } // Merge converted block into entry block. Also add an unconditional branch // to the 'false' branch. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); MergeBlocks(BBI, *CvtBBI); + bool IterIfcvt = true; if (!isNextBlock(BBI.BB, NextBBI->BB)) { InsertUncondBranch(BBI.BB, NextBBI->BB, TII); + BBI.hasFallThrough = false; if (BBI.ModifyPredicate) // Now ifcvt'd block will look like this: // BB: @@ -555,9 +573,9 @@ // if t op // b BBf // - // We cannot further ifcvt this block because the unconditional branch will - // have to be predicated on the new condition, that will not be available - // if cmp executes. + // We cannot further ifcvt this block because the unconditional branch + // will have to be predicated on the new condition, that will not be + // available if cmp executes. IterIfcvt = false; } std::copy(Cond.begin(), Cond.end(), std::back_inserter(BBI.Predicate)); @@ -602,6 +620,7 @@ FalseBBDead = true; } else if (!isNextBlock(TrueBBI.BB, FalseBBI.BB)) { InsertUncondBranch(TrueBBI.BB, FalseBBI.BB, TII); + TrueBBI.hasFallThrough = false; if (BBI.ModifyPredicate || TrueBBI.ModifyPredicate) // Now ifcvt'd block will look like this: // BB: @@ -715,8 +734,14 @@ // Add an unconditional branch from 'false' to to 'false' successor if it // will not be the fallthrough block. - if (NeedBr2 && !isNextBlock(BBI2->BB, *BBI2->BB->succ_begin())) - InsertUncondBranch(BBI2->BB, *BBI2->BB->succ_begin(), TII); + if (NeedBr2 && !NeedBr1) { + // If BBI2 isn't going to be merged in, then the existing fallthrough + // or branch is fine. + if (!isNextBlock(BBI.BB, *BBI2->BB->succ_begin())) { + InsertUncondBranch(BBI2->BB, *BBI2->BB->succ_begin(), TII); + BBI2->hasFallThrough = false; + } + } // Keep them as two separate blocks if there is an early exit. if (!NeedBr1) @@ -727,11 +752,18 @@ // Merge the combined block into the entry of the diamond. MergeBlocks(BBI, *BBI1); + std::copy(Cond1->begin(), Cond1->end(), + std::back_inserter(BBI.Predicate)); + if (!NeedBr1) + std::copy(Cond2->begin(), Cond2->end(), + std::back_inserter(BBI.Predicate)); // 'True' and 'false' aren't combined, see if we need to add a unconditional // branch to the 'false' block. - if (NeedBr1 && !isNextBlock(BBI.BB, BBI2->BB)) - InsertUncondBranch(BBI1->BB, BBI2->BB, TII); + if (NeedBr1 && !isNextBlock(BBI.BB, BBI2->BB)) { + InsertUncondBranch(BBI.BB, BBI2->BB, TII); + BBI1->hasFallThrough = false; + } // If the if-converted block fallthrough or unconditionally branch into the // tail block, and the tail block does not have other predecessors, then @@ -775,28 +807,12 @@ NumIfConvBBs++; } -/// TransferPreds - Transfer all the predecessors of FromBB to ToBB. -/// -static void TransferPreds(MachineBasicBlock *ToBB, MachineBasicBlock *FromBB) { - for (MachineBasicBlock::pred_iterator I = FromBB->pred_begin(), - E = FromBB->pred_end(); I != E; ++I) { - MachineBasicBlock *Pred = *I; - Pred->removeSuccessor(FromBB); - if (!Pred->isSuccessor(ToBB)) - Pred->addSuccessor(ToBB); - } -} - -/// TransferSuccs - Transfer all the successors of FromBB to ToBB. -/// -static void TransferSuccs(MachineBasicBlock *ToBB, MachineBasicBlock *FromBB) { - for (MachineBasicBlock::succ_iterator I = FromBB->succ_begin(), - E = FromBB->succ_end(); I != E; ++I) { - MachineBasicBlock *Succ = *I; - FromBB->removeSuccessor(Succ); - if (!ToBB->isSuccessor(Succ)) - ToBB->addSuccessor(Succ); - } +static MachineBasicBlock *getNextBlock(MachineBasicBlock *BB) { + MachineFunction::iterator I = BB; + MachineFunction::iterator E = BB->getParent()->end(); + if (++I == E) + return NULL; + return I; } /// MergeBlocks - Move all instructions from FromBB to the end of ToBB. @@ -805,23 +821,33 @@ ToBBI.BB->splice(ToBBI.BB->end(), FromBBI.BB, FromBBI.BB->begin(), FromBBI.BB->end()); - // If FromBBI is previously a successor, remove it from ToBBI's successor - // list and update its TrueBB / FalseBB field if needed. - if (ToBBI.BB->isSuccessor(FromBBI.BB)) - ToBBI.BB->removeSuccessor(FromBBI.BB); - // Redirect all branches to FromBB to ToBB. std::vector Preds(FromBBI.BB->pred_begin(), FromBBI.BB->pred_end()); - for (unsigned i = 0, e = Preds.size(); i != e; ++i) - Preds[i]->ReplaceUsesOfBlockWith(FromBBI.BB, ToBBI.BB); + for (unsigned i = 0, e = Preds.size(); i != e; ++i) { + MachineBasicBlock *Pred = Preds[i]; + if (Pred == ToBBI.BB) + continue; + Pred->ReplaceUsesOfBlockWith(FromBBI.BB, ToBBI.BB); + } + + std::vector Succs(FromBBI.BB->succ_begin(), + FromBBI.BB->succ_end()); + MachineBasicBlock *FallThrough = FromBBI.hasFallThrough + ? getNextBlock(FromBBI.BB) : NULL; + + for (unsigned i = 0, e = Succs.size(); i != e; ++i) { + MachineBasicBlock *Succ = Succs[i]; + if (Succ == FallThrough) + continue; + FromBBI.BB->removeSuccessor(Succ); + if (!ToBBI.BB->isSuccessor(Succ)) + ToBBI.BB->addSuccessor(Succ); + } - // Transfer preds / succs and update size. - TransferPreds(ToBBI.BB, FromBBI.BB); - if (!blockFallsThrough(FromBBI)) - TransferSuccs(ToBBI.BB, FromBBI.BB); ToBBI.NonPredSize += FromBBI.NonPredSize; FromBBI.NonPredSize = 0; ToBBI.ModifyPredicate |= FromBBI.ModifyPredicate; + ToBBI.hasFallThrough = FromBBI.hasFallThrough; } From nicholas at mxc.ca Wed Jun 6 21:19:57 2007 From: nicholas at mxc.ca (Nick Lewycky) Date: Wed, 06 Jun 2007 22:19:57 -0400 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp In-Reply-To: <200706041738.l54HcOO8002633@zion.cs.uiuc.edu> References: <200706041738.l54HcOO8002633@zion.cs.uiuc.edu> Message-ID: <46676B4D.1020503@mxc.ca> Predicate simplifier uses this to get the DFS nums for a BB. We also pass around ETNode*s to avoid having a lot of functions doing BB->ETNode lookups. Similarly with updateDFSNumbers. More than a performance issue, if the DFS nums aren't up to date predsimplify will crash (and if it didn't crash it wouldn't work; it needs correct DFS nums). I spoke with Dan Berlin about it and he says that there's no guarantee that the DFS nums will be up to date upon entry to a pass, so I call it there. I'm open to suggestions. Nick Devang Patel wrote: > +// FIXME : There is no need to make getNodeForBlock public. Fix > +// predicate simplifier. > ETNode *ETForest::getNodeForBlock(BasicBlock *BB) { > ETNode *&BBNode = Nodes[BB]; > if (BBNode) return BBNode; From clattner at apple.com Wed Jun 6 23:53:49 2007 From: clattner at apple.com (Chris Lattner) Date: Wed, 6 Jun 2007 21:53:49 -0700 Subject: [llvm-commits] CVS: llvm/lib/Target/ARM/ARMInstrInfo.cpp In-Reply-To: <200706070138.l571cGnr012780@zion.cs.uiuc.edu> References: <200706070138.l571cGnr012780@zion.cs.uiuc.edu> Message-ID: <45E1E403-9E35-4F7D-AFE2-DE9EAC8A94FF@apple.com> On Jun 6, 2007, at 6:38 PM, Evan Cheng wrote: > > Stupid cut-n-paste bug caused me soooo much grief. Why wasn't there > a compilation warning? I blame it on the FE folks. Geeze, if backend people wouldn't write code like this, the f.e. people would have a much easier time ;-) -Chris > --- > Diffs of the changes: (+1 -1) > > ARMInstrInfo.cpp | 2 +- > 1 files changed, 1 insertion(+), 1 deletion(-) > > > Index: llvm/lib/Target/ARM/ARMInstrInfo.cpp > diff -u llvm/lib/Target/ARM/ARMInstrInfo.cpp:1.32 llvm/lib/Target/ > ARM/ARMInstrInfo.cpp:1.33 > --- llvm/lib/Target/ARM/ARMInstrInfo.cpp:1.32 Tue May 29 13:42:18 2007 > +++ llvm/lib/Target/ARM/ARMInstrInfo.cpp Wed Jun 6 20:37:54 2007 > @@ -476,7 +476,7 @@ > return CC2 == ARMCC::LO || CC2 == ARMCC::EQ; > case ARMCC::GE: > return CC2 == ARMCC::GT || CC2 == ARMCC::EQ; > - case ARMCC::LE: return "le"; > + case ARMCC::LE: > return CC2 == ARMCC::LT || CC2 == ARMCC::EQ; > } > } > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From zhousheng00 at gmail.com Thu Jun 7 01:12:25 2007 From: zhousheng00 at gmail.com (Zhou Sheng) Date: Thu, 7 Jun 2007 01:12:25 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Verifier.cpp Message-ID: <200706070612.l576CPcD018438@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Verifier.cpp updated: 1.212 -> 1.213 --- Log message: Add assert to check if the attributes ZExt/SExt, NoAlias are apply to the correct type of parameters. --- Diffs of the changes: (+15 -0) Verifier.cpp | 15 +++++++++++++++ 1 files changed, 15 insertions(+) Index: llvm/lib/VMCore/Verifier.cpp diff -u llvm/lib/VMCore/Verifier.cpp:1.212 llvm/lib/VMCore/Verifier.cpp:1.213 --- llvm/lib/VMCore/Verifier.cpp:1.212 Wed May 2 20:11:54 2007 +++ llvm/lib/VMCore/Verifier.cpp Thu Jun 7 01:12:03 2007 @@ -46,6 +46,7 @@ #include "llvm/Pass.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" +#include "llvm/ParameterAttributes.h" #include "llvm/DerivedTypes.h" #include "llvm/InlineAsm.h" #include "llvm/Instructions.h" @@ -358,6 +359,20 @@ FT->getNumParams() > 0 && isa(FT->getParamType(0))), "Invalid struct-return function!", &F); + if (const ParamAttrsList *Attrs = FT->getParamAttrs()) { + unsigned Idx = 1; + for (FunctionType::param_iterator I = FT->param_begin(), + E = FT->param_end(); I != E; ++I, ++Idx) { + if (Attrs->paramHasAttr(Idx, ParamAttr::ZExt) || + Attrs->paramHasAttr(Idx, ParamAttr::SExt)) + Assert1(FT->getParamType(Idx-1)->isInteger(), + "Attribute ZExt should only apply to Integer type!", &F); + if (Attrs->paramHasAttr(Idx, ParamAttr::NoAlias)) + Assert1(isa(FT->getParamType(Idx-1)), + "Attribute NoAlias should only apply to Pointer type!", &F); + } + } + // Check that this function meets the restrictions on this calling convention. switch (F.getCallingConv()) { default: From baldrick at free.fr Thu Jun 7 02:14:48 2007 From: baldrick at free.fr (Duncan Sands) Date: Thu, 7 Jun 2007 09:14:48 +0200 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/InlineSimple.cpp In-Reply-To: <200706062159.l56Lxoi5006920@zion.cs.uiuc.edu> References: <200706062159.l56Lxoi5006920@zion.cs.uiuc.edu> Message-ID: <200706070914.49332.baldrick@free.fr> Missing spaces after "if": > + if(GV == 0) > + if(InitList == 0) > + if(const Function *f = dyn_cast(Elt)) Also, in this last "if" you call the function "f" but I guess "F" would be more consistent. Ciao, Duncan. From evan.cheng at apple.com Thu Jun 7 03:13:22 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 7 Jun 2007 03:13:22 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706070813.l578DMI0029840@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.35 -> 1.36 --- Log message: ifcvt a triangle: don't merge ifcvt block with rejoin block if it can fall through to it. If merged, the resulting block is not a candidate for iterative ifcvting since it contains both predicated and non-predicated code. --- Diffs of the changes: (+29 -17) IfConversion.cpp | 46 +++++++++++++++++++++++++++++----------------- 1 files changed, 29 insertions(+), 17 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.35 llvm/lib/CodeGen/IfConversion.cpp:1.36 --- llvm/lib/CodeGen/IfConversion.cpp:1.35 Wed Jun 6 21:12:15 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Thu Jun 7 03:13:00 2007 @@ -615,29 +615,41 @@ BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; bool FalseBBDead = false; bool IterIfcvt = true; - if (!HasEarlyExit && FalseBBI.BB->pred_size() == 2) { - MergeBlocks(TrueBBI, FalseBBI); - FalseBBDead = true; - } else if (!isNextBlock(TrueBBI.BB, FalseBBI.BB)) { - InsertUncondBranch(TrueBBI.BB, FalseBBI.BB, TII); - TrueBBI.hasFallThrough = false; - if (BBI.ModifyPredicate || TrueBBI.ModifyPredicate) - // Now ifcvt'd block will look like this: - // BB: - // ... - // t, f = cmp - // if t op - // b BBf - // - // We cannot further ifcvt this block because the unconditional branch will - // have to be predicated on the new condition, that will not be available - // if cmp executes. + bool isFallThrough = isNextBlock(TrueBBI.BB, FalseBBI.BB); + if (!isFallThrough) { + // Only merge them if the true block does not fallthrough to the false + // block. By not merging them, we make it possible to iteratively + // ifcvt the blocks. + if (!HasEarlyExit && FalseBBI.BB->pred_size() == 2) { + MergeBlocks(TrueBBI, FalseBBI); + FalseBBDead = true; + // Mixed predicated and unpredicated code. This cannot be iteratively + // predicated. IterIfcvt = false; + } else { + InsertUncondBranch(TrueBBI.BB, FalseBBI.BB, TII); + TrueBBI.hasFallThrough = false; + if (BBI.ModifyPredicate || TrueBBI.ModifyPredicate) + // Now ifcvt'd block will look like this: + // BB: + // ... + // t, f = cmp + // if t op + // b BBf + // + // We cannot further ifcvt this block because the unconditional branch will + // have to be predicated on the new condition, that will not be available + // if cmp executes. + IterIfcvt = false; + } } // Now merge the entry of the triangle with the true block. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); MergeBlocks(BBI, TrueBBI); + // Remove entry to false edge. + if (BBI.BB->isSuccessor(FalseBBI.BB)) + BBI.BB->removeSuccessor(FalseBBI.BB); std::copy(BBI.BrCond.begin(), BBI.BrCond.end(), std::back_inserter(BBI.Predicate)); From baldrick at free.fr Thu Jun 7 04:01:10 2007 From: baldrick at free.fr (Duncan Sands) Date: Thu, 7 Jun 2007 04:01:10 -0500 Subject: [llvm-commits] CVS: llvm/test/C++Frontend/2007-05-23-TryFinally.cpp Message-ID: <200706070901.l5791AHj030657@zion.cs.uiuc.edu> Changes in directory llvm/test/C++Frontend: 2007-05-23-TryFinally.cpp updated: 1.1 -> 1.2 --- Log message: Make this test pass if llvm-g++ was built without exception handling support. --- Diffs of the changes: (+1 -1) 2007-05-23-TryFinally.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/test/C++Frontend/2007-05-23-TryFinally.cpp diff -u llvm/test/C++Frontend/2007-05-23-TryFinally.cpp:1.1 llvm/test/C++Frontend/2007-05-23-TryFinally.cpp:1.2 --- llvm/test/C++Frontend/2007-05-23-TryFinally.cpp:1.1 Wed May 30 05:16:19 2007 +++ llvm/test/C++Frontend/2007-05-23-TryFinally.cpp Thu Jun 7 04:00:48 2007 @@ -1,4 +1,4 @@ -// RUN: %llvmgxx %s -S -emit-llvm -O2 -o - | grep _Unwind_Resume | wc -l | grep {\[03\]} +// RUN: %llvmgxx %s -S -emit-llvm -O2 -o - | grep -c {handle\\|_Unwind_Resume} | grep {\[14\]} struct One { }; struct Two { }; From baldrick at free.fr Thu Jun 7 04:35:54 2007 From: baldrick at free.fr (Duncan Sands) Date: Thu, 7 Jun 2007 04:35:54 -0500 Subject: [llvm-commits] CVS: llvm/test/CFrontend/2007-05-07-NestedStructReturn.c Message-ID: <200706070935.l579ZsJe031888@zion.cs.uiuc.edu> Changes in directory llvm/test/CFrontend: 2007-05-07-NestedStructReturn.c updated: 1.1 -> 1.2 --- Log message: Make the struct bigger, in an attempt to get a "struct return" on more platforms. --- Diffs of the changes: (+1 -1) 2007-05-07-NestedStructReturn.c | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/test/CFrontend/2007-05-07-NestedStructReturn.c diff -u llvm/test/CFrontend/2007-05-07-NestedStructReturn.c:1.1 llvm/test/CFrontend/2007-05-07-NestedStructReturn.c:1.2 --- llvm/test/CFrontend/2007-05-07-NestedStructReturn.c:1.1 Wed May 9 03:41:26 2007 +++ llvm/test/CFrontend/2007-05-07-NestedStructReturn.c Thu Jun 7 04:35:33 2007 @@ -1,6 +1,6 @@ // RUN: %llvmgcc %s -S -fnested-functions -o - | grep {sret *%agg.result} -struct X { int m, n; }; +struct X { int m, n, o, p; }; struct X p(int n) { struct X c(int m) { From tonic at nondot.org Thu Jun 7 11:45:21 2007 From: tonic at nondot.org (Tanya Lattner) Date: Thu, 7 Jun 2007 11:45:21 -0500 Subject: [llvm-commits] CVS: llvm/docs/WritingAnLLVMPass.html Message-ID: <200706071645.l57GjLpX009349@zion.cs.uiuc.edu> Changes in directory llvm/docs: WritingAnLLVMPass.html updated: 1.61 -> 1.62 --- Log message: Correct typo. Should be "not allowed" --- Diffs of the changes: (+2 -2) WritingAnLLVMPass.html | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/docs/WritingAnLLVMPass.html diff -u llvm/docs/WritingAnLLVMPass.html:1.61 llvm/docs/WritingAnLLVMPass.html:1.62 --- llvm/docs/WritingAnLLVMPass.html:1.61 Fri May 18 00:38:44 2007 +++ llvm/docs/WritingAnLLVMPass.html Thu Jun 7 11:44:52 2007 @@ -537,7 +537,7 @@
    • ... not allowed to modify any Functions that are not in the current SCC.
    • -
    • ... allowed to inspect any Function's other than those in the +
    • ... not allowed to inspect any Function's other than those in the current SCC and the direct callees of the SCC.
    • ... required to preserve the current CallGraph object, updating it @@ -1809,7 +1809,7 @@ Chris Lattner
      The LLVM Compiler Infrastructure
      - Last modified: $Date: 2007/05/18 05:38:44 $ + Last modified: $Date: 2007/06/07 16:44:52 $ From tonic at nondot.org Thu Jun 7 12:12:38 2007 From: tonic at nondot.org (Tanya Lattner) Date: Thu, 7 Jun 2007 12:12:38 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/InlineSimple.cpp Message-ID: <200706071712.l57HCc06009951@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: InlineSimple.cpp updated: 1.84 -> 1.85 --- Log message: Formating fixes. --- Diffs of the changes: (+4 -4) InlineSimple.cpp | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) Index: llvm/lib/Transforms/IPO/InlineSimple.cpp diff -u llvm/lib/Transforms/IPO/InlineSimple.cpp:1.84 llvm/lib/Transforms/IPO/InlineSimple.cpp:1.85 --- llvm/lib/Transforms/IPO/InlineSimple.cpp:1.84 Wed Jun 6 16:59:26 2007 +++ llvm/lib/Transforms/IPO/InlineSimple.cpp Thu Jun 7 12:12:16 2007 @@ -291,12 +291,12 @@ // Get llvm.noinline GlobalVariable *GV = M.getNamedGlobal("llvm.noinline"); - if(GV == 0) + if (GV == 0) return false; const ConstantArray *InitList = dyn_cast(GV->getInitializer()); - if(InitList == 0) + if (InitList == 0) return false; // Iterate over each element and add to the NeverInline set @@ -310,8 +310,8 @@ Elt = CE->getOperand(0); // Insert into set of functions to never inline - if(const Function *f = dyn_cast(Elt)) - NeverInline.insert(f); + if (const Function *F = dyn_cast(Elt)) + NeverInline.insert(F); } return false; From lattner at apple.com Thu Jun 7 12:13:35 2007 From: lattner at apple.com (Tanya Lattner) Date: Thu, 7 Jun 2007 10:13:35 -0700 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/InlineSimple.cpp In-Reply-To: <200706070914.49332.baldrick@free.fr> References: <200706062159.l56Lxoi5006920@zion.cs.uiuc.edu> <200706070914.49332.baldrick@free.fr> Message-ID: Fixed. Thanks! -Tanya On Jun 7, 2007, at 12:14 AM, Duncan Sands wrote: > Missing spaces after "if": > >> + if(GV == 0) > >> + if(InitList == 0) > >> + if(const Function *f = dyn_cast(Elt)) > > Also, in this last "if" you call the function "f" but I guess > "F" would be more consistent. > > Ciao, > > Duncan. > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From dpatel at apple.com Thu Jun 7 12:21:13 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 10:21:13 -0700 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp In-Reply-To: <46676B4D.1020503@mxc.ca> References: <200706041738.l54HcOO8002633@zion.cs.uiuc.edu> <46676B4D.1020503@mxc.ca> Message-ID: Nick, On Jun 6, 2007, at 7:19 PM, Nick Lewycky wrote: > Predicate simplifier uses this to get the DFS nums for a BB. We also > pass around ETNode*s to avoid having a lot of functions doing BB- > >ETNode > lookups. I am not familiar with predicate simplifier implementation, but why do such look ups ? I am exploring the idea to make ETNode completely private unless there is a good reason. Usually, a transformation needs dominance info, it does not matter whether ETNode or DomTreeNode or SomeOtherNode is used as part of DomTree or ETForest or SomeJungle to get that info. > Similarly with updateDFSNumbers. More than a performance issue, if the > DFS nums aren't up to date predsimplify will crash (and if it didn't > crash it wouldn't work; it needs correct DFS nums). I spoke with Dan > Berlin about it and he says that there's no guarantee that the DFS > nums > will be up to date upon entry to a pass, so I call it there. If you're interested then the simple way is to invoke updateDFSNumbers() after each pass that claims that it preserves dom info. - Devang > I'm open to suggestions. > > Nick > > Devang Patel wrote: >> +// FIXME : There is no need to make getNodeForBlock public. Fix >> +// predicate simplifier. >> ETNode *ETForest::getNodeForBlock(BasicBlock *BB) { >> ETNode *&BBNode = Nodes[BB]; >> if (BBNode) return BBNode; > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From nicholas at mxc.ca Thu Jun 7 12:46:05 2007 From: nicholas at mxc.ca (Nick Lewycky) Date: Thu, 07 Jun 2007 13:46:05 -0400 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp In-Reply-To: References: <200706041738.l54HcOO8002633@zion.cs.uiuc.edu> <46676B4D.1020503@mxc.ca> Message-ID: <4668445D.2050606@mxc.ca> Devang Patel wrote: > On Jun 6, 2007, at 7:19 PM, Nick Lewycky wrote: > >>Predicate simplifier uses this to get the DFS nums for a BB. We also >>pass around ETNode*s to avoid having a lot of functions doing BB- >> >>>ETNode >> >>lookups. > > I am not familiar with predicate simplifier implementation, but why do > such look ups ? > > I am exploring the idea to make ETNode completely private unless there > is a good reason. Usually, a transformation needs dominance info, > it does not matter whether ETNode or DomTreeNode or SomeOtherNode is > used as part of DomTree or ETForest or SomeJungle to get that info. The data structure that predsimplify really needs is a dominator tree with depth first search numberings on every block. Currently we simulate that by combining both the DominatorTree and ETForest passes. I chose what gets passed around based on performance. For example, if you need both a BasicBlock * and a DominatorTree::Node, pass the DTNode around because you can convert it to the BB in O(1) while converting a BB to DTNode takes a map lookup. Similarly, I pass ETNodes around to functions that don't care about which BB is actually involved, but do need the DFS numbers for whatever reason. This is very pervasive; in my dev tree, ETNode is mentioned in 38 lines of code in predsimplify, mostly function parameters. Six lines of code do lookups turning blocks into ETNodes. If we passed around BasicBlock* instead, there would need to be an additional 32 places that perform BB->ETNode lookups. One of those would be inside the comparison operator used to sort some vectors. In other words, it would almost certainly be a performance disaster. >>Similarly with updateDFSNumbers. More than a performance issue, if the >>DFS nums aren't up to date predsimplify will crash (and if it didn't >>crash it wouldn't work; it needs correct DFS nums). I spoke with Dan >>Berlin about it and he says that there's no guarantee that the DFS >>nums >>will be up to date upon entry to a pass, so I call it there. > > If you're interested then the simple way is to invoke > updateDFSNumbers() after each pass that claims that it preserves dom > info. Ok. Passes that don't access DFS numbers directly (every pass except predsimplify) would take a small performance hit as ETForest updates the numberings. That doesn't make it wrong though. Nick From dpatel at apple.com Thu Jun 7 12:47:47 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 12:47:47 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706071747.l57HllSl010744@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.92 -> 1.93 --- Log message: Maintain ETNode as part of DomTreeNode. This adds redundancy for now. --- Diffs of the changes: (+60 -24) Dominators.h | 84 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 60 insertions(+), 24 deletions(-) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.92 llvm/include/llvm/Analysis/Dominators.h:1.93 --- llvm/include/llvm/Analysis/Dominators.h:1.92 Tue Jun 5 19:59:48 2007 +++ llvm/include/llvm/Analysis/Dominators.h Thu Jun 7 12:47:21 2007 @@ -63,6 +63,7 @@ class DomTreeNode { BasicBlock *TheBB; DomTreeNode *IDom; + ETNode *ETN; std::vector Children; public: typedef std::vector::iterator iterator; @@ -75,28 +76,14 @@ inline BasicBlock *getBlock() const { return TheBB; } inline DomTreeNode *getIDom() const { return IDom; } + inline ETNode *getETNode() const { return ETN; } inline const std::vector &getChildren() const { return Children; } - /// properlyDominates - Returns true iff this dominates N and this != N. - /// Note that this is not a constant time operation! - /// - bool properlyDominates(const DomTreeNode *N) const { - const DomTreeNode *IDom; - if (this == 0 || N == 0) return false; - while ((IDom = N->getIDom()) != 0 && IDom != this) - N = IDom; // Walk up the tree - return IDom != 0; - } - - /// dominates - Returns true iff this dominates N. Note that this is not a - /// constant time operation! - /// - inline bool dominates(const DomTreeNode *N) const { - if (N == this) return true; // A node trivially dominates itself. - return properlyDominates(N); + inline DomTreeNode(BasicBlock *BB, DomTreeNode *iDom, ETNode *E) + : TheBB(BB), IDom(iDom), ETN(E) { + if (IDom) + ETN->setFather(IDom->getETNode()); } - - inline DomTreeNode(BasicBlock *BB, DomTreeNode *iDom) : TheBB(BB), IDom(iDom) {} inline DomTreeNode *addChild(DomTreeNode *C) { Children.push_back(C); return C; } void setIDom(DomTreeNode *NewIDom); }; @@ -107,12 +94,16 @@ class DominatorTreeBase : public DominatorBase { protected: - std::map DomTreeNodes; void reset(); typedef std::map DomTreeNodeMapType; - + DomTreeNodeMapType DomTreeNodes; DomTreeNode *RootNode; + typedef std::map ETMapType; + ETMapType ETNodes; + + bool DFSInfoValid; + unsigned int SlowQueries; // Information record used during immediate dominators computation. struct InfoRec { unsigned Semi; @@ -134,7 +125,7 @@ public: DominatorTreeBase(intptr_t ID, bool isPostDom) - : DominatorBase(ID, isPostDom) {} + : DominatorBase(ID, isPostDom), DFSInfoValid(false), SlowQueries(0) {} ~DominatorTreeBase() { reset(); } virtual void releaseMemory() { reset(); } @@ -161,6 +152,47 @@ DomTreeNode *getRootNode() { return RootNode; } const DomTreeNode *getRootNode() const { return RootNode; } + /// properlyDominates - Returns true iff this dominates N and this != N. + /// Note that this is not a constant time operation! + /// + bool properlyDominates(const DomTreeNode *A, DomTreeNode *B) const { + if (A == 0 || B == 0) return false; + return dominatedBySlowTreeWalk(A, B); + } + + bool dominatedBySlowTreeWalk(const DomTreeNode *A, + const DomTreeNode *B) const { + const DomTreeNode *IDom; + if (A == 0 || B == 0) return false; + while ((IDom = B->getIDom()) != 0 && IDom != A) + B = IDom; // Walk up the tree + return IDom != 0; + } + + void updateDFSNumbers(); + /// dominates - Returns true iff this dominates N. Note that this is not a + /// constant time operation! + /// + inline bool dominates(const DomTreeNode *A, DomTreeNode *B) { + if (B == A) return true; // A node trivially dominates itself. + + ETNode *NodeA = A->getETNode(); + ETNode *NodeB = B->getETNode(); + + if (DFSInfoValid) + return NodeB->DominatedBy(NodeA); + + // If we end up with too many slow queries, just update the + // DFS numbers on the theory that we are going to keep querying. + SlowQueries++; + if (SlowQueries > 32) { + updateDFSNumbers(); + return NodeB->DominatedBy(NodeA); + } + //return NodeB->DominatedBySlow(NodeA); + return dominatedBySlowTreeWalk(A, B); + } + //===--------------------------------------------------------------------===// // API to update (Post)DominatorTree information based on modifications to // the CFG... @@ -172,7 +204,11 @@ assert(getNode(BB) == 0 && "Block already in dominator tree!"); DomTreeNode *IDomNode = getNode(DomBB); assert(IDomNode && "Not immediate dominator specified for block!"); - return DomTreeNodes[BB] = IDomNode->addChild(new DomTreeNode(BB, IDomNode)); + DFSInfoValid = false; + ETNode *E = new ETNode(BB); + ETNodes[BB] = E; + return DomTreeNodes[BB] = + IDomNode->addChild(new DomTreeNode(BB, IDomNode, E)); } /// changeImmediateDominator - This method is used to update the dominator @@ -180,6 +216,7 @@ /// void changeImmediateDominator(DomTreeNode *N, DomTreeNode *NewIDom) { assert(N && NewIDom && "Cannot change null node pointers!"); + DFSInfoValid = false; N->setIDom(NewIDom); } @@ -187,7 +224,6 @@ changeImmediateDominator(getNode(BB), getNode(NewBB)); } - /// removeNode - Removes a node from the dominator tree. Block must not /// dominate any other blocks. Invalidates any node pointing to removed /// block. From dpatel at apple.com Thu Jun 7 12:47:54 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 12:47:54 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp LCSSA.cpp Message-ID: <200706071747.l57HlspY010759@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: BreakCriticalEdges.cpp updated: 1.51 -> 1.52 LCSSA.cpp updated: 1.45 -> 1.46 --- Log message: Maintain ETNode as part of DomTreeNode. This adds redundancy for now. --- Diffs of the changes: (+2 -2) BreakCriticalEdges.cpp | 2 +- LCSSA.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp diff -u llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp:1.51 llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp:1.52 --- llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp:1.51 Mon Jun 4 11:43:25 2007 +++ llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp Thu Jun 7 12:47:21 2007 @@ -217,7 +217,7 @@ DestBBNode = DT->getNode(DestBB); while (!OtherPreds.empty() && NewBBDominatesDestBB) { if (DomTreeNode *OPNode = DT->getNode(OtherPreds.back())) - NewBBDominatesDestBB = DestBBNode->dominates(OPNode); + NewBBDominatesDestBB = DT->dominates(DestBBNode, OPNode); OtherPreds.pop_back(); } OtherPreds.clear(); Index: llvm/lib/Transforms/Utils/LCSSA.cpp diff -u llvm/lib/Transforms/Utils/LCSSA.cpp:1.45 llvm/lib/Transforms/Utils/LCSSA.cpp:1.46 --- llvm/lib/Transforms/Utils/LCSSA.cpp:1.45 Sun Jun 3 19:32:22 2007 +++ llvm/lib/Transforms/Utils/LCSSA.cpp Thu Jun 7 12:47:21 2007 @@ -157,7 +157,7 @@ BasicBlock *BB = *BBI; DomTreeNode *ExitBBNode = DT->getNode(BB); Value *&Phi = Phis[ExitBBNode]; - if (!Phi && InstrNode->dominates(ExitBBNode)) { + if (!Phi && DT->dominates(InstrNode, ExitBBNode)) { PHINode *PN = new PHINode(Instr->getType(), Instr->getName()+".lcssa", BB->begin()); PN->reserveOperandSpace(std::distance(pred_begin(BB), pred_end(BB))); From dpatel at apple.com Thu Jun 7 12:47:54 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 12:47:54 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/PostDominators.cpp Message-ID: <200706071747.l57HlsS2010764@zion.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: PostDominators.cpp updated: 1.72 -> 1.73 --- Log message: Maintain ETNode as part of DomTreeNode. This adds redundancy for now. --- Diffs of the changes: (+24 -4) PostDominators.cpp | 28 ++++++++++++++++++++++++---- 1 files changed, 24 insertions(+), 4 deletions(-) Index: llvm/lib/Analysis/PostDominators.cpp diff -u llvm/lib/Analysis/PostDominators.cpp:1.72 llvm/lib/Analysis/PostDominators.cpp:1.73 --- llvm/lib/Analysis/PostDominators.cpp:1.72 Sun Jun 3 19:32:21 2007 +++ llvm/lib/Analysis/PostDominators.cpp Thu Jun 7 12:47:21 2007 @@ -165,7 +165,9 @@ // one exit block, or it may be the virtual exit (denoted by (BasicBlock *)0) // which postdominates all real exits if there are multiple exit blocks. BasicBlock *Root = Roots.size() == 1 ? Roots[0] : 0; - DomTreeNodes[Root] = RootNode = new DomTreeNode(Root, 0); + ETNode *ERoot = new ETNode(Root); + ETNodes[Root] = ERoot; + DomTreeNodes[Root] = RootNode = new DomTreeNode(Root, 0, ERoot); // Loop over all of the reachable blocks in the function... for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) @@ -177,7 +179,11 @@ // Add a new tree node for this BasicBlock, and link it as a child of // IDomNode - BBNode = IPDomNode->addChild(new DomTreeNode(I, IPDomNode)); + ETNode *ET = new ETNode(I); + ETNodes[I] = ET; + DomTreeNode *C = new DomTreeNode(I, IPDomNode, ET); + DomTreeNodes[I] = C; + BBNode = IPDomNode->addChild(C); } } @@ -185,6 +191,16 @@ IDoms.clear(); Info.clear(); std::vector().swap(Vertex); + + int dfsnum = 0; + // Iterate over all nodes in depth first order... + for (unsigned i = 0, e = Roots.size(); i != e; ++i) + for (idf_iterator I = idf_begin(Roots[i]), + E = idf_end(Roots[i]); I != E; ++I) { + if (!getNodeForBlock(*I)->getETNode()->hasFather()) + getNodeForBlock(*I)->getETNode()->assignDFSNumber(dfsnum); + } + DFSInfoValid = true; } @@ -199,7 +215,11 @@ // Add a new tree node for this BasicBlock, and link it as a child of // IDomNode - return BBNode = IPDomNode->addChild(new DomTreeNode(BB, IPDomNode)); + ETNode *ET = new ETNode(BB); + ETNodes[BB] = ET; + DomTreeNode *C = new DomTreeNode(BB, IPDomNode, ET); + DomTreeNodes[BB] = C; + return BBNode = IPDomNode->addChild(C); } //===----------------------------------------------------------------------===// @@ -303,7 +323,7 @@ DomSetType::const_iterator CDFI = ChildDF.begin(), CDFE = ChildDF.end(); for (; CDFI != CDFE; ++CDFI) { - if (!Node->properlyDominates(DT[*CDFI])) + if (!DT.properlyDominates(Node, DT[*CDFI])) S.insert(*CDFI); } } From dpatel at apple.com Thu Jun 7 12:47:54 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 12:47:54 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp Message-ID: <200706071747.l57HlsAW010769@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Dominators.cpp updated: 1.106 -> 1.107 --- Log message: Maintain ETNode as part of DomTreeNode. This adds redundancy for now. --- Diffs of the changes: (+38 -5) Dominators.cpp | 43 ++++++++++++++++++++++++++++++++++++++----- 1 files changed, 38 insertions(+), 5 deletions(-) Index: llvm/lib/VMCore/Dominators.cpp diff -u llvm/lib/VMCore/Dominators.cpp:1.106 llvm/lib/VMCore/Dominators.cpp:1.107 --- llvm/lib/VMCore/Dominators.cpp:1.106 Wed Jun 6 15:08:11 2007 +++ llvm/lib/VMCore/Dominators.cpp Thu Jun 7 12:47:21 2007 @@ -233,8 +233,11 @@ void DominatorTree::calculate(Function& F) { BasicBlock* Root = Roots[0]; - - DomTreeNodes[Root] = RootNode = new DomTreeNode(Root, 0); // Add a node for the root... + + // Add a node for the root... + ETNode *ERoot = new ETNode(Root); + ETNodes[Root] = ERoot; + DomTreeNodes[Root] = RootNode = new DomTreeNode(Root, 0, ERoot); Vertex.push_back(0); @@ -289,7 +292,9 @@ // Add a new tree node for this BasicBlock, and link it as a child of // IDomNode - DomTreeNode *C = new DomTreeNode(I, IDomNode); + ETNode *ET = new ETNode(I); + ETNodes[I] = ET; + DomTreeNode *C = new DomTreeNode(I, IDomNode, ET); DomTreeNodes[I] = C; BBNode = IDomNode->addChild(C); } @@ -299,8 +304,27 @@ Info.clear(); IDoms.clear(); std::vector().swap(Vertex); + + updateDFSNumbers(); +} + +void DominatorTreeBase::updateDFSNumbers() +{ + int dfsnum = 0; + // Iterate over all nodes in depth first order. + for (unsigned i = 0, e = Roots.size(); i != e; ++i) + for (df_iterator I = df_begin(Roots[i]), + E = df_end(Roots[i]); I != E; ++I) { + BasicBlock *BB = *I; + ETNode *ETN = getNode(BB)->getETNode(); + if (ETN && !ETN->hasFather()) + ETN->assignDFSNumber(dfsnum); + } + SlowQueries = 0; + DFSInfoValid = true; } + // DominatorTreeBase::reset - Free all of the tree node memory. // void DominatorTreeBase::reset() { @@ -326,6 +350,13 @@ // Switch to new dominator IDom = NewIDom; IDom->Children.push_back(this); + + if (!ETN->hasFather()) + ETN->setFather(IDom->getETNode()); + else if (ETN->getFather()->getData() != IDom->getBlock()) { + ETN->Split(); + ETN->setFather(IDom->getETNode()); + } } } @@ -340,7 +371,9 @@ // Add a new tree node for this BasicBlock, and link it as a child of // IDomNode - DomTreeNode *C = new DomTreeNode(BB, IDomNode); + ETNode *ET = new ETNode(BB); + ETNodes[BB] = ET; + DomTreeNode *C = new DomTreeNode(BB, IDomNode, ET); DomTreeNodes[BB] = C; return BBNode = IDomNode->addChild(C); } @@ -463,7 +496,7 @@ DomSetType::const_iterator CDFI = S.begin(), CDFE = S.end(); DomSetType &parentSet = Frontiers[parentBB]; for (; CDFI != CDFE; ++CDFI) { - if (!parentNode->properlyDominates(DT[*CDFI])) + if (!DT.properlyDominates(parentNode, DT[*CDFI])) parentSet.insert(*CDFI); } workList.pop_back(); From dpatel at apple.com Thu Jun 7 13:40:02 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 13:40:02 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706071840.l57Ie2hO012047@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.93 -> 1.94 --- Log message: Add BasicBlock level dominates(A,B) interface. --- Diffs of the changes: (+14 -2) Dominators.h | 16 ++++++++++++++-- 1 files changed, 14 insertions(+), 2 deletions(-) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.93 llvm/include/llvm/Analysis/Dominators.h:1.94 --- llvm/include/llvm/Analysis/Dominators.h:1.93 Thu Jun 7 12:47:21 2007 +++ llvm/include/llvm/Analysis/Dominators.h Thu Jun 7 13:39:40 2007 @@ -170,11 +170,16 @@ } void updateDFSNumbers(); + /// dominates - Returns true iff this dominates N. Note that this is not a /// constant time operation! /// inline bool dominates(const DomTreeNode *A, DomTreeNode *B) { - if (B == A) return true; // A node trivially dominates itself. + if (B == A) + return true; // A node trivially dominates itself. + + if (A == 0 || B == 0) + return false; ETNode *NodeA = A->getETNode(); ETNode *NodeB = B->getETNode(); @@ -192,7 +197,14 @@ //return NodeB->DominatedBySlow(NodeA); return dominatedBySlowTreeWalk(A, B); } - + + inline bool dominates(BasicBlock *A, BasicBlock *B) { + if (A == B) + return true; + + return dominates(getNode(A), getNode(B)); + } + //===--------------------------------------------------------------------===// // API to update (Post)DominatorTree information based on modifications to // the CFG... From dpatel at apple.com Thu Jun 7 13:41:17 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 13:41:17 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GCSE.cpp Message-ID: <200706071841.l57IfHEN012087@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GCSE.cpp updated: 1.59 -> 1.60 --- Log message: Use DominatorTree instead of ETForest. --- Diffs of the changes: (+3 -3) GCSE.cpp | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) Index: llvm/lib/Transforms/Scalar/GCSE.cpp diff -u llvm/lib/Transforms/Scalar/GCSE.cpp:1.59 llvm/lib/Transforms/Scalar/GCSE.cpp:1.60 --- llvm/lib/Transforms/Scalar/GCSE.cpp:1.59 Sun Jun 3 19:32:21 2007 +++ llvm/lib/Transforms/Scalar/GCSE.cpp Thu Jun 7 13:40:55 2007 @@ -68,9 +68,9 @@ bool Changed = false; // Get pointers to the analysis results that we will be using... - ETForest &EF = getAnalysis(); - ValueNumbering &VN = getAnalysis(); DominatorTree &DT = getAnalysis(); + ETForest &ET = getAnalysis(); + ValueNumbering &VN = getAnalysis(); std::vector EqualValues; @@ -145,7 +145,7 @@ if (OtherI->getParent() == BB) Dominates = BlockInsts.count(OtherI); else - Dominates = EF.dominates(OtherI->getParent(), BB); + Dominates = ET.dominates(OtherI->getParent(), BB); if (Dominates) { // Okay, we found an instruction with the same value as this one From dpatel at apple.com Thu Jun 7 13:45:26 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 13:45:26 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GCSE.cpp Message-ID: <200706071845.l57IjQKD012182@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GCSE.cpp updated: 1.60 -> 1.61 --- Log message: Use DominatorTree instead of ETForest. --- Diffs of the changes: (+1 -3) GCSE.cpp | 4 +--- 1 files changed, 1 insertion(+), 3 deletions(-) Index: llvm/lib/Transforms/Scalar/GCSE.cpp diff -u llvm/lib/Transforms/Scalar/GCSE.cpp:1.60 llvm/lib/Transforms/Scalar/GCSE.cpp:1.61 --- llvm/lib/Transforms/Scalar/GCSE.cpp:1.60 Thu Jun 7 13:40:55 2007 +++ llvm/lib/Transforms/Scalar/GCSE.cpp Thu Jun 7 13:45:06 2007 @@ -48,7 +48,6 @@ // This transformation requires dominator and immediate dominator info virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); - AU.addRequired(); AU.addRequired(); AU.addRequired(); } @@ -69,7 +68,6 @@ // Get pointers to the analysis results that we will be using... DominatorTree &DT = getAnalysis(); - ETForest &ET = getAnalysis(); ValueNumbering &VN = getAnalysis(); std::vector EqualValues; @@ -145,7 +143,7 @@ if (OtherI->getParent() == BB) Dominates = BlockInsts.count(OtherI); else - Dominates = ET.dominates(OtherI->getParent(), BB); + Dominates = DT.dominates(OtherI->getParent(), BB); if (Dominates) { // Okay, we found an instruction with the same value as this one From dpatel at apple.com Thu Jun 7 13:50:43 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 11:50:43 -0700 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp In-Reply-To: <4668445D.2050606@mxc.ca> References: <200706041738.l54HcOO8002633@zion.cs.uiuc.edu> <46676B4D.1020503@mxc.ca> <4668445D.2050606@mxc.ca> Message-ID: On Jun 7, 2007, at 10:46 AM, Nick Lewycky wrote: > Devang Patel wrote: >> On Jun 6, 2007, at 7:19 PM, Nick Lewycky wrote: >> >>> Predicate simplifier uses this to get the DFS nums for a BB. We also >>> pass around ETNode*s to avoid having a lot of functions doing BB- >>> >>>> ETNode >>> >>> lookups. >> >> I am not familiar with predicate simplifier implementation, but why >> do >> such look ups ? >> >> I am exploring the idea to make ETNode completely private unless >> there >> is a good reason. Usually, a transformation needs dominance info, >> it does not matter whether ETNode or DomTreeNode or SomeOtherNode is >> used as part of DomTree or ETForest or SomeJungle to get that info. > > The data structure that predsimplify really needs is a dominator tree > with depth first search numberings on every block. Currently we > simulate > that by combining both the DominatorTree and ETForest passes. > > I chose what gets passed around based on performance. For example, if > you need both a BasicBlock * and a DominatorTree::Node, pass the > DTNode > around because you can convert it to the BB in O(1) while converting a > BB to DTNode takes a map lookup. > > Similarly, I pass ETNodes around to functions that don't care about > which BB is actually involved, but do need the DFS numbers for > whatever > reason. In that case what's the use of ETNode ? > This is very pervasive; in my dev tree, ETNode is mentioned in 38 > lines > of code in predsimplify, mostly function parameters. Six lines of code > do lookups turning blocks into ETNodes. If we passed around > BasicBlock* > instead, there would need to be an additional 32 places that perform > BB->ETNode lookups. One of those would be inside the comparison > operator > used to sort some vectors. In other words, it would almost certainly > be > a performance disaster. > >>> Similarly with updateDFSNumbers. More than a performance issue, if >>> the >>> DFS nums aren't up to date predsimplify will crash (and if it didn't >>> crash it wouldn't work; it needs correct DFS nums). I spoke with Dan >>> Berlin about it and he says that there's no guarantee that the DFS >>> nums >>> will be up to date upon entry to a pass, so I call it there. >> >> If you're interested then the simple way is to invoke >> updateDFSNumbers() after each pass that claims that it preserves dom >> info. > > Ok. Passes that don't access DFS numbers directly (every pass except > predsimplify) would take a small performance hit as ETForest updates > the > numberings. That doesn't make it wrong though. IMO, cost is part of promise "I'm preserving info". We do not want to go in the direction of "preserving info partially", which is the case if DFS numbers are out of sync at the end of a pass. - Devang From nicholas at mxc.ca Thu Jun 7 13:59:09 2007 From: nicholas at mxc.ca (Nick Lewycky) Date: Thu, 07 Jun 2007 14:59:09 -0400 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp In-Reply-To: References: <200706041738.l54HcOO8002633@zion.cs.uiuc.edu> <46676B4D.1020503@mxc.ca> <4668445D.2050606@mxc.ca> Message-ID: <4668557D.2080002@mxc.ca> Devang Patel wrote: > On Jun 7, 2007, at 10:46 AM, Nick Lewycky wrote: >>Similarly, I pass ETNodes around to functions that don't care about >>which BB is actually involved, but do need the DFS numbers for >>whatever reason. > > In that case what's the use of ETNode ? The DFS numbers. ETNode is the only way to see what the DFS in and DFS out numbers are. At a conceptual level, those numbers uniquely identify the scope and are used in determining which InequalityGraph properties (also stored per-ETNode) apply by comparing them for dominance, using the DFS numbers. Yes we could pass BBs around and modify ETForest to return DFS numbers from BBs directly, but it would probably be too slow. > IMO, cost is part of promise "I'm preserving info". We do not want to > go in > the direction of "preserving info partially", which is the case if DFS > numbers are > out of sync at the end of a pass. Sounds good to me. Nick From dalej at apple.com Thu Jun 7 16:07:37 2007 From: dalej at apple.com (Dale Johannesen) Date: Thu, 7 Jun 2007 16:07:37 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Message-ID: <200706072107.l57L7bbw016113@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAGISel.cpp updated: 1.457 -> 1.458 --- Log message: Do not change the size of function arguments. PR 1489: http://llvm.org/PR1489 . --- Diffs of the changes: (+9 -1) SelectionDAGISel.cpp | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletion(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.457 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.458 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.457 Wed Jun 6 05:05:18 2007 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Thu Jun 7 16:07:15 2007 @@ -3993,7 +3993,15 @@ Op = DAG.getNode(ExtOp, getTypeToTransformTo(VT), Op); } else { assert(MVT::isFloatingPoint(VT) && "Not int or FP?"); - Op = DAG.getNode(ISD::FP_EXTEND, getTypeToTransformTo(VT), Op); + // A true promotion would change the size of the argument. + // Instead, pretend this is an int. If FP objects are not + // passed the same as ints, the original type should be Legal + // and we should not get here. + Op = DAG.getNode(ISD::BIT_CONVERT, + VT==MVT::f32 ? MVT::i32 : + (VT==MVT::f64 ? MVT::i64 : + MVT::Other), + Op); } Ops.push_back(Op); Ops.push_back(DAG.getConstant(Flags, MVT::i32)); From dpatel at apple.com Thu Jun 7 16:34:44 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 16:34:44 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706072134.l57LYi0b016754@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.94 -> 1.95 --- Log message: Add basic block level properlyDominates(A,B) interface. --- Diffs of the changes: (+4 -0) Dominators.h | 4 ++++ 1 files changed, 4 insertions(+) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.94 llvm/include/llvm/Analysis/Dominators.h:1.95 --- llvm/include/llvm/Analysis/Dominators.h:1.94 Thu Jun 7 13:39:40 2007 +++ llvm/include/llvm/Analysis/Dominators.h Thu Jun 7 16:34:22 2007 @@ -160,6 +160,10 @@ return dominatedBySlowTreeWalk(A, B); } + inline bool properlyDominates(BasicBlock *A, BasicBlock *B) { + return properlyDominates(getNode(A), getNode(B)); + } + bool dominatedBySlowTreeWalk(const DomTreeNode *A, const DomTreeNode *B) const { const DomTreeNode *IDom; From dpatel at apple.com Thu Jun 7 16:35:48 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 16:35:48 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp Message-ID: <200706072135.l57LZm0f016787@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: CorrelatedExprs.cpp updated: 1.63 -> 1.64 --- Log message: Use DominatorTree instead of ETForest. --- Diffs of the changes: (+25 -23) CorrelatedExprs.cpp | 48 +++++++++++++++++++++++++----------------------- 1 files changed, 25 insertions(+), 23 deletions(-) Index: llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp diff -u llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp:1.63 llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp:1.64 --- llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp:1.63 Mon Jun 4 18:45:02 2007 +++ llvm/lib/Transforms/Scalar/CorrelatedExprs.cpp Thu Jun 7 16:35:27 2007 @@ -223,7 +223,7 @@ class VISIBILITY_HIDDEN CEE : public FunctionPass { std::map RankMap; std::map RegionInfoMap; - ETForest *EF; + DominatorTree *DT; public: static char ID; // Pass identification, replacement for typeid CEE() : FunctionPass((intptr_t)&ID) {} @@ -232,7 +232,7 @@ // We don't modify the program, so we preserve all analyses virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + AU.addRequired(); AU.addRequiredID(BreakCriticalEdgesID); }; @@ -304,7 +304,7 @@ // Traverse the dominator tree, computing information for each node in the // tree. Note that our traversal will not even touch unreachable basic // blocks. - EF = &getAnalysis(); + DT = &getAnalysis(); std::set VisitedBlocks; bool Changed = TransformRegion(&F.getEntryBlock(), VisitedBlocks); @@ -351,14 +351,14 @@ // blocks that are dominated by this one, we can safely propagate the // information down now. // - std::vector children; - EF->getETNodeChildren(BB, children); + DomTreeNode *BBDom = DT->getNode(BB); if (!RI.empty()) { // Time opt: only propagate if we can change something - for (std::vector::iterator CI = children.begin(), - E = children.end(); CI != E; ++CI) { - assert(RegionInfoMap.find(*CI) == RegionInfoMap.end() && + for (std::vector::iterator DI = BBDom->begin(), + E = BBDom->end(); DI != E; ++DI) { + BasicBlock *ChildBB = (*DI)->getBlock(); + assert(RegionInfoMap.find(ChildBB) == RegionInfoMap.end() && "RegionInfo should be calculated in dominanace order!"); - getRegionInfo(*CI) = RI; + getRegionInfo(ChildBB) = RI; } } @@ -383,9 +383,11 @@ } // Now that all of our successors have information, recursively process them. - for (std::vector::iterator CI = children.begin(), - E = children.end(); CI != E; ++CI) - Changed |= TransformRegion(*CI, VisitedBlocks); + for (std::vector::iterator DI = BBDom->begin(), + E = BBDom->end(); DI != E; ++DI) { + BasicBlock *ChildBB = (*DI)->getBlock(); + Changed |= TransformRegion(ChildBB, VisitedBlocks); + } return Changed; } @@ -552,7 +554,7 @@ // insert dead phi nodes, but it is more trouble to see if they are used than // to just blindly insert them. // - if (EF->dominates(OldSucc, Dest)) { + if (DT->dominates(OldSucc, Dest)) { // RegionExitBlocks - Find all of the blocks that are not dominated by Dest, // but have predecessors that are. Additionally, prune down the set to only // include blocks that are dominated by OldSucc as well. @@ -652,7 +654,7 @@ for (Value::use_iterator I = Orig->use_begin(), E = Orig->use_end(); I != E; ++I) if (Instruction *User = dyn_cast(*I)) - if (EF->dominates(RegionDominator, User->getParent())) + if (DT->dominates(RegionDominator, User->getParent())) InstsToChange.push_back(User); else if (PHINode *PN = dyn_cast(User)) { PHIsToChange.push_back(PN); @@ -665,7 +667,7 @@ PHINode *PN = PHIsToChange[i]; for (unsigned j = 0, e = PN->getNumIncomingValues(); j != e; ++j) if (PN->getIncomingValue(j) == Orig && - EF->dominates(RegionDominator, PN->getIncomingBlock(j))) + DT->dominates(RegionDominator, PN->getIncomingBlock(j))) PN->setIncomingValue(j, New); } @@ -679,7 +681,7 @@ // values that correspond to basic blocks in the region. for (unsigned j = 0, e = PN->getNumIncomingValues(); j != e; ++j) if (PN->getIncomingValue(j) == Orig && - EF->dominates(RegionDominator, PN->getIncomingBlock(j))) + DT->dominates(RegionDominator, PN->getIncomingBlock(j))) PN->setIncomingValue(j, New); } else { @@ -689,14 +691,14 @@ static void CalcRegionExitBlocks(BasicBlock *Header, BasicBlock *BB, std::set &Visited, - ETForest &EF, + DominatorTree &DT, std::vector &RegionExitBlocks) { if (Visited.count(BB)) return; Visited.insert(BB); - if (EF.dominates(Header, BB)) { // Block in the region, recursively traverse + if (DT.dominates(Header, BB)) { // Block in the region, recursively traverse for (succ_iterator I = succ_begin(BB), E = succ_end(BB); I != E; ++I) - CalcRegionExitBlocks(Header, *I, Visited, EF, RegionExitBlocks); + CalcRegionExitBlocks(Header, *I, Visited, DT, RegionExitBlocks); } else { // Header does not dominate this block, but we have a predecessor that does // dominate us. Add ourself to the list. @@ -713,11 +715,11 @@ std::set Visited; // Don't infinite loop // Recursively calculate blocks we are interested in... - CalcRegionExitBlocks(BB, BB, Visited, *EF, RegionExitBlocks); + CalcRegionExitBlocks(BB, BB, Visited, *DT, RegionExitBlocks); // Filter out blocks that are not dominated by OldSucc... for (unsigned i = 0; i != RegionExitBlocks.size(); ) { - if (EF->dominates(OldSucc, RegionExitBlocks[i])) + if (DT->dominates(OldSucc, RegionExitBlocks[i])) ++i; // Block is ok, keep it. else { // Move to end of list... @@ -746,7 +748,7 @@ PI != PE; ++PI) { // If the incoming edge is from the region dominated by BB, use BBVal, // otherwise use OldVal. - NewPN->addIncoming(EF->dominates(BB, *PI) ? BBVal : OldVal, *PI); + NewPN->addIncoming(DT->dominates(BB, *PI) ? BBVal : OldVal, *PI); } // Now make everyone dominated by this block use this new value! @@ -989,7 +991,7 @@ // here. This check is also effectively checking to make sure that Inst // is in the same function as our region (in case V is a global f.e.). // - if (EF->properlyDominates(Inst->getParent(), RI.getEntryBlock())) + if (DT->properlyDominates(Inst->getParent(), RI.getEntryBlock())) IncorporateInstruction(Inst, RI); } } From dpatel at apple.com Thu Jun 7 16:42:40 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 16:42:40 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200706072142.l57LgeTA016944@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopStrengthReduce.cpp updated: 1.139 -> 1.140 --- Log message: Use DominatorTree instead of ETForest. --- Diffs of the changes: (+7 -8) LoopStrengthReduce.cpp | 15 +++++++-------- 1 files changed, 7 insertions(+), 8 deletions(-) Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp diff -u llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.139 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.140 --- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.139 Tue Jun 5 20:23:55 2007 +++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Thu Jun 7 16:42:15 2007 @@ -111,7 +111,7 @@ class VISIBILITY_HIDDEN LoopStrengthReduce : public LoopPass { LoopInfo *LI; - ETForest *EF; + DominatorTree *DT; ScalarEvolution *SE; const TargetData *TD; const Type *UIntPtrTy; @@ -156,13 +156,12 @@ // many analyses if they are around. AU.addPreservedID(LoopSimplifyID); AU.addPreserved(); - AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); AU.addRequiredID(LoopSimplifyID); AU.addRequired(); - AU.addRequired(); + AU.addRequired(); AU.addRequired(); AU.addRequired(); } @@ -353,7 +352,7 @@ /// the loop, resulting in reg-reg copies (if we use the pre-inc value when we /// should use the post-inc value). static bool IVUseShouldUsePostIncValue(Instruction *User, Instruction *IV, - Loop *L, ETForest *EF, Pass *P) { + Loop *L, DominatorTree *DT, Pass *P) { // If the user is in the loop, use the preinc value. if (L->contains(User->getParent())) return false; @@ -361,7 +360,7 @@ // Ok, the user is outside of the loop. If it is dominated by the latch // block, use the post-inc value. - if (EF->dominates(LatchBlock, User->getParent())) + if (DT->dominates(LatchBlock, User->getParent())) return true; // There is one case we have to be careful of: PHI nodes. These little guys @@ -378,7 +377,7 @@ for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) if (PN->getIncomingValue(i) == IV) { ++NumUses; - if (!EF->dominates(LatchBlock, PN->getIncomingBlock(i))) + if (!DT->dominates(LatchBlock, PN->getIncomingBlock(i))) return false; } @@ -456,7 +455,7 @@ // Okay, we found a user that we cannot reduce. Analyze the instruction // and decide what to do with it. If we are a use inside of the loop, use // the value before incrementation, otherwise use it after incrementation. - if (IVUseShouldUsePostIncValue(User, I, L, EF, this)) { + if (IVUseShouldUsePostIncValue(User, I, L, DT, this)) { // The value used will be incremented by the stride more than we are // expecting, so subtract this off. SCEVHandle NewStart = SCEV::getMinusSCEV(Start, Stride); @@ -1400,7 +1399,7 @@ bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager &LPM) { LI = &getAnalysis(); - EF = &getAnalysis(); + DT = &getAnalysis(); SE = &getAnalysis(); TD = &getAnalysis(); UIntPtrTy = TD->getIntPtrType(); From dpatel at apple.com Thu Jun 7 16:57:25 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 16:57:25 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h Message-ID: <200706072157.l57LvPmA017254@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms/Utils: PromoteMemToReg.h updated: 1.12 -> 1.13 --- Log message: Use DominatorTree instead of ETForest. This allows faster immediate domiantor walk. --- Diffs of the changes: (+2 -2) PromoteMemToReg.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h diff -u llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h:1.12 llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h:1.13 --- llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h:1.12 Wed Apr 25 13:41:11 2007 +++ llvm/include/llvm/Transforms/Utils/PromoteMemToReg.h Thu Jun 7 16:57:03 2007 @@ -20,7 +20,7 @@ namespace llvm { class AllocaInst; -class ETForest; +class DominatorTree; class DominanceFrontier; class AliasSetTracker; @@ -38,7 +38,7 @@ /// made to the IR. /// void PromoteMemToReg(const std::vector &Allocas, - ETForest &ET, DominanceFrontier &DF, + DominatorTree &DT, DominanceFrontier &DF, AliasSetTracker *AST = 0); } // End llvm namespace From dpatel at apple.com Thu Jun 7 16:57:26 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 16:57:26 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LICM.cpp ScalarReplAggregates.cpp Message-ID: <200706072157.l57LvQGt017261@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LICM.cpp updated: 1.105 -> 1.106 ScalarReplAggregates.cpp updated: 1.96 -> 1.97 --- Log message: Use DominatorTree instead of ETForest. This allows faster immediate domiantor walk. --- Diffs of the changes: (+5 -5) LICM.cpp | 4 ++-- ScalarReplAggregates.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) Index: llvm/lib/Transforms/Scalar/LICM.cpp diff -u llvm/lib/Transforms/Scalar/LICM.cpp:1.105 llvm/lib/Transforms/Scalar/LICM.cpp:1.106 --- llvm/lib/Transforms/Scalar/LICM.cpp:1.105 Tue Jun 5 11:05:55 2007 +++ llvm/lib/Transforms/Scalar/LICM.cpp Thu Jun 7 16:57:03 2007 @@ -565,7 +565,7 @@ if (AI) { std::vector Allocas; Allocas.push_back(AI); - PromoteMemToReg(Allocas, *ET, *DF, CurAST); + PromoteMemToReg(Allocas, *DT, *DF, CurAST); } } } @@ -746,7 +746,7 @@ PromotedAllocas.reserve(PromotedValues.size()); for (unsigned i = 0, e = PromotedValues.size(); i != e; ++i) PromotedAllocas.push_back(PromotedValues[i].first); - PromoteMemToReg(PromotedAllocas, *ET, *DF, CurAST); + PromoteMemToReg(PromotedAllocas, *DT, *DF, CurAST); } /// FindPromotableValuesInLoop - Check the current loop for stores to definite Index: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp diff -u llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.96 llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.97 --- llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.96 Wed May 30 01:11:23 2007 +++ llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Thu Jun 7 16:57:03 2007 @@ -58,7 +58,7 @@ // getAnalysisUsage - This pass does not require any passes, but we know it // will not alter the CFG, so say so. virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.setPreservesCFG(); @@ -138,7 +138,7 @@ bool SROA::performPromotion(Function &F) { std::vector Allocas; - ETForest &ET = getAnalysis(); + DominatorTree &DT = getAnalysis(); DominanceFrontier &DF = getAnalysis(); BasicBlock &BB = F.getEntryBlock(); // Get the entry node for the function @@ -157,7 +157,7 @@ if (Allocas.empty()) break; - PromoteMemToReg(Allocas, ET, DF); + PromoteMemToReg(Allocas, DT, DF); NumPromoted += Allocas.size(); Changed = true; } From dpatel at apple.com Thu Jun 7 16:57:32 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 16:57:32 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/Mem2Reg.cpp PromoteMemoryToRegister.cpp Message-ID: <200706072157.l57LvWDh017270@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: Mem2Reg.cpp updated: 1.30 -> 1.31 PromoteMemoryToRegister.cpp updated: 1.100 -> 1.101 --- Log message: Use DominatorTree instead of ETForest. This allows faster immediate domiantor walk. --- Diffs of the changes: (+15 -13) Mem2Reg.cpp | 6 +++--- PromoteMemoryToRegister.cpp | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 13 deletions(-) Index: llvm/lib/Transforms/Utils/Mem2Reg.cpp diff -u llvm/lib/Transforms/Utils/Mem2Reg.cpp:1.30 llvm/lib/Transforms/Utils/Mem2Reg.cpp:1.31 --- llvm/lib/Transforms/Utils/Mem2Reg.cpp:1.30 Sun May 6 08:37:16 2007 +++ llvm/lib/Transforms/Utils/Mem2Reg.cpp Thu Jun 7 16:57:03 2007 @@ -38,7 +38,7 @@ // getAnalysisUsage - We need dominance frontiers // virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); + AU.addRequired(); AU.addRequired(); AU.setPreservesCFG(); // This is a cluster of orthogonal Transforms @@ -61,7 +61,7 @@ bool Changed = false; - ETForest &ET = getAnalysis(); + DominatorTree &DT = getAnalysis(); DominanceFrontier &DF = getAnalysis(); while (1) { @@ -76,7 +76,7 @@ if (Allocas.empty()) break; - PromoteMemToReg(Allocas, ET, DF); + PromoteMemToReg(Allocas, DT, DF); NumPromoted += Allocas.size(); Changed = true; } Index: llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp diff -u llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.100 llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.101 --- llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.100 Wed Apr 25 13:32:35 2007 +++ llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp Thu Jun 7 16:57:03 2007 @@ -88,7 +88,7 @@ /// std::vector Allocas; SmallVector &RetryList; - ETForest &ET; + DominatorTree &DT; DominanceFrontier &DF; /// AST - An AliasSetTracker object to update. If null, don't update it. @@ -126,9 +126,9 @@ public: PromoteMem2Reg(const std::vector &A, - SmallVector &Retry, ETForest &et, + SmallVector &Retry, DominatorTree &dt, DominanceFrontier &df, AliasSetTracker *ast) - : Allocas(A), RetryList(Retry), ET(et), DF(df), AST(ast) {} + : Allocas(A), RetryList(Retry), DT(dt), DF(df), AST(ast) {} void run(); @@ -137,13 +137,13 @@ bool properlyDominates(Instruction *I1, Instruction *I2) const { if (InvokeInst *II = dyn_cast(I1)) I1 = II->getNormalDest()->begin(); - return ET.properlyDominates(I1->getParent(), I2->getParent()); + return DT.properlyDominates(I1->getParent(), I2->getParent()); } - /// dominates - Return true if BB1 dominates BB2 using the ETForest. + /// dominates - Return true if BB1 dominates BB2 using the DominatorTree. /// bool dominates(BasicBlock *BB1, BasicBlock *BB2) const { - return ET.dominates(BB1, BB2); + return DT.dominates(BB1, BB2); } private: @@ -532,7 +532,9 @@ SmallPtrSet &DeadPHINodes) { // Scan the immediate dominators of this block looking for a block which has a // PHI node for Alloca num. If we find it, mark the PHI node as being alive! - for (BasicBlock* DomBB = BB; DomBB; DomBB = ET.getIDom(DomBB)) { + DomTreeNode *IDomNode = DT.getNode(BB); + for (DomTreeNode *IDom = IDomNode; IDom; IDom = IDom->getIDom()) { + BasicBlock *DomBB = IDom->getBlock(); DenseMap, PHINode*>::iterator I = NewPhiNodes.find(std::make_pair(DomBB, AllocaNum)); if (I != NewPhiNodes.end()) { @@ -803,13 +805,13 @@ /// made to the IR. /// void llvm::PromoteMemToReg(const std::vector &Allocas, - ETForest &ET, DominanceFrontier &DF, + DominatorTree &DT, DominanceFrontier &DF, AliasSetTracker *AST) { // If there is nothing to do, bail out... if (Allocas.empty()) return; SmallVector RetryList; - PromoteMem2Reg(Allocas, RetryList, ET, DF, AST).run(); + PromoteMem2Reg(Allocas, RetryList, DT, DF, AST).run(); // PromoteMem2Reg may not have been able to promote all of the allocas in one // pass, run it again if needed. @@ -827,7 +829,7 @@ NewAllocas.assign(RetryList.begin(), RetryList.end()); RetryList.clear(); - PromoteMem2Reg(NewAllocas, RetryList, ET, DF, AST).run(); + PromoteMem2Reg(NewAllocas, RetryList, DT, DF, AST).run(); NewAllocas.clear(); } } From dpatel at apple.com Thu Jun 7 17:17:38 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 17:17:38 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706072217.l57MHcJ4017685@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.95 -> 1.96 --- Log message: Do not use ETForest as well as DomiantorTree. DominatorTree is sufficient. --- Diffs of the changes: (+10 -0) Dominators.h | 10 ++++++++++ 1 files changed, 10 insertions(+) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.95 llvm/include/llvm/Analysis/Dominators.h:1.96 --- llvm/include/llvm/Analysis/Dominators.h:1.95 Thu Jun 7 16:34:22 2007 +++ llvm/include/llvm/Analysis/Dominators.h Thu Jun 7 17:17:16 2007 @@ -142,6 +142,16 @@ return getNode(BB); } + /// getIDomBlock - return basic block BB's immediate domiantor basic block. + /// + BasicBlock *getIDomBlock(BasicBlock *BB) { + DomTreeNode *N = getNode(BB); + assert (N && "Missing dominator tree node"); + DomTreeNode *I = N->getIDom(); + assert (N && "Missing immediate dominator"); + return I->getBlock(); + } + /// getRootNode - This returns the entry node for the CFG of the function. If /// this tree represents the post-dominance relations for a function, however, /// this root may be a node with the block == NULL. This is the case when From dpatel at apple.com Thu Jun 7 17:17:45 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 17:17:45 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/IPO/LoopExtractor.cpp Message-ID: <200706072217.l57MHj24017692@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/IPO: LoopExtractor.cpp updated: 1.28 -> 1.29 --- Log message: Do not use ETForest as well as DomiantorTree. DominatorTree is sufficient. --- Diffs of the changes: (+3 -5) LoopExtractor.cpp | 8 +++----- 1 files changed, 3 insertions(+), 5 deletions(-) Index: llvm/lib/Transforms/IPO/LoopExtractor.cpp diff -u llvm/lib/Transforms/IPO/LoopExtractor.cpp:1.28 llvm/lib/Transforms/IPO/LoopExtractor.cpp:1.29 --- llvm/lib/Transforms/IPO/LoopExtractor.cpp:1.28 Sun May 6 08:37:16 2007 +++ llvm/lib/Transforms/IPO/LoopExtractor.cpp Thu Jun 7 17:17:16 2007 @@ -45,7 +45,6 @@ virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequiredID(BreakCriticalEdgesID); AU.addRequiredID(LoopSimplifyID); - AU.addRequired(); AU.addRequired(); AU.addRequired(); } @@ -78,7 +77,6 @@ if (LI.begin() == LI.end()) return false; - ETForest &EF = getAnalysis(); DominatorTree &DT = getAnalysis(); // If there is more than one top-level loop in this function, extract all of @@ -88,7 +86,7 @@ for (LoopInfo::iterator i = LI.begin(), e = LI.end(); i != e; ++i) { if (NumLoops == 0) return Changed; --NumLoops; - Changed |= ExtractLoop(EF, DT, *i) != 0; + Changed |= ExtractLoop(DT, *i) != 0; ++NumExtracted; } } else { @@ -118,7 +116,7 @@ if (ShouldExtractLoop) { if (NumLoops == 0) return Changed; --NumLoops; - Changed |= ExtractLoop(EF, DT, TLL) != 0; + Changed |= ExtractLoop(DT, TLL) != 0; ++NumExtracted; } else { // Okay, this function is a minimal container around the specified loop. @@ -128,7 +126,7 @@ for (Loop::iterator i = TLL->begin(), e = TLL->end(); i != e; ++i) { if (NumLoops == 0) return Changed; --NumLoops; - Changed |= ExtractLoop(EF, DT, *i) != 0; + Changed |= ExtractLoop(DT, *i) != 0; ++NumExtracted; } } From dpatel at apple.com Thu Jun 7 17:17:47 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 17:17:47 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/CodeExtractor.cpp Message-ID: <200706072217.l57MHlj0017700@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: CodeExtractor.cpp updated: 1.56 -> 1.57 --- Log message: Do not use ETForest as well as DomiantorTree. DominatorTree is sufficient. --- Diffs of the changes: (+15 -16) CodeExtractor.cpp | 31 +++++++++++++++---------------- 1 files changed, 15 insertions(+), 16 deletions(-) Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp diff -u llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.56 llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.57 --- llvm/lib/Transforms/Utils/CodeExtractor.cpp:1.56 Mon Jun 4 11:43:25 2007 +++ llvm/lib/Transforms/Utils/CodeExtractor.cpp Thu Jun 7 17:17:16 2007 @@ -44,14 +44,13 @@ class VISIBILITY_HIDDEN CodeExtractor { typedef std::vector Values; std::set BlocksToExtract; - ETForest *EF; DominatorTree* DT; bool AggregateArgs; unsigned NumExitBlocks; const Type *RetTy; public: - CodeExtractor(ETForest *ef = 0, DominatorTree* dt = 0, bool AggArgs = false) - : EF(ef), DT(dt), AggregateArgs(AggArgs||AggregateArgsOpt), NumExitBlocks(~0U) {} + CodeExtractor(DominatorTree* dt = 0, bool AggArgs = false) + : DT(dt), AggregateArgs(AggArgs||AggregateArgsOpt), NumExitBlocks(~0U) {} Function *ExtractCodeRegion(const std::vector &code); @@ -141,17 +140,17 @@ // Okay, update dominator sets. The blocks that dominate the new one are the // blocks that dominate TIBB plus the new block itself. - if (EF) { - BasicBlock* idom = EF->getIDom(OldPred); + if (DT) { + DomTreeNode *OPNode = DT->getNode(OldPred); + DomTreeNode *IDomNode = OPNode->getIDom(); + BasicBlock* idom = IDomNode->getBlock(); DT->addNewBlock(NewBB, idom); - EF->addNewBlock(NewBB, idom); // Additionally, NewBB replaces OldPred as the immediate dominator of blocks Function *F = Header->getParent(); for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) - if (EF->getIDom(I) == OldPred) { + if (DT->getIDomBlock(I) == OldPred) { DT->changeImmediateDominator(I, NewBB); - EF->setImmediateDominator(I, NewBB); } } @@ -509,12 +508,12 @@ // In the extract block case, if the block we are extracting ends // with an invoke instruction, make sure that we don't emit a // store of the invoke value for the unwind block. - if (!EF && DefBlock != OldTarget) + if (!DT && DefBlock != OldTarget) DominatesDef = false; } - if (EF) - DominatesDef = EF->dominates(DefBlock, OldTarget); + if (DT) + DominatesDef = DT->dominates(DefBlock, OldTarget); if (DominatesDef) { if (AggregateArgs) { @@ -728,16 +727,16 @@ /// ExtractCodeRegion - slurp a sequence of basic blocks into a brand new /// function /// -Function* llvm::ExtractCodeRegion(ETForest &EF, DominatorTree &DT, +Function* llvm::ExtractCodeRegion(DominatorTree &DT, const std::vector &code, bool AggregateArgs) { - return CodeExtractor(&EF, &DT, AggregateArgs).ExtractCodeRegion(code); + return CodeExtractor(&DT, AggregateArgs).ExtractCodeRegion(code); } /// ExtractBasicBlock - slurp a natural loop into a brand new function /// -Function* llvm::ExtractLoop(ETForest &EF, DominatorTree &DF, Loop *L, bool AggregateArgs) { - return CodeExtractor(&EF, &DF, AggregateArgs).ExtractCodeRegion(L->getBlocks()); +Function* llvm::ExtractLoop(DominatorTree &DT, Loop *L, bool AggregateArgs) { + return CodeExtractor(&DT, AggregateArgs).ExtractCodeRegion(L->getBlocks()); } /// ExtractBasicBlock - slurp a basic block into a brand new function @@ -745,5 +744,5 @@ Function* llvm::ExtractBasicBlock(BasicBlock *BB, bool AggregateArgs) { std::vector Blocks; Blocks.push_back(BB); - return CodeExtractor(0, 0, AggregateArgs).ExtractCodeRegion(Blocks); + return CodeExtractor(0, AggregateArgs).ExtractCodeRegion(Blocks); } From dpatel at apple.com Thu Jun 7 17:17:47 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 17:17:47 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Utils/FunctionUtils.h Message-ID: <200706072217.l57MHlD5017699@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms/Utils: FunctionUtils.h updated: 1.11 -> 1.12 --- Log message: Do not use ETForest as well as DomiantorTree. DominatorTree is sufficient. --- Diffs of the changes: (+2 -2) FunctionUtils.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/include/llvm/Transforms/Utils/FunctionUtils.h diff -u llvm/include/llvm/Transforms/Utils/FunctionUtils.h:1.11 llvm/include/llvm/Transforms/Utils/FunctionUtils.h:1.12 --- llvm/include/llvm/Transforms/Utils/FunctionUtils.h:1.11 Sat Apr 7 02:17:27 2007 +++ llvm/include/llvm/Transforms/Utils/FunctionUtils.h Thu Jun 7 17:17:16 2007 @@ -24,13 +24,13 @@ /// ExtractCodeRegion - rip out a sequence of basic blocks into a new function /// - Function* ExtractCodeRegion(ETForest &DS, DominatorTree& DT, + Function* ExtractCodeRegion(DominatorTree& DT, const std::vector &code, bool AggregateArgs = false); /// ExtractLoop - rip out a natural loop into a new function /// - Function* ExtractLoop(ETForest &DS, DominatorTree& DT, Loop *L, + Function* ExtractLoop(DominatorTree& DT, Loop *L, bool AggregateArgs = false); /// ExtractBasicBlock - rip out a basic block into a new function From dpatel at apple.com Thu Jun 7 17:21:36 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 17:21:36 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LICM.cpp Message-ID: <200706072221.l57MLanq017790@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LICM.cpp updated: 1.106 -> 1.107 --- Log message: Do not require ETForest. Now it is unused by LICM. --- Diffs of the changes: (+0 -3) LICM.cpp | 3 --- 1 files changed, 3 deletions(-) Index: llvm/lib/Transforms/Scalar/LICM.cpp diff -u llvm/lib/Transforms/Scalar/LICM.cpp:1.106 llvm/lib/Transforms/Scalar/LICM.cpp:1.107 --- llvm/lib/Transforms/Scalar/LICM.cpp:1.106 Thu Jun 7 16:57:03 2007 +++ llvm/lib/Transforms/Scalar/LICM.cpp Thu Jun 7 17:21:15 2007 @@ -76,7 +76,6 @@ AU.addRequiredID(LoopSimplifyID); AU.addRequired(); AU.addRequired(); - AU.addRequired(); AU.addRequired(); // For scalar promotion (mem2reg) AU.addRequired(); } @@ -90,7 +89,6 @@ // Various analyses that we use... AliasAnalysis *AA; // Current AliasAnalysis information LoopInfo *LI; // Current LoopInfo - ETForest *ET; // ETForest for the current loop.. DominatorTree *DT; // Dominator Tree for the current Loop... DominanceFrontier *DF; // Current Dominance Frontier @@ -220,7 +218,6 @@ AA = &getAnalysis(); DF = &getAnalysis(); DT = &getAnalysis(); - ET = &getAnalysis(); CurAST = new AliasSetTracker(*AA); // Collect Alias info from subloops From evan.cheng at apple.com Thu Jun 7 17:31:50 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 7 Jun 2007 17:31:50 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706072231.l57MVoWL018042@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.36 -> 1.37 --- Log message: Only remove the edge from entry to false if false block is merged. --- Diffs of the changes: (+2 -2) IfConversion.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.36 llvm/lib/CodeGen/IfConversion.cpp:1.37 --- llvm/lib/CodeGen/IfConversion.cpp:1.36 Thu Jun 7 03:13:00 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Thu Jun 7 17:31:28 2007 @@ -647,8 +647,8 @@ // Now merge the entry of the triangle with the true block. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); MergeBlocks(BBI, TrueBBI); - // Remove entry to false edge. - if (BBI.BB->isSuccessor(FalseBBI.BB)) + // Remove entry to false edge if false block is merged in as well. + if (FalseBBDead && BBI.BB->isSuccessor(FalseBBI.BB)) BBI.BB->removeSuccessor(FalseBBI.BB); std::copy(BBI.BrCond.begin(), BBI.BrCond.end(), std::back_inserter(BBI.Predicate)); From dpatel at apple.com Thu Jun 7 18:53:01 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 18:53:01 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp Message-ID: <200706072353.l57Nr1aq019790@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Dominators.cpp updated: 1.107 -> 1.108 --- Log message: Add instruction level dominates(A,B) interface. --- Diffs of the changes: (+23 -0) Dominators.cpp | 23 +++++++++++++++++++++++ 1 files changed, 23 insertions(+) Index: llvm/lib/VMCore/Dominators.cpp diff -u llvm/lib/VMCore/Dominators.cpp:1.107 llvm/lib/VMCore/Dominators.cpp:1.108 --- llvm/lib/VMCore/Dominators.cpp:1.107 Thu Jun 7 12:47:21 2007 +++ llvm/lib/VMCore/Dominators.cpp Thu Jun 7 18:52:40 2007 @@ -324,6 +324,29 @@ DFSInfoValid = true; } +// dominates - Return true if A dominates B. THis performs the +// special checks necessary if A and B are in the same basic block. +bool DominatorTreeBase::dominates(Instruction *A, Instruction *B) { + BasicBlock *BBA = A->getParent(), *BBB = B->getParent(); + if (BBA != BBB) return dominates(BBA, BBB); + + // It is not possible to determine dominance between two PHI nodes + // based on their ordering. + if (isa(A) && isa(B)) + return false; + + // Loop through the basic block until we find A or B. + BasicBlock::iterator I = BBA->begin(); + for (; &*I != A && &*I != B; ++I) /*empty*/; + + if(!IsPostDominators) { + // A dominates B if it is found first in the basic block. + return &*I == A; + } else { + // A post-dominates B if B is found first in the basic block. + return &*I == B; + } +} // DominatorTreeBase::reset - Free all of the tree node memory. // From dpatel at apple.com Thu Jun 7 18:53:02 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 18:53:02 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706072353.l57Nr2mF019793@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.96 -> 1.97 --- Log message: Add instruction level dominates(A,B) interface. --- Diffs of the changes: (+4 -0) Dominators.h | 4 ++++ 1 files changed, 4 insertions(+) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.96 llvm/include/llvm/Analysis/Dominators.h:1.97 --- llvm/include/llvm/Analysis/Dominators.h:1.96 Thu Jun 7 17:17:16 2007 +++ llvm/include/llvm/Analysis/Dominators.h Thu Jun 7 18:52:40 2007 @@ -219,6 +219,10 @@ return dominates(getNode(A), getNode(B)); } + // dominates - Return true if A dominates B. This performs the + // special checks necessary if A and B are in the same basic block. + bool dominates(Instruction *A, Instruction *B); + //===--------------------------------------------------------------------===// // API to update (Post)DominatorTree information based on modifications to // the CFG... From dpatel at apple.com Thu Jun 7 18:53:59 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 18:53:59 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/LoadValueNumbering.cpp Message-ID: <200706072353.l57Nrxmv019825@zion.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: LoadValueNumbering.cpp updated: 1.42 -> 1.43 --- Log message: Use DominatorTree instead of ETForest. --- Diffs of the changes: (+9 -9) LoadValueNumbering.cpp | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-) Index: llvm/lib/Analysis/LoadValueNumbering.cpp diff -u llvm/lib/Analysis/LoadValueNumbering.cpp:1.42 llvm/lib/Analysis/LoadValueNumbering.cpp:1.43 --- llvm/lib/Analysis/LoadValueNumbering.cpp:1.42 Wed May 2 20:11:53 2007 +++ llvm/lib/Analysis/LoadValueNumbering.cpp Thu Jun 7 18:53:38 2007 @@ -101,7 +101,7 @@ AU.setPreservesAll(); AU.addRequiredTransitive(); AU.addRequired(); - AU.addRequiredTransitive(); + AU.addRequiredTransitive(); AU.addRequiredTransitive(); } @@ -201,20 +201,20 @@ // ANY memory. // if (MRB == AliasAnalysis::OnlyReadsMemory) { - ETForest &EF = getAnalysis(); + DominatorTree &DT = getAnalysis(); BasicBlock *CIBB = CI->getParent(); for (unsigned i = 0; i != IdenticalCalls.size(); ++i) { CallInst *C = IdenticalCalls[i]; bool CantEqual = false; - if (EF.dominates(CIBB, C->getParent())) { + if (DT.dominates(CIBB, C->getParent())) { // FIXME: we currently only handle the case where both calls are in the // same basic block. if (CIBB != C->getParent()) { CantEqual = true; } else { Instruction *First = CI, *Second = C; - if (!EF.dominates(CI, C)) + if (!DT.dominates(CI, C)) std::swap(First, Second); // Scan the instructions between the calls, checking for stores or @@ -239,7 +239,7 @@ } } - } else if (EF.dominates(C->getParent(), CIBB)) { + } else if (DT.dominates(C->getParent(), CIBB)) { // FIXME: We could implement this, but we don't for now. CantEqual = true; } else { @@ -380,7 +380,7 @@ } // Get dominators. - ETForest &EF = getAnalysis(); + DominatorTree &DT = getAnalysis(); // TransparentBlocks - For each basic block the load/store is alive across, // figure out if the pointer is invalidated or not. If it is invalidated, the @@ -399,12 +399,12 @@ // Right now we only can handle cases where one load dominates the other. // FIXME: generalize this! BasicBlock *BB1 = I->first, *BB2 = LoadBB; - if (EF.dominates(BB1, BB2)) { + if (DT.dominates(BB1, BB2)) { // The other load dominates LI. If the loaded value is killed entering // the LoadBB block, we know the load is not live. if (LoadInvalidatedInBBBefore) CantEqual = true; - } else if (EF.dominates(BB2, BB1)) { + } else if (DT.dominates(BB2, BB1)) { std::swap(BB1, BB2); // Canonicalize // LI dominates the other load. If the loaded value is killed exiting // the LoadBB block, we know the load is not live. @@ -486,7 +486,7 @@ for (std::set::iterator I = CandidateStores.begin(), E = CandidateStores.end(); I != E; ++I) - if (EF.dominates(*I, LoadBB)) { + if (DT.dominates(*I, LoadBB)) { BasicBlock *StoreBB = *I; // Check to see if the path from the store to the load is transparent From dpatel at apple.com Thu Jun 7 19:02:30 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 19:02:30 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp Message-ID: <200706080002.l5802UrN020044@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: BreakCriticalEdges.cpp updated: 1.52 -> 1.53 --- Log message: Do not preserve ETForest. --- Diffs of the changes: (+5 -26) BreakCriticalEdges.cpp | 31 +++++-------------------------- 1 files changed, 5 insertions(+), 26 deletions(-) Index: llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp diff -u llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp:1.52 llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp:1.53 --- llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp:1.52 Thu Jun 7 12:47:21 2007 +++ llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp Thu Jun 7 19:02:08 2007 @@ -40,7 +40,6 @@ virtual bool runOnFunction(Function &F); virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); @@ -110,11 +109,11 @@ } // SplitCriticalEdge - If this edge is a critical edge, insert a new node to -// split the critical edge. This will update ETForest, ImmediateDominator, -// DominatorTree, and DominatorFrontier information if it is available, thus -// calling this pass will not invalidate any of them. This returns true if -// the edge was split, false otherwise. This ensures that all edges to that -// dest go to one block instead of each going to a different block. +// split the critical edge. This will update DominatorTree, and DominatorFrontier +// information if it is available, thus calling this pass will not invalidate +// any of them. This returns true if the edge was split, false otherwise. +// This ensures that all edges to that dest go to one block instead of each +// going to a different block. // bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P, bool MergeIdenticalEdges) { @@ -181,26 +180,6 @@ bool NewBBDominatesDestBB = true; - // Update the forest? - if (ETForest *EF = P->getAnalysisToUpdate()) { - // NewBB is dominated by TIBB. - EF->addNewBlock(NewBB, TIBB); - - // If NewBBDominatesDestBB hasn't been computed yet, do so with EF. - if (!OtherPreds.empty()) { - while (!OtherPreds.empty() && NewBBDominatesDestBB) { - NewBBDominatesDestBB = EF->dominates(DestBB, OtherPreds.back()); - OtherPreds.pop_back(); - } - OtherPreds.clear(); - } - - // If NewBBDominatesDestBB, then NewBB dominates DestBB, otherwise it - // doesn't dominate anything. - if (NewBBDominatesDestBB) - EF->setImmediateDominator(DestBB, NewBB); - } - // Should we update DominatorTree information? if (DominatorTree *DT = P->getAnalysisToUpdate()) { DomTreeNode *TINode = DT->getNode(TIBB); From dpatel at apple.com Thu Jun 7 19:02:30 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 19:02:30 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h Message-ID: <200706080002.l5802U74020047@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Transforms/Utils: BasicBlockUtils.h updated: 1.16 -> 1.17 --- Log message: Do not preserve ETForest. --- Diffs of the changes: (+9 -9) BasicBlockUtils.h | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-) Index: llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h diff -u llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h:1.16 llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h:1.17 --- llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h:1.16 Sat Apr 7 02:17:27 2007 +++ llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h Thu Jun 7 19:02:08 2007 @@ -61,15 +61,15 @@ bool AllowIdenticalEdges = false); /// SplitCriticalEdge - If this edge is a critical edge, insert a new node to -/// split the critical edge. This will update ETForest, ImmediateDominator, -/// DominatorTree, and DominatorFrontier information if it is available, thus -/// calling this pass will not invalidate either of them. This returns true if -/// the edge was split, false otherwise. If MergeIdenticalEdges is true (the -/// default), *all* edges from TI to the specified successor will be merged into -/// the same critical edge block. This is most commonly interesting with switch -/// instructions, which may have many edges to any one destination. This -/// ensures that all edges to that dest go to one block instead of each going to -/// a different block, but isn't the standard definition of a "critical edge". +/// split the critical edge. This will update DominatorTree, and DominatorFrontier +/// information if it is available, thus calling this pass will not invalidate +/// either of them. This returns true if the edge was split, false otherwise. +/// If MergeIdenticalEdges is true (the default), *all* edges from TI to the +/// specified successor will be merged into the same critical edge block. +/// This is most commonly interesting with switch instructions, which may +/// have many edges to any one destination. This ensures that all edges to that +/// dest go to one block instead of each going to a different block, but isn't +/// the standard definition of a "critical edge". /// bool SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P = 0, bool MergeIdenticalEdges = false); From dpatel at apple.com Thu Jun 7 19:17:35 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 19:17:35 -0500 Subject: [llvm-commits] CVS: llvm/lib/Analysis/LoopInfo.cpp Message-ID: <200706080017.l580HZKK020485@zion.cs.uiuc.edu> Changes in directory llvm/lib/Analysis: LoopInfo.cpp updated: 1.86 -> 1.87 --- Log message: Use DominatorTree instead of ETForest. --- Diffs of the changes: (+9 -9) LoopInfo.cpp | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-) Index: llvm/lib/Analysis/LoopInfo.cpp diff -u llvm/lib/Analysis/LoopInfo.cpp:1.86 llvm/lib/Analysis/LoopInfo.cpp:1.87 --- llvm/lib/Analysis/LoopInfo.cpp:1.86 Wed May 2 20:11:53 2007 +++ llvm/lib/Analysis/LoopInfo.cpp Thu Jun 7 19:17:13 2007 @@ -91,7 +91,7 @@ // bool LoopInfo::runOnFunction(Function &) { releaseMemory(); - Calculate(getAnalysis()); // Update + Calculate(getAnalysis()); // Update return false; } @@ -105,18 +105,18 @@ } -void LoopInfo::Calculate(ETForest &EF) { - BasicBlock *RootNode = EF.getRoot(); +void LoopInfo::Calculate(DominatorTree &DT) { + BasicBlock *RootNode = DT.getRootNode()->getBlock(); for (df_iterator NI = df_begin(RootNode), NE = df_end(RootNode); NI != NE; ++NI) - if (Loop *L = ConsiderForLoop(*NI, EF)) + if (Loop *L = ConsiderForLoop(*NI, DT)) TopLevelLoops.push_back(L); } void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); - AU.addRequired(); + AU.addRequired(); } void LoopInfo::print(std::ostream &OS, const Module* ) const { @@ -136,7 +136,7 @@ return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop); } -Loop *LoopInfo::ConsiderForLoop(BasicBlock *BB, ETForest &EF) { +Loop *LoopInfo::ConsiderForLoop(BasicBlock *BB, DominatorTree &DT) { if (BBMap.find(BB) != BBMap.end()) return 0; // Haven't processed this node? std::vector TodoStack; @@ -144,7 +144,7 @@ // Scan the predecessors of BB, checking to see if BB dominates any of // them. This identifies backedges which target this node... for (pred_iterator I = pred_begin(BB), E = pred_end(BB); I != E; ++I) - if (EF.dominates(BB, *I)) // If BB dominates it's predecessor... + if (DT.dominates(BB, *I)) // If BB dominates it's predecessor... TodoStack.push_back(*I); if (TodoStack.empty()) return 0; // No backedges to this block... @@ -160,7 +160,7 @@ TodoStack.pop_back(); if (!L->contains(X) && // As of yet unprocessed?? - EF.dominates(EntryBlock, X)) { // X is reachable from entry block? + DT.dominates(EntryBlock, X)) { // X is reachable from entry block? // Check to see if this block already belongs to a loop. If this occurs // then we have a case where a loop that is supposed to be a child of the // current loop was processed before the current loop. When this occurs, @@ -192,7 +192,7 @@ // If there are any loops nested within this loop, create them now! for (std::vector::iterator I = L->Blocks.begin(), E = L->Blocks.end(); I != E; ++I) - if (Loop *NewLoop = ConsiderForLoop(*I, EF)) { + if (Loop *NewLoop = ConsiderForLoop(*I, DT)) { L->SubLoops.push_back(NewLoop); NewLoop->ParentLoop = L; } From dpatel at apple.com Thu Jun 7 19:17:35 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 19:17:35 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/LoopInfo.h Message-ID: <200706080017.l580HZe5020488@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: LoopInfo.h updated: 1.67 -> 1.68 --- Log message: Use DominatorTree instead of ETForest. --- Diffs of the changes: (+3 -3) LoopInfo.h | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) Index: llvm/include/llvm/Analysis/LoopInfo.h diff -u llvm/include/llvm/Analysis/LoopInfo.h:1.67 llvm/include/llvm/Analysis/LoopInfo.h:1.68 --- llvm/include/llvm/Analysis/LoopInfo.h:1.67 Sun May 6 08:37:15 2007 +++ llvm/include/llvm/Analysis/LoopInfo.h Thu Jun 7 19:17:13 2007 @@ -35,7 +35,7 @@ namespace llvm { -class ETForest; +class DominatorTree; class LoopInfo; class PHINode; class Instruction; @@ -321,8 +321,8 @@ void removeBlock(BasicBlock *BB); private: - void Calculate(ETForest &EF); - Loop *ConsiderForLoop(BasicBlock *BB, ETForest &EF); + void Calculate(DominatorTree &DT); + Loop *ConsiderForLoop(BasicBlock *BB, DominatorTree &DT); void MoveSiblingLoopInto(Loop *NewChild, Loop *NewParent); void InsertLoopInto(Loop *L, Loop *Parent); }; From dpatel at apple.com Thu Jun 7 19:21:40 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 19:21:40 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706080021.l580LewU020595@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.97 -> 1.98 --- Log message: Add new method - nearestCommonDominator(). --- Diffs of the changes: (+11 -0) Dominators.h | 11 +++++++++++ 1 files changed, 11 insertions(+) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.97 llvm/include/llvm/Analysis/Dominators.h:1.98 --- llvm/include/llvm/Analysis/Dominators.h:1.97 Thu Jun 7 18:52:40 2007 +++ llvm/include/llvm/Analysis/Dominators.h Thu Jun 7 19:21:17 2007 @@ -185,6 +185,17 @@ void updateDFSNumbers(); + /// Return the nearest common dominator of A and B. + BasicBlock *nearestCommonDominator(BasicBlock *A, BasicBlock *B) const { + ETNode *NodeA = getNode(A)->getETNode(); + ETNode *NodeB = getNode(B)->getETNode(); + + ETNode *Common = NodeA->NCA(NodeB); + if (!Common) + return NULL; + return Common->getData(); + } + /// dominates - Returns true iff this dominates N. Note that this is not a /// constant time operation! /// From dalej at apple.com Thu Jun 7 19:34:49 2007 From: dalej at apple.com (Dale Johannesen) Date: Thu, 7 Jun 2007 19:34:49 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/BranchFolding.cpp Message-ID: <200706080034.l580YnU9020951@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: BranchFolding.cpp updated: 1.65 -> 1.66 --- Log message: Throttle tail merging; handling blocks with large numbers of predecessors is too slow. --- Diffs of the changes: (+6 -2) BranchFolding.cpp | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) Index: llvm/lib/CodeGen/BranchFolding.cpp diff -u llvm/lib/CodeGen/BranchFolding.cpp:1.65 llvm/lib/CodeGen/BranchFolding.cpp:1.66 --- llvm/lib/CodeGen/BranchFolding.cpp:1.65 Mon Jun 4 18:52:54 2007 +++ llvm/lib/CodeGen/BranchFolding.cpp Thu Jun 7 19:34:27 2007 @@ -564,6 +564,9 @@ return MadeChange; } +// Throttle for huge numbers of predecessors (compile speed problems) +#define THRESHOLD 100 + bool BranchFolder::TailMergeBlocks(MachineFunction &MF) { if (!EnableTailMerge) return false; @@ -577,7 +580,8 @@ MergePotentials.push_back(std::make_pair(HashEndOfMBB(I, 2U), I)); } // See if we can do any tail merging on those. - MadeChange |= TryMergeBlocks(NULL, NULL); + if (MergePotentials.size() < THRESHOLD) + MadeChange |= TryMergeBlocks(NULL, NULL); // Look at blocks (IBB) with multiple predecessors (PBB). // We change each predecessor to a canonical form, by @@ -599,7 +603,7 @@ // transformations.) for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { - if (!I->succ_empty() && I->pred_size() >= 2) { + if (!I->succ_empty() && I->pred_size() >= 2 && I->pred_size() < THRESHOLD) { MachineBasicBlock *IBB = I; MachineBasicBlock *PredBB = prior(I); MergePotentials.clear(); From clattner at apple.com Thu Jun 7 19:37:44 2007 From: clattner at apple.com (Chris Lattner) Date: Thu, 7 Jun 2007 17:37:44 -0700 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/BranchFolding.cpp In-Reply-To: <200706080034.l580YnU9020951@zion.cs.uiuc.edu> References: <200706080034.l580YnU9020951@zion.cs.uiuc.edu> Message-ID: > BranchFolding.cpp updated: 1.65 -> 1.66 > --- > Log message: > > Throttle tail merging; handling blocks with large numbers of > predecessors > is too slow. Thanks Dale, Please make this a hidden command line option like loop-unswitch- threshold. -Chris > > --- > Diffs of the changes: (+6 -2) > > BranchFolding.cpp | 8 ++++++-- > 1 files changed, 6 insertions(+), 2 deletions(-) > > > Index: llvm/lib/CodeGen/BranchFolding.cpp > diff -u llvm/lib/CodeGen/BranchFolding.cpp:1.65 llvm/lib/CodeGen/ > BranchFolding.cpp:1.66 > --- llvm/lib/CodeGen/BranchFolding.cpp:1.65 Mon Jun 4 18:52:54 2007 > +++ llvm/lib/CodeGen/BranchFolding.cpp Thu Jun 7 19:34:27 2007 > @@ -564,6 +564,9 @@ > return MadeChange; > } > > +// Throttle for huge numbers of predecessors (compile speed problems) > +#define THRESHOLD 100 > + > bool BranchFolder::TailMergeBlocks(MachineFunction &MF) { > > if (!EnableTailMerge) return false; > @@ -577,7 +580,8 @@ > MergePotentials.push_back(std::make_pair(HashEndOfMBB(I, > 2U), I)); > } > // See if we can do any tail merging on those. > - MadeChange |= TryMergeBlocks(NULL, NULL); > + if (MergePotentials.size() < THRESHOLD) > + MadeChange |= TryMergeBlocks(NULL, NULL); > > // Look at blocks (IBB) with multiple predecessors (PBB). > // We change each predecessor to a canonical form, by > @@ -599,7 +603,7 @@ > // transformations.) > > for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I ! > = E; ++I) { > - if (!I->succ_empty() && I->pred_size() >= 2) { > + if (!I->succ_empty() && I->pred_size() >= 2 && I->pred_size() > < THRESHOLD) { > MachineBasicBlock *IBB = I; > MachineBasicBlock *PredBB = prior(I); > MergePotentials.clear(); > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From resistor at mac.com Thu Jun 7 20:03:23 2007 From: resistor at mac.com (Owen Anderson) Date: Thu, 7 Jun 2007 20:03:23 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706080103.l5813N1N021469@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.22 -> 1.23 --- Log message: Add partial redundancy elimination. --- Diffs of the changes: (+249 -84) GVNPRE.cpp | 333 +++++++++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 249 insertions(+), 84 deletions(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.22 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.23 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.22 Tue Jun 5 20:27:49 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Thu Jun 7 20:03:01 2007 @@ -27,6 +27,7 @@ #include "llvm/Analysis/PostDominators.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Support/CFG.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include @@ -64,6 +65,9 @@ private: uint32_t nextValueNumber; typedef std::map ValueTable; + ValueTable VN; + std::set MS; + std::set createdExpressions; virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); @@ -73,25 +77,23 @@ // Helper fuctions // FIXME: eliminate or document these better - void dump(ValueTable& VN, std::set& s); - void dump_unique(ValueTable& VN, std::set& s); - void clean(ValueTable VN, std::set& set); - bool add(ValueTable& VN, std::set& MS, Value* V); - Value* find_leader(std::set& vals, Value* v); - Value* phi_translate(ValueTable& VN, std::set& MS, - std::set& set, + void dump(std::set& s); + void dump_unique(std::set& s); + void clean(std::set& set); + bool add(Value* V, uint32_t number); + Value* find_leader(std::set& vals, + Value* v); + Value* phi_translate(std::set& set, Value* V, BasicBlock* pred); - void phi_translate_set(ValueTable& VN, std::set& MS, - std::set& anticIn, BasicBlock* B, + void phi_translate_set(std::set& anticIn, BasicBlock* B, std::set& out); - void topo_sort(ValueTable& VN, std::set& set, + void topo_sort(std::set& set, std::vector& vec); // For a given block, calculate the generated expressions, temporaries, // and the AVAIL_OUT set - void CalculateAvailOut(ValueTable& VN, std::set& MS, - DomTreeNode* DI, + void CalculateAvailOut(DomTreeNode* DI, std::set& currExps, std::set& currPhis, std::set& currTemps, @@ -111,35 +113,33 @@ -bool GVNPRE::add(ValueTable& VN, std::set& MS, Value* V) { - std::pair ret = VN.insert(std::make_pair(V, nextValueNumber)); - if (ret.second) - nextValueNumber++; +bool GVNPRE::add(Value* V, uint32_t number) { + std::pair ret = VN.insert(std::make_pair(V, number)); if (isa(V) || isa(V)) MS.insert(V); return ret.second; } -Value* GVNPRE::find_leader(std::set& vals, - Value* v) { - ExprLT cmp; +Value* GVNPRE::find_leader(std::set& vals, Value* v) { for (std::set::iterator I = vals.begin(), E = vals.end(); - I != E; ++I) - if (!cmp(v, *I) && !cmp(*I, v)) + I != E; ++I) { + assert(VN.find(v) != VN.end() && "Value not numbered?"); + assert(VN.find(*I) != VN.end() && "Value not numbered?"); + if (VN[v] == VN[*I]) return *I; + } return 0; } -Value* GVNPRE::phi_translate(ValueTable& VN, std::set& MS, - std::set& set, +Value* GVNPRE::phi_translate(std::set& set, Value* V, BasicBlock* pred) { if (V == 0) return 0; if (BinaryOperator* BO = dyn_cast(V)) { Value* newOp1 = isa(BO->getOperand(0)) - ? phi_translate(VN, MS, set, + ? phi_translate(set, find_leader(set, BO->getOperand(0)), pred) : BO->getOperand(0); @@ -147,7 +147,7 @@ return 0; Value* newOp2 = isa(BO->getOperand(1)) - ? phi_translate(VN, MS, set, + ? phi_translate(set, find_leader(set, BO->getOperand(1)), pred) : BO->getOperand(1); @@ -155,12 +155,14 @@ return 0; if (newOp1 != BO->getOperand(0) || newOp2 != BO->getOperand(1)) { - Value* newVal = BinaryOperator::create(BO->getOpcode(), + Instruction* newVal = BinaryOperator::create(BO->getOpcode(), newOp1, newOp2, BO->getName()+".gvnpre"); - + if (add(newVal, nextValueNumber)) + nextValueNumber++; if (!find_leader(set, newVal)) { - add(VN, MS, newVal); + DOUT << "Creating value: " << std::hex << newVal << std::dec << "\n"; + createdExpressions.insert(newVal); return newVal; } else { delete newVal; @@ -175,39 +177,42 @@ return V; } -void GVNPRE::phi_translate_set(GVNPRE::ValueTable& VN, - std::set& MS, - std::set& anticIn, BasicBlock* B, +void GVNPRE::phi_translate_set(std::set& anticIn, BasicBlock* B, std::set& out) { for (std::set::iterator I = anticIn.begin(), E = anticIn.end(); I != E; ++I) { - Value* V = phi_translate(VN, MS, anticIn, *I, B); + Value* V = phi_translate(anticIn, *I, B); if (V != 0) out.insert(V); } } // Remove all expressions whose operands are not themselves in the set -void GVNPRE::clean(GVNPRE::ValueTable VN, std::set& set) { +void GVNPRE::clean(std::set& set) { std::vector worklist; - topo_sort(VN, set, worklist); + topo_sort(set, worklist); - while (!worklist.empty()) { - Value* v = worklist.back(); - worklist.pop_back(); + for (unsigned i = 0; i < worklist.size(); ++i) { + Value* v = worklist[i]; if (BinaryOperator* BO = dyn_cast(v)) { - bool lhsValid = false; - for (std::set::iterator I = set.begin(), E = set.end(); - I != E; ++I) - if (VN[*I] == VN[BO->getOperand(0)]); - lhsValid = true; + bool lhsValid = !isa(BO->getOperand(0)); + if (!lhsValid) + for (std::set::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN[*I] == VN[BO->getOperand(0)]) { + lhsValid = true; + break; + } - bool rhsValid = false; + bool rhsValid = !isa(BO->getOperand(1)); + if (!rhsValid) for (std::set::iterator I = set.begin(), E = set.end(); I != E; ++I) - if (VN[*I] == VN[BO->getOperand(1)]); + if (VN[*I] == VN[BO->getOperand(1)]) { rhsValid = true; + break; + } if (!lhsValid || !rhsValid) set.erase(BO); @@ -215,25 +220,26 @@ } } -void GVNPRE::topo_sort(GVNPRE::ValueTable& VN, - std::set& set, +void GVNPRE::topo_sort(std::set& set, std::vector& vec) { - std::set toErase; + std::set toErase; for (std::set::iterator I = set.begin(), E = set.end(); I != E; ++I) { if (BinaryOperator* BO = dyn_cast(*I)) for (std::set::iterator SI = set.begin(); SI != E; ++SI) { - if (VN[BO->getOperand(0)] == VN[*SI] || VN[BO->getOperand(1)] == VN[*SI]) { - toErase.insert(BO); + if (VN[BO->getOperand(0)] == VN[*SI] || + VN[BO->getOperand(1)] == VN[*SI]) { + toErase.insert(*SI); } } } std::vector Q; - std::insert_iterator > q_ins(Q, Q.begin()); - std::set_difference(set.begin(), set.end(), - toErase.begin(), toErase.end(), - q_ins); + for (std::set::iterator I = set.begin(), E = set.end(); + I != E; ++I) { + if (toErase.find(*I) == toErase.end()) + Q.push_back(*I); + } std::set visited; while (!Q.empty()) { @@ -263,7 +269,7 @@ } -void GVNPRE::dump(GVNPRE::ValueTable& VN, std::set& s) { +void GVNPRE::dump(std::set& s) { DOUT << "{ "; for (std::set::iterator I = s.begin(), E = s.end(); I != E; ++I) { @@ -272,7 +278,7 @@ DOUT << "}\n\n"; } -void GVNPRE::dump_unique(GVNPRE::ValueTable& VN, std::set& s) { +void GVNPRE::dump_unique(std::set& s) { DOUT << "{ "; for (std::set::iterator I = s.begin(), E = s.end(); I != E; ++I) { @@ -281,8 +287,7 @@ DOUT << "}\n\n"; } -void GVNPRE::CalculateAvailOut(GVNPRE::ValueTable& VN, std::set& MS, - DomTreeNode* DI, +void GVNPRE::CalculateAvailOut(DomTreeNode* DI, std::set& currExps, std::set& currPhis, std::set& currTemps, @@ -302,7 +307,8 @@ // Handle PHI nodes... if (PHINode* p = dyn_cast(BI)) { - add(VN, MS, p); + if (add(p, nextValueNumber)) + nextValueNumber++; currPhis.insert(p); // Handle binary ops... @@ -310,7 +316,8 @@ Value* leftValue = BO->getOperand(0); Value* rightValue = BO->getOperand(1); - add(VN, MS, BO); + if (add(BO, nextValueNumber)) + nextValueNumber++; if (isa(leftValue)) currExps.insert(leftValue); @@ -320,7 +327,8 @@ // Handle unsupported ops } else if (!BI->isTerminator()){ - add(VN, MS, BI); + if (add(BI, nextValueNumber)) + nextValueNumber++; currTemps.insert(BI); } @@ -330,8 +338,9 @@ } bool GVNPRE::runOnFunction(Function &F) { - ValueTable VN; - std::set maximalSet; + VN.clear(); + MS.clear(); + createdExpressions.clear(); std::map > generatedExpressions; std::map > generatedPhis; @@ -355,12 +364,12 @@ std::set& currTemps = generatedTemporaries[DI->getBlock()]; std::set& currAvail = availableOut[DI->getBlock()]; - CalculateAvailOut(VN, maximalSet, *DI, currExps, currPhis, + CalculateAvailOut(*DI, currExps, currPhis, currTemps, currAvail, availableOut); } DOUT << "Maximal Set: "; - dump_unique(VN, maximalSet); + dump_unique(MS); DOUT << "\n"; PostDominatorTree &PDT = getAnalysis(); @@ -377,16 +386,16 @@ // Top-down walk of the postdominator tree for (df_iterator PDI = - df_begin(PDT.getRootNode()), E = df_end(DT.getRootNode()); + df_begin(PDT.getRootNode()), E = df_end(PDT.getRootNode()); PDI != E; ++PDI) { BasicBlock* BB = PDI->getBlock(); DOUT << "Block: " << BB->getName() << "\n"; DOUT << "TMP_GEN: "; - dump(VN, generatedTemporaries[BB]); + dump(generatedTemporaries[BB]); DOUT << "\n"; DOUT << "EXP_GEN: "; - dump_unique(VN, generatedExpressions[BB]); + dump_unique(generatedExpressions[BB]); visited.insert(BB); std::set& anticIn = anticipatedIn[BB]; @@ -395,9 +404,9 @@ if (BB->getTerminator()->getNumSuccessors() == 1) { if (visited.find(BB->getTerminator()->getSuccessor(0)) == visited.end()) - phi_translate_set(VN, maximalSet, maximalSet, BB, anticOut); + phi_translate_set(MS, BB, anticOut); else - phi_translate_set(VN, maximalSet, + phi_translate_set( anticipatedIn[BB->getTerminator()->getSuccessor(0)], BB, anticOut); } else if (BB->getTerminator()->getNumSuccessors() > 1) { BasicBlock* first = BB->getTerminator()->getSuccessor(0); @@ -420,7 +429,7 @@ } DOUT << "ANTIC_OUT: "; - dump_unique(VN, anticOut); + dump_unique(anticOut); DOUT << "\n"; std::set S; @@ -438,10 +447,10 @@ anticIn.insert(*I); } - clean(VN, anticIn); + clean(anticIn); DOUT << "ANTIC_IN: "; - dump_unique(VN, anticIn); + dump_unique(anticIn); DOUT << "\n"; if (old.size() != anticIn.size()) @@ -459,25 +468,173 @@ DOUT << "Name: " << I->getName().c_str() << "\n"; DOUT << "TMP_GEN: "; - dump(VN, generatedTemporaries[I]); + dump(generatedTemporaries[I]); DOUT << "\n"; DOUT << "EXP_GEN: "; - dump_unique(VN, generatedExpressions[I]); + dump_unique(generatedExpressions[I]); DOUT << "\n"; DOUT << "ANTIC_IN: "; - dump_unique(VN, anticipatedIn[I]); + dump_unique(anticipatedIn[I]); DOUT << "\n"; DOUT << "AVAIL_OUT: "; - dump_unique(VN, availableOut[I]); + dump_unique(availableOut[I]); DOUT << "\n"; } // Phase 2: Insert - // FIXME: Not implemented yet + + DOUT<< "\nPhase 2: Insertion\n"; + + std::map > new_sets; + unsigned i_iterations = 0; + bool new_stuff = true; + while (new_stuff) { + new_stuff = false; + DOUT << "Iteration: " << i_iterations << "\n\n"; + for (df_iterator DI = df_begin(DT.getRootNode()), + E = df_end(DT.getRootNode()); DI != E; ++DI) { + BasicBlock* BB = DI->getBlock(); + + std::set& new_set = new_sets[BB]; + std::set& availOut = availableOut[BB]; + std::set& anticIn = anticipatedIn[BB]; + + // Replace leaders with leaders inherited from dominator + if (DI->getIDom() != 0) { + std::set& dom_set = new_sets[DI->getIDom()->getBlock()]; + for (std::set::iterator I = dom_set.begin(), + E = dom_set.end(); I != E; ++I) { + new_set.insert(*I); + + std::set::iterator val = availOut.find(*I); + if (val != availOut.end()) + new_set.erase(val); + new_set.insert(*I); + } + } + + // If there is more than one predecessor... + if (pred_begin(BB) != pred_end(BB) && ++pred_begin(BB) != pred_end(BB)) { + std::vector workList; + topo_sort(anticIn, workList); + + DOUT << "Merge Block: " << BB->getName() << "\n"; + DOUT << "ANTIC_IN: "; + dump_unique(anticIn); + DOUT << "\n"; + + while (!workList.empty()) { + Value* e = workList.back(); + workList.pop_back(); + + if (isa(e)) { + if (find_leader(availableOut[DI->getIDom()->getBlock()], e) != 0) + continue; + + std::map avail; + bool by_some = false; + int num_avail = 0; + + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; + ++PI) { + Value *e2 = phi_translate(anticIn, e, *PI); + Value *e3 = find_leader(availableOut[*PI], e2); + + if (e3 == 0) { + std::map::iterator av = avail.find(*PI); + if (av != avail.end()) + avail.erase(av); + avail.insert(std::make_pair(*PI, e2)); + } else { + std::map::iterator av = avail.find(*PI); + if (av != avail.end()) + avail.erase(av); + avail.insert(std::make_pair(*PI, e3)); + + by_some = true; + num_avail++; + } + } + + if (by_some && + num_avail < std::distance(pred_begin(BB), pred_end(BB))) { + DOUT << "Processing Value: "; + DEBUG(e->dump()); + DOUT << "\n\n"; + + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + PI != PE; ++PI) { + Value* e2 = avail[*PI]; + if (!find_leader(availableOut[*PI], e2)) { + BinaryOperator* BO = cast(e2); + + Value* s1 = 0; + if (isa(BO->getOperand(0))) + s1 = find_leader(availableOut[*PI], BO->getOperand(0)); + else + s1 = BO->getOperand(0); + + Value* s2 = 0; + if (isa(BO->getOperand(1))) + s2 = find_leader(availableOut[*PI], BO->getOperand(1)); + else + s2 = BO->getOperand(1); + + Value* newVal = BinaryOperator::create(BO->getOpcode(), + s1, s2, + BO->getName()+".gvnpre", + (*PI)->getTerminator()); + add(newVal, VN[BO]); + availableOut[*PI].insert(newVal); + + DOUT << "Creating value: " << std::hex << newVal << std::dec << "\n"; + + std::map::iterator av = avail.find(*PI); + if (av != avail.end()) + avail.erase(av); + avail.insert(std::make_pair(*PI, newVal)); + } + } + + PHINode* p = 0; + + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + PI != PE; ++PI) { + if (p == 0) + p = new PHINode(avail[*PI]->getType(), "gvnpre-join", + BB->begin()); + + p->addIncoming(avail[*PI], *PI); + } + + add(p, VN[e]); + DOUT << "Creating value: " << std::hex << p << std::dec << "\n"; + + availOut.insert(p); + new_stuff = true; + + DOUT << "Preds After Processing: "; + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + PI != PE; ++PI) + DEBUG((*PI)->dump()); + DOUT << "\n\n"; + + DOUT << "Merge Block After Processing: "; + DEBUG(BB->dump()); + DOUT << "\n\n"; + + new_set.insert(p); + } + } + } + } + } + i_iterations++; + } // Phase 3: Eliminate for (df_iterator DI = df_begin(DT.getRootNode()), @@ -488,13 +645,15 @@ for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI) { - Value* leader = find_leader(availableOut[BB], BI); - if (leader != 0) - if (Instruction* Instr = dyn_cast(leader)) - if (Instr->getParent() != 0 && Instr != BI) { - BI->replaceAllUsesWith(leader); - erase.push_back(BI); - } + if (!BI->isTerminator()) { + Value* leader = find_leader(availableOut[BB], BI); + if (leader != 0) + if (Instruction* Instr = dyn_cast(leader)) + if (Instr->getParent() != 0 && Instr != BI) { + BI->replaceAllUsesWith(leader); + erase.push_back(BI); + } + } } for (std::vector::iterator I = erase.begin(), E = erase.end(); @@ -502,5 +661,11 @@ (*I)->eraseFromParent(); } + // Phase 4: Cleanup + for (std::set::iterator I = createdExpressions.begin(), + E = createdExpressions.end(); I != E; ++I) { + delete *I; + } + return false; } From dalej at apple.com Thu Jun 7 20:09:13 2007 From: dalej at apple.com (Dale Johannesen) Date: Thu, 7 Jun 2007 20:09:13 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/BranchFolding.cpp Message-ID: <200706080109.l5819DQQ021585@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: BranchFolding.cpp updated: 1.66 -> 1.67 --- Log message: Make throttle a hidden parameter, per review. --- Diffs of the changes: (+11 -6) BranchFolding.cpp | 17 +++++++++++------ 1 files changed, 11 insertions(+), 6 deletions(-) Index: llvm/lib/CodeGen/BranchFolding.cpp diff -u llvm/lib/CodeGen/BranchFolding.cpp:1.66 llvm/lib/CodeGen/BranchFolding.cpp:1.67 --- llvm/lib/CodeGen/BranchFolding.cpp:1.66 Thu Jun 7 19:34:27 2007 +++ llvm/lib/CodeGen/BranchFolding.cpp Thu Jun 7 20:08:52 2007 @@ -38,6 +38,12 @@ static cl::opt FlagEnableTailMerge("enable-tail-merge", cl::init(cl::BOU_UNSET), cl::Hidden); namespace { + // Throttle for huge numbers of predecessors (compile speed problems) + cl::opt + TailMergeThreshold("tail-merge-threshold", + cl::desc("Max number of predecessors to consider tail merging"), + cl::init(100), cl::Hidden); + struct BranchFolder : public MachineFunctionPass { static char ID; BranchFolder(bool defaultEnableTailMerge) : @@ -564,9 +570,6 @@ return MadeChange; } -// Throttle for huge numbers of predecessors (compile speed problems) -#define THRESHOLD 100 - bool BranchFolder::TailMergeBlocks(MachineFunction &MF) { if (!EnableTailMerge) return false; @@ -580,7 +583,7 @@ MergePotentials.push_back(std::make_pair(HashEndOfMBB(I, 2U), I)); } // See if we can do any tail merging on those. - if (MergePotentials.size() < THRESHOLD) + if (MergePotentials.size() < TailMergeThreshold) MadeChange |= TryMergeBlocks(NULL, NULL); // Look at blocks (IBB) with multiple predecessors (PBB). @@ -603,11 +606,13 @@ // transformations.) for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { - if (!I->succ_empty() && I->pred_size() >= 2 && I->pred_size() < THRESHOLD) { + if (!I->succ_empty() && I->pred_size() >= 2 && + I->pred_size() < TailMergeThreshold) { MachineBasicBlock *IBB = I; MachineBasicBlock *PredBB = prior(I); MergePotentials.clear(); - for (MachineBasicBlock::pred_iterator P = I->pred_begin(), E2 = I->pred_end(); + for (MachineBasicBlock::pred_iterator P = I->pred_begin(), + E2 = I->pred_end(); P != E2; ++P) { MachineBasicBlock* PBB = *P; // Skip blocks that loop to themselves, can't tail merge these. From isanbard at gmail.com Thu Jun 7 20:33:46 2007 From: isanbard at gmail.com (Bill Wendling) Date: Thu, 7 Jun 2007 18:33:46 -0700 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp In-Reply-To: <200706080103.l5813N1N021469@zion.cs.uiuc.edu> References: <200706080103.l5813N1N021469@zion.cs.uiuc.edu> Message-ID: <16e5fdf90706071833u3dea40bewb8d9c2473faa8993@mail.gmail.com> Hi Owen, One suggestion: > + void dump(std::set& s); > + void dump_unique(std::set& s); My guess is that you want to pass these in as "const". Perhaps even making the method const? -bw From dpatel at apple.com Thu Jun 7 20:50:55 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 20:50:55 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/LoopSimplify.cpp Message-ID: <200706080150.l581ot66022343@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: LoopSimplify.cpp updated: 1.99 -> 1.100 --- Log message: Update LoopSimplify to require and preserve DominatorTree only. Now LoopSimplify does not require nor preserve ETForest. --- Diffs of the changes: (+26 -32) LoopSimplify.cpp | 58 ++++++++++++++++++++++++------------------------------- 1 files changed, 26 insertions(+), 32 deletions(-) Index: llvm/lib/Transforms/Utils/LoopSimplify.cpp diff -u llvm/lib/Transforms/Utils/LoopSimplify.cpp:1.99 llvm/lib/Transforms/Utils/LoopSimplify.cpp:1.100 --- llvm/lib/Transforms/Utils/LoopSimplify.cpp:1.99 Mon Jun 4 11:43:25 2007 +++ llvm/lib/Transforms/Utils/LoopSimplify.cpp Thu Jun 7 20:50:32 2007 @@ -68,10 +68,8 @@ // We need loop information to identify the loops... AU.addRequired(); AU.addRequired(); - AU.addRequired(); AU.addPreserved(); - AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); AU.addPreservedID(BreakCriticalEdgesID); // No critical edges added. @@ -315,10 +313,10 @@ // Can we eliminate this phi node now? if (Value *V = PN->hasConstantValue(true)) { Instruction *I = dyn_cast(V); - // If I is in NewBB, the ETForest call will fail, because NewBB isn't - // registered in ETForest yet. Handle this case explicitly. + // If I is in NewBB, the Dominator call will fail, because NewBB isn't + // registered in DominatorTree yet. Handle this case explicitly. if (!I || (I->getParent() != NewBB && - getAnalysis().dominates(I, PN))) { + getAnalysis().dominates(I, PN))) { PN->replaceAllUsesWith(V); if (AA) AA->deleteValue(PN); BB->getInstList().erase(PN); @@ -429,13 +427,13 @@ /// FindPHIToPartitionLoops - The first part of loop-nestification is to find a /// PHI node that tells us how to partition the loops. -static PHINode *FindPHIToPartitionLoops(Loop *L, ETForest *EF, +static PHINode *FindPHIToPartitionLoops(Loop *L, DominatorTree *DT, AliasAnalysis *AA) { for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ) { PHINode *PN = cast(I); ++I; if (Value *V = PN->hasConstantValue()) - if (!isa(V) || EF->dominates(cast(V), PN)) { + if (!isa(V) || DT->dominates(cast(V), PN)) { // This is a degenerate PHI already, don't modify it! PN->replaceAllUsesWith(V); if (AA) AA->deleteValue(PN); @@ -509,8 +507,8 @@ /// created. /// Loop *LoopSimplify::SeparateNestedLoop(Loop *L) { - ETForest *EF = getAnalysisToUpdate(); - PHINode *PN = FindPHIToPartitionLoops(L, EF, AA); + DominatorTree *DT = getAnalysisToUpdate(); + PHINode *PN = FindPHIToPartitionLoops(L, DT, AA); if (PN == 0) return 0; // No known way to partition. // Pull out all predecessors that have varying values in the loop. This @@ -555,7 +553,7 @@ // the Outer loop now. std::set BlocksInL; for (pred_iterator PI = pred_begin(Header), E = pred_end(Header); PI!=E; ++PI) - if (EF->dominates(Header, *PI)) + if (DT->dominates(Header, *PI)) AddBlockAndPredsToSet(*PI, Header, BlocksInL); @@ -686,10 +684,10 @@ // Returns true if BasicBlock A dominates at least one block in vector B // Helper function for UpdateDomInfoForRevectoredPreds static bool BlockDominatesAny(BasicBlock* A, const std::vector& B, - ETForest& ETF) { + DominatorTree &DT) { for (std::vector::const_iterator BI = B.begin(), BE = B.end(); BI != BE; ++BI) { - if (ETF.dominates(A, *BI)) + if (DT.dominates(A, *BI)) return true; } return false; @@ -715,8 +713,8 @@ ++succ_begin(NewBB) == succ_end(NewBB) && "NewBB should have a single successor!"); BasicBlock *NewBBSucc = *succ_begin(NewBB); - ETForest& ETF = getAnalysis(); - + DominatorTree &DT = getAnalysis(); + // The newly inserted basic block will dominate existing basic blocks iff the // PredBlocks dominate all of the non-pred blocks. If all predblocks dominate // the non-pred blocks, then they all must be the same block! @@ -725,13 +723,13 @@ { BasicBlock *OnePred = PredBlocks[0]; unsigned i = 1, e = PredBlocks.size(); - for (i = 1; !ETF.isReachableFromEntry(OnePred); ++i) { + for (i = 1; !DT.isReachableFromEntry(OnePred); ++i) { assert(i != e && "Didn't find reachable pred?"); OnePred = PredBlocks[i]; } for (; i != e; ++i) - if (PredBlocks[i] != OnePred && ETF.isReachableFromEntry(OnePred)){ + if (PredBlocks[i] != OnePred && DT.isReachableFromEntry(OnePred)){ NewBBDominatesNewBBSucc = false; break; } @@ -739,7 +737,7 @@ if (NewBBDominatesNewBBSucc) for (pred_iterator PI = pred_begin(NewBBSucc), E = pred_end(NewBBSucc); PI != E; ++PI) - if (*PI != NewBB && !ETF.dominates(NewBBSucc, *PI)) { + if (*PI != NewBB && !DT.dominates(NewBBSucc, *PI)) { NewBBDominatesNewBBSucc = false; break; } @@ -752,7 +750,7 @@ NewBBDominatesNewBBSucc = true; for (pred_iterator PI = pred_begin(NewBBSucc), E = pred_end(NewBBSucc); PI != E; ++PI) - if (*PI != NewBB && !ETF.dominates(NewBBSucc, *PI)) { + if (*PI != NewBB && !DT.dominates(NewBBSucc, *PI)) { NewBBDominatesNewBBSucc = false; break; } @@ -767,14 +765,16 @@ if (!NewBBIDom) { unsigned i = 0; for (i = 0; i < PredBlocks.size(); ++i) - if (ETF.dominates(&PredBlocks[i]->getParent()->getEntryBlock(), PredBlocks[i])) { + if (DT->dominates(&PredBlocks[i]->getParent()->getEntryBlock(), + PredBlocks[i])) { NewBBIDom = PredBlocks[i]; break; } assert(i != PredBlocks.size() && "No reachable preds?"); for (i = i + 1; i < PredBlocks.size(); ++i) { - if (ETF.dominates(&PredBlocks[i]->getParent()->getEntryBlock(), PredBlocks[i])) - NewBBIDom = ETF.nearestCommonDominator(NewBBIDom, PredBlocks[i]); + if (DT->dominates(&PredBlocks[i]->getParent()->getEntryBlock(), + PredBlocks[i])) + NewBBIDom = DT->nearestCommonDominator(NewBBIDom, PredBlocks[i]); } assert(NewBBIDom && "No immediate dominator found??"); } @@ -790,13 +790,6 @@ } } - // Update ET-Forest information if it is active. - if (ETForest *EF = getAnalysisToUpdate()) { - EF->addNewBlock(NewBB, NewBBIDom); - if (NewBBDominatesNewBBSucc) - EF->setImmediateDominator(NewBBSucc, NewBB); - } - // Update dominance frontier information... if (DominanceFrontier *DF = getAnalysisToUpdate()) { // If NewBB dominates NewBBSucc, then DF(NewBB) is now going to be the @@ -812,7 +805,7 @@ bool DominatesPred = false; for (pred_iterator PI = pred_begin(*SetI), E = pred_end(*SetI); PI != E; ++PI) - if (ETF.dominates(NewBB, *PI)) + if (DT.dominates(NewBB, *PI)) DominatesPred = true; if (!DominatesPred) Set.erase(SetI++); @@ -845,17 +838,18 @@ // Only consider dominators of NewBBSucc if (!DFI->second.count(NewBBSucc)) continue; - if (BlockDominatesAny(FI, PredBlocks, ETF)) { + if (BlockDominatesAny(FI, PredBlocks, DT)) { // If NewBBSucc should not stay in our dominator frontier, remove it. // We remove it unless there is a predecessor of NewBBSucc that we // dominate, but we don't strictly dominate NewBBSucc. bool ShouldRemove = true; - if ((BasicBlock*)FI == NewBBSucc || !ETF.dominates(FI, NewBBSucc)) { + if ((BasicBlock*)FI == NewBBSucc + || !DT.dominates(FI, NewBBSucc)) { // Okay, we know that PredDom does not strictly dominate NewBBSucc. // Check to see if it dominates any predecessors of NewBBSucc. for (pred_iterator PI = pred_begin(NewBBSucc), E = pred_end(NewBBSucc); PI != E; ++PI) - if (ETF.dominates(FI, *PI)) { + if (DT.dominates(FI, *PI)) { ShouldRemove = false; break; } From dpatel at apple.com Thu Jun 7 20:51:00 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 20:51:00 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706080151.l581p0ax022348@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.98 -> 1.99 --- Log message: Update LoopSimplify to require and preserve DominatorTree only. Now LoopSimplify does not require nor preserve ETForest. --- Diffs of the changes: (+4 -0) Dominators.h | 4 ++++ 1 files changed, 4 insertions(+) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.98 llvm/include/llvm/Analysis/Dominators.h:1.99 --- llvm/include/llvm/Analysis/Dominators.h:1.98 Thu Jun 7 19:21:17 2007 +++ llvm/include/llvm/Analysis/Dominators.h Thu Jun 7 20:50:32 2007 @@ -195,6 +195,10 @@ return NULL; return Common->getData(); } + + /// isReachableFromEntry - Return true if A is dominated by the entry + /// block of the function containing it. + const bool isReachableFromEntry(BasicBlock* A); /// dominates - Returns true iff this dominates N. Note that this is not a /// constant time operation! From dpatel at apple.com Thu Jun 7 20:51:00 2007 From: dpatel at apple.com (Devang Patel) Date: Thu, 7 Jun 2007 20:51:00 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp Message-ID: <200706080151.l581p07t022353@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Dominators.cpp updated: 1.108 -> 1.109 --- Log message: Update LoopSimplify to require and preserve DominatorTree only. Now LoopSimplify does not require nor preserve ETForest. --- Diffs of the changes: (+12 -3) Dominators.cpp | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-) Index: llvm/lib/VMCore/Dominators.cpp diff -u llvm/lib/VMCore/Dominators.cpp:1.108 llvm/lib/VMCore/Dominators.cpp:1.109 --- llvm/lib/VMCore/Dominators.cpp:1.108 Thu Jun 7 18:52:40 2007 +++ llvm/lib/VMCore/Dominators.cpp Thu Jun 7 20:50:32 2007 @@ -316,14 +316,23 @@ for (df_iterator I = df_begin(Roots[i]), E = df_end(Roots[i]); I != E; ++I) { BasicBlock *BB = *I; - ETNode *ETN = getNode(BB)->getETNode(); - if (ETN && !ETN->hasFather()) - ETN->assignDFSNumber(dfsnum); + DomTreeNode *BBNode = getNode(BB); + if (BBNode) { + ETNode *ETN = BBNode->getETNode(); + if (ETN && !ETN->hasFather()) + ETN->assignDFSNumber(dfsnum); + } } SlowQueries = 0; DFSInfoValid = true; } +/// isReachableFromEntry - Return true if A is dominated by the entry +/// block of the function containing it. +const bool DominatorTreeBase::isReachableFromEntry(BasicBlock* A) { + return dominates(&A->getParent()->getEntryBlock(), A); +} + // dominates - Return true if A dominates B. THis performs the // special checks necessary if A and B are in the same basic block. bool DominatorTreeBase::dominates(Instruction *A, Instruction *B) { From resistor at mac.com Thu Jun 7 20:53:07 2007 From: resistor at mac.com (Owen Anderson) Date: Thu, 7 Jun 2007 20:53:07 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706080153.l581r7wY022402@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.23 -> 1.24 --- Log message: Small bugfix, and const-ify some methods (Thanks, Bill). --- Diffs of the changes: (+6 -6) GVNPRE.cpp | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.23 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.24 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.23 Thu Jun 7 20:03:01 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Thu Jun 7 20:52:45 2007 @@ -77,8 +77,8 @@ // Helper fuctions // FIXME: eliminate or document these better - void dump(std::set& s); - void dump_unique(std::set& s); + void dump(const std::set& s) const; + void dump_unique(const std::set& s) const; void clean(std::set& set); bool add(Value* V, uint32_t number); Value* find_leader(std::set& vals, @@ -269,7 +269,7 @@ } -void GVNPRE::dump(std::set& s) { +void GVNPRE::dump(const std::set& s) const { DOUT << "{ "; for (std::set::iterator I = s.begin(), E = s.end(); I != E; ++I) { @@ -278,7 +278,7 @@ DOUT << "}\n\n"; } -void GVNPRE::dump_unique(std::set& s) { +void GVNPRE::dump_unique(const std::set& s) const { DOUT << "{ "; for (std::set::iterator I = s.begin(), E = s.end(); I != E; ++I) { @@ -512,8 +512,8 @@ std::set::iterator val = availOut.find(*I); if (val != availOut.end()) - new_set.erase(val); - new_set.insert(*I); + availOut.erase(val); + availOut.insert(*I); } } From evan.cheng at apple.com Fri Jun 8 01:33:37 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 01:33:37 -0500 Subject: [llvm-commits] CVS: llvm-test/SingleSource/Benchmarks/Shootout-C++/lists.cpp objinst.cpp Message-ID: <200706080633.l586Xbdp028246@zion.cs.uiuc.edu> Changes in directory llvm-test/SingleSource/Benchmarks/Shootout-C++: lists.cpp updated: 1.4 -> 1.5 objinst.cpp updated: 1.3 -> 1.4 --- Log message: SMALL_PROBLEM_SIZE --- Diffs of the changes: (+7 -3) lists.cpp | 6 +++++- objinst.cpp | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) Index: llvm-test/SingleSource/Benchmarks/Shootout-C++/lists.cpp diff -u llvm-test/SingleSource/Benchmarks/Shootout-C++/lists.cpp:1.4 llvm-test/SingleSource/Benchmarks/Shootout-C++/lists.cpp:1.5 --- llvm-test/SingleSource/Benchmarks/Shootout-C++/lists.cpp:1.4 Thu May 3 11:55:46 2007 +++ llvm-test/SingleSource/Benchmarks/Shootout-C++/lists.cpp Fri Jun 8 01:33:15 2007 @@ -1,5 +1,5 @@ // -*- mode: c++ -*- -// $Id: lists.cpp,v 1.4 2007/05/03 16:55:46 laurov Exp $ +// $Id: lists.cpp,v 1.5 2007/06/08 06:33:15 evancheng Exp $ // http://www.bagley.org/~doug/shootout/ // from Bill Lear @@ -9,7 +9,11 @@ using namespace std; +#ifdef SMALL_PROBLEM_SIZE +const size_t SIZE = 1000; +#else const size_t SIZE = 10000; +#endif template void Index: llvm-test/SingleSource/Benchmarks/Shootout-C++/objinst.cpp diff -u llvm-test/SingleSource/Benchmarks/Shootout-C++/objinst.cpp:1.3 llvm-test/SingleSource/Benchmarks/Shootout-C++/objinst.cpp:1.4 --- llvm-test/SingleSource/Benchmarks/Shootout-C++/objinst.cpp:1.3 Thu May 3 11:55:46 2007 +++ llvm-test/SingleSource/Benchmarks/Shootout-C++/objinst.cpp Fri Jun 8 01:33:15 2007 @@ -1,5 +1,5 @@ // -*- mode: c++ -*- -// $Id: objinst.cpp,v 1.3 2007/05/03 16:55:46 laurov Exp $ +// $Id: objinst.cpp,v 1.4 2007/06/08 06:33:15 evancheng Exp $ // http://www.bagley.org/~doug/shootout/ #include @@ -41,7 +41,7 @@ int main(int argc, char *argv[]) { #ifdef SMALL_PROBLEM_SIZE -#define LENGTH 7000000 +#define LENGTH 1000000 #else #define LENGTH 70000000 #endif From baldrick at free.fr Fri Jun 8 03:59:33 2007 From: baldrick at free.fr (Duncan Sands) Date: Fri, 8 Jun 2007 03:59:33 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/DwarfWriter.cpp Message-ID: <200706080859.l588xXju007910@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: DwarfWriter.cpp updated: 1.151 -> 1.152 --- Log message: Use more realistically sized vectors. Reserve capacity if we know in advance how much will be used. --- Diffs of the changes: (+7 -4) DwarfWriter.cpp | 11 +++++++---- 1 files changed, 7 insertions(+), 4 deletions(-) Index: llvm/lib/CodeGen/DwarfWriter.cpp diff -u llvm/lib/CodeGen/DwarfWriter.cpp:1.151 llvm/lib/CodeGen/DwarfWriter.cpp:1.152 --- llvm/lib/CodeGen/DwarfWriter.cpp:1.151 Wed Jun 6 10:37:31 2007 +++ llvm/lib/CodeGen/DwarfWriter.cpp Fri Jun 8 03:59:11 2007 @@ -2973,16 +2973,19 @@ // Sort the landing pads in order of their type ids. This is used to fold // duplicate actions. - SmallVector LandingPads(PadInfos.size(), NULL); + SmallVector LandingPads; + + LandingPads.reserve(PadInfos.size()); for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) - LandingPads[i] = &PadInfos[i]; + LandingPads.push_back(&PadInfos[i]); std::sort(LandingPads.begin(), LandingPads.end(), PadLT); // Gather first action index for each landing pad site. - SmallVector FirstActions; + SmallVector FirstActions; + FirstActions.reserve(PadInfos.size()); // The actions table. - SmallVector Actions; + SmallVector Actions; // Compute sizes for exception table. unsigned SizeSites = 0; From evan.cheng at apple.com Fri Jun 8 04:13:45 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 04:13:45 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/ARM/ARMInstrThumb.td Message-ID: <200706080913.l589Djvj012280@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/ARM: ARMInstrThumb.td updated: 1.29 -> 1.30 --- Log message: tBcc is not a barrier. --- Diffs of the changes: (+1 -1) ARMInstrThumb.td | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Target/ARM/ARMInstrThumb.td diff -u llvm/lib/Target/ARM/ARMInstrThumb.td:1.29 llvm/lib/Target/ARM/ARMInstrThumb.td:1.30 --- llvm/lib/Target/ARM/ARMInstrThumb.td:1.29 Wed Jun 6 05:17:05 2007 +++ llvm/lib/Target/ARM/ARMInstrThumb.td Fri Jun 8 04:13:23 2007 @@ -222,7 +222,7 @@ } } -let isBranch = 1, isTerminator = 1, noResults = 1, isBarrier = 1 in +let isBranch = 1, isTerminator = 1, noResults = 1 in def tBcc : TI<(ops brtarget:$dst, ccop:$cc), "b$cc $dst", [(ARMbrcond bb:$dst, imm:$cc)]>; From evan.cheng at apple.com Fri Jun 8 04:15:09 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 04:15:09 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/ARM/ARMInstrInfo.cpp Message-ID: <200706080915.l589F9Cp012333@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/ARM: ARMInstrInfo.cpp updated: 1.33 -> 1.34 --- Log message: Fix ARM condition code subsumission check. --- Diffs of the changes: (+3 -3) ARMInstrInfo.cpp | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) Index: llvm/lib/Target/ARM/ARMInstrInfo.cpp diff -u llvm/lib/Target/ARM/ARMInstrInfo.cpp:1.33 llvm/lib/Target/ARM/ARMInstrInfo.cpp:1.34 --- llvm/lib/Target/ARM/ARMInstrInfo.cpp:1.33 Wed Jun 6 20:37:54 2007 +++ llvm/lib/Target/ARM/ARMInstrInfo.cpp Fri Jun 8 04:14:47 2007 @@ -471,13 +471,13 @@ case ARMCC::AL: return true; case ARMCC::HS: - return CC2 == ARMCC::HI || CC2 == ARMCC::EQ; + return CC2 == ARMCC::HI; case ARMCC::LS: return CC2 == ARMCC::LO || CC2 == ARMCC::EQ; case ARMCC::GE: - return CC2 == ARMCC::GT || CC2 == ARMCC::EQ; + return CC2 == ARMCC::GT; case ARMCC::LE: - return CC2 == ARMCC::LT || CC2 == ARMCC::EQ; + return CC2 == ARMCC::LT; } } From evan.cheng at apple.com Fri Jun 8 04:36:23 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 04:36:23 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706080936.l589aNls012757@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.37 -> 1.38 --- Log message: Allow more cmp / bcc to be predicated; clean up triangle ifcvt checking code. --- Diffs of the changes: (+135 -144) IfConversion.cpp | 279 ++++++++++++++++++++++++++----------------------------- 1 files changed, 135 insertions(+), 144 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.37 llvm/lib/CodeGen/IfConversion.cpp:1.38 --- llvm/lib/CodeGen/IfConversion.cpp:1.37 Thu Jun 7 17:31:28 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Fri Jun 8 04:36:04 2007 @@ -98,13 +98,14 @@ private: bool ReverseBranchCondition(BBInfo &BBI); - bool BlockModifyPredicate(MachineBasicBlock *BB) const; - bool ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI) const; + bool ValidSimple(BBInfo &TrueBBI) const; + bool ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI, + bool FalseBranch = false) const; bool ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI) const; - void StructuralAnalysis(MachineBasicBlock *BB); - bool FeasibilityAnalysis(BBInfo &BBI, - std::vector &Cond, - bool IgnoreTerm = false); + void ScanInstructions(BBInfo &BBI); + void AnalyzeBlock(MachineBasicBlock *BB); + bool FeasibilityAnalysis(BBInfo &BBI, std::vector &Cond, + bool isTriangle = false, bool RevBranch = false); bool AttemptRestructuring(BBInfo &BBI); bool AnalyzeBlocks(MachineFunction &MF, std::vector &Candidates); @@ -235,47 +236,44 @@ return false; } -/// BlockModifyPredicate - Returns true if any instruction in the block may -/// clobber the condition code or register(s) used to predicate instructions, -/// e.g. call, cmp. -bool IfConverter::BlockModifyPredicate(MachineBasicBlock *BB) const { - for (MachineBasicBlock::const_reverse_iterator I = BB->rbegin(), - E = BB->rend(); I != E; ++I) - if (I->getInstrDescriptor()->Flags & M_CLOBBERS_PRED) - return true; - return false; +/// ValidSimple - Returns true if the 'true' block (along with its +/// predecessor) forms a valid simple shape for ifcvt. +bool IfConverter::ValidSimple(BBInfo &TrueBBI) const { + return !blockAlwaysFallThrough(TrueBBI) && + TrueBBI.BrCond.size() == 0 && TrueBBI.BB->pred_size() == 1; } -/// ValidTriangle - Returns true if the 'true' and 'false' blocks paths (along +/// ValidTriangle - Returns true if the 'true' and 'false' blocks (along /// with their common predecessor) forms a valid triangle shape for ifcvt. -bool IfConverter::ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI) const { +bool IfConverter::ValidTriangle(BBInfo &TrueBBI, BBInfo &FalseBBI, + bool FalseBranch) const { if (TrueBBI.BB->pred_size() != 1) return false; - MachineBasicBlock *TTBB = TrueBBI.TrueBB; - if (!TTBB && blockAlwaysFallThrough(TrueBBI)) { + MachineBasicBlock *TExit = FalseBranch ? TrueBBI.FalseBB : TrueBBI.TrueBB; + if (!TExit && blockAlwaysFallThrough(TrueBBI)) { MachineFunction::iterator I = TrueBBI.BB; if (++I == TrueBBI.BB->getParent()->end()) return false; - TTBB = I; + TExit = I; } - return TTBB && TTBB == FalseBBI.BB; + return TExit && TExit == FalseBBI.BB; } -/// ValidDiamond - Returns true if the 'true' and 'false' blocks paths (along +/// ValidDiamond - Returns true if the 'true' and 'false' blocks (along /// with their common predecessor) forms a valid diamond shape for ifcvt. bool IfConverter::ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI) const { + // FIXME: Also look for fallthrough return (TrueBBI.TrueBB == FalseBBI.TrueBB && TrueBBI.BB->pred_size() == 1 && FalseBBI.BB->pred_size() == 1 && - !(TrueBBI.ModifyPredicate && FalseBBI.ModifyPredicate) && !TrueBBI.FalseBB && !FalseBBI.FalseBB); } -/// StructuralAnalysis - Analyze the structure of the sub-CFG starting from +/// AnalyzeBlock - Analyze the structure of the sub-CFG starting from /// the specified block. Record its successors and whether it looks like an /// if-conversion candidate. -void IfConverter::StructuralAnalysis(MachineBasicBlock *BB) { +void IfConverter::AnalyzeBlock(MachineBasicBlock *BB) { BBInfo &BBI = BBAnalysis[BB->getNumber()]; if (BBI.Kind == ICReAnalyze) { @@ -286,7 +284,6 @@ return; // Already analyzed. BBI.BB = BB; BBI.NonPredSize = std::distance(BB->begin(), BB->end()); - BBI.ModifyPredicate = BlockModifyPredicate(BB); } // Look for 'root' of a simple (non-nested) triangle or diamond. @@ -301,7 +298,7 @@ if (BBI.TrueBB == BB || BBI.FalseBB == BB) return; - StructuralAnalysis(BBI.TrueBB); + AnalyzeBlock(BBI.TrueBB); BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; // No false branch. This BB must end with a conditional branch and a @@ -310,7 +307,7 @@ BBI.FalseBB = findFalseBlock(BB, BBI.TrueBB); assert(BBI.FalseBB && "Expected to find the fallthrough block!"); - StructuralAnalysis(BBI.FalseBB); + AnalyzeBlock(BBI.FalseBB); BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; // If both paths are dead, then forget about it. @@ -323,34 +320,11 @@ // the CFG to form a triangle with the 'false' path. std::vector RevCond(BBI.BrCond); bool CanRevCond = !TII->ReverseBranchCondition(RevCond); - if (FalseBBI.FalseBB) { - if (TrueBBI.TrueBB && TrueBBI.TrueBB == BBI.FalseBB) - return; - std::vector Cond(BBI.BrCond); - if (CanRevCond && - FalseBBI.TrueBB && FalseBBI.BB->pred_size() == 1 && - FeasibilityAnalysis(FalseBBI, RevCond, true)) { - std::vector FalseCond(FalseBBI.BrCond); - if (FalseBBI.TrueBB == BBI.TrueBB && - TII->SubsumesPredicate(FalseCond, BBI.BrCond)) { - // Reverse 'true' and 'false' paths. - ReverseBranchCondition(BBI); - BBI.Kind = ICTriangle; - FalseBBI.Kind = ICChild; - } else if (FalseBBI.FalseBB == BBI.TrueBB && - !TII->ReverseBranchCondition(FalseCond) && - TII->SubsumesPredicate(FalseCond, BBI.BrCond)) { - // Reverse 'false' block's 'true' and 'false' paths and then - // reverse 'true' and 'false' paths. - ReverseBranchCondition(FalseBBI); - ReverseBranchCondition(BBI); - BBI.Kind = ICTriangle; - FalseBBI.Kind = ICChild; - } - } - } else if (CanRevCond && ValidDiamond(TrueBBI, FalseBBI) && - FeasibilityAnalysis(TrueBBI, BBI.BrCond) && - FeasibilityAnalysis(FalseBBI, RevCond)) { + + if (CanRevCond && ValidDiamond(TrueBBI, FalseBBI) && + !(TrueBBI.ModifyPredicate && FalseBBI.ModifyPredicate) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond) && + FeasibilityAnalysis(FalseBBI, RevCond)) { // Diamond: // EBB // / \_ @@ -364,50 +338,46 @@ BBI.TailBB = TrueBBI.TrueBB; } else { // FIXME: Consider duplicating if BB is small. - bool TryTriangle = ValidTriangle(TrueBBI, FalseBBI); - bool TrySimple = !blockAlwaysFallThrough(TrueBBI) && - TrueBBI.BrCond.size() == 0 && TrueBBI.BB->pred_size() == 1; - if ((TryTriangle || TrySimple) && - FeasibilityAnalysis(TrueBBI, BBI.BrCond)) { - if (TryTriangle) { - // Triangle: - // EBB - // | \_ - // | | - // | TBB - // | / - // FBB - BBI.Kind = ICTriangle; - TrueBBI.Kind = ICChild; - } else { - // Simple (split, no rejoin): - // EBB - // | \_ - // | | - // | TBB---> exit - // | - // FBB - BBI.Kind = ICSimple; - TrueBBI.Kind = ICChild; - } - } else if (FalseBBI.BrCond.size() == 0 && FalseBBI.BB->pred_size() == 1) { + if (ValidTriangle(TrueBBI, FalseBBI) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond, true)) { + // Triangle: + // EBB + // | \_ + // | | + // | TBB + // | / + // FBB + BBI.Kind = ICTriangle; + TrueBBI.Kind = ICChild; + } else if (ValidSimple(TrueBBI) && + FeasibilityAnalysis(TrueBBI, BBI.BrCond)) { + // Simple (split, no rejoin): + // EBB + // | \_ + // | | + // | TBB---> exit + // | + // FBB + BBI.Kind = ICSimple; + TrueBBI.Kind = ICChild; + } else if (CanRevCond) { // Try the other path... - bool TryTriangle = ValidTriangle(FalseBBI, TrueBBI); - bool TrySimple = !blockAlwaysFallThrough(FalseBBI); - if (TryTriangle || TrySimple) { - std::vector RevCond(BBI.BrCond); - if (!TII->ReverseBranchCondition(RevCond) && - FeasibilityAnalysis(FalseBBI, RevCond)) { - if (TryTriangle) { - // Reverse 'true' and 'false' paths. - ReverseBranchCondition(BBI); - BBI.Kind = ICTriangle; - FalseBBI.Kind = ICChild; - } else { - BBI.Kind = ICSimpleFalse; - FalseBBI.Kind = ICChild; - } - } + if (ValidTriangle(FalseBBI, TrueBBI) && + FeasibilityAnalysis(FalseBBI, RevCond, true)) { + // Reverse 'true' and 'false' paths. + ReverseBranchCondition(BBI); + BBI.Kind = ICTriangle; + FalseBBI.Kind = ICChild; + } else if (ValidTriangle(FalseBBI, TrueBBI, true) && + FeasibilityAnalysis(FalseBBI, RevCond, true, true)) { + ReverseBranchCondition(FalseBBI); + ReverseBranchCondition(BBI); + BBI.Kind = ICTriangle; + FalseBBI.Kind = ICChild; + } else if (ValidSimple(FalseBBI) && + FeasibilityAnalysis(FalseBBI, RevCond)) { + BBI.Kind = ICSimpleFalse; + FalseBBI.Kind = ICChild; } } } @@ -418,11 +388,10 @@ /// cases, that means all the instructions in the block has M_PREDICABLE flag. /// Also checks if the block contains any instruction which can clobber a /// predicate (e.g. condition code register). If so, the block is not -/// predicable unless it's the last instruction. If IgnoreTerm is true then -/// all the terminator instructions are skipped. +/// predicable unless it's the last instruction. bool IfConverter::FeasibilityAnalysis(BBInfo &BBI, - std::vector &Cond, - bool IgnoreTerm) { + std::vector &Pred, + bool isTriangle, bool RevBranch) { // If the block is dead, or it is going to be the entry block of a sub-CFG // that will be if-converted, then it cannot be predicated. if (BBI.Kind != ICNotAnalyzed && @@ -436,13 +405,46 @@ // If it is already predicated, check if its predicate subsumes the new // predicate. - if (BBI.Predicate.size() && !TII->SubsumesPredicate(BBI.Predicate, Cond)) + if (BBI.Predicate.size() && !TII->SubsumesPredicate(BBI.Predicate, Pred)) return false; + bool SeenPredMod = false; + bool SeenCondBr = false; for (MachineBasicBlock::iterator I = BBI.BB->begin(), E = BBI.BB->end(); I != E; ++I) { - if (IgnoreTerm && TII->isTerminatorInstr(I->getOpcode())) - continue; + const TargetInstrDescriptor *TID = I->getInstrDescriptor(); + if (SeenPredMod) { + // Predicate modification instruction should end the block (except for + // already predicated instructions and end of block branches). + if (!TII->isPredicated(I)) { + // This is the 'true' block of a triangle, i.e. its 'true' block is + // the same as the 'false' block of the entry. So false positive + // is ok. + if (isTriangle && !SeenCondBr && BBI.IsAnalyzable && + (TID->Flags & M_BRANCH_FLAG) != 0 && + (TID->Flags & M_BARRIER_FLAG) == 0) { + // This is the first conditional branch, test predicate subsumsion. + std::vector RevPred(Pred); + std::vector Cond(BBI.BrCond); + if (RevBranch) { + if (TII->ReverseBranchCondition(Cond)) + return false; + } + if (TII->ReverseBranchCondition(RevPred) || + !TII->SubsumesPredicate(Cond, RevPred)) + return false; + SeenCondBr = true; + continue; // Conditional branches is not predicable. + } + return false; + } + } + + if (TID->Flags & M_CLOBBERS_PRED) { + BBI.ModifyPredicate = true; + SeenPredMod = true; + } + if (!I->isPredicable()) return false; } @@ -488,7 +490,7 @@ for (idf_ext_iterator I=idf_ext_begin(Roots[i],Visited), E = idf_ext_end(Roots[i], Visited); I != E; ++I) { MachineBasicBlock *BB = *I; - StructuralAnalysis(BB); + AnalyzeBlock(BB); BBInfo &BBI = BBAnalysis[BB->getNumber()]; switch (BBI.Kind) { case ICSimple: @@ -560,23 +562,23 @@ // to the 'false' branch. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); MergeBlocks(BBI, *CvtBBI); + BBI.BB->removeSuccessor(CvtBBI->BB); bool IterIfcvt = true; if (!isNextBlock(BBI.BB, NextBBI->BB)) { InsertUncondBranch(BBI.BB, NextBBI->BB, TII); BBI.hasFallThrough = false; - if (BBI.ModifyPredicate) - // Now ifcvt'd block will look like this: - // BB: - // ... - // t, f = cmp - // if t op - // b BBf - // - // We cannot further ifcvt this block because the unconditional branch - // will have to be predicated on the new condition, that will not be - // available if cmp executes. - IterIfcvt = false; + // Now ifcvt'd block will look like this: + // BB: + // ... + // t, f = cmp + // if t op + // b BBf + // + // We cannot further ifcvt this block because the unconditional branch + // will have to be predicated on the new condition, that will not be + // available if cmp executes. + IterIfcvt = false; } std::copy(Cond.begin(), Cond.end(), std::back_inserter(BBI.Predicate)); @@ -610,45 +612,34 @@ TII->InsertBranch(*BBI.TrueBB, TrueBBI.FalseBB, NULL, RevCond); } - // Join the 'true' and 'false' blocks if the 'false' block has no other - // predecessors. Otherwise, add a unconditional branch from 'true' to 'false'. + // Now merge the entry of the triangle with the true block. + BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); + MergeBlocks(BBI, TrueBBI); + + // Merge in the 'false' block if the 'false' block has no other + // predecessors. Otherwise, add a unconditional branch from to 'false'. BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; bool FalseBBDead = false; bool IterIfcvt = true; - bool isFallThrough = isNextBlock(TrueBBI.BB, FalseBBI.BB); + bool isFallThrough = isNextBlock(BBI.BB, FalseBBI.BB); if (!isFallThrough) { // Only merge them if the true block does not fallthrough to the false // block. By not merging them, we make it possible to iteratively // ifcvt the blocks. - if (!HasEarlyExit && FalseBBI.BB->pred_size() == 2) { - MergeBlocks(TrueBBI, FalseBBI); + if (!HasEarlyExit && FalseBBI.BB->pred_size() == 1) { + MergeBlocks(BBI, FalseBBI); FalseBBDead = true; - // Mixed predicated and unpredicated code. This cannot be iteratively - // predicated. - IterIfcvt = false; } else { - InsertUncondBranch(TrueBBI.BB, FalseBBI.BB, TII); + InsertUncondBranch(BBI.BB, FalseBBI.BB, TII); TrueBBI.hasFallThrough = false; - if (BBI.ModifyPredicate || TrueBBI.ModifyPredicate) - // Now ifcvt'd block will look like this: - // BB: - // ... - // t, f = cmp - // if t op - // b BBf - // - // We cannot further ifcvt this block because the unconditional branch will - // have to be predicated on the new condition, that will not be available - // if cmp executes. - IterIfcvt = false; } + // Mixed predicated and unpredicated code. This cannot be iteratively + // predicated. + IterIfcvt = false; } - // Now merge the entry of the triangle with the true block. - BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); - MergeBlocks(BBI, TrueBBI); // Remove entry to false edge if false block is merged in as well. - if (FalseBBDead && BBI.BB->isSuccessor(FalseBBI.BB)) + if (FalseBBDead) BBI.BB->removeSuccessor(FalseBBI.BB); std::copy(BBI.BrCond.begin(), BBI.BrCond.end(), std::back_inserter(BBI.Predicate)); From sabre at nondot.org Fri Jun 8 11:52:37 2007 From: sabre at nondot.org (Chris Lattner) Date: Fri, 8 Jun 2007 11:52:37 -0500 Subject: [llvm-commits] CVS: llvm/docs/LangRef.html Message-ID: <200706081652.l58GqbhH023441@zion.cs.uiuc.edu> Changes in directory llvm/docs: LangRef.html updated: 1.251 -> 1.252 --- Log message: wording fix noticed by Ivan Novick --- Diffs of the changes: (+2 -2) LangRef.html | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/docs/LangRef.html diff -u llvm/docs/LangRef.html:1.251 llvm/docs/LangRef.html:1.252 --- llvm/docs/LangRef.html:1.251 Wed Jun 6 13:28:13 2007 +++ llvm/docs/LangRef.html Fri Jun 8 11:52:14 2007 @@ -698,7 +698,7 @@ with a terminator instruction (such as a branch or function return).

      -

      The first basic block in a program is special in two ways: it is immediately +

      The first basic block in a function is special in two ways: it is immediately executed on entrance to the function, and it is not allowed to have predecessor basic blocks (i.e. there can not be any branches to the entry block of a function). Because the block can have no predecessors, it also cannot have any @@ -4830,7 +4830,7 @@ Chris Lattner
      The LLVM Compiler Infrastructure
      - Last modified: $Date: 2007/06/06 18:28:13 $ + Last modified: $Date: 2007/06/08 16:52:14 $ From greened at obbligato.org Fri Jun 8 12:19:20 2007 From: greened at obbligato.org (David Greene) Date: Fri, 8 Jun 2007 12:19:20 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/SimpleRegisterCoalescing.h Passes.h LiveIntervalAnalysis.h Message-ID: <200706081719.l58HJKAG024077@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: SimpleRegisterCoalescing.h added (r1.1) Passes.h updated: 1.26 -> 1.27 LiveIntervalAnalysis.h updated: 1.85 -> 1.86 --- Log message: Factor live variable analysis so it does not do register coalescing simultaneously. Move that pass to SimpleRegisterCoalescing. This makes it easier to implement alternative register allocation and coalescing strategies while maintaining reuse of the existing live interval analysis. --- Diffs of the changes: (+195 -114) LiveIntervalAnalysis.h | 144 ++++++++-------------------------------- Passes.h | 5 + SimpleRegisterCoalescing.h | 160 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 114 deletions(-) Index: llvm/include/llvm/CodeGen/SimpleRegisterCoalescing.h diff -c /dev/null llvm/include/llvm/CodeGen/SimpleRegisterCoalescing.h:1.1 *** /dev/null Fri Jun 8 12:19:06 2007 --- llvm/include/llvm/CodeGen/SimpleRegisterCoalescing.h Fri Jun 8 12:18:56 2007 *************** *** 0 **** --- 1,160 ---- + //===-- SimpleRegisterCoalescing.h - Register Coalescing --------*- C++ -*-===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by the LLVM research group and is distributed under + // the University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file implements a simple register copy coalescing phase. + // + //===----------------------------------------------------------------------===// + + #ifndef LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H + #define LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H + + #include "llvm/CodeGen/MachineFunctionPass.h" + #include "llvm/CodeGen/LiveInterval.h" + #include "llvm/CodeGen/LiveIntervalAnalysis.h" + #include "llvm/ADT/BitVector.h" + #include "llvm/ADT/IndexedMap.h" + + namespace llvm { + + class LiveVariables; + class MRegisterInfo; + class TargetInstrInfo; + class VirtRegMap; + + class SimpleRegisterCoalescing : public MachineFunctionPass { + MachineFunction* mf_; + const TargetMachine* tm_; + const MRegisterInfo* mri_; + const TargetInstrInfo* tii_; + LiveIntervals *li_; + LiveVariables *lv_; + + typedef IndexedMap Reg2RegMap; + Reg2RegMap r2rMap_; + + BitVector allocatableRegs_; + DenseMap allocatableRCRegs_; + + /// JoinedLIs - Keep track which register intervals have been coalesced + /// with other intervals. + BitVector JoinedLIs; + + public: + static char ID; // Pass identifcation, replacement for typeid + SimpleRegisterCoalescing() : MachineFunctionPass((intptr_t)&ID) {}; + + struct CopyRec { + MachineInstr *MI; + unsigned SrcReg, DstReg; + }; + CopyRec getCopyRec(MachineInstr *MI, unsigned SrcReg, unsigned DstReg) { + CopyRec R; + R.MI = MI; + R.SrcReg = SrcReg; + R.DstReg = DstReg; + return R; + } + struct InstrSlots { + enum { + LOAD = 0, + USE = 1, + DEF = 2, + STORE = 3, + NUM = 4 + }; + }; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(std::ostream &O, const Module* = 0) const; + void print(std::ostream *O, const Module* M = 0) const { + if (O) print(*O, M); + } + + private: + /// joinIntervals - join compatible live intervals + void joinIntervals(); + + /// CopyCoallesceInMBB - Coallsece copies in the specified MBB, putting + /// copies that cannot yet be coallesced into the "TryAgain" list. + void CopyCoallesceInMBB(MachineBasicBlock *MBB, + std::vector *TryAgain, bool PhysOnly = false); + + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, + /// which are the src/dst of the copy instruction CopyMI. This returns true + /// if the copy was successfully coallesced away, or if it is never possible + /// to coallesce these this copy, due to register constraints. It returns + /// false if it is not currently possible to coallesce this interval, but + /// it may be possible if other things get coallesced. + bool JoinCopy(MachineInstr *CopyMI, unsigned SrcReg, unsigned DstReg, + bool PhysOnly = false); + + /// JoinIntervals - Attempt to join these two intervals. On failure, this + /// returns false. Otherwise, if one of the intervals being joined is a + /// physreg, this method always canonicalizes DestInt to be it. The output + /// "SrcInt" will not have been modified, so we can use this information + /// below to update aliases. + bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS); + + /// SimpleJoin - Attempt to join the specified interval into this one. The + /// caller of this method must guarantee that the RHS only contains a single + /// value number and that the RHS is not defined by a copy from this + /// interval. This returns false if the intervals are not joinable, or it + /// joins them and returns true. + bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS); + + /// Return true if the two specified registers belong to different + /// register classes. The registers may be either phys or virt regs. + bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; + + + bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB, + MachineInstr *CopyMI); + + /// lastRegisterUse - Returns the last use of the specific register between + /// cycles Start and End. It also returns the use operand by reference. It + /// returns NULL if there are no uses. + MachineInstr *lastRegisterUse(unsigned Start, unsigned End, unsigned Reg, + MachineOperand *&MOU); + + /// findDefOperand - Returns the MachineOperand that is a def of the specific + /// register. It returns NULL if the def is not found. + MachineOperand *findDefOperand(MachineInstr *MI, unsigned Reg); + + /// unsetRegisterKill - Unset IsKill property of all uses of the specific + /// register of the specific instruction. + void unsetRegisterKill(MachineInstr *MI, unsigned Reg); + + /// unsetRegisterKills - Unset IsKill property of all uses of specific register + /// between cycles Start and End. + void unsetRegisterKills(unsigned Start, unsigned End, unsigned Reg); + + /// hasRegisterDef - True if the instruction defines the specific register. + /// + bool hasRegisterDef(MachineInstr *MI, unsigned Reg); + + /// rep - returns the representative of this register + unsigned rep(unsigned Reg) { + unsigned Rep = r2rMap_[Reg]; + if (Rep) + return r2rMap_[Reg] = rep(Rep); + return Reg; + } + + void printRegName(unsigned reg) const; + }; + + } // End llvm namespace + + #endif Index: llvm/include/llvm/CodeGen/Passes.h diff -u llvm/include/llvm/CodeGen/Passes.h:1.26 llvm/include/llvm/CodeGen/Passes.h:1.27 --- llvm/include/llvm/CodeGen/Passes.h:1.26 Tue May 22 12:14:46 2007 +++ llvm/include/llvm/CodeGen/Passes.h Fri Jun 8 12:18:56 2007 @@ -44,6 +44,11 @@ /// extern const PassInfo *PHIEliminationID; + /// SimpleRegisterCoalescing pass. Aggressively coalesces every register + /// copy it can. + /// + extern const PassInfo *SimpleRegisterCoalescingID; + /// TwoAddressInstruction pass - This pass reduces two-address instructions to /// use two operands. This destroys SSA information but it is desired by /// register allocators. Index: llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h diff -u llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h:1.85 llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h:1.86 --- llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h:1.85 Mon May 14 16:10:05 2007 +++ llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h Fri Jun 8 12:18:56 2007 @@ -44,7 +44,7 @@ /// MBB2IdxMap - The index of the first instruction in the specified basic /// block. std::vector MBB2IdxMap; - + typedef std::map Mi2IndexMap; Mi2IndexMap mi2iMap_; @@ -54,31 +54,12 @@ typedef std::map Reg2IntervalMap; Reg2IntervalMap r2iMap_; - typedef IndexedMap Reg2RegMap; - Reg2RegMap r2rMap_; - BitVector allocatableRegs_; - DenseMap allocatableRCRegs_; - - /// JoinedLIs - Keep track which register intervals have been coalesced - /// with other intervals. - BitVector JoinedLIs; public: static char ID; // Pass identification, replacement for typeid LiveIntervals() : MachineFunctionPass((intptr_t)&ID) {} - struct CopyRec { - MachineInstr *MI; - unsigned SrcReg, DstReg; - }; - CopyRec getCopyRec(MachineInstr *MI, unsigned SrcReg, unsigned DstReg) { - CopyRec R; - R.MI = MI; - R.SrcReg = SrcReg; - R.DstReg = DstReg; - return R; - } struct InstrSlots { enum { LOAD = 0, @@ -158,29 +139,31 @@ "index does not correspond to an instruction"); return i2miMap_[index]; } - - std::vector addIntervalsForSpills(const LiveInterval& i, - VirtRegMap& vrm, - int slot); + + // Interval creation + + LiveInterval &getOrCreateInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + if (I == r2iMap_.end()) + I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg))); + return I->second; + } /// CreateNewLiveInterval - Create a new live interval with the given live /// ranges. The new live interval will have an infinite spill weight. LiveInterval &CreateNewLiveInterval(const LiveInterval *LI, const std::vector &LRs); - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); + std::vector addIntervalsForSpills(const LiveInterval& i, + VirtRegMap& vrm, + int slot); - /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); + // Interval removal - /// print - Implement the dump method. - virtual void print(std::ostream &O, const Module* = 0) const; - void print(std::ostream *O, const Module* M = 0) const { - if (O) print(*O, M); + void removeInterval(unsigned Reg) { + r2iMap_.erase(Reg); } - private: /// isRemoved - returns true if the specified machine instr has been /// removed. bool isRemoved(MachineInstr* instr) const { @@ -198,40 +181,22 @@ mi2iMap_.erase(mi2i); } } - - /// computeIntervals - Compute live intervals. - void computeIntervals(); - /// joinIntervals - join compatible live intervals - void joinIntervals(); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); - /// CopyCoallesceInMBB - Coallsece copies in the specified MBB, putting - /// copies that cannot yet be coallesced into the "TryAgain" list. - void CopyCoallesceInMBB(MachineBasicBlock *MBB, - std::vector *TryAgain, bool PhysOnly = false); - - /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, - /// which are the src/dst of the copy instruction CopyMI. This returns true - /// if the copy was successfully coallesced away, or if it is never possible - /// to coallesce these this copy, due to register constraints. It returns - /// false if it is not currently possible to coallesce this interval, but - /// it may be possible if other things get coallesced. - bool JoinCopy(MachineInstr *CopyMI, unsigned SrcReg, unsigned DstReg, - bool PhysOnly = false); - - /// JoinIntervals - Attempt to join these two intervals. On failure, this - /// returns false. Otherwise, if one of the intervals being joined is a - /// physreg, this method always canonicalizes DestInt to be it. The output - /// "SrcInt" will not have been modified, so we can use this information - /// below to update aliases. - bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS); - - /// SimpleJoin - Attempt to join the specified interval into this one. The - /// caller of this method must guarantee that the RHS only contains a single - /// value number and that the RHS is not defined by a copy from this - /// interval. This returns false if the intervals are not joinable, or it - /// joins them and returns true. - bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS); + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(std::ostream &O, const Module* = 0) const; + void print(std::ostream *O, const Module* M = 0) const { + if (O) print(*O, M); + } + + private: + /// computeIntervals - Compute live intervals. + void computeIntervals(); /// handleRegisterDef - update intervals for a register def /// (calls handlePhysicalRegisterDef and @@ -260,57 +225,8 @@ unsigned MIIdx, LiveInterval &interval, bool isAlias = false); - /// Return true if the two specified registers belong to different - /// register classes. The registers may be either phys or virt regs. - bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; - - - bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB, - MachineInstr *CopyMI); - - /// lastRegisterUse - Returns the last use of the specific register between - /// cycles Start and End. It also returns the use operand by reference. It - /// returns NULL if there are no uses. - MachineInstr *lastRegisterUse(unsigned Start, unsigned End, unsigned Reg, - MachineOperand *&MOU); - - /// findDefOperand - Returns the MachineOperand that is a def of the specific - /// register. It returns NULL if the def is not found. - MachineOperand *findDefOperand(MachineInstr *MI, unsigned Reg); - - /// unsetRegisterKill - Unset IsKill property of all uses of the specific - /// register of the specific instruction. - void unsetRegisterKill(MachineInstr *MI, unsigned Reg); - - /// unsetRegisterKills - Unset IsKill property of all uses of specific register - /// between cycles Start and End. - void unsetRegisterKills(unsigned Start, unsigned End, unsigned Reg); - - /// hasRegisterDef - True if the instruction defines the specific register. - /// - bool hasRegisterDef(MachineInstr *MI, unsigned Reg); - static LiveInterval createInterval(unsigned Reg); - void removeInterval(unsigned Reg) { - r2iMap_.erase(Reg); - } - - LiveInterval &getOrCreateInterval(unsigned reg) { - Reg2IntervalMap::iterator I = r2iMap_.find(reg); - if (I == r2iMap_.end()) - I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg))); - return I->second; - } - - /// rep - returns the representative of this register - unsigned rep(unsigned Reg) { - unsigned Rep = r2rMap_[Reg]; - if (Rep) - return r2rMap_[Reg] = rep(Rep); - return Reg; - } - void printRegName(unsigned reg) const; }; From greened at obbligato.org Fri Jun 8 12:19:20 2007 From: greened at obbligato.org (David Greene) Date: Fri, 8 Jun 2007 12:19:20 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp RegAllocLinearScan.cpp LiveIntervalAnalysis.cpp Message-ID: <200706081719.l58HJKIk024078@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: SimpleRegisterCoalescing.cpp added (r1.1) RegAllocLinearScan.cpp updated: 1.149 -> 1.150 LiveIntervalAnalysis.cpp updated: 1.245 -> 1.246 --- Log message: Factor live variable analysis so it does not do register coalescing simultaneously. Move that pass to SimpleRegisterCoalescing. This makes it easier to implement alternative register allocation and coalescing strategies while maintaining reuse of the existing live interval analysis. --- Diffs of the changes: (+1142 -1055) LiveIntervalAnalysis.cpp | 1058 --------------------------------------- RegAllocLinearScan.cpp | 1 SimpleRegisterCoalescing.cpp | 1138 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1142 insertions(+), 1055 deletions(-) Index: llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp diff -c /dev/null llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp:1.1 *** /dev/null Fri Jun 8 12:19:06 2007 --- llvm/lib/CodeGen/SimpleRegisterCoalescing.cpp Fri Jun 8 12:18:56 2007 *************** *** 0 **** --- 1,1138 ---- + //===-- SimpleRegisterCoalescing.cpp - Register Coalescing ----------------===// + // + // The LLVM Compiler Infrastructure + // + // This file was developed by the LLVM research group and is distributed under + // the University of Illinois Open Source License. See LICENSE.TXT for details. + // + //===----------------------------------------------------------------------===// + // + // This file implements a simple register coalescing pass that attempts to + // aggressively coalesce every register copy that it can. + // + //===----------------------------------------------------------------------===// + + #define DEBUG_TYPE "simpleregistercoalescing" + #include "llvm/CodeGen/SimpleRegisterCoalescing.h" + #include "llvm/CodeGen/LiveIntervalAnalysis.h" + #include "VirtRegMap.h" + #include "llvm/Value.h" + #include "llvm/Analysis/LoopInfo.h" + #include "llvm/CodeGen/LiveVariables.h" + #include "llvm/CodeGen/MachineFrameInfo.h" + #include "llvm/CodeGen/MachineInstr.h" + #include "llvm/CodeGen/Passes.h" + #include "llvm/CodeGen/SSARegMap.h" + #include "llvm/Target/MRegisterInfo.h" + #include "llvm/Target/TargetInstrInfo.h" + #include "llvm/Target/TargetMachine.h" + #include "llvm/Support/CommandLine.h" + #include "llvm/Support/Debug.h" + #include "llvm/ADT/SmallSet.h" + #include "llvm/ADT/Statistic.h" + #include "llvm/ADT/STLExtras.h" + #include + #include + using namespace llvm; + + STATISTIC(numJoins , "Number of interval joins performed"); + STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); + STATISTIC(numAborts , "Number of times interval joining aborted"); + + char SimpleRegisterCoalescing::ID = 0; + namespace { + static cl::opt + EnableJoining("join-liveintervals", + cl::desc("Coallesce copies (default=true)"), + cl::init(true)); + + RegisterPass + X("simple-register-coalescing", + "Simple register coalescing to eliminate all possible register copies"); + } + + const PassInfo *llvm::SimpleRegisterCoalescingID = X.getPassInfo(); + + void SimpleRegisterCoalescing::getAnalysisUsage(AnalysisUsage &AU) const { + //AU.addPreserved(); + AU.addPreserved(); + AU.addPreservedID(PHIEliminationID); + AU.addPreservedID(TwoAddressInstructionPassID); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + /// AdjustCopiesBackFrom - We found a non-trivially-coallescable copy with IntA + /// being the source and IntB being the dest, thus this defines a value number + /// in IntB. If the source value number (in IntA) is defined by a copy from B, + /// see if we can merge these two pieces of B into a single value number, + /// eliminating a copy. For example: + /// + /// A3 = B0 + /// ... + /// B1 = A3 <- this copy + /// + /// In this case, B0 can be extended to where the B1 copy lives, allowing the B1 + /// value number to be replaced with B0 (which simplifies the B liveinterval). + /// + /// This returns true if an interval was modified. + /// + bool SimpleRegisterCoalescing::AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB, + MachineInstr *CopyMI) { + unsigned CopyIdx = li_->getDefIndex(li_->getInstructionIndex(CopyMI)); + + // BValNo is a value number in B that is defined by a copy from A. 'B3' in + // the example above. + LiveInterval::iterator BLR = IntB.FindLiveRangeContaining(CopyIdx); + unsigned BValNo = BLR->ValId; + + // Get the location that B is defined at. Two options: either this value has + // an unknown definition point or it is defined at CopyIdx. If unknown, we + // can't process it. + unsigned BValNoDefIdx = IntB.getInstForValNum(BValNo); + if (BValNoDefIdx == ~0U) return false; + assert(BValNoDefIdx == CopyIdx && + "Copy doesn't define the value?"); + + // AValNo is the value number in A that defines the copy, A0 in the example. + LiveInterval::iterator AValLR = IntA.FindLiveRangeContaining(CopyIdx-1); + unsigned AValNo = AValLR->ValId; + + // If AValNo is defined as a copy from IntB, we can potentially process this. + + // Get the instruction that defines this value number. + unsigned SrcReg = IntA.getSrcRegForValNum(AValNo); + if (!SrcReg) return false; // Not defined by a copy. + + // If the value number is not defined by a copy instruction, ignore it. + + // If the source register comes from an interval other than IntB, we can't + // handle this. + if (rep(SrcReg) != IntB.reg) return false; + + // Get the LiveRange in IntB that this value number starts with. + unsigned AValNoInstIdx = IntA.getInstForValNum(AValNo); + LiveInterval::iterator ValLR = IntB.FindLiveRangeContaining(AValNoInstIdx-1); + + // Make sure that the end of the live range is inside the same block as + // CopyMI. + MachineInstr *ValLREndInst = li_->getInstructionFromIndex(ValLR->end-1); + if (!ValLREndInst || + ValLREndInst->getParent() != CopyMI->getParent()) return false; + + // Okay, we now know that ValLR ends in the same block that the CopyMI + // live-range starts. If there are no intervening live ranges between them in + // IntB, we can merge them. + if (ValLR+1 != BLR) return false; + + DOUT << "\nExtending: "; IntB.print(DOUT, mri_); + + // We are about to delete CopyMI, so need to remove it as the 'instruction + // that defines this value #'. + IntB.setValueNumberInfo(BValNo, std::make_pair(~0U, 0)); + + // Okay, we can merge them. We need to insert a new liverange: + // [ValLR.end, BLR.begin) of either value number, then we merge the + // two value numbers. + unsigned FillerStart = ValLR->end, FillerEnd = BLR->start; + IntB.addRange(LiveRange(FillerStart, FillerEnd, BValNo)); + + // If the IntB live range is assigned to a physical register, and if that + // physreg has aliases, + if (MRegisterInfo::isPhysicalRegister(IntB.reg)) { + // Update the liveintervals of sub-registers. + for (const unsigned *AS = mri_->getSubRegisters(IntB.reg); *AS; ++AS) { + LiveInterval &AliasLI = li_->getInterval(*AS); + AliasLI.addRange(LiveRange(FillerStart, FillerEnd, + AliasLI.getNextValue(~0U, 0))); + } + } + + // Okay, merge "B1" into the same value number as "B0". + if (BValNo != ValLR->ValId) + IntB.MergeValueNumberInto(BValNo, ValLR->ValId); + DOUT << " result = "; IntB.print(DOUT, mri_); + DOUT << "\n"; + + // If the source instruction was killing the source register before the + // merge, unset the isKill marker given the live range has been extended. + int UIdx = ValLREndInst->findRegisterUseOperandIdx(IntB.reg, true); + if (UIdx != -1) + ValLREndInst->getOperand(UIdx).unsetIsKill(); + + // Finally, delete the copy instruction. + li_->RemoveMachineInstrFromMaps(CopyMI); + CopyMI->eraseFromParent(); + ++numPeep; + return true; + } + + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, + /// which are the src/dst of the copy instruction CopyMI. This returns true + /// if the copy was successfully coallesced away, or if it is never possible + /// to coallesce this copy, due to register constraints. It returns + /// false if it is not currently possible to coallesce this interval, but + /// it may be possible if other things get coallesced. + bool SimpleRegisterCoalescing::JoinCopy(MachineInstr *CopyMI, + unsigned SrcReg, unsigned DstReg, bool PhysOnly) { + DOUT << li_->getInstructionIndex(CopyMI) << '\t' << *CopyMI; + + // Get representative registers. + unsigned repSrcReg = rep(SrcReg); + unsigned repDstReg = rep(DstReg); + + // If they are already joined we continue. + if (repSrcReg == repDstReg) { + DOUT << "\tCopy already coallesced.\n"; + return true; // Not coallescable. + } + + bool SrcIsPhys = MRegisterInfo::isPhysicalRegister(repSrcReg); + bool DstIsPhys = MRegisterInfo::isPhysicalRegister(repDstReg); + if (PhysOnly && !SrcIsPhys && !DstIsPhys) + // Only joining physical registers with virtual registers in this round. + return true; + + // If they are both physical registers, we cannot join them. + if (SrcIsPhys && DstIsPhys) { + DOUT << "\tCan not coallesce physregs.\n"; + return true; // Not coallescable. + } + + // We only join virtual registers with allocatable physical registers. + if (SrcIsPhys && !allocatableRegs_[repSrcReg]) { + DOUT << "\tSrc reg is unallocatable physreg.\n"; + return true; // Not coallescable. + } + if (DstIsPhys && !allocatableRegs_[repDstReg]) { + DOUT << "\tDst reg is unallocatable physreg.\n"; + return true; // Not coallescable. + } + + // If they are not of the same register class, we cannot join them. + if (differingRegisterClasses(repSrcReg, repDstReg)) { + DOUT << "\tSrc/Dest are different register classes.\n"; + return true; // Not coallescable. + } + + LiveInterval &SrcInt = li_->getInterval(repSrcReg); + LiveInterval &DstInt = li_->getInterval(repDstReg); + assert(SrcInt.reg == repSrcReg && DstInt.reg == repDstReg && + "Register mapping is horribly broken!"); + + DOUT << "\t\tInspecting "; SrcInt.print(DOUT, mri_); + DOUT << " and "; DstInt.print(DOUT, mri_); + DOUT << ": "; + + // Check if it is necessary to propagate "isDead" property before intervals + // are joined. + MachineOperand *mopd = CopyMI->findRegisterDefOperand(DstReg); + bool isDead = mopd->isDead(); + bool isShorten = false; + unsigned SrcStart = 0, RemoveStart = 0; + unsigned SrcEnd = 0, RemoveEnd = 0; + if (isDead) { + unsigned CopyIdx = li_->getInstructionIndex(CopyMI); + LiveInterval::iterator SrcLR = + SrcInt.FindLiveRangeContaining(li_->getUseIndex(CopyIdx)); + RemoveStart = SrcStart = SrcLR->start; + RemoveEnd = SrcEnd = SrcLR->end; + // The instruction which defines the src is only truly dead if there are + // no intermediate uses and there isn't a use beyond the copy. + // FIXME: find the last use, mark is kill and shorten the live range. + if (SrcEnd > li_->getDefIndex(CopyIdx)) { + isDead = false; + } else { + MachineOperand *MOU; + MachineInstr *LastUse= lastRegisterUse(SrcStart, CopyIdx, repSrcReg, MOU); + if (LastUse) { + // Shorten the liveinterval to the end of last use. + MOU->setIsKill(); + isDead = false; + isShorten = true; + RemoveStart = li_->getDefIndex(li_->getInstructionIndex(LastUse)); + RemoveEnd = SrcEnd; + } else { + MachineInstr *SrcMI = li_->getInstructionFromIndex(SrcStart); + if (SrcMI) { + MachineOperand *mops = findDefOperand(SrcMI, repSrcReg); + if (mops) + // A dead def should have a single cycle interval. + ++RemoveStart; + } + } + } + } + + // We need to be careful about coalescing a source physical register with a + // virtual register. Once the coalescing is done, it cannot be broken and + // these are not spillable! If the destination interval uses are far away, + // think twice about coalescing them! + if (!mopd->isDead() && (SrcIsPhys || DstIsPhys)) { + LiveInterval &JoinVInt = SrcIsPhys ? DstInt : SrcInt; + unsigned JoinVReg = SrcIsPhys ? repDstReg : repSrcReg; + unsigned JoinPReg = SrcIsPhys ? repSrcReg : repDstReg; + const TargetRegisterClass *RC = mf_->getSSARegMap()->getRegClass(JoinVReg); + unsigned Threshold = allocatableRCRegs_[RC].count(); + + // If the virtual register live interval is long has it has low use desity, + // do not join them, instead mark the physical register as its allocation + // preference. + unsigned Length = JoinVInt.getSize() / InstrSlots::NUM; + LiveVariables::VarInfo &vi = lv_->getVarInfo(JoinVReg); + if (Length > Threshold && + (((float)vi.NumUses / Length) < (1.0 / Threshold))) { + JoinVInt.preference = JoinPReg; + ++numAborts; + DOUT << "\tMay tie down a physical register, abort!\n"; + return false; + } + } + + // Okay, attempt to join these two intervals. On failure, this returns false. + // Otherwise, if one of the intervals being joined is a physreg, this method + // always canonicalizes DstInt to be it. The output "SrcInt" will not have + // been modified, so we can use this information below to update aliases. + if (JoinIntervals(DstInt, SrcInt)) { + if (isDead) { + // Result of the copy is dead. Propagate this property. + if (SrcStart == 0) { + assert(MRegisterInfo::isPhysicalRegister(repSrcReg) && + "Live-in must be a physical register!"); + // Live-in to the function but dead. Remove it from entry live-in set. + // JoinIntervals may end up swapping the two intervals. + mf_->begin()->removeLiveIn(repSrcReg); + } else { + MachineInstr *SrcMI = li_->getInstructionFromIndex(SrcStart); + if (SrcMI) { + MachineOperand *mops = findDefOperand(SrcMI, repSrcReg); + if (mops) + mops->setIsDead(); + } + } + } + + if (isShorten || isDead) { + // Shorten the live interval. + LiveInterval &LiveInInt = (repSrcReg == DstInt.reg) ? DstInt : SrcInt; + LiveInInt.removeRange(RemoveStart, RemoveEnd); + } + } else { + // Coallescing failed. + + // If we can eliminate the copy without merging the live ranges, do so now. + if (AdjustCopiesBackFrom(SrcInt, DstInt, CopyMI)) + return true; + + // Otherwise, we are unable to join the intervals. + DOUT << "Interference!\n"; + return false; + } + + bool Swapped = repSrcReg == DstInt.reg; + if (Swapped) + std::swap(repSrcReg, repDstReg); + assert(MRegisterInfo::isVirtualRegister(repSrcReg) && + "LiveInterval::join didn't work right!"); + + // If we're about to merge live ranges into a physical register live range, + // we have to update any aliased register's live ranges to indicate that they + // have clobbered values for this range. + if (MRegisterInfo::isPhysicalRegister(repDstReg)) { + // Unset unnecessary kills. + if (!DstInt.containsOneValue()) { + for (LiveInterval::Ranges::const_iterator I = SrcInt.begin(), + E = SrcInt.end(); I != E; ++I) + unsetRegisterKills(I->start, I->end, repDstReg); + } + + // Update the liveintervals of sub-registers. + for (const unsigned *AS = mri_->getSubRegisters(repDstReg); *AS; ++AS) + li_->getInterval(*AS).MergeInClobberRanges(SrcInt); + } else { + // Merge use info if the destination is a virtual register. + LiveVariables::VarInfo& dVI = lv_->getVarInfo(repDstReg); + LiveVariables::VarInfo& sVI = lv_->getVarInfo(repSrcReg); + dVI.NumUses += sVI.NumUses; + } + + DOUT << "\n\t\tJoined. Result = "; DstInt.print(DOUT, mri_); + DOUT << "\n"; + + // Remember these liveintervals have been joined. + JoinedLIs.set(repSrcReg - MRegisterInfo::FirstVirtualRegister); + if (MRegisterInfo::isVirtualRegister(repDstReg)) + JoinedLIs.set(repDstReg - MRegisterInfo::FirstVirtualRegister); + + // If the intervals were swapped by Join, swap them back so that the register + // mapping (in the r2i map) is correct. + if (Swapped) SrcInt.swap(DstInt); + li_->removeInterval(repSrcReg); + r2rMap_[repSrcReg] = repDstReg; + + // Finally, delete the copy instruction. + li_->RemoveMachineInstrFromMaps(CopyMI); + CopyMI->eraseFromParent(); + ++numPeep; + ++numJoins; + return true; + } + + /// ComputeUltimateVN - Assuming we are going to join two live intervals, + /// compute what the resultant value numbers for each value in the input two + /// ranges will be. This is complicated by copies between the two which can + /// and will commonly cause multiple value numbers to be merged into one. + /// + /// VN is the value number that we're trying to resolve. InstDefiningValue + /// keeps track of the new InstDefiningValue assignment for the result + /// LiveInterval. ThisFromOther/OtherFromThis are sets that keep track of + /// whether a value in this or other is a copy from the opposite set. + /// ThisValNoAssignments/OtherValNoAssignments keep track of value #'s that have + /// already been assigned. + /// + /// ThisFromOther[x] - If x is defined as a copy from the other interval, this + /// contains the value number the copy is from. + /// + static unsigned ComputeUltimateVN(unsigned VN, + SmallVector, 16> &ValueNumberInfo, + SmallVector &ThisFromOther, + SmallVector &OtherFromThis, + SmallVector &ThisValNoAssignments, + SmallVector &OtherValNoAssignments, + LiveInterval &ThisLI, LiveInterval &OtherLI) { + // If the VN has already been computed, just return it. + if (ThisValNoAssignments[VN] >= 0) + return ThisValNoAssignments[VN]; + // assert(ThisValNoAssignments[VN] != -2 && "Cyclic case?"); + + // If this val is not a copy from the other val, then it must be a new value + // number in the destination. + int OtherValNo = ThisFromOther[VN]; + if (OtherValNo == -1) { + ValueNumberInfo.push_back(ThisLI.getValNumInfo(VN)); + return ThisValNoAssignments[VN] = ValueNumberInfo.size()-1; + } + + // Otherwise, this *is* a copy from the RHS. If the other side has already + // been computed, return it. + if (OtherValNoAssignments[OtherValNo] >= 0) + return ThisValNoAssignments[VN] = OtherValNoAssignments[OtherValNo]; + + // Mark this value number as currently being computed, then ask what the + // ultimate value # of the other value is. + ThisValNoAssignments[VN] = -2; + unsigned UltimateVN = + ComputeUltimateVN(OtherValNo, ValueNumberInfo, + OtherFromThis, ThisFromOther, + OtherValNoAssignments, ThisValNoAssignments, + OtherLI, ThisLI); + return ThisValNoAssignments[VN] = UltimateVN; + } + + static bool InVector(unsigned Val, const SmallVector &V) { + return std::find(V.begin(), V.end(), Val) != V.end(); + } + + /// SimpleJoin - Attempt to joint the specified interval into this one. The + /// caller of this method must guarantee that the RHS only contains a single + /// value number and that the RHS is not defined by a copy from this + /// interval. This returns false if the intervals are not joinable, or it + /// joins them and returns true. + bool SimpleRegisterCoalescing::SimpleJoin(LiveInterval &LHS, LiveInterval &RHS) { + assert(RHS.containsOneValue()); + + // Some number (potentially more than one) value numbers in the current + // interval may be defined as copies from the RHS. Scan the overlapping + // portions of the LHS and RHS, keeping track of this and looking for + // overlapping live ranges that are NOT defined as copies. If these exist, we + // cannot coallesce. + + LiveInterval::iterator LHSIt = LHS.begin(), LHSEnd = LHS.end(); + LiveInterval::iterator RHSIt = RHS.begin(), RHSEnd = RHS.end(); + + if (LHSIt->start < RHSIt->start) { + LHSIt = std::upper_bound(LHSIt, LHSEnd, RHSIt->start); + if (LHSIt != LHS.begin()) --LHSIt; + } else if (RHSIt->start < LHSIt->start) { + RHSIt = std::upper_bound(RHSIt, RHSEnd, LHSIt->start); + if (RHSIt != RHS.begin()) --RHSIt; + } + + SmallVector EliminatedLHSVals; + + while (1) { + // Determine if these live intervals overlap. + bool Overlaps = false; + if (LHSIt->start <= RHSIt->start) + Overlaps = LHSIt->end > RHSIt->start; + else + Overlaps = RHSIt->end > LHSIt->start; + + // If the live intervals overlap, there are two interesting cases: if the + // LHS interval is defined by a copy from the RHS, it's ok and we record + // that the LHS value # is the same as the RHS. If it's not, then we cannot + // coallesce these live ranges and we bail out. + if (Overlaps) { + // If we haven't already recorded that this value # is safe, check it. + if (!InVector(LHSIt->ValId, EliminatedLHSVals)) { + // Copy from the RHS? + unsigned SrcReg = LHS.getSrcRegForValNum(LHSIt->ValId); + if (rep(SrcReg) != RHS.reg) + return false; // Nope, bail out. + + EliminatedLHSVals.push_back(LHSIt->ValId); + } + + // We know this entire LHS live range is okay, so skip it now. + if (++LHSIt == LHSEnd) break; + continue; + } + + if (LHSIt->end < RHSIt->end) { + if (++LHSIt == LHSEnd) break; + } else { + // One interesting case to check here. It's possible that we have + // something like "X3 = Y" which defines a new value number in the LHS, + // and is the last use of this liverange of the RHS. In this case, we + // want to notice this copy (so that it gets coallesced away) even though + // the live ranges don't actually overlap. + if (LHSIt->start == RHSIt->end) { + if (InVector(LHSIt->ValId, EliminatedLHSVals)) { + // We already know that this value number is going to be merged in + // if coallescing succeeds. Just skip the liverange. + if (++LHSIt == LHSEnd) break; + } else { + // Otherwise, if this is a copy from the RHS, mark it as being merged + // in. + if (rep(LHS.getSrcRegForValNum(LHSIt->ValId)) == RHS.reg) { + EliminatedLHSVals.push_back(LHSIt->ValId); + + // We know this entire LHS live range is okay, so skip it now. + if (++LHSIt == LHSEnd) break; + } + } + } + + if (++RHSIt == RHSEnd) break; + } + } + + // If we got here, we know that the coallescing will be successful and that + // the value numbers in EliminatedLHSVals will all be merged together. Since + // the most common case is that EliminatedLHSVals has a single number, we + // optimize for it: if there is more than one value, we merge them all into + // the lowest numbered one, then handle the interval as if we were merging + // with one value number. + unsigned LHSValNo; + if (EliminatedLHSVals.size() > 1) { + // Loop through all the equal value numbers merging them into the smallest + // one. + unsigned Smallest = EliminatedLHSVals[0]; + for (unsigned i = 1, e = EliminatedLHSVals.size(); i != e; ++i) { + if (EliminatedLHSVals[i] < Smallest) { + // Merge the current notion of the smallest into the smaller one. + LHS.MergeValueNumberInto(Smallest, EliminatedLHSVals[i]); + Smallest = EliminatedLHSVals[i]; + } else { + // Merge into the smallest. + LHS.MergeValueNumberInto(EliminatedLHSVals[i], Smallest); + } + } + LHSValNo = Smallest; + } else { + assert(!EliminatedLHSVals.empty() && "No copies from the RHS?"); + LHSValNo = EliminatedLHSVals[0]; + } + + // Okay, now that there is a single LHS value number that we're merging the + // RHS into, update the value number info for the LHS to indicate that the + // value number is defined where the RHS value number was. + LHS.setValueNumberInfo(LHSValNo, RHS.getValNumInfo(0)); + + // Okay, the final step is to loop over the RHS live intervals, adding them to + // the LHS. + LHS.MergeRangesInAsValue(RHS, LHSValNo); + LHS.weight += RHS.weight; + if (RHS.preference && !LHS.preference) + LHS.preference = RHS.preference; + + return true; + } + + /// JoinIntervals - Attempt to join these two intervals. On failure, this + /// returns false. Otherwise, if one of the intervals being joined is a + /// physreg, this method always canonicalizes LHS to be it. The output + /// "RHS" will not have been modified, so we can use this information + /// below to update aliases. + bool SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS) { + // Compute the final value assignment, assuming that the live ranges can be + // coallesced. + SmallVector LHSValNoAssignments; + SmallVector RHSValNoAssignments; + SmallVector, 16> ValueNumberInfo; + + // If a live interval is a physical register, conservatively check if any + // of its sub-registers is overlapping the live interval of the virtual + // register. If so, do not coalesce. + if (MRegisterInfo::isPhysicalRegister(LHS.reg) && + *mri_->getSubRegisters(LHS.reg)) { + for (const unsigned* SR = mri_->getSubRegisters(LHS.reg); *SR; ++SR) + if (li_->hasInterval(*SR) && RHS.overlaps(li_->getInterval(*SR))) { + DOUT << "Interfere with sub-register "; + DEBUG(li_->getInterval(*SR).print(DOUT, mri_)); + return false; + } + } else if (MRegisterInfo::isPhysicalRegister(RHS.reg) && + *mri_->getSubRegisters(RHS.reg)) { + for (const unsigned* SR = mri_->getSubRegisters(RHS.reg); *SR; ++SR) + if (li_->hasInterval(*SR) && LHS.overlaps(li_->getInterval(*SR))) { + DOUT << "Interfere with sub-register "; + DEBUG(li_->getInterval(*SR).print(DOUT, mri_)); + return false; + } + } + + // Compute ultimate value numbers for the LHS and RHS values. + if (RHS.containsOneValue()) { + // Copies from a liveinterval with a single value are simple to handle and + // very common, handle the special case here. This is important, because + // often RHS is small and LHS is large (e.g. a physreg). + + // Find out if the RHS is defined as a copy from some value in the LHS. + int RHSValID = -1; + std::pair RHSValNoInfo; + unsigned RHSSrcReg = RHS.getSrcRegForValNum(0); + if ((RHSSrcReg == 0 || rep(RHSSrcReg) != LHS.reg)) { + // If RHS is not defined as a copy from the LHS, we can use simpler and + // faster checks to see if the live ranges are coallescable. This joiner + // can't swap the LHS/RHS intervals though. + if (!MRegisterInfo::isPhysicalRegister(RHS.reg)) { + return SimpleJoin(LHS, RHS); + } else { + RHSValNoInfo = RHS.getValNumInfo(0); + } + } else { + // It was defined as a copy from the LHS, find out what value # it is. + unsigned ValInst = RHS.getInstForValNum(0); + RHSValID = LHS.getLiveRangeContaining(ValInst-1)->ValId; + RHSValNoInfo = LHS.getValNumInfo(RHSValID); + } + + LHSValNoAssignments.resize(LHS.getNumValNums(), -1); + RHSValNoAssignments.resize(RHS.getNumValNums(), -1); + ValueNumberInfo.resize(LHS.getNumValNums()); + + // Okay, *all* of the values in LHS that are defined as a copy from RHS + // should now get updated. + for (unsigned VN = 0, e = LHS.getNumValNums(); VN != e; ++VN) { + if (unsigned LHSSrcReg = LHS.getSrcRegForValNum(VN)) { + if (rep(LHSSrcReg) != RHS.reg) { + // If this is not a copy from the RHS, its value number will be + // unmodified by the coallescing. + ValueNumberInfo[VN] = LHS.getValNumInfo(VN); + LHSValNoAssignments[VN] = VN; + } else if (RHSValID == -1) { + // Otherwise, it is a copy from the RHS, and we don't already have a + // value# for it. Keep the current value number, but remember it. + LHSValNoAssignments[VN] = RHSValID = VN; + ValueNumberInfo[VN] = RHSValNoInfo; + } else { + // Otherwise, use the specified value #. + LHSValNoAssignments[VN] = RHSValID; + if (VN != (unsigned)RHSValID) + ValueNumberInfo[VN].first = ~1U; + else + ValueNumberInfo[VN] = RHSValNoInfo; + } + } else { + ValueNumberInfo[VN] = LHS.getValNumInfo(VN); + LHSValNoAssignments[VN] = VN; + } + } + + assert(RHSValID != -1 && "Didn't find value #?"); + RHSValNoAssignments[0] = RHSValID; + + } else { + // Loop over the value numbers of the LHS, seeing if any are defined from + // the RHS. + SmallVector LHSValsDefinedFromRHS; + LHSValsDefinedFromRHS.resize(LHS.getNumValNums(), -1); + for (unsigned VN = 0, e = LHS.getNumValNums(); VN != e; ++VN) { + unsigned ValSrcReg = LHS.getSrcRegForValNum(VN); + if (ValSrcReg == 0) // Src not defined by a copy? + continue; + + // DstReg is known to be a register in the LHS interval. If the src is + // from the RHS interval, we can use its value #. + if (rep(ValSrcReg) != RHS.reg) + continue; + + // Figure out the value # from the RHS. + unsigned ValInst = LHS.getInstForValNum(VN); + LHSValsDefinedFromRHS[VN] = RHS.getLiveRangeContaining(ValInst-1)->ValId; + } + + // Loop over the value numbers of the RHS, seeing if any are defined from + // the LHS. + SmallVector RHSValsDefinedFromLHS; + RHSValsDefinedFromLHS.resize(RHS.getNumValNums(), -1); + for (unsigned VN = 0, e = RHS.getNumValNums(); VN != e; ++VN) { + unsigned ValSrcReg = RHS.getSrcRegForValNum(VN); + if (ValSrcReg == 0) // Src not defined by a copy? + continue; + + // DstReg is known to be a register in the RHS interval. If the src is + // from the LHS interval, we can use its value #. + if (rep(ValSrcReg) != LHS.reg) + continue; + + // Figure out the value # from the LHS. + unsigned ValInst = RHS.getInstForValNum(VN); + RHSValsDefinedFromLHS[VN] = LHS.getLiveRangeContaining(ValInst-1)->ValId; + } + + LHSValNoAssignments.resize(LHS.getNumValNums(), -1); + RHSValNoAssignments.resize(RHS.getNumValNums(), -1); + ValueNumberInfo.reserve(LHS.getNumValNums() + RHS.getNumValNums()); + + for (unsigned VN = 0, e = LHS.getNumValNums(); VN != e; ++VN) { + if (LHSValNoAssignments[VN] >= 0 || LHS.getInstForValNum(VN) == ~2U) + continue; + ComputeUltimateVN(VN, ValueNumberInfo, + LHSValsDefinedFromRHS, RHSValsDefinedFromLHS, + LHSValNoAssignments, RHSValNoAssignments, LHS, RHS); + } + for (unsigned VN = 0, e = RHS.getNumValNums(); VN != e; ++VN) { + if (RHSValNoAssignments[VN] >= 0 || RHS.getInstForValNum(VN) == ~2U) + continue; + // If this value number isn't a copy from the LHS, it's a new number. + if (RHSValsDefinedFromLHS[VN] == -1) { + ValueNumberInfo.push_back(RHS.getValNumInfo(VN)); + RHSValNoAssignments[VN] = ValueNumberInfo.size()-1; + continue; + } + + ComputeUltimateVN(VN, ValueNumberInfo, + RHSValsDefinedFromLHS, LHSValsDefinedFromRHS, + RHSValNoAssignments, LHSValNoAssignments, RHS, LHS); + } + } + + // Armed with the mappings of LHS/RHS values to ultimate values, walk the + // interval lists to see if these intervals are coallescable. + LiveInterval::const_iterator I = LHS.begin(); + LiveInterval::const_iterator IE = LHS.end(); + LiveInterval::const_iterator J = RHS.begin(); + LiveInterval::const_iterator JE = RHS.end(); + + // Skip ahead until the first place of potential sharing. + if (I->start < J->start) { + I = std::upper_bound(I, IE, J->start); + if (I != LHS.begin()) --I; + } else if (J->start < I->start) { + J = std::upper_bound(J, JE, I->start); + if (J != RHS.begin()) --J; + } + + while (1) { + // Determine if these two live ranges overlap. + bool Overlaps; + if (I->start < J->start) { + Overlaps = I->end > J->start; + } else { + Overlaps = J->end > I->start; + } + + // If so, check value # info to determine if they are really different. + if (Overlaps) { + // If the live range overlap will map to the same value number in the + // result liverange, we can still coallesce them. If not, we can't. + if (LHSValNoAssignments[I->ValId] != RHSValNoAssignments[J->ValId]) + return false; + } + + if (I->end < J->end) { + ++I; + if (I == IE) break; + } else { + ++J; + if (J == JE) break; + } + } + + // If we get here, we know that we can coallesce the live ranges. Ask the + // intervals to coallesce themselves now. + LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], + ValueNumberInfo); + return true; + } + + namespace { + // DepthMBBCompare - Comparison predicate that sort first based on the loop + // depth of the basic block (the unsigned), and then on the MBB number. + struct DepthMBBCompare { + typedef std::pair DepthMBBPair; + bool operator()(const DepthMBBPair &LHS, const DepthMBBPair &RHS) const { + if (LHS.first > RHS.first) return true; // Deeper loops first + return LHS.first == RHS.first && + LHS.second->getNumber() < RHS.second->getNumber(); + } + }; + } + + void SimpleRegisterCoalescing::CopyCoallesceInMBB(MachineBasicBlock *MBB, + std::vector *TryAgain, bool PhysOnly) { + DOUT << ((Value*)MBB->getBasicBlock())->getName() << ":\n"; + + for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end(); + MII != E;) { + MachineInstr *Inst = MII++; + + // If this isn't a copy, we can't join intervals. + unsigned SrcReg, DstReg; + if (!tii_->isMoveInstr(*Inst, SrcReg, DstReg)) continue; + + if (TryAgain && !JoinCopy(Inst, SrcReg, DstReg, PhysOnly)) + TryAgain->push_back(getCopyRec(Inst, SrcReg, DstReg)); + } + } + + void SimpleRegisterCoalescing::joinIntervals() { + DOUT << "********** JOINING INTERVALS ***********\n"; + + JoinedLIs.resize(li_->getNumIntervals()); + JoinedLIs.reset(); + + std::vector TryAgainList; + const LoopInfo &LI = getAnalysis(); + if (LI.begin() == LI.end()) { + // If there are no loops in the function, join intervals in function order. + for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); + I != E; ++I) + CopyCoallesceInMBB(I, &TryAgainList); + } else { + // Otherwise, join intervals in inner loops before other intervals. + // Unfortunately we can't just iterate over loop hierarchy here because + // there may be more MBB's than BB's. Collect MBB's for sorting. + + // Join intervals in the function prolog first. We want to join physical + // registers with virtual registers before the intervals got too long. + std::vector > MBBs; + for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); I != E;++I) + MBBs.push_back(std::make_pair(LI.getLoopDepth(I->getBasicBlock()), I)); + + // Sort by loop depth. + std::sort(MBBs.begin(), MBBs.end(), DepthMBBCompare()); + + // Finally, join intervals in loop nest order. + for (unsigned i = 0, e = MBBs.size(); i != e; ++i) + CopyCoallesceInMBB(MBBs[i].second, NULL, true); + for (unsigned i = 0, e = MBBs.size(); i != e; ++i) + CopyCoallesceInMBB(MBBs[i].second, &TryAgainList, false); + } + + // Joining intervals can allow other intervals to be joined. Iteratively join + // until we make no progress. + bool ProgressMade = true; + while (ProgressMade) { + ProgressMade = false; + + for (unsigned i = 0, e = TryAgainList.size(); i != e; ++i) { + CopyRec &TheCopy = TryAgainList[i]; + if (TheCopy.MI && + JoinCopy(TheCopy.MI, TheCopy.SrcReg, TheCopy.DstReg)) { + TheCopy.MI = 0; // Mark this one as done. + ProgressMade = true; + } + } + } + + // Some live range has been lengthened due to colaescing, eliminate the + // unnecessary kills. + int RegNum = JoinedLIs.find_first(); + while (RegNum != -1) { + unsigned Reg = RegNum + MRegisterInfo::FirstVirtualRegister; + unsigned repReg = rep(Reg); + LiveInterval &LI = li_->getInterval(repReg); + LiveVariables::VarInfo& svi = lv_->getVarInfo(Reg); + for (unsigned i = 0, e = svi.Kills.size(); i != e; ++i) { + MachineInstr *Kill = svi.Kills[i]; + // Suppose vr1 = op vr2, x + // and vr1 and vr2 are coalesced. vr2 should still be marked kill + // unless it is a two-address operand. + if (li_->isRemoved(Kill) || hasRegisterDef(Kill, repReg)) + continue; + if (LI.liveAt(li_->getInstructionIndex(Kill) + InstrSlots::NUM)) + unsetRegisterKill(Kill, repReg); + } + RegNum = JoinedLIs.find_next(RegNum); + } + + DOUT << "*** Register mapping ***\n"; + for (int i = 0, e = r2rMap_.size(); i != e; ++i) + if (r2rMap_[i]) { + DOUT << " reg " << i << " -> "; + DEBUG(printRegName(r2rMap_[i])); + DOUT << "\n"; + } + } + + /// Return true if the two specified registers belong to different register + /// classes. The registers may be either phys or virt regs. + bool SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA, + unsigned RegB) const { + + // Get the register classes for the first reg. + if (MRegisterInfo::isPhysicalRegister(RegA)) { + assert(MRegisterInfo::isVirtualRegister(RegB) && + "Shouldn't consider two physregs!"); + return !mf_->getSSARegMap()->getRegClass(RegB)->contains(RegA); + } + + // Compare against the regclass for the second reg. + const TargetRegisterClass *RegClass = mf_->getSSARegMap()->getRegClass(RegA); + if (MRegisterInfo::isVirtualRegister(RegB)) + return RegClass != mf_->getSSARegMap()->getRegClass(RegB); + else + return !RegClass->contains(RegB); + } + + /// lastRegisterUse - Returns the last use of the specific register between + /// cycles Start and End. It also returns the use operand by reference. It + /// returns NULL if there are no uses. + MachineInstr * + SimpleRegisterCoalescing::lastRegisterUse(unsigned Start, unsigned End, unsigned Reg, + MachineOperand *&MOU) { + int e = (End-1) / InstrSlots::NUM * InstrSlots::NUM; + int s = Start; + while (e >= s) { + // Skip deleted instructions + MachineInstr *MI = li_->getInstructionFromIndex(e); + while ((e - InstrSlots::NUM) >= s && !MI) { + e -= InstrSlots::NUM; + MI = li_->getInstructionFromIndex(e); + } + if (e < s || MI == NULL) + return NULL; + + for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isUse() && MO.getReg() && + mri_->regsOverlap(rep(MO.getReg()), Reg)) { + MOU = &MO; + return MI; + } + } + + e -= InstrSlots::NUM; + } + + return NULL; + } + + + /// findDefOperand - Returns the MachineOperand that is a def of the specific + /// register. It returns NULL if the def is not found. + MachineOperand *SimpleRegisterCoalescing::findDefOperand(MachineInstr *MI, unsigned Reg) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && + mri_->regsOverlap(rep(MO.getReg()), Reg)) + return &MO; + } + return NULL; + } + + /// unsetRegisterKill - Unset IsKill property of all uses of specific register + /// of the specific instruction. + void SimpleRegisterCoalescing::unsetRegisterKill(MachineInstr *MI, unsigned Reg) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isUse() && MO.isKill() && MO.getReg() && + mri_->regsOverlap(rep(MO.getReg()), Reg)) + MO.unsetIsKill(); + } + } + + /// unsetRegisterKills - Unset IsKill property of all uses of specific register + /// between cycles Start and End. + void SimpleRegisterCoalescing::unsetRegisterKills(unsigned Start, unsigned End, + unsigned Reg) { + int e = (End-1) / InstrSlots::NUM * InstrSlots::NUM; + int s = Start; + while (e >= s) { + // Skip deleted instructions + MachineInstr *MI = li_->getInstructionFromIndex(e); + while ((e - InstrSlots::NUM) >= s && !MI) { + e -= InstrSlots::NUM; + MI = li_->getInstructionFromIndex(e); + } + if (e < s || MI == NULL) + return; + + for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isUse() && MO.isKill() && MO.getReg() && + mri_->regsOverlap(rep(MO.getReg()), Reg)) { + MO.unsetIsKill(); + } + } + + e -= InstrSlots::NUM; + } + } + + /// hasRegisterDef - True if the instruction defines the specific register. + /// + bool SimpleRegisterCoalescing::hasRegisterDef(MachineInstr *MI, unsigned Reg) { + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && + mri_->regsOverlap(rep(MO.getReg()), Reg)) + return true; + } + return false; + } + + void SimpleRegisterCoalescing::printRegName(unsigned reg) const { + if (MRegisterInfo::isPhysicalRegister(reg)) + cerr << mri_->getName(reg); + else + cerr << "%reg" << reg; + } + + void SimpleRegisterCoalescing::releaseMemory() { + r2rMap_.clear(); + JoinedLIs.clear(); + } + + static bool isZeroLengthInterval(LiveInterval *li) { + for (LiveInterval::Ranges::const_iterator + i = li->ranges.begin(), e = li->ranges.end(); i != e; ++i) + if (i->end - i->start > LiveIntervals::InstrSlots::NUM) + return false; + return true; + } + + bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { + mf_ = &fn; + tm_ = &fn.getTarget(); + mri_ = tm_->getRegisterInfo(); + tii_ = tm_->getInstrInfo(); + li_ = &getAnalysis(); + lv_ = &getAnalysis(); + + DOUT << "********** SIMPLE REGISTER COALESCING **********\n" + << "********** Function: " + << ((Value*)mf_->getFunction())->getName() << '\n'; + + allocatableRegs_ = mri_->getAllocatableSet(fn); + for (MRegisterInfo::regclass_iterator I = mri_->regclass_begin(), + E = mri_->regclass_end(); I != E; ++I) + allocatableRCRegs_.insert(std::make_pair(*I,mri_->getAllocatableSet(fn, *I))); + + r2rMap_.grow(mf_->getSSARegMap()->getLastVirtReg()); + + // Join (coallesce) intervals if requested. + if (EnableJoining) { + joinIntervals(); + DOUT << "********** INTERVALS POST JOINING **********\n"; + for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); I != E; ++I) { + I->second.print(DOUT, mri_); + DOUT << "\n"; + } + } + + // perform a final pass over the instructions and compute spill + // weights, coalesce virtual registers and remove identity moves. + const LoopInfo &loopInfo = getAnalysis(); + + for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); + mbbi != mbbe; ++mbbi) { + MachineBasicBlock* mbb = mbbi; + unsigned loopDepth = loopInfo.getLoopDepth(mbb->getBasicBlock()); + + for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); + mii != mie; ) { + // if the move will be an identity move delete it + unsigned srcReg, dstReg, RegRep; + if (tii_->isMoveInstr(*mii, srcReg, dstReg) && + (RegRep = rep(srcReg)) == rep(dstReg)) { + // remove from def list + LiveInterval &RegInt = li_->getOrCreateInterval(RegRep); + MachineOperand *MO = mii->findRegisterDefOperand(dstReg); + // If def of this move instruction is dead, remove its live range from + // the dstination register's live interval. + if (MO->isDead()) { + unsigned MoveIdx = li_->getDefIndex(li_->getInstructionIndex(mii)); + LiveInterval::iterator MLR = RegInt.FindLiveRangeContaining(MoveIdx); + RegInt.removeRange(MLR->start, MoveIdx+1); + if (RegInt.empty()) + li_->removeInterval(RegRep); + } + li_->RemoveMachineInstrFromMaps(mii); + mii = mbbi->erase(mii); + ++numPeep; + } else { + SmallSet UniqueUses; + for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) { + const MachineOperand &mop = mii->getOperand(i); + if (mop.isRegister() && mop.getReg() && + MRegisterInfo::isVirtualRegister(mop.getReg())) { + // replace register with representative register + unsigned reg = rep(mop.getReg()); + mii->getOperand(i).setReg(reg); + + // Multiple uses of reg by the same instruction. It should not + // contribute to spill weight again. + if (UniqueUses.count(reg) != 0) + continue; + LiveInterval &RegInt = li_->getInterval(reg); + float w = (mop.isUse()+mop.isDef()) * powf(10.0F, (float)loopDepth); + // If the definition instruction is re-materializable, its spill + // weight is half of what it would have been normally unless it's + // a load from fixed stack slot. + int Dummy; + if (RegInt.remat && !tii_->isLoadFromStackSlot(RegInt.remat, Dummy)) + w /= 2; + RegInt.weight += w; + UniqueUses.insert(reg); + } + } + ++mii; + } + } + } + + for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); I != E; ++I) { + LiveInterval &LI = I->second; + if (MRegisterInfo::isVirtualRegister(LI.reg)) { + // If the live interval length is essentially zero, i.e. in every live + // range the use follows def immediately, it doesn't make sense to spill + // it and hope it will be easier to allocate for this li. + if (isZeroLengthInterval(&LI)) + LI.weight = HUGE_VALF; + + // Slightly prefer live interval that has been assigned a preferred reg. + if (LI.preference) + LI.weight *= 1.01F; + + // Divide the weight of the interval by its size. This encourages + // spilling of intervals that are large and have few uses, and + // discourages spilling of small intervals with many uses. + LI.weight /= LI.getSize(); + } + } + + DEBUG(dump()); + return true; + } + + /// print - Implement the dump method. + void SimpleRegisterCoalescing::print(std::ostream &O, const Module* m) const { + li_->print(O, m); + } Index: llvm/lib/CodeGen/RegAllocLinearScan.cpp diff -u llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.149 llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.150 --- llvm/lib/CodeGen/RegAllocLinearScan.cpp:1.149 Tue May 8 14:02:46 2007 +++ llvm/lib/CodeGen/RegAllocLinearScan.cpp Fri Jun 8 12:18:56 2007 @@ -96,6 +96,7 @@ virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); + AU.addRequiredID(SimpleRegisterCoalescingID); MachineFunctionPass::getAnalysisUsage(AU); } Index: llvm/lib/CodeGen/LiveIntervalAnalysis.cpp diff -u llvm/lib/CodeGen/LiveIntervalAnalysis.cpp:1.245 llvm/lib/CodeGen/LiveIntervalAnalysis.cpp:1.246 --- llvm/lib/CodeGen/LiveIntervalAnalysis.cpp:1.245 Mon May 14 16:23:51 2007 +++ llvm/lib/CodeGen/LiveIntervalAnalysis.cpp Fri Jun 8 12:18:56 2007 @@ -39,22 +39,15 @@ STATISTIC(numIntervals, "Number of original intervals"); STATISTIC(numIntervalsAfter, "Number of intervals after coalescing"); -STATISTIC(numJoins , "Number of interval joins performed"); -STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); STATISTIC(numFolded , "Number of loads/stores folded into instructions"); -STATISTIC(numAborts , "Number of times interval joining aborted"); char LiveIntervals::ID = 0; namespace { RegisterPass X("liveintervals", "Live Interval Analysis"); - - static cl::opt - EnableJoining("join-liveintervals", - cl::desc("Coallesce copies (default=true)"), - cl::init(true)); } void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); AU.addRequired(); AU.addPreservedID(PHIEliminationID); AU.addRequiredID(PHIEliminationID); @@ -67,20 +60,8 @@ mi2iMap_.clear(); i2miMap_.clear(); r2iMap_.clear(); - r2rMap_.clear(); - JoinedLIs.clear(); -} - - -static bool isZeroLengthInterval(LiveInterval *li) { - for (LiveInterval::Ranges::const_iterator - i = li->ranges.begin(), e = li->ranges.end(); i != e; ++i) - if (i->end - i->start > LiveIntervals::InstrSlots::NUM) - return false; - return true; } - /// runOnMachineFunction - Register allocate the whole function /// bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { @@ -89,11 +70,7 @@ mri_ = tm_->getRegisterInfo(); tii_ = tm_->getInstrInfo(); lv_ = &getAnalysis(); - r2rMap_.grow(mf_->getSSARegMap()->getLastVirtReg()); allocatableRegs_ = mri_->getAllocatableSet(fn); - for (MRegisterInfo::regclass_iterator I = mri_->regclass_begin(), - E = mri_->regclass_end(); I != E; ++I) - allocatableRCRegs_.insert(std::make_pair(*I,mri_->getAllocatableSet(fn, *I))); // Number MachineInstrs and MachineBasicBlocks. // Initialize MBB indexes to a sentinal. @@ -124,99 +101,7 @@ DOUT << "\n"; } - // Join (coallesce) intervals if requested. - if (EnableJoining) { - joinIntervals(); - DOUT << "********** INTERVALS POST JOINING **********\n"; - for (iterator I = begin(), E = end(); I != E; ++I) { - I->second.print(DOUT, mri_); - DOUT << "\n"; - } - } - numIntervalsAfter += getNumIntervals(); - - // perform a final pass over the instructions and compute spill - // weights, coalesce virtual registers and remove identity moves. - const LoopInfo &loopInfo = getAnalysis(); - - for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); - mbbi != mbbe; ++mbbi) { - MachineBasicBlock* mbb = mbbi; - unsigned loopDepth = loopInfo.getLoopDepth(mbb->getBasicBlock()); - - for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); - mii != mie; ) { - // if the move will be an identity move delete it - unsigned srcReg, dstReg, RegRep; - if (tii_->isMoveInstr(*mii, srcReg, dstReg) && - (RegRep = rep(srcReg)) == rep(dstReg)) { - // remove from def list - LiveInterval &RegInt = getOrCreateInterval(RegRep); - MachineOperand *MO = mii->findRegisterDefOperand(dstReg); - // If def of this move instruction is dead, remove its live range from - // the dstination register's live interval. - if (MO->isDead()) { - unsigned MoveIdx = getDefIndex(getInstructionIndex(mii)); - LiveInterval::iterator MLR = RegInt.FindLiveRangeContaining(MoveIdx); - RegInt.removeRange(MLR->start, MoveIdx+1); - if (RegInt.empty()) - removeInterval(RegRep); - } - RemoveMachineInstrFromMaps(mii); - mii = mbbi->erase(mii); - ++numPeep; - } else { - SmallSet UniqueUses; - for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) { - const MachineOperand &mop = mii->getOperand(i); - if (mop.isRegister() && mop.getReg() && - MRegisterInfo::isVirtualRegister(mop.getReg())) { - // replace register with representative register - unsigned reg = rep(mop.getReg()); - mii->getOperand(i).setReg(reg); - - // Multiple uses of reg by the same instruction. It should not - // contribute to spill weight again. - if (UniqueUses.count(reg) != 0) - continue; - LiveInterval &RegInt = getInterval(reg); - float w = (mop.isUse()+mop.isDef()) * powf(10.0F, (float)loopDepth); - // If the definition instruction is re-materializable, its spill - // weight is half of what it would have been normally unless it's - // a load from fixed stack slot. - int Dummy; - if (RegInt.remat && !tii_->isLoadFromStackSlot(RegInt.remat, Dummy)) - w /= 2; - RegInt.weight += w; - UniqueUses.insert(reg); - } - } - ++mii; - } - } - } - - for (iterator I = begin(), E = end(); I != E; ++I) { - LiveInterval &LI = I->second; - if (MRegisterInfo::isVirtualRegister(LI.reg)) { - // If the live interval length is essentially zero, i.e. in every live - // range the use follows def immediately, it doesn't make sense to spill - // it and hope it will be easier to allocate for this li. - if (isZeroLengthInterval(&LI)) - LI.weight = HUGE_VALF; - - // Slightly prefer live interval that has been assigned a preferred reg. - if (LI.preference) - LI.weight *= 1.01F; - - // Divide the weight of the interval by its size. This encourages - // spilling of intervals that are large and have few uses, and - // discourages spilling of small intervals with many uses. - LI.weight /= LI.getSize(); - } - } - DEBUG(dump()); return true; } @@ -240,6 +125,7 @@ } } +// Not called? /// CreateNewLiveInterval - Create a new live interval with the given live /// ranges. The new live interval will have an infinite spill weight. LiveInterval& @@ -268,7 +154,7 @@ for (unsigned J = 0, e = MI->getNumOperands(); J != e; ++J) { MachineOperand &MOp = MI->getOperand(J); - if (MOp.isRegister() && rep(MOp.getReg()) == LI->reg) + if (MOp.isRegister() && MOp.getReg() == LI->reg) MOp.setReg(NewVReg); } } @@ -794,944 +680,6 @@ } } -/// AdjustCopiesBackFrom - We found a non-trivially-coallescable copy with IntA -/// being the source and IntB being the dest, thus this defines a value number -/// in IntB. If the source value number (in IntA) is defined by a copy from B, -/// see if we can merge these two pieces of B into a single value number, -/// eliminating a copy. For example: -/// -/// A3 = B0 -/// ... -/// B1 = A3 <- this copy -/// -/// In this case, B0 can be extended to where the B1 copy lives, allowing the B1 -/// value number to be replaced with B0 (which simplifies the B liveinterval). -/// -/// This returns true if an interval was modified. -/// -bool LiveIntervals::AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB, - MachineInstr *CopyMI) { - unsigned CopyIdx = getDefIndex(getInstructionIndex(CopyMI)); - - // BValNo is a value number in B that is defined by a copy from A. 'B3' in - // the example above. - LiveInterval::iterator BLR = IntB.FindLiveRangeContaining(CopyIdx); - unsigned BValNo = BLR->ValId; - - // Get the location that B is defined at. Two options: either this value has - // an unknown definition point or it is defined at CopyIdx. If unknown, we - // can't process it. - unsigned BValNoDefIdx = IntB.getInstForValNum(BValNo); - if (BValNoDefIdx == ~0U) return false; - assert(BValNoDefIdx == CopyIdx && - "Copy doesn't define the value?"); - - // AValNo is the value number in A that defines the copy, A0 in the example. - LiveInterval::iterator AValLR = IntA.FindLiveRangeContaining(CopyIdx-1); - unsigned AValNo = AValLR->ValId; - - // If AValNo is defined as a copy from IntB, we can potentially process this. - - // Get the instruction that defines this value number. - unsigned SrcReg = IntA.getSrcRegForValNum(AValNo); - if (!SrcReg) return false; // Not defined by a copy. - - // If the value number is not defined by a copy instruction, ignore it. - - // If the source register comes from an interval other than IntB, we can't - // handle this. - if (rep(SrcReg) != IntB.reg) return false; - - // Get the LiveRange in IntB that this value number starts with. - unsigned AValNoInstIdx = IntA.getInstForValNum(AValNo); - LiveInterval::iterator ValLR = IntB.FindLiveRangeContaining(AValNoInstIdx-1); - - // Make sure that the end of the live range is inside the same block as - // CopyMI. - MachineInstr *ValLREndInst = getInstructionFromIndex(ValLR->end-1); - if (!ValLREndInst || - ValLREndInst->getParent() != CopyMI->getParent()) return false; - - // Okay, we now know that ValLR ends in the same block that the CopyMI - // live-range starts. If there are no intervening live ranges between them in - // IntB, we can merge them. - if (ValLR+1 != BLR) return false; - - DOUT << "\nExtending: "; IntB.print(DOUT, mri_); - - // We are about to delete CopyMI, so need to remove it as the 'instruction - // that defines this value #'. - IntB.setValueNumberInfo(BValNo, std::make_pair(~0U, 0)); - - // Okay, we can merge them. We need to insert a new liverange: - // [ValLR.end, BLR.begin) of either value number, then we merge the - // two value numbers. - unsigned FillerStart = ValLR->end, FillerEnd = BLR->start; - IntB.addRange(LiveRange(FillerStart, FillerEnd, BValNo)); - - // If the IntB live range is assigned to a physical register, and if that - // physreg has aliases, - if (MRegisterInfo::isPhysicalRegister(IntB.reg)) { - // Update the liveintervals of sub-registers. - for (const unsigned *AS = mri_->getSubRegisters(IntB.reg); *AS; ++AS) { - LiveInterval &AliasLI = getInterval(*AS); - AliasLI.addRange(LiveRange(FillerStart, FillerEnd, - AliasLI.getNextValue(~0U, 0))); - } - } - - // Okay, merge "B1" into the same value number as "B0". - if (BValNo != ValLR->ValId) - IntB.MergeValueNumberInto(BValNo, ValLR->ValId); - DOUT << " result = "; IntB.print(DOUT, mri_); - DOUT << "\n"; - - // If the source instruction was killing the source register before the - // merge, unset the isKill marker given the live range has been extended. - int UIdx = ValLREndInst->findRegisterUseOperandIdx(IntB.reg, true); - if (UIdx != -1) - ValLREndInst->getOperand(UIdx).unsetIsKill(); - - // Finally, delete the copy instruction. - RemoveMachineInstrFromMaps(CopyMI); - CopyMI->eraseFromParent(); - ++numPeep; - return true; -} - - -/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, -/// which are the src/dst of the copy instruction CopyMI. This returns true -/// if the copy was successfully coallesced away, or if it is never possible -/// to coallesce this copy, due to register constraints. It returns -/// false if it is not currently possible to coallesce this interval, but -/// it may be possible if other things get coallesced. -bool LiveIntervals::JoinCopy(MachineInstr *CopyMI, - unsigned SrcReg, unsigned DstReg, bool PhysOnly) { - DOUT << getInstructionIndex(CopyMI) << '\t' << *CopyMI; - - // Get representative registers. - unsigned repSrcReg = rep(SrcReg); - unsigned repDstReg = rep(DstReg); - - // If they are already joined we continue. - if (repSrcReg == repDstReg) { - DOUT << "\tCopy already coallesced.\n"; - return true; // Not coallescable. - } - - bool SrcIsPhys = MRegisterInfo::isPhysicalRegister(repSrcReg); - bool DstIsPhys = MRegisterInfo::isPhysicalRegister(repDstReg); - if (PhysOnly && !SrcIsPhys && !DstIsPhys) - // Only joining physical registers with virtual registers in this round. - return true; - - // If they are both physical registers, we cannot join them. - if (SrcIsPhys && DstIsPhys) { - DOUT << "\tCan not coallesce physregs.\n"; - return true; // Not coallescable. - } - - // We only join virtual registers with allocatable physical registers. - if (SrcIsPhys && !allocatableRegs_[repSrcReg]) { - DOUT << "\tSrc reg is unallocatable physreg.\n"; - return true; // Not coallescable. - } - if (DstIsPhys && !allocatableRegs_[repDstReg]) { - DOUT << "\tDst reg is unallocatable physreg.\n"; - return true; // Not coallescable. - } - - // If they are not of the same register class, we cannot join them. - if (differingRegisterClasses(repSrcReg, repDstReg)) { - DOUT << "\tSrc/Dest are different register classes.\n"; - return true; // Not coallescable. - } - - LiveInterval &SrcInt = getInterval(repSrcReg); - LiveInterval &DstInt = getInterval(repDstReg); - assert(SrcInt.reg == repSrcReg && DstInt.reg == repDstReg && - "Register mapping is horribly broken!"); - - DOUT << "\t\tInspecting "; SrcInt.print(DOUT, mri_); - DOUT << " and "; DstInt.print(DOUT, mri_); - DOUT << ": "; - - // Check if it is necessary to propagate "isDead" property before intervals - // are joined. - MachineOperand *mopd = CopyMI->findRegisterDefOperand(DstReg); - bool isDead = mopd->isDead(); - bool isShorten = false; - unsigned SrcStart = 0, RemoveStart = 0; - unsigned SrcEnd = 0, RemoveEnd = 0; - if (isDead) { - unsigned CopyIdx = getInstructionIndex(CopyMI); - LiveInterval::iterator SrcLR = - SrcInt.FindLiveRangeContaining(getUseIndex(CopyIdx)); - RemoveStart = SrcStart = SrcLR->start; - RemoveEnd = SrcEnd = SrcLR->end; - // The instruction which defines the src is only truly dead if there are - // no intermediate uses and there isn't a use beyond the copy. - // FIXME: find the last use, mark is kill and shorten the live range. - if (SrcEnd > getDefIndex(CopyIdx)) { - isDead = false; - } else { - MachineOperand *MOU; - MachineInstr *LastUse= lastRegisterUse(SrcStart, CopyIdx, repSrcReg, MOU); - if (LastUse) { - // Shorten the liveinterval to the end of last use. - MOU->setIsKill(); - isDead = false; - isShorten = true; - RemoveStart = getDefIndex(getInstructionIndex(LastUse)); - RemoveEnd = SrcEnd; - } else { - MachineInstr *SrcMI = getInstructionFromIndex(SrcStart); - if (SrcMI) { - MachineOperand *mops = findDefOperand(SrcMI, repSrcReg); - if (mops) - // A dead def should have a single cycle interval. - ++RemoveStart; - } - } - } - } - - // We need to be careful about coalescing a source physical register with a - // virtual register. Once the coalescing is done, it cannot be broken and - // these are not spillable! If the destination interval uses are far away, - // think twice about coalescing them! - if (!mopd->isDead() && (SrcIsPhys || DstIsPhys)) { - LiveInterval &JoinVInt = SrcIsPhys ? DstInt : SrcInt; - unsigned JoinVReg = SrcIsPhys ? repDstReg : repSrcReg; - unsigned JoinPReg = SrcIsPhys ? repSrcReg : repDstReg; - const TargetRegisterClass *RC = mf_->getSSARegMap()->getRegClass(JoinVReg); - unsigned Threshold = allocatableRCRegs_[RC].count(); - - // If the virtual register live interval is long has it has low use desity, - // do not join them, instead mark the physical register as its allocation - // preference. - unsigned Length = JoinVInt.getSize() / InstrSlots::NUM; - LiveVariables::VarInfo &vi = lv_->getVarInfo(JoinVReg); - if (Length > Threshold && - (((float)vi.NumUses / Length) < (1.0 / Threshold))) { - JoinVInt.preference = JoinPReg; - ++numAborts; - DOUT << "\tMay tie down a physical register, abort!\n"; - return false; - } - } - - // Okay, attempt to join these two intervals. On failure, this returns false. - // Otherwise, if one of the intervals being joined is a physreg, this method - // always canonicalizes DstInt to be it. The output "SrcInt" will not have - // been modified, so we can use this information below to update aliases. - if (JoinIntervals(DstInt, SrcInt)) { - if (isDead) { - // Result of the copy is dead. Propagate this property. - if (SrcStart == 0) { - assert(MRegisterInfo::isPhysicalRegister(repSrcReg) && - "Live-in must be a physical register!"); - // Live-in to the function but dead. Remove it from entry live-in set. - // JoinIntervals may end up swapping the two intervals. - mf_->begin()->removeLiveIn(repSrcReg); - } else { - MachineInstr *SrcMI = getInstructionFromIndex(SrcStart); - if (SrcMI) { - MachineOperand *mops = findDefOperand(SrcMI, repSrcReg); - if (mops) - mops->setIsDead(); - } - } - } - - if (isShorten || isDead) { - // Shorten the live interval. - LiveInterval &LiveInInt = (repSrcReg == DstInt.reg) ? DstInt : SrcInt; - LiveInInt.removeRange(RemoveStart, RemoveEnd); - } - } else { - // Coallescing failed. - - // If we can eliminate the copy without merging the live ranges, do so now. - if (AdjustCopiesBackFrom(SrcInt, DstInt, CopyMI)) - return true; - - // Otherwise, we are unable to join the intervals. - DOUT << "Interference!\n"; - return false; - } - - bool Swapped = repSrcReg == DstInt.reg; - if (Swapped) - std::swap(repSrcReg, repDstReg); - assert(MRegisterInfo::isVirtualRegister(repSrcReg) && - "LiveInterval::join didn't work right!"); - - // If we're about to merge live ranges into a physical register live range, - // we have to update any aliased register's live ranges to indicate that they - // have clobbered values for this range. - if (MRegisterInfo::isPhysicalRegister(repDstReg)) { - // Unset unnecessary kills. - if (!DstInt.containsOneValue()) { - for (LiveInterval::Ranges::const_iterator I = SrcInt.begin(), - E = SrcInt.end(); I != E; ++I) - unsetRegisterKills(I->start, I->end, repDstReg); - } - - // Update the liveintervals of sub-registers. - for (const unsigned *AS = mri_->getSubRegisters(repDstReg); *AS; ++AS) - getInterval(*AS).MergeInClobberRanges(SrcInt); - } else { - // Merge use info if the destination is a virtual register. - LiveVariables::VarInfo& dVI = lv_->getVarInfo(repDstReg); - LiveVariables::VarInfo& sVI = lv_->getVarInfo(repSrcReg); - dVI.NumUses += sVI.NumUses; - } - - DOUT << "\n\t\tJoined. Result = "; DstInt.print(DOUT, mri_); - DOUT << "\n"; - - // Remember these liveintervals have been joined. - JoinedLIs.set(repSrcReg - MRegisterInfo::FirstVirtualRegister); - if (MRegisterInfo::isVirtualRegister(repDstReg)) - JoinedLIs.set(repDstReg - MRegisterInfo::FirstVirtualRegister); - - // If the intervals were swapped by Join, swap them back so that the register - // mapping (in the r2i map) is correct. - if (Swapped) SrcInt.swap(DstInt); - removeInterval(repSrcReg); - r2rMap_[repSrcReg] = repDstReg; - - // Finally, delete the copy instruction. - RemoveMachineInstrFromMaps(CopyMI); - CopyMI->eraseFromParent(); - ++numPeep; - ++numJoins; - return true; -} - -/// ComputeUltimateVN - Assuming we are going to join two live intervals, -/// compute what the resultant value numbers for each value in the input two -/// ranges will be. This is complicated by copies between the two which can -/// and will commonly cause multiple value numbers to be merged into one. -/// -/// VN is the value number that we're trying to resolve. InstDefiningValue -/// keeps track of the new InstDefiningValue assignment for the result -/// LiveInterval. ThisFromOther/OtherFromThis are sets that keep track of -/// whether a value in this or other is a copy from the opposite set. -/// ThisValNoAssignments/OtherValNoAssignments keep track of value #'s that have -/// already been assigned. -/// -/// ThisFromOther[x] - If x is defined as a copy from the other interval, this -/// contains the value number the copy is from. -/// -static unsigned ComputeUltimateVN(unsigned VN, - SmallVector, 16> &ValueNumberInfo, - SmallVector &ThisFromOther, - SmallVector &OtherFromThis, - SmallVector &ThisValNoAssignments, - SmallVector &OtherValNoAssignments, - LiveInterval &ThisLI, LiveInterval &OtherLI) { - // If the VN has already been computed, just return it. - if (ThisValNoAssignments[VN] >= 0) - return ThisValNoAssignments[VN]; -// assert(ThisValNoAssignments[VN] != -2 && "Cyclic case?"); - - // If this val is not a copy from the other val, then it must be a new value - // number in the destination. - int OtherValNo = ThisFromOther[VN]; - if (OtherValNo == -1) { - ValueNumberInfo.push_back(ThisLI.getValNumInfo(VN)); - return ThisValNoAssignments[VN] = ValueNumberInfo.size()-1; - } - - // Otherwise, this *is* a copy from the RHS. If the other side has already - // been computed, return it. - if (OtherValNoAssignments[OtherValNo] >= 0) - return ThisValNoAssignments[VN] = OtherValNoAssignments[OtherValNo]; - - // Mark this value number as currently being computed, then ask what the - // ultimate value # of the other value is. - ThisValNoAssignments[VN] = -2; - unsigned UltimateVN = - ComputeUltimateVN(OtherValNo, ValueNumberInfo, - OtherFromThis, ThisFromOther, - OtherValNoAssignments, ThisValNoAssignments, - OtherLI, ThisLI); - return ThisValNoAssignments[VN] = UltimateVN; -} - -static bool InVector(unsigned Val, const SmallVector &V) { - return std::find(V.begin(), V.end(), Val) != V.end(); -} - -/// SimpleJoin - Attempt to joint the specified interval into this one. The -/// caller of this method must guarantee that the RHS only contains a single -/// value number and that the RHS is not defined by a copy from this -/// interval. This returns false if the intervals are not joinable, or it -/// joins them and returns true. -bool LiveIntervals::SimpleJoin(LiveInterval &LHS, LiveInterval &RHS) { - assert(RHS.containsOneValue()); - - // Some number (potentially more than one) value numbers in the current - // interval may be defined as copies from the RHS. Scan the overlapping - // portions of the LHS and RHS, keeping track of this and looking for - // overlapping live ranges that are NOT defined as copies. If these exist, we - // cannot coallesce. - - LiveInterval::iterator LHSIt = LHS.begin(), LHSEnd = LHS.end(); - LiveInterval::iterator RHSIt = RHS.begin(), RHSEnd = RHS.end(); - - if (LHSIt->start < RHSIt->start) { - LHSIt = std::upper_bound(LHSIt, LHSEnd, RHSIt->start); - if (LHSIt != LHS.begin()) --LHSIt; - } else if (RHSIt->start < LHSIt->start) { - RHSIt = std::upper_bound(RHSIt, RHSEnd, LHSIt->start); - if (RHSIt != RHS.begin()) --RHSIt; - } - - SmallVector EliminatedLHSVals; - - while (1) { - // Determine if these live intervals overlap. - bool Overlaps = false; - if (LHSIt->start <= RHSIt->start) - Overlaps = LHSIt->end > RHSIt->start; - else - Overlaps = RHSIt->end > LHSIt->start; - - // If the live intervals overlap, there are two interesting cases: if the - // LHS interval is defined by a copy from the RHS, it's ok and we record - // that the LHS value # is the same as the RHS. If it's not, then we cannot - // coallesce these live ranges and we bail out. - if (Overlaps) { - // If we haven't already recorded that this value # is safe, check it. - if (!InVector(LHSIt->ValId, EliminatedLHSVals)) { - // Copy from the RHS? - unsigned SrcReg = LHS.getSrcRegForValNum(LHSIt->ValId); - if (rep(SrcReg) != RHS.reg) - return false; // Nope, bail out. - - EliminatedLHSVals.push_back(LHSIt->ValId); - } - - // We know this entire LHS live range is okay, so skip it now. - if (++LHSIt == LHSEnd) break; - continue; - } - - if (LHSIt->end < RHSIt->end) { - if (++LHSIt == LHSEnd) break; - } else { - // One interesting case to check here. It's possible that we have - // something like "X3 = Y" which defines a new value number in the LHS, - // and is the last use of this liverange of the RHS. In this case, we - // want to notice this copy (so that it gets coallesced away) even though - // the live ranges don't actually overlap. - if (LHSIt->start == RHSIt->end) { - if (InVector(LHSIt->ValId, EliminatedLHSVals)) { - // We already know that this value number is going to be merged in - // if coallescing succeeds. Just skip the liverange. - if (++LHSIt == LHSEnd) break; - } else { - // Otherwise, if this is a copy from the RHS, mark it as being merged - // in. - if (rep(LHS.getSrcRegForValNum(LHSIt->ValId)) == RHS.reg) { - EliminatedLHSVals.push_back(LHSIt->ValId); - - // We know this entire LHS live range is okay, so skip it now. - if (++LHSIt == LHSEnd) break; - } - } - } - - if (++RHSIt == RHSEnd) break; - } - } - - // If we got here, we know that the coallescing will be successful and that - // the value numbers in EliminatedLHSVals will all be merged together. Since - // the most common case is that EliminatedLHSVals has a single number, we - // optimize for it: if there is more than one value, we merge them all into - // the lowest numbered one, then handle the interval as if we were merging - // with one value number. - unsigned LHSValNo; - if (EliminatedLHSVals.size() > 1) { - // Loop through all the equal value numbers merging them into the smallest - // one. - unsigned Smallest = EliminatedLHSVals[0]; - for (unsigned i = 1, e = EliminatedLHSVals.size(); i != e; ++i) { - if (EliminatedLHSVals[i] < Smallest) { - // Merge the current notion of the smallest into the smaller one. - LHS.MergeValueNumberInto(Smallest, EliminatedLHSVals[i]); - Smallest = EliminatedLHSVals[i]; - } else { - // Merge into the smallest. - LHS.MergeValueNumberInto(EliminatedLHSVals[i], Smallest); - } - } - LHSValNo = Smallest; - } else { - assert(!EliminatedLHSVals.empty() && "No copies from the RHS?"); - LHSValNo = EliminatedLHSVals[0]; - } - - // Okay, now that there is a single LHS value number that we're merging the - // RHS into, update the value number info for the LHS to indicate that the - // value number is defined where the RHS value number was. - LHS.setValueNumberInfo(LHSValNo, RHS.getValNumInfo(0)); - - // Okay, the final step is to loop over the RHS live intervals, adding them to - // the LHS. - LHS.MergeRangesInAsValue(RHS, LHSValNo); - LHS.weight += RHS.weight; - if (RHS.preference && !LHS.preference) - LHS.preference = RHS.preference; - - return true; -} - -/// JoinIntervals - Attempt to join these two intervals. On failure, this -/// returns false. Otherwise, if one of the intervals being joined is a -/// physreg, this method always canonicalizes LHS to be it. The output -/// "RHS" will not have been modified, so we can use this information -/// below to update aliases. -bool LiveIntervals::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS) { - // Compute the final value assignment, assuming that the live ranges can be - // coallesced. - SmallVector LHSValNoAssignments; - SmallVector RHSValNoAssignments; - SmallVector, 16> ValueNumberInfo; - - // If a live interval is a physical register, conservatively check if any - // of its sub-registers is overlapping the live interval of the virtual - // register. If so, do not coalesce. - if (MRegisterInfo::isPhysicalRegister(LHS.reg) && - *mri_->getSubRegisters(LHS.reg)) { - for (const unsigned* SR = mri_->getSubRegisters(LHS.reg); *SR; ++SR) - if (hasInterval(*SR) && RHS.overlaps(getInterval(*SR))) { - DOUT << "Interfere with sub-register "; - DEBUG(getInterval(*SR).print(DOUT, mri_)); - return false; - } - } else if (MRegisterInfo::isPhysicalRegister(RHS.reg) && - *mri_->getSubRegisters(RHS.reg)) { - for (const unsigned* SR = mri_->getSubRegisters(RHS.reg); *SR; ++SR) - if (hasInterval(*SR) && LHS.overlaps(getInterval(*SR))) { - DOUT << "Interfere with sub-register "; - DEBUG(getInterval(*SR).print(DOUT, mri_)); - return false; - } - } - - // Compute ultimate value numbers for the LHS and RHS values. - if (RHS.containsOneValue()) { - // Copies from a liveinterval with a single value are simple to handle and - // very common, handle the special case here. This is important, because - // often RHS is small and LHS is large (e.g. a physreg). - - // Find out if the RHS is defined as a copy from some value in the LHS. - int RHSValID = -1; - std::pair RHSValNoInfo; - unsigned RHSSrcReg = RHS.getSrcRegForValNum(0); - if ((RHSSrcReg == 0 || rep(RHSSrcReg) != LHS.reg)) { - // If RHS is not defined as a copy from the LHS, we can use simpler and - // faster checks to see if the live ranges are coallescable. This joiner - // can't swap the LHS/RHS intervals though. - if (!MRegisterInfo::isPhysicalRegister(RHS.reg)) { - return SimpleJoin(LHS, RHS); - } else { - RHSValNoInfo = RHS.getValNumInfo(0); - } - } else { - // It was defined as a copy from the LHS, find out what value # it is. - unsigned ValInst = RHS.getInstForValNum(0); - RHSValID = LHS.getLiveRangeContaining(ValInst-1)->ValId; - RHSValNoInfo = LHS.getValNumInfo(RHSValID); - } - - LHSValNoAssignments.resize(LHS.getNumValNums(), -1); - RHSValNoAssignments.resize(RHS.getNumValNums(), -1); - ValueNumberInfo.resize(LHS.getNumValNums()); - - // Okay, *all* of the values in LHS that are defined as a copy from RHS - // should now get updated. - for (unsigned VN = 0, e = LHS.getNumValNums(); VN != e; ++VN) { - if (unsigned LHSSrcReg = LHS.getSrcRegForValNum(VN)) { - if (rep(LHSSrcReg) != RHS.reg) { - // If this is not a copy from the RHS, its value number will be - // unmodified by the coallescing. - ValueNumberInfo[VN] = LHS.getValNumInfo(VN); - LHSValNoAssignments[VN] = VN; - } else if (RHSValID == -1) { - // Otherwise, it is a copy from the RHS, and we don't already have a - // value# for it. Keep the current value number, but remember it. - LHSValNoAssignments[VN] = RHSValID = VN; - ValueNumberInfo[VN] = RHSValNoInfo; - } else { - // Otherwise, use the specified value #. - LHSValNoAssignments[VN] = RHSValID; - if (VN != (unsigned)RHSValID) - ValueNumberInfo[VN].first = ~1U; - else - ValueNumberInfo[VN] = RHSValNoInfo; - } - } else { - ValueNumberInfo[VN] = LHS.getValNumInfo(VN); - LHSValNoAssignments[VN] = VN; - } - } - - assert(RHSValID != -1 && "Didn't find value #?"); - RHSValNoAssignments[0] = RHSValID; - - } else { - // Loop over the value numbers of the LHS, seeing if any are defined from - // the RHS. - SmallVector LHSValsDefinedFromRHS; - LHSValsDefinedFromRHS.resize(LHS.getNumValNums(), -1); - for (unsigned VN = 0, e = LHS.getNumValNums(); VN != e; ++VN) { - unsigned ValSrcReg = LHS.getSrcRegForValNum(VN); - if (ValSrcReg == 0) // Src not defined by a copy? - continue; - - // DstReg is known to be a register in the LHS interval. If the src is - // from the RHS interval, we can use its value #. - if (rep(ValSrcReg) != RHS.reg) - continue; - - // Figure out the value # from the RHS. - unsigned ValInst = LHS.getInstForValNum(VN); - LHSValsDefinedFromRHS[VN] = RHS.getLiveRangeContaining(ValInst-1)->ValId; - } - - // Loop over the value numbers of the RHS, seeing if any are defined from - // the LHS. - SmallVector RHSValsDefinedFromLHS; - RHSValsDefinedFromLHS.resize(RHS.getNumValNums(), -1); - for (unsigned VN = 0, e = RHS.getNumValNums(); VN != e; ++VN) { - unsigned ValSrcReg = RHS.getSrcRegForValNum(VN); - if (ValSrcReg == 0) // Src not defined by a copy? - continue; - - // DstReg is known to be a register in the RHS interval. If the src is - // from the LHS interval, we can use its value #. - if (rep(ValSrcReg) != LHS.reg) - continue; - - // Figure out the value # from the LHS. - unsigned ValInst = RHS.getInstForValNum(VN); - RHSValsDefinedFromLHS[VN] = LHS.getLiveRangeContaining(ValInst-1)->ValId; - } - - LHSValNoAssignments.resize(LHS.getNumValNums(), -1); - RHSValNoAssignments.resize(RHS.getNumValNums(), -1); - ValueNumberInfo.reserve(LHS.getNumValNums() + RHS.getNumValNums()); - - for (unsigned VN = 0, e = LHS.getNumValNums(); VN != e; ++VN) { - if (LHSValNoAssignments[VN] >= 0 || LHS.getInstForValNum(VN) == ~2U) - continue; - ComputeUltimateVN(VN, ValueNumberInfo, - LHSValsDefinedFromRHS, RHSValsDefinedFromLHS, - LHSValNoAssignments, RHSValNoAssignments, LHS, RHS); - } - for (unsigned VN = 0, e = RHS.getNumValNums(); VN != e; ++VN) { - if (RHSValNoAssignments[VN] >= 0 || RHS.getInstForValNum(VN) == ~2U) - continue; - // If this value number isn't a copy from the LHS, it's a new number. - if (RHSValsDefinedFromLHS[VN] == -1) { - ValueNumberInfo.push_back(RHS.getValNumInfo(VN)); - RHSValNoAssignments[VN] = ValueNumberInfo.size()-1; - continue; - } - - ComputeUltimateVN(VN, ValueNumberInfo, - RHSValsDefinedFromLHS, LHSValsDefinedFromRHS, - RHSValNoAssignments, LHSValNoAssignments, RHS, LHS); - } - } - - // Armed with the mappings of LHS/RHS values to ultimate values, walk the - // interval lists to see if these intervals are coallescable. - LiveInterval::const_iterator I = LHS.begin(); - LiveInterval::const_iterator IE = LHS.end(); - LiveInterval::const_iterator J = RHS.begin(); - LiveInterval::const_iterator JE = RHS.end(); - - // Skip ahead until the first place of potential sharing. - if (I->start < J->start) { - I = std::upper_bound(I, IE, J->start); - if (I != LHS.begin()) --I; - } else if (J->start < I->start) { - J = std::upper_bound(J, JE, I->start); - if (J != RHS.begin()) --J; - } - - while (1) { - // Determine if these two live ranges overlap. - bool Overlaps; - if (I->start < J->start) { - Overlaps = I->end > J->start; - } else { - Overlaps = J->end > I->start; - } - - // If so, check value # info to determine if they are really different. - if (Overlaps) { - // If the live range overlap will map to the same value number in the - // result liverange, we can still coallesce them. If not, we can't. - if (LHSValNoAssignments[I->ValId] != RHSValNoAssignments[J->ValId]) - return false; - } - - if (I->end < J->end) { - ++I; - if (I == IE) break; - } else { - ++J; - if (J == JE) break; - } - } - - // If we get here, we know that we can coallesce the live ranges. Ask the - // intervals to coallesce themselves now. - LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], - ValueNumberInfo); - return true; -} - - -namespace { - // DepthMBBCompare - Comparison predicate that sort first based on the loop - // depth of the basic block (the unsigned), and then on the MBB number. - struct DepthMBBCompare { - typedef std::pair DepthMBBPair; - bool operator()(const DepthMBBPair &LHS, const DepthMBBPair &RHS) const { - if (LHS.first > RHS.first) return true; // Deeper loops first - return LHS.first == RHS.first && - LHS.second->getNumber() < RHS.second->getNumber(); - } - }; -} - - -void LiveIntervals::CopyCoallesceInMBB(MachineBasicBlock *MBB, - std::vector *TryAgain, bool PhysOnly) { - DOUT << ((Value*)MBB->getBasicBlock())->getName() << ":\n"; - - for (MachineBasicBlock::iterator MII = MBB->begin(), E = MBB->end(); - MII != E;) { - MachineInstr *Inst = MII++; - - // If this isn't a copy, we can't join intervals. - unsigned SrcReg, DstReg; - if (!tii_->isMoveInstr(*Inst, SrcReg, DstReg)) continue; - - if (TryAgain && !JoinCopy(Inst, SrcReg, DstReg, PhysOnly)) - TryAgain->push_back(getCopyRec(Inst, SrcReg, DstReg)); - } -} - - -void LiveIntervals::joinIntervals() { - DOUT << "********** JOINING INTERVALS ***********\n"; - - JoinedLIs.resize(getNumIntervals()); - JoinedLIs.reset(); - - std::vector TryAgainList; - const LoopInfo &LI = getAnalysis(); - if (LI.begin() == LI.end()) { - // If there are no loops in the function, join intervals in function order. - for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); - I != E; ++I) - CopyCoallesceInMBB(I, &TryAgainList); - } else { - // Otherwise, join intervals in inner loops before other intervals. - // Unfortunately we can't just iterate over loop hierarchy here because - // there may be more MBB's than BB's. Collect MBB's for sorting. - - // Join intervals in the function prolog first. We want to join physical - // registers with virtual registers before the intervals got too long. - std::vector > MBBs; - for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); I != E;++I) - MBBs.push_back(std::make_pair(LI.getLoopDepth(I->getBasicBlock()), I)); - - // Sort by loop depth. - std::sort(MBBs.begin(), MBBs.end(), DepthMBBCompare()); - - // Finally, join intervals in loop nest order. - for (unsigned i = 0, e = MBBs.size(); i != e; ++i) - CopyCoallesceInMBB(MBBs[i].second, NULL, true); - for (unsigned i = 0, e = MBBs.size(); i != e; ++i) - CopyCoallesceInMBB(MBBs[i].second, &TryAgainList, false); - } - - // Joining intervals can allow other intervals to be joined. Iteratively join - // until we make no progress. - bool ProgressMade = true; - while (ProgressMade) { - ProgressMade = false; - - for (unsigned i = 0, e = TryAgainList.size(); i != e; ++i) { - CopyRec &TheCopy = TryAgainList[i]; - if (TheCopy.MI && - JoinCopy(TheCopy.MI, TheCopy.SrcReg, TheCopy.DstReg)) { - TheCopy.MI = 0; // Mark this one as done. - ProgressMade = true; - } - } - } - - // Some live range has been lengthened due to colaescing, eliminate the - // unnecessary kills. - int RegNum = JoinedLIs.find_first(); - while (RegNum != -1) { - unsigned Reg = RegNum + MRegisterInfo::FirstVirtualRegister; - unsigned repReg = rep(Reg); - LiveInterval &LI = getInterval(repReg); - LiveVariables::VarInfo& svi = lv_->getVarInfo(Reg); - for (unsigned i = 0, e = svi.Kills.size(); i != e; ++i) { - MachineInstr *Kill = svi.Kills[i]; - // Suppose vr1 = op vr2, x - // and vr1 and vr2 are coalesced. vr2 should still be marked kill - // unless it is a two-address operand. - if (isRemoved(Kill) || hasRegisterDef(Kill, repReg)) - continue; - if (LI.liveAt(getInstructionIndex(Kill) + InstrSlots::NUM)) - unsetRegisterKill(Kill, repReg); - } - RegNum = JoinedLIs.find_next(RegNum); - } - - DOUT << "*** Register mapping ***\n"; - for (int i = 0, e = r2rMap_.size(); i != e; ++i) - if (r2rMap_[i]) { - DOUT << " reg " << i << " -> "; - DEBUG(printRegName(r2rMap_[i])); - DOUT << "\n"; - } -} - -/// Return true if the two specified registers belong to different register -/// classes. The registers may be either phys or virt regs. -bool LiveIntervals::differingRegisterClasses(unsigned RegA, - unsigned RegB) const { - - // Get the register classes for the first reg. - if (MRegisterInfo::isPhysicalRegister(RegA)) { - assert(MRegisterInfo::isVirtualRegister(RegB) && - "Shouldn't consider two physregs!"); - return !mf_->getSSARegMap()->getRegClass(RegB)->contains(RegA); - } - - // Compare against the regclass for the second reg. - const TargetRegisterClass *RegClass = mf_->getSSARegMap()->getRegClass(RegA); - if (MRegisterInfo::isVirtualRegister(RegB)) - return RegClass != mf_->getSSARegMap()->getRegClass(RegB); - else - return !RegClass->contains(RegB); -} - -/// lastRegisterUse - Returns the last use of the specific register between -/// cycles Start and End. It also returns the use operand by reference. It -/// returns NULL if there are no uses. -MachineInstr * -LiveIntervals::lastRegisterUse(unsigned Start, unsigned End, unsigned Reg, - MachineOperand *&MOU) { - int e = (End-1) / InstrSlots::NUM * InstrSlots::NUM; - int s = Start; - while (e >= s) { - // Skip deleted instructions - MachineInstr *MI = getInstructionFromIndex(e); - while ((e - InstrSlots::NUM) >= s && !MI) { - e -= InstrSlots::NUM; - MI = getInstructionFromIndex(e); - } - if (e < s || MI == NULL) - return NULL; - - for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) { - MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.isUse() && MO.getReg() && - mri_->regsOverlap(rep(MO.getReg()), Reg)) { - MOU = &MO; - return MI; - } - } - - e -= InstrSlots::NUM; - } - - return NULL; -} - - -/// findDefOperand - Returns the MachineOperand that is a def of the specific -/// register. It returns NULL if the def is not found. -MachineOperand *LiveIntervals::findDefOperand(MachineInstr *MI, unsigned Reg) { - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.isDef() && - mri_->regsOverlap(rep(MO.getReg()), Reg)) - return &MO; - } - return NULL; -} - -/// unsetRegisterKill - Unset IsKill property of all uses of specific register -/// of the specific instruction. -void LiveIntervals::unsetRegisterKill(MachineInstr *MI, unsigned Reg) { - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.isUse() && MO.isKill() && MO.getReg() && - mri_->regsOverlap(rep(MO.getReg()), Reg)) - MO.unsetIsKill(); - } -} - -/// unsetRegisterKills - Unset IsKill property of all uses of specific register -/// between cycles Start and End. -void LiveIntervals::unsetRegisterKills(unsigned Start, unsigned End, - unsigned Reg) { - int e = (End-1) / InstrSlots::NUM * InstrSlots::NUM; - int s = Start; - while (e >= s) { - // Skip deleted instructions - MachineInstr *MI = getInstructionFromIndex(e); - while ((e - InstrSlots::NUM) >= s && !MI) { - e -= InstrSlots::NUM; - MI = getInstructionFromIndex(e); - } - if (e < s || MI == NULL) - return; - - for (unsigned i = 0, NumOps = MI->getNumOperands(); i != NumOps; ++i) { - MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.isUse() && MO.isKill() && MO.getReg() && - mri_->regsOverlap(rep(MO.getReg()), Reg)) { - MO.unsetIsKill(); - } - } - - e -= InstrSlots::NUM; - } -} - -/// hasRegisterDef - True if the instruction defines the specific register. -/// -bool LiveIntervals::hasRegisterDef(MachineInstr *MI, unsigned Reg) { - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.isDef() && - mri_->regsOverlap(rep(MO.getReg()), Reg)) - return true; - } - return false; -} - LiveInterval LiveIntervals::createInterval(unsigned reg) { float Weight = MRegisterInfo::isPhysicalRegister(reg) ? HUGE_VALF : 0.0F; From greened at obbligato.org Fri Jun 8 12:20:30 2007 From: greened at obbligato.org (David Greene) Date: Fri, 8 Jun 2007 12:20:30 -0500 Subject: [llvm-commits] CVS: llvm/CREDITS.TXT Message-ID: <200706081720.l58HKUu0024124@zion.cs.uiuc.edu> Changes in directory llvm: CREDITS.TXT updated: 1.83 -> 1.84 --- Log message: Add entry to CREDITS. --- Diffs of the changes: (+5 -0) CREDITS.TXT | 5 +++++ 1 files changed, 5 insertions(+) Index: llvm/CREDITS.TXT diff -u llvm/CREDITS.TXT:1.83 llvm/CREDITS.TXT:1.84 --- llvm/CREDITS.TXT:1.83 Wed May 30 23:14:28 2007 +++ llvm/CREDITS.TXT Fri Jun 8 12:20:08 2007 @@ -95,6 +95,11 @@ E: djg at cray.com D: Miscellaneous bug fixes +N: David Greene +E: greened at obbligato.org +D: Miscellaneous bug fixes +D: Register allocation refactoring + N: Paolo Invernizzi E: arathorn at fastwebnet.it D: Visual C++ compatibility fixes From clattner at apple.com Fri Jun 8 12:39:02 2007 From: clattner at apple.com (Chris Lattner) Date: Fri, 8 Jun 2007 10:39:02 -0700 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Dominators.cpp In-Reply-To: <4668557D.2080002@mxc.ca> References: <200706041738.l54HcOO8002633@zion.cs.uiuc.edu> <46676B4D.1020503@mxc.ca> <4668445D.2050606@mxc.ca> <4668557D.2080002@mxc.ca> Message-ID: <846F7961-8CAC-4E09-BA77-627912EE1B25@apple.com> On Jun 7, 2007, at 11:59 AM, Nick Lewycky wrote: > Devang Patel wrote: >> On Jun 7, 2007, at 10:46 AM, Nick Lewycky wrote: >>> Similarly, I pass ETNodes around to functions that don't care about >>> which BB is actually involved, but do need the DFS numbers for >>> whatever reason. >> >> In that case what's the use of ETNode ? > > The DFS numbers. ETNode is the only way to see what the DFS in and DFS > out numbers are. > > At a conceptual level, those numbers uniquely identify the scope > and are > used in determining which InequalityGraph properties (also stored > per-ETNode) apply by comparing them for dominance, using the DFS > numbers. > > Yes we could pass BBs around and modify ETForest to return DFS numbers > from BBs directly, but it would probably be too slow. More generally, the df numbers are an internal implementation detail of domtree. If predsimplify needs df numbers, it should just compute them itself and store them in a map. This gives it complete control over them and allows you to do whatever you want with them. Doing a DFS is both fast and easy (just use llvm/ADT/DepthFirstIterator.h). -Chris From clattner at apple.com Fri Jun 8 12:47:25 2007 From: clattner at apple.com (Chris Lattner) Date: Fri, 8 Jun 2007 10:47:25 -0700 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h In-Reply-To: <200706072217.l57MHcJ4017685@zion.cs.uiuc.edu> References: <200706072217.l57MHcJ4017685@zion.cs.uiuc.edu> Message-ID: > --- llvm/include/llvm/Analysis/Dominators.h:1.95 Thu Jun 7 > 16:34:22 2007 > +++ llvm/include/llvm/Analysis/Dominators.h Thu Jun 7 17:17:16 2007 > @@ -142,6 +142,16 @@ > return getNode(BB); > } > > + /// getIDomBlock - return basic block BB's immediate domiantor > basic block. > + /// > + BasicBlock *getIDomBlock(BasicBlock *BB) { > + DomTreeNode *N = getNode(BB); > + assert (N && "Missing dominator tree node"); > + DomTreeNode *I = N->getIDom(); > + assert (N && "Missing immediate dominator"); > + return I->getBlock(); > + } This will assert and die if called on the entry node, because it has no idom. Would it make sense to have this function return null in this case? If so, please document it as returning null in that case. Also, "domiantor" is misspelled in the comment, -Chris From dpatel at apple.com Fri Jun 8 12:54:03 2007 From: dpatel at apple.com (Devang Patel) Date: Fri, 8 Jun 2007 10:54:03 -0700 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h In-Reply-To: References: <200706072217.l57MHcJ4017685@zion.cs.uiuc.edu> Message-ID: <538821E9-65EB-4433-88CE-A0432E49EF2C@apple.com> On Jun 8, 2007, at 10:47 AM, Chris Lattner wrote: >> --- llvm/include/llvm/Analysis/Dominators.h:1.95 Thu Jun 7 >> 16:34:22 2007 >> +++ llvm/include/llvm/Analysis/Dominators.h Thu Jun 7 17:17:16 2007 >> @@ -142,6 +142,16 @@ >> return getNode(BB); >> } >> >> + /// getIDomBlock - return basic block BB's immediate domiantor >> basic block. >> + /// >> + BasicBlock *getIDomBlock(BasicBlock *BB) { >> + DomTreeNode *N = getNode(BB); >> + assert (N && "Missing dominator tree node"); >> + DomTreeNode *I = N->getIDom(); >> + assert (N && "Missing immediate dominator"); >> + return I->getBlock(); >> + } > > This will assert and die if called on the entry node, because it has > no idom. Would it make sense to have this function return null in > this case? If so, please document it as returning null in that > case. Current clients do not expect null here. > Also, "domiantor" is misspelled in the comment, oops - Devang From dpatel at apple.com Fri Jun 8 12:59:24 2007 From: dpatel at apple.com (Devang Patel) Date: Fri, 8 Jun 2007 12:59:24 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h Message-ID: <200706081759.l58HxO7n025062@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Analysis: Dominators.h updated: 1.99 -> 1.100 --- Log message: Fix spelling. --- Diffs of the changes: (+1 -1) Dominators.h | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/include/llvm/Analysis/Dominators.h diff -u llvm/include/llvm/Analysis/Dominators.h:1.99 llvm/include/llvm/Analysis/Dominators.h:1.100 --- llvm/include/llvm/Analysis/Dominators.h:1.99 Thu Jun 7 20:50:32 2007 +++ llvm/include/llvm/Analysis/Dominators.h Fri Jun 8 12:59:02 2007 @@ -142,7 +142,7 @@ return getNode(BB); } - /// getIDomBlock - return basic block BB's immediate domiantor basic block. + /// getIDomBlock - return basic block BB's immediate dominator basic block. /// BasicBlock *getIDomBlock(BasicBlock *BB) { DomTreeNode *N = getNode(BB); From clattner at apple.com Fri Jun 8 13:00:21 2007 From: clattner at apple.com (Chris Lattner) Date: Fri, 8 Jun 2007 11:00:21 -0700 Subject: [llvm-commits] CVS: llvm/include/llvm/Analysis/Dominators.h In-Reply-To: <538821E9-65EB-4433-88CE-A0432E49EF2C@apple.com> References: <200706072217.l57MHcJ4017685@zion.cs.uiuc.edu> <538821E9-65EB-4433-88CE-A0432E49EF2C@apple.com> Message-ID: <82E3ED6B-5D60-4319-ADE5-9DD7CF213F0F@apple.com> >>> + /// getIDomBlock - return basic block BB's immediate domiantor >>> basic block. >>> + /// >>> + BasicBlock *getIDomBlock(BasicBlock *BB) { >>> + DomTreeNode *N = getNode(BB); >>> + assert (N && "Missing dominator tree node"); >>> + DomTreeNode *I = N->getIDom(); >>> + assert (N && "Missing immediate dominator"); >>> + return I->getBlock(); >>> + } >> >> This will assert and die if called on the entry node, because it has >> no idom. Would it make sense to have this function return null in >> this case? If so, please document it as returning null in that >> case. > > Current clients do not expect null here. I assume that current clients never call this on an entry block. If they did it would assert :). I'm just saying that would be the behavior I would expect if calling this from a new client. -Chris From evan.cheng at apple.com Fri Jun 8 13:15:30 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 11:15:30 -0700 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/SimpleRegisterCoalescing.h Passes.h LiveIntervalAnalysis.h In-Reply-To: <200706081719.l58HJKAG024077@zion.cs.uiuc.edu> References: <200706081719.l58HJKAG024077@zion.cs.uiuc.edu> Message-ID: <204B30E7-8475-4772-96C2-DB27ACA9ADA2@apple.com> Woot! Thanks! Evan On Jun 8, 2007, at 10:19 AM, David Greene wrote: > > > Changes in directory llvm/include/llvm/CodeGen: > > SimpleRegisterCoalescing.h added (r1.1) > Passes.h updated: 1.26 -> 1.27 > LiveIntervalAnalysis.h updated: 1.85 -> 1.86 > --- > Log message: > > Factor live variable analysis so it does not do register coalescing > simultaneously. Move that pass to SimpleRegisterCoalescing. > > This makes it easier to implement alternative register allocation and > coalescing strategies while maintaining reuse of the existing live > interval analysis. > > > --- > Diffs of the changes: (+195 -114) > > LiveIntervalAnalysis.h | 144 +++++++ > +-------------------------------- > Passes.h | 5 + > SimpleRegisterCoalescing.h | 160 +++++++++++++++++++++++++++++++++ > ++++++++++++ > 3 files changed, 195 insertions(+), 114 deletions(-) > > > Index: llvm/include/llvm/CodeGen/SimpleRegisterCoalescing.h > diff -c /dev/null llvm/include/llvm/CodeGen/ > SimpleRegisterCoalescing.h:1.1 > *** /dev/null Fri Jun 8 12:19:06 2007 > --- llvm/include/llvm/CodeGen/SimpleRegisterCoalescing.h Fri Jun 8 > 12:18:56 2007 > *************** > *** 0 **** > --- 1,160 ---- > + //===-- SimpleRegisterCoalescing.h - Register Coalescing -------- > *- C++ -*-===// > + // > + // The LLVM Compiler Infrastructure > + // > + // This file was developed by the LLVM research group and is > distributed under > + // the University of Illinois Open Source License. See > LICENSE.TXT for details. > + // > + // > ===------------------------------------------------------------------- > ---===// > + // > + // This file implements a simple register copy coalescing phase. > + // > + // > ===------------------------------------------------------------------- > ---===// > + > + #ifndef LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H > + #define LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H > + > + #include "llvm/CodeGen/MachineFunctionPass.h" > + #include "llvm/CodeGen/LiveInterval.h" > + #include "llvm/CodeGen/LiveIntervalAnalysis.h" > + #include "llvm/ADT/BitVector.h" > + #include "llvm/ADT/IndexedMap.h" > + > + namespace llvm { > + > + class LiveVariables; > + class MRegisterInfo; > + class TargetInstrInfo; > + class VirtRegMap; > + > + class SimpleRegisterCoalescing : public MachineFunctionPass { > + MachineFunction* mf_; > + const TargetMachine* tm_; > + const MRegisterInfo* mri_; > + const TargetInstrInfo* tii_; > + LiveIntervals *li_; > + LiveVariables *lv_; > + > + typedef IndexedMap Reg2RegMap; > + Reg2RegMap r2rMap_; > + > + BitVector allocatableRegs_; > + DenseMap > allocatableRCRegs_; > + > + /// JoinedLIs - Keep track which register intervals have been > coalesced > + /// with other intervals. > + BitVector JoinedLIs; > + > + public: > + static char ID; // Pass identifcation, replacement for typeid > + SimpleRegisterCoalescing() : MachineFunctionPass((intptr_t) > &ID) {}; > + > + struct CopyRec { > + MachineInstr *MI; > + unsigned SrcReg, DstReg; > + }; > + CopyRec getCopyRec(MachineInstr *MI, unsigned SrcReg, > unsigned DstReg) { > + CopyRec R; > + R.MI = MI; > + R.SrcReg = SrcReg; > + R.DstReg = DstReg; > + return R; > + } > + struct InstrSlots { > + enum { > + LOAD = 0, > + USE = 1, > + DEF = 2, > + STORE = 3, > + NUM = 4 > + }; > + }; > + > + virtual void getAnalysisUsage(AnalysisUsage &AU) const; > + virtual void releaseMemory(); > + > + /// runOnMachineFunction - pass entry point > + virtual bool runOnMachineFunction(MachineFunction&); > + > + /// print - Implement the dump method. > + virtual void print(std::ostream &O, const Module* = 0) const; > + void print(std::ostream *O, const Module* M = 0) const { > + if (O) print(*O, M); > + } > + > + private: > + /// joinIntervals - join compatible live intervals > + void joinIntervals(); > + > + /// CopyCoallesceInMBB - Coallsece copies in the specified > MBB, putting > + /// copies that cannot yet be coallesced into the "TryAgain" > list. > + void CopyCoallesceInMBB(MachineBasicBlock *MBB, > + std::vector *TryAgain, bool > PhysOnly = false); > + > + /// JoinCopy - Attempt to join intervals corresponding to > SrcReg/DstReg, > + /// which are the src/dst of the copy instruction CopyMI. > This returns true > + /// if the copy was successfully coallesced away, or if it is > never possible > + /// to coallesce these this copy, due to register > constraints. It returns > + /// false if it is not currently possible to coallesce this > interval, but > + /// it may be possible if other things get coallesced. > + bool JoinCopy(MachineInstr *CopyMI, unsigned SrcReg, unsigned > DstReg, > + bool PhysOnly = false); > + > + /// JoinIntervals - Attempt to join these two intervals. On > failure, this > + /// returns false. Otherwise, if one of the intervals being > joined is a > + /// physreg, this method always canonicalizes DestInt to be > it. The output > + /// "SrcInt" will not have been modified, so we can use this > information > + /// below to update aliases. > + bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS); > + > + /// SimpleJoin - Attempt to join the specified interval into > this one. The > + /// caller of this method must guarantee that the RHS only > contains a single > + /// value number and that the RHS is not defined by a copy > from this > + /// interval. This returns false if the intervals are not > joinable, or it > + /// joins them and returns true. > + bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS); > + > + /// Return true if the two specified registers belong to > different > + /// register classes. The registers may be either phys or > virt regs. > + bool differingRegisterClasses(unsigned RegA, unsigned RegB) > const; > + > + > + bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval > &IntB, > + MachineInstr *CopyMI); > + > + /// lastRegisterUse - Returns the last use of the specific > register between > + /// cycles Start and End. It also returns the use operand by > reference. It > + /// returns NULL if there are no uses. > + MachineInstr *lastRegisterUse(unsigned Start, unsigned End, > unsigned Reg, > + MachineOperand *&MOU); > + > + /// findDefOperand - Returns the MachineOperand that is a def > of the specific > + /// register. It returns NULL if the def is not found. > + MachineOperand *findDefOperand(MachineInstr *MI, unsigned Reg); > + > + /// unsetRegisterKill - Unset IsKill property of all uses of > the specific > + /// register of the specific instruction. > + void unsetRegisterKill(MachineInstr *MI, unsigned Reg); > + > + /// unsetRegisterKills - Unset IsKill property of all uses of > specific register > + /// between cycles Start and End. > + void unsetRegisterKills(unsigned Start, unsigned End, > unsigned Reg); > + > + /// hasRegisterDef - True if the instruction defines the > specific register. > + /// > + bool hasRegisterDef(MachineInstr *MI, unsigned Reg); > + > + /// rep - returns the representative of this register > + unsigned rep(unsigned Reg) { > + unsigned Rep = r2rMap_[Reg]; > + if (Rep) > + return r2rMap_[Reg] = rep(Rep); > + return Reg; > + } > + > + void printRegName(unsigned reg) const; > + }; > + > + } // End llvm namespace > + > + #endif > > > Index: llvm/include/llvm/CodeGen/Passes.h > diff -u llvm/include/llvm/CodeGen/Passes.h:1.26 llvm/include/llvm/ > CodeGen/Passes.h:1.27 > --- llvm/include/llvm/CodeGen/Passes.h:1.26 Tue May 22 12:14:46 2007 > +++ llvm/include/llvm/CodeGen/Passes.h Fri Jun 8 12:18:56 2007 > @@ -44,6 +44,11 @@ > /// > extern const PassInfo *PHIEliminationID; > > + /// SimpleRegisterCoalescing pass. Aggressively coalesces every > register > + /// copy it can. > + /// > + extern const PassInfo *SimpleRegisterCoalescingID; > + > /// TwoAddressInstruction pass - This pass reduces two-address > instructions to > /// use two operands. This destroys SSA information but it is > desired by > /// register allocators. > > > Index: llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h > diff -u llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h:1.85 llvm/ > include/llvm/CodeGen/LiveIntervalAnalysis.h:1.86 > --- llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h:1.85 Mon May > 14 16:10:05 2007 > +++ llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h Fri Jun 8 > 12:18:56 2007 > @@ -44,7 +44,7 @@ > /// MBB2IdxMap - The index of the first instruction in the > specified basic > /// block. > std::vector MBB2IdxMap; > - > + > typedef std::map Mi2IndexMap; > Mi2IndexMap mi2iMap_; > > @@ -54,31 +54,12 @@ > typedef std::map Reg2IntervalMap; > Reg2IntervalMap r2iMap_; > > - typedef IndexedMap Reg2RegMap; > - Reg2RegMap r2rMap_; > - > BitVector allocatableRegs_; > - DenseMap > allocatableRCRegs_; > - > - /// JoinedLIs - Keep track which register intervals have been > coalesced > - /// with other intervals. > - BitVector JoinedLIs; > > public: > static char ID; // Pass identification, replacement for typeid > LiveIntervals() : MachineFunctionPass((intptr_t)&ID) {} > > - struct CopyRec { > - MachineInstr *MI; > - unsigned SrcReg, DstReg; > - }; > - CopyRec getCopyRec(MachineInstr *MI, unsigned SrcReg, unsigned > DstReg) { > - CopyRec R; > - R.MI = MI; > - R.SrcReg = SrcReg; > - R.DstReg = DstReg; > - return R; > - } > struct InstrSlots { > enum { > LOAD = 0, > @@ -158,29 +139,31 @@ > "index does not correspond to an instruction"); > return i2miMap_[index]; > } > - > - std::vector addIntervalsForSpills(const > LiveInterval& i, > - VirtRegMap& vrm, > - int slot); > + > + // Interval creation > + > + LiveInterval &getOrCreateInterval(unsigned reg) { > + Reg2IntervalMap::iterator I = r2iMap_.find(reg); > + if (I == r2iMap_.end()) > + I = r2iMap_.insert(I, std::make_pair(reg, createInterval > (reg))); > + return I->second; > + } > > /// CreateNewLiveInterval - Create a new live interval with > the given live > /// ranges. The new live interval will have an infinite spill > weight. > LiveInterval &CreateNewLiveInterval(const LiveInterval *LI, > const > std::vector &LRs); > > - virtual void getAnalysisUsage(AnalysisUsage &AU) const; > - virtual void releaseMemory(); > + std::vector addIntervalsForSpills(const > LiveInterval& i, > + VirtRegMap& vrm, > + int slot); > > - /// runOnMachineFunction - pass entry point > - virtual bool runOnMachineFunction(MachineFunction&); > + // Interval removal > > - /// print - Implement the dump method. > - virtual void print(std::ostream &O, const Module* = 0) const; > - void print(std::ostream *O, const Module* M = 0) const { > - if (O) print(*O, M); > + void removeInterval(unsigned Reg) { > + r2iMap_.erase(Reg); > } > > - private: > /// isRemoved - returns true if the specified machine instr > has been > /// removed. > bool isRemoved(MachineInstr* instr) const { > @@ -198,40 +181,22 @@ > mi2iMap_.erase(mi2i); > } > } > - > - /// computeIntervals - Compute live intervals. > - void computeIntervals(); > > - /// joinIntervals - join compatible live intervals > - void joinIntervals(); > + virtual void getAnalysisUsage(AnalysisUsage &AU) const; > + virtual void releaseMemory(); > > - /// CopyCoallesceInMBB - Coallsece copies in the specified > MBB, putting > - /// copies that cannot yet be coallesced into the "TryAgain" > list. > - void CopyCoallesceInMBB(MachineBasicBlock *MBB, > - std::vector *TryAgain, bool > PhysOnly = false); > - > - /// JoinCopy - Attempt to join intervals corresponding to > SrcReg/DstReg, > - /// which are the src/dst of the copy instruction CopyMI. > This returns true > - /// if the copy was successfully coallesced away, or if it is > never possible > - /// to coallesce these this copy, due to register > constraints. It returns > - /// false if it is not currently possible to coallesce this > interval, but > - /// it may be possible if other things get coallesced. > - bool JoinCopy(MachineInstr *CopyMI, unsigned SrcReg, unsigned > DstReg, > - bool PhysOnly = false); > - > - /// JoinIntervals - Attempt to join these two intervals. On > failure, this > - /// returns false. Otherwise, if one of the intervals being > joined is a > - /// physreg, this method always canonicalizes DestInt to be > it. The output > - /// "SrcInt" will not have been modified, so we can use this > information > - /// below to update aliases. > - bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS); > - > - /// SimpleJoin - Attempt to join the specified interval into > this one. The > - /// caller of this method must guarantee that the RHS only > contains a single > - /// value number and that the RHS is not defined by a copy > from this > - /// interval. This returns false if the intervals are not > joinable, or it > - /// joins them and returns true. > - bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS); > + /// runOnMachineFunction - pass entry point > + virtual bool runOnMachineFunction(MachineFunction&); > + > + /// print - Implement the dump method. > + virtual void print(std::ostream &O, const Module* = 0) const; > + void print(std::ostream *O, const Module* M = 0) const { > + if (O) print(*O, M); > + } > + > + private: > + /// computeIntervals - Compute live intervals. > + void computeIntervals(); > > /// handleRegisterDef - update intervals for a register def > /// (calls handlePhysicalRegisterDef and > @@ -260,57 +225,8 @@ > unsigned MIIdx, > LiveInterval &interval, bool isAlias > = false); > > - /// Return true if the two specified registers belong to > different > - /// register classes. The registers may be either phys or > virt regs. > - bool differingRegisterClasses(unsigned RegA, unsigned RegB) > const; > - > - > - bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB, > - MachineInstr *CopyMI); > - > - /// lastRegisterUse - Returns the last use of the specific > register between > - /// cycles Start and End. It also returns the use operand by > reference. It > - /// returns NULL if there are no uses. > - MachineInstr *lastRegisterUse(unsigned Start, unsigned End, > unsigned Reg, > - MachineOperand *&MOU); > - > - /// findDefOperand - Returns the MachineOperand that is a def > of the specific > - /// register. It returns NULL if the def is not found. > - MachineOperand *findDefOperand(MachineInstr *MI, unsigned Reg); > - > - /// unsetRegisterKill - Unset IsKill property of all uses of > the specific > - /// register of the specific instruction. > - void unsetRegisterKill(MachineInstr *MI, unsigned Reg); > - > - /// unsetRegisterKills - Unset IsKill property of all uses of > specific register > - /// between cycles Start and End. > - void unsetRegisterKills(unsigned Start, unsigned End, unsigned > Reg); > - > - /// hasRegisterDef - True if the instruction defines the > specific register. > - /// > - bool hasRegisterDef(MachineInstr *MI, unsigned Reg); > - > static LiveInterval createInterval(unsigned Reg); > > - void removeInterval(unsigned Reg) { > - r2iMap_.erase(Reg); > - } > - > - LiveInterval &getOrCreateInterval(unsigned reg) { > - Reg2IntervalMap::iterator I = r2iMap_.find(reg); > - if (I == r2iMap_.end()) > - I = r2iMap_.insert(I, std::make_pair(reg, createInterval > (reg))); > - return I->second; > - } > - > - /// rep - returns the representative of this register > - unsigned rep(unsigned Reg) { > - unsigned Rep = r2rMap_[Reg]; > - if (Rep) > - return r2rMap_[Reg] = rep(Rep); > - return Reg; > - } > - > void printRegName(unsigned reg) const; > }; > > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From evan.cheng at apple.com Fri Jun 8 14:11:13 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 14:11:13 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706081911.l58JBDmO026807@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.38 -> 1.39 --- Log message: Hidden options to help debugging ifcvt issues. --- Diffs of the changes: (+32 -2) IfConversion.cpp | 34 ++++++++++++++++++++++++++++++++-- 1 files changed, 32 insertions(+), 2 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.38 llvm/lib/CodeGen/IfConversion.cpp:1.39 --- llvm/lib/CodeGen/IfConversion.cpp:1.38 Fri Jun 8 04:36:04 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Fri Jun 8 14:10:51 2007 @@ -19,11 +19,27 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/Statistic.h" using namespace llvm; +namespace { + // Hidden options for help debugging. + cl::opt IfCvtFnStart("ifcvt-fn-start", cl::init(-1), cl::Hidden); + cl::opt IfCvtFnStop("ifcvt-fn-stop", cl::init(-1), cl::Hidden); + cl::opt IfCvtLimit("ifcvt-limit", cl::init(-1), cl::Hidden); + cl::opt DisableSimple("disable-ifcvt-simple", + cl::init(false), cl::Hidden); + cl::opt DisableSimpleFalse("disable-ifcvt-simple-false", + cl::init(false), cl::Hidden); + cl::opt DisableTriangle("disable-ifcvt-triangle", + cl::init(false), cl::Hidden); + cl::opt DisableDiamond("disable-ifcvt-diamond", + cl::init(false), cl::Hidden); +} + STATISTIC(NumSimple, "Number of simple if-conversions performed"); STATISTIC(NumSimpleRev, "Number of simple (reversed) if-conversions performed"); STATISTIC(NumTriangle, "Number of triangle if-conversions performed"); @@ -139,7 +155,15 @@ TII = MF.getTarget().getInstrInfo(); if (!TII) return false; - DOUT << "\nIfcvt: function \'" << MF.getFunction()->getName() << "\'\n"; + static int FnNum = -1; + DOUT << "\nIfcvt: function (" << ++FnNum << ") \'" + << MF.getFunction()->getName() << "\'"; + + if (FnNum < IfCvtFnStart || (IfCvtFnStop != -1 && FnNum > IfCvtFnStop)) { + DOUT << " skipped\n"; + return false; + } + DOUT << "\n"; MF.RenumberBlocks(); BBAnalysis.resize(MF.getNumBlockIDs()); @@ -151,7 +175,7 @@ std::vector Candidates; MadeChange = false; - while (true) { + while (IfCvtLimit == -1 || (int)NumIfConvBBs < IfCvtLimit) { // Do an intial analysis for each basic block and finding all the potential // candidates to perform if-convesion. bool Change = AnalyzeBlocks(MF, Candidates); @@ -171,6 +195,7 @@ case ICSimple: case ICSimpleFalse: { bool isRev = BBI.Kind == ICSimpleFalse; + if ((isRev && DisableSimpleFalse) || (!isRev && DisableSimple)) break; DOUT << "Ifcvt (Simple" << (BBI.Kind == ICSimpleFalse ? " false" : "") << "): BB#" << BBI.BB->getNumber() << " (" << ((BBI.Kind == ICSimpleFalse) @@ -183,6 +208,7 @@ break; } case ICTriangle: + if (DisableTriangle) break; DOUT << "Ifcvt (Triangle): BB#" << BBI.BB->getNumber() << " (T:" << BBI.TrueBB->getNumber() << ",F:" << BBI.FalseBB->getNumber() << ") "; @@ -191,6 +217,7 @@ if (RetVal) NumTriangle++; break; case ICDiamond: + if (DisableDiamond) break; DOUT << "Ifcvt (Diamond): BB#" << BBI.BB->getNumber() << " (T:" << BBI.TrueBB->getNumber() << ",F:" << BBI.FalseBB->getNumber(); if (BBI.TailBB) @@ -202,6 +229,9 @@ break; } Change |= RetVal; + + if (IfCvtLimit != -1 && (int)NumIfConvBBs > IfCvtLimit) + break; } if (!Change) From evan.cheng at apple.com Fri Jun 8 14:17:34 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 14:17:34 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706081917.l58JHYbt026928@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.39 -> 1.40 --- Log message: Correct transfer predicate information. --- Diffs of the changes: (+6 -8) IfConversion.cpp | 14 ++++++-------- 1 files changed, 6 insertions(+), 8 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.39 llvm/lib/CodeGen/IfConversion.cpp:1.40 --- llvm/lib/CodeGen/IfConversion.cpp:1.39 Fri Jun 8 14:10:51 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Fri Jun 8 14:17:12 2007 @@ -610,7 +610,6 @@ // available if cmp executes. IterIfcvt = false; } - std::copy(Cond.begin(), Cond.end(), std::back_inserter(BBI.Predicate)); // Update block info. BB can be iteratively if-converted. if (IterIfcvt) @@ -671,8 +670,6 @@ // Remove entry to false edge if false block is merged in as well. if (FalseBBDead) BBI.BB->removeSuccessor(FalseBBI.BB); - std::copy(BBI.BrCond.begin(), BBI.BrCond.end(), - std::back_inserter(BBI.Predicate)); // Update block info. BB can be iteratively if-converted. if (IterIfcvt) @@ -785,11 +782,6 @@ // Merge the combined block into the entry of the diamond. MergeBlocks(BBI, *BBI1); - std::copy(Cond1->begin(), Cond1->end(), - std::back_inserter(BBI.Predicate)); - if (!NeedBr1) - std::copy(Cond2->begin(), Cond2->end(), - std::back_inserter(BBI.Predicate)); // 'True' and 'false' aren't combined, see if we need to add a unconditional // branch to the 'false' block. @@ -837,6 +829,8 @@ } BBI.NonPredSize = 0; + std::copy(Cond.begin(), Cond.end(), std::back_inserter(BBI.Predicate)); + NumIfConvBBs++; } @@ -883,4 +877,8 @@ ToBBI.ModifyPredicate |= FromBBI.ModifyPredicate; ToBBI.hasFallThrough = FromBBI.hasFallThrough; + + std::copy(FromBBI.Predicate.begin(), FromBBI.Predicate.end(), + std::back_inserter(ToBBI.Predicate)); + FromBBI.Predicate.clear(); } From resistor at mac.com Fri Jun 8 15:44:24 2007 From: resistor at mac.com (Owen Anderson) Date: Fri, 8 Jun 2007 15:44:24 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706082044.l58KiOn9028850@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.24 -> 1.25 --- Log message: Fix a bug that was causing the elimination phase not to replace values when it should be. With this patch, GVN-PRE now correctly optimizes the example from the thesis. Many thanks to Daniel Berlin for helping me find errors in this. --- Diffs of the changes: (+56 -13) GVNPRE.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 56 insertions(+), 13 deletions(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.24 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.25 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.24 Thu Jun 7 20:52:45 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Fri Jun 8 15:44:02 2007 @@ -45,7 +45,9 @@ BinaryOperator* BO1 = cast(left); BinaryOperator* BO2 = cast(right); - if ((*this)(BO1->getOperand(0), BO2->getOperand(0))) + if (BO1->getOpcode() != BO2->getOpcode()) + return BO1->getOpcode() < BO2->getOpcode(); + else if ((*this)(BO1->getOperand(0), BO2->getOperand(0))) return true; else if ((*this)(BO2->getOperand(0), BO1->getOperand(0))) return false; @@ -158,6 +160,7 @@ Instruction* newVal = BinaryOperator::create(BO->getOpcode(), newOp1, newOp2, BO->getName()+".gvnpre"); + if (add(newVal, nextValueNumber)) nextValueNumber++; if (!find_leader(set, newVal)) { @@ -165,6 +168,14 @@ createdExpressions.insert(newVal); return newVal; } else { + ValueTable::iterator I = VN.find(newVal); + if (I->first == newVal) + VN.erase(newVal); + + std::set::iterator F = MS.find(newVal); + if (*F == newVal) + MS.erase(newVal); + delete newVal; return 0; } @@ -486,7 +497,6 @@ // Phase 2: Insert - DOUT<< "\nPhase 2: Insertion\n"; std::map > new_sets; @@ -503,6 +513,8 @@ std::set& availOut = availableOut[BB]; std::set& anticIn = anticipatedIn[BB]; + new_set.clear(); + // Replace leaders with leaders inherited from dominator if (DI->getIDom() != 0) { std::set& dom_set = new_sets[DI->getIDom()->getBlock()]; @@ -510,9 +522,11 @@ E = dom_set.end(); I != E; ++I) { new_set.insert(*I); - std::set::iterator val = availOut.find(*I); - if (val != availOut.end()) + Value* val = find_leader(availOut, *I); + while (val != 0) { availOut.erase(val); + val = find_leader(availOut, *I); + } availOut.insert(*I); } } @@ -589,7 +603,14 @@ BO->getName()+".gvnpre", (*PI)->getTerminator()); add(newVal, VN[BO]); - availableOut[*PI].insert(newVal); + + std::set& predAvail = availableOut[*PI]; + Value* val = find_leader(predAvail, newVal); + while (val != 0) { + predAvail.erase(val); + val = find_leader(predAvail, newVal); + } + predAvail.insert(newVal); DOUT << "Creating value: " << std::hex << newVal << std::dec << "\n"; @@ -614,7 +635,13 @@ add(p, VN[e]); DOUT << "Creating value: " << std::hex << p << std::dec << "\n"; + Value* val = find_leader(availOut, p); + while (val != 0) { + availOut.erase(val); + val = find_leader(availOut, p); + } availOut.insert(p); + new_stuff = true; DOUT << "Preds After Processing: "; @@ -637,30 +664,46 @@ } // Phase 3: Eliminate + DOUT << "\n\nPhase 3: Elimination\n\n"; + + std::vector > replace; + std::vector erase; + for (df_iterator DI = df_begin(DT.getRootNode()), E = df_end(DT.getRootNode()); DI != E; ++DI) { BasicBlock* BB = DI->getBlock(); - std::vector erase; + DOUT << "Block: " << BB->getName() << "\n"; + dump_unique(availableOut[BB]); + DOUT << "\n\n"; for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI) { - if (!BI->isTerminator()) { - Value* leader = find_leader(availableOut[BB], BI); + + if (isa(BI)) { + Value *leader = find_leader(availableOut[BB], BI); + if (leader != 0) if (Instruction* Instr = dyn_cast(leader)) if (Instr->getParent() != 0 && Instr != BI) { - BI->replaceAllUsesWith(leader); + replace.push_back(std::make_pair(BI, leader)); erase.push_back(BI); } } } - - for (std::vector::iterator I = erase.begin(), E = erase.end(); - I != E; ++I) - (*I)->eraseFromParent(); } + while (!replace.empty()) { + std::pair rep = replace.back(); + replace.pop_back(); + + rep.first->replaceAllUsesWith(rep.second); + } + + for (std::vector::iterator I = erase.begin(), E = erase.end(); + I != E; ++I) + (*I)->eraseFromParent(); + // Phase 4: Cleanup for (std::set::iterator I = createdExpressions.begin(), E = createdExpressions.end(); I != E; ++I) { From resistor at mac.com Fri Jun 8 15:57:30 2007 From: resistor at mac.com (Owen Anderson) Date: Fri, 8 Jun 2007 15:57:30 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706082057.l58KvUCi029148@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.25 -> 1.26 --- Log message: Fix typo in a comment. --- Diffs of the changes: (+1 -1) GVNPRE.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.25 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.26 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.25 Fri Jun 8 15:44:02 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Fri Jun 8 15:57:08 2007 @@ -13,7 +13,7 @@ // the optimization. It replaces redundant values with uses of earlier // occurences of the same value. While this is beneficial in that it eliminates // unneeded computation, it also increases register pressure by creating large -// live ranges, and should be used with caution on platforms that a very +// live ranges, and should be used with caution on platforms that are very // sensitive to register pressure. // //===----------------------------------------------------------------------===// From lauro.venancio at gmail.com Fri Jun 8 16:06:45 2007 From: lauro.venancio at gmail.com (Lauro Ramos Venancio) Date: Fri, 8 Jun 2007 16:06:45 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/ARM/ARMTargetAsmInfo.cpp Message-ID: <200706082106.l58L6jN3029352@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/ARM: ARMTargetAsmInfo.cpp updated: 1.21 -> 1.22 --- Log message: Define AsmTransCBE for ARM. --- Diffs of the changes: (+25 -0) ARMTargetAsmInfo.cpp | 25 +++++++++++++++++++++++++ 1 files changed, 25 insertions(+) Index: llvm/lib/Target/ARM/ARMTargetAsmInfo.cpp diff -u llvm/lib/Target/ARM/ARMTargetAsmInfo.cpp:1.21 llvm/lib/Target/ARM/ARMTargetAsmInfo.cpp:1.22 --- llvm/lib/Target/ARM/ARMTargetAsmInfo.cpp:1.21 Mon May 14 13:32:55 2007 +++ llvm/lib/Target/ARM/ARMTargetAsmInfo.cpp Fri Jun 8 16:06:23 2007 @@ -18,8 +18,33 @@ #include using namespace llvm; +static const char* arm_asm_table[] = {"{r0}", "r0", + "{r1}", "r1", + "{r2}", "r2", + "{r3}", "r3", + "{r4}", "r4", + "{r5}", "r5", + "{r6}", "r6", + "{r7}", "r7", + "{r8}", "r8", + "{r9}", "r9", + "{r10}", "r10", + "{r11}", "r11", + "{r12}", "r12", + "{r13}", "r13", + "{r14}", "r14", + "{lr}", "lr", + "{sp}", "sp", + "{ip}", "ip", + "{fp}", "fp", + "{sl}", "sl", + "{memory}", "memory", + "{cc}", "cc", + 0,0}; + ARMTargetAsmInfo::ARMTargetAsmInfo(const ARMTargetMachine &TM) { Subtarget = &TM.getSubtarget(); + AsmTransCBE = arm_asm_table; if (Subtarget->isTargetDarwin()) { GlobalPrefix = "_"; PrivateGlobalPrefix = "L"; From evan.cheng at apple.com Fri Jun 8 16:59:26 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 16:59:26 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Target/TargetInstrInfo.h Message-ID: <200706082159.l58LxQmG030554@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Target: TargetInstrInfo.h updated: 1.126 -> 1.127 --- Log message: Add a utility routine to check for unpredicated terminator instruction. --- Diffs of the changes: (+6 -2) TargetInstrInfo.h | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) Index: llvm/include/llvm/Target/TargetInstrInfo.h diff -u llvm/include/llvm/Target/TargetInstrInfo.h:1.126 llvm/include/llvm/Target/TargetInstrInfo.h:1.127 --- llvm/include/llvm/Target/TargetInstrInfo.h:1.126 Wed Jun 6 05:13:55 2007 +++ llvm/include/llvm/Target/TargetInstrInfo.h Fri Jun 8 16:59:04 2007 @@ -399,19 +399,23 @@ abort(); } - /// isPredicable - Returns true if the instruction is already predicated. + /// isPredicated - Returns true if the instruction is already predicated. /// virtual bool isPredicated(const MachineInstr *MI) const { return false; } + /// isUnpredicatedTerminator - Returns true if the instruction is a + /// terminator instruction that has not been predicated. + bool isUnpredicatedTerminator(const MachineInstr *MI) const; + /// PredicateInstruction - Convert the instruction into a predicated /// instruction. It returns true if the operation was successful. virtual bool PredicateInstruction(MachineInstr *MI, const std::vector &Pred) const; - /// SubsumesPredicate - Returns true if the first specified predicated + /// SubsumesPredicate - Returns true if the first specified predicate /// subsumes the second, e.g. GE subsumes GT. virtual bool SubsumesPredicate(const std::vector &Pred1, From evan.cheng at apple.com Fri Jun 8 17:00:19 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 17:00:19 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/ARM/ARMInstrInfo.cpp Message-ID: <200706082200.l58M0JXb030615@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/ARM: ARMInstrInfo.cpp updated: 1.34 -> 1.35 --- Log message: Add a utility routine to check for unpredicated terminator instruction. --- Diffs of the changes: (+3 -3) ARMInstrInfo.cpp | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) Index: llvm/lib/Target/ARM/ARMInstrInfo.cpp diff -u llvm/lib/Target/ARM/ARMInstrInfo.cpp:1.34 llvm/lib/Target/ARM/ARMInstrInfo.cpp:1.35 --- llvm/lib/Target/ARM/ARMInstrInfo.cpp:1.34 Fri Jun 8 04:14:47 2007 +++ llvm/lib/Target/ARM/ARMInstrInfo.cpp Fri Jun 8 16:59:56 2007 @@ -304,7 +304,7 @@ std::vector &Cond) const { // If the block has no terminators, it just falls into the block after it. MachineBasicBlock::iterator I = MBB.end(); - if (I == MBB.begin() || !isTerminatorInstr((--I)->getOpcode())) + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) return false; // Get the last instruction in the block. @@ -313,7 +313,7 @@ // If there is only one terminator instruction, process it. unsigned LastOpc = LastInst->getOpcode(); if (I == MBB.begin() || - isPredicated(--I) || !isTerminatorInstr(I->getOpcode())) { + isPredicated(--I) || !isUnpredicatedTerminator(I)) { if (LastOpc == ARM::B || LastOpc == ARM::tB) { TBB = LastInst->getOperand(0).getMachineBasicBlock(); return false; @@ -332,7 +332,7 @@ // If there are three terminators, we don't know what sort of block this is. if (SecondLastInst && I != MBB.begin() && - !isPredicated(--I) && isTerminatorInstr(I->getOpcode())) + !isPredicated(--I) && isUnpredicatedTerminator(I)) return true; // If the block ends with ARM::B/ARM::tB and a ARM::Bcc/ARM::tBcc, handle it. From evan.cheng at apple.com Fri Jun 8 17:00:30 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 17:00:30 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPCInstrInfo.cpp Message-ID: <200706082200.l58M0U4X030623@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPCInstrInfo.cpp updated: 1.39 -> 1.40 --- Log message: Add a utility routine to check for unpredicated terminator instruction. --- Diffs of the changes: (+3 -3) PPCInstrInfo.cpp | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) Index: llvm/lib/Target/PowerPC/PPCInstrInfo.cpp diff -u llvm/lib/Target/PowerPC/PPCInstrInfo.cpp:1.39 llvm/lib/Target/PowerPC/PPCInstrInfo.cpp:1.40 --- llvm/lib/Target/PowerPC/PPCInstrInfo.cpp:1.39 Mon May 21 13:43:25 2007 +++ llvm/lib/Target/PowerPC/PPCInstrInfo.cpp Fri Jun 8 16:59:56 2007 @@ -180,14 +180,14 @@ std::vector &Cond) const { // If the block has no terminators, it just falls into the block after it. MachineBasicBlock::iterator I = MBB.end(); - if (I == MBB.begin() || !isTerminatorInstr((--I)->getOpcode())) + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) return false; // Get the last instruction in the block. MachineInstr *LastInst = I; // If there is only one terminator instruction, process it. - if (I == MBB.begin() || !isTerminatorInstr((--I)->getOpcode())) { + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { if (LastInst->getOpcode() == PPC::B) { TBB = LastInst->getOperand(0).getMachineBasicBlock(); return false; @@ -207,7 +207,7 @@ // If there are three terminators, we don't know what sort of block this is. if (SecondLastInst && I != MBB.begin() && - isTerminatorInstr((--I)->getOpcode())) + isUnpredicatedTerminator(--I)) return true; // If the block ends with PPC::B and PPC:BCC, handle it. From evan.cheng at apple.com Fri Jun 8 17:00:30 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 17:00:30 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86InstrInfo.cpp Message-ID: <200706082200.l58M0UTO030626@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86InstrInfo.cpp updated: 1.87 -> 1.88 --- Log message: Add a utility routine to check for unpredicated terminator instruction. --- Diffs of the changes: (+2 -2) X86InstrInfo.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/Target/X86/X86InstrInfo.cpp diff -u llvm/lib/Target/X86/X86InstrInfo.cpp:1.87 llvm/lib/Target/X86/X86InstrInfo.cpp:1.88 --- llvm/lib/Target/X86/X86InstrInfo.cpp:1.87 Mon May 21 13:43:02 2007 +++ llvm/lib/Target/X86/X86InstrInfo.cpp Fri Jun 8 16:59:56 2007 @@ -382,14 +382,14 @@ // If the block has no terminators, it just falls into the block after it. MachineBasicBlock::iterator I = MBB.end(); - if (I == MBB.begin() || !isTerminatorInstr((--I)->getOpcode())) + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) return false; // Get the last instruction in the block. MachineInstr *LastInst = I; // If there is only one terminator instruction, process it. - if (I == MBB.begin() || !isTerminatorInstr((--I)->getOpcode())) { + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { if (!isBranch(LastInst->getOpcode())) return true; From evan.cheng at apple.com Fri Jun 8 17:00:30 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 17:00:30 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/TargetInstrInfo.cpp Message-ID: <200706082200.l58M0UY8030633@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target: TargetInstrInfo.cpp updated: 1.32 -> 1.33 --- Log message: Add a utility routine to check for unpredicated terminator instruction. --- Diffs of the changes: (+7 -0) TargetInstrInfo.cpp | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm/lib/Target/TargetInstrInfo.cpp diff -u llvm/lib/Target/TargetInstrInfo.cpp:1.32 llvm/lib/Target/TargetInstrInfo.cpp:1.33 --- llvm/lib/Target/TargetInstrInfo.cpp:1.32 Tue May 29 13:35:22 2007 +++ llvm/lib/Target/TargetInstrInfo.cpp Fri Jun 8 16:59:56 2007 @@ -84,3 +84,10 @@ } return MadeChange; } + +bool TargetInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const { + const TargetInstrDescriptor *TID = MI->getInstrDescriptor(); + if (TID->Flags & M_TERMINATOR_FLAG) + return !isPredicated(MI); + return false; +} From evan.cheng at apple.com Fri Jun 8 17:00:31 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 17:00:31 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaInstrInfo.cpp Message-ID: <200706082200.l58M0V0J030636@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Alpha: AlphaInstrInfo.cpp updated: 1.19 -> 1.20 --- Log message: Add a utility routine to check for unpredicated terminator instruction. --- Diffs of the changes: (+3 -3) AlphaInstrInfo.cpp | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) Index: llvm/lib/Target/Alpha/AlphaInstrInfo.cpp diff -u llvm/lib/Target/Alpha/AlphaInstrInfo.cpp:1.19 llvm/lib/Target/Alpha/AlphaInstrInfo.cpp:1.20 --- llvm/lib/Target/Alpha/AlphaInstrInfo.cpp:1.19 Mon May 21 13:44:17 2007 +++ llvm/lib/Target/Alpha/AlphaInstrInfo.cpp Fri Jun 8 16:59:56 2007 @@ -158,14 +158,14 @@ std::vector &Cond) const { // If the block has no terminators, it just falls into the block after it. MachineBasicBlock::iterator I = MBB.end(); - if (I == MBB.begin() || !isTerminatorInstr((--I)->getOpcode())) + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) return false; // Get the last instruction in the block. MachineInstr *LastInst = I; // If there is only one terminator instruction, process it. - if (I == MBB.begin() || !isTerminatorInstr((--I)->getOpcode())) { + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { if (LastInst->getOpcode() == Alpha::BR) { TBB = LastInst->getOperand(0).getMachineBasicBlock(); return false; @@ -186,7 +186,7 @@ // If there are three terminators, we don't know what sort of block this is. if (SecondLastInst && I != MBB.begin() && - isTerminatorInstr((--I)->getOpcode())) + isUnpredicatedTerminator(--I)) return true; // If the block ends with Alpha::BR and Alpha::COND_BRANCH_*, handle it. From evan.cheng at apple.com Fri Jun 8 17:01:29 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 17:01:29 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706082201.l58M1Tj1030678@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.40 -> 1.41 --- Log message: Carefully remove extraneous CFG edges after each ifcvt. --- Diffs of the changes: (+51 -24) IfConversion.cpp | 75 +++++++++++++++++++++++++++++++++++++------------------ 1 files changed, 51 insertions(+), 24 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.40 llvm/lib/CodeGen/IfConversion.cpp:1.41 --- llvm/lib/CodeGen/IfConversion.cpp:1.40 Fri Jun 8 14:17:12 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Fri Jun 8 17:01:07 2007 @@ -126,6 +126,7 @@ bool AnalyzeBlocks(MachineFunction &MF, std::vector &Candidates); void ReTryPreds(MachineBasicBlock *BB); + void RemoveExtraEdges(BBInfo &BBI); bool IfConvertSimple(BBInfo &BBI); bool IfConvertTriangle(BBInfo &BBI); bool IfConvertDiamond(BBInfo &BBI); @@ -542,9 +543,10 @@ return Change; } -/// isNextBlock - Returns true either if ToBB the next block after BB or -/// that all the intervening blocks are empty. -static bool isNextBlock(MachineBasicBlock *BB, MachineBasicBlock *ToBB) { +/// canFallThroughTo - Returns true either if ToBB is the next block after BB or +/// that all the intervening blocks are empty (given BB can fall through to its +/// next block). +static bool canFallThroughTo(MachineBasicBlock *BB, MachineBasicBlock *ToBB) { MachineFunction::iterator I = BB; MachineFunction::iterator TI = ToBB; MachineFunction::iterator E = BB->getParent()->end(); @@ -554,13 +556,24 @@ return true; } +/// getNextBlock - Returns the next block in the function blocks ordering. If +/// it is the end, returns NULL. +static inline MachineBasicBlock *getNextBlock(MachineBasicBlock *BB) { + MachineFunction::iterator I = BB; + MachineFunction::iterator E = BB->getParent()->end(); + if (++I == E) + return NULL; + return I; +} + /// ReTryPreds - Invalidate predecessor BB info so it would be re-analyzed /// to determine if it can be if-converted. void IfConverter::ReTryPreds(MachineBasicBlock *BB) { for (MachineBasicBlock::pred_iterator PI = BB->pred_begin(), E = BB->pred_end(); PI != E; ++PI) { BBInfo &PBBI = BBAnalysis[(*PI)->getNumber()]; - PBBI.Kind = ICReAnalyze; + if (PBBI.Kind == ICNotClassfied) + PBBI.Kind = ICReAnalyze; } } @@ -572,6 +585,23 @@ TII->InsertBranch(*BB, ToBB, NULL, NoCond); } +/// RemoveExtraEdges - Remove true / false edges if either / both are no longer +/// successors. +void IfConverter::RemoveExtraEdges(BBInfo &BBI) { + MachineBasicBlock *TBB = NULL, *FBB = NULL; + std::vector Cond; + bool isAnalyzable = !TII->AnalyzeBranch(*BBI.BB, TBB, FBB, Cond); + bool CanFallthrough = isAnalyzable && (TBB == NULL || FBB == NULL); + if (BBI.TrueBB && BBI.BB->isSuccessor(BBI.TrueBB)) + if (!(BBI.TrueBB == TBB || BBI.TrueBB == FBB || + (CanFallthrough && getNextBlock(BBI.BB) == BBI.TrueBB))) + BBI.BB->removeSuccessor(BBI.TrueBB); + if (BBI.FalseBB && BBI.BB->isSuccessor(BBI.FalseBB)) + if (!(BBI.FalseBB == TBB || BBI.FalseBB == FBB || + (CanFallthrough && getNextBlock(BBI.BB) == BBI.FalseBB))) + BBI.BB->removeSuccessor(BBI.FalseBB); +} + /// IfConvertSimple - If convert a simple (split, no rejoin) sub-CFG. /// bool IfConverter::IfConvertSimple(BBInfo &BBI) { @@ -588,14 +618,12 @@ PredicateBlock(*CvtBBI, Cond); - // Merge converted block into entry block. Also add an unconditional branch - // to the 'false' branch. + // Merge converted block into entry block. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); MergeBlocks(BBI, *CvtBBI); - BBI.BB->removeSuccessor(CvtBBI->BB); bool IterIfcvt = true; - if (!isNextBlock(BBI.BB, NextBBI->BB)) { + if (!canFallThroughTo(BBI.BB, NextBBI->BB)) { InsertUncondBranch(BBI.BB, NextBBI->BB, TII); BBI.hasFallThrough = false; // Now ifcvt'd block will look like this: @@ -611,6 +639,8 @@ IterIfcvt = false; } + RemoveExtraEdges(BBI); + // Update block info. BB can be iteratively if-converted. if (IterIfcvt) BBI.Kind = ICReAnalyze; @@ -650,7 +680,7 @@ BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; bool FalseBBDead = false; bool IterIfcvt = true; - bool isFallThrough = isNextBlock(BBI.BB, FalseBBI.BB); + bool isFallThrough = canFallThroughTo(BBI.BB, FalseBBI.BB); if (!isFallThrough) { // Only merge them if the true block does not fallthrough to the false // block. By not merging them, we make it possible to iteratively @@ -667,9 +697,7 @@ IterIfcvt = false; } - // Remove entry to false edge if false block is merged in as well. - if (FalseBBDead) - BBI.BB->removeSuccessor(FalseBBI.BB); + RemoveExtraEdges(BBI); // Update block info. BB can be iteratively if-converted. if (IterIfcvt) @@ -767,7 +795,7 @@ if (NeedBr2 && !NeedBr1) { // If BBI2 isn't going to be merged in, then the existing fallthrough // or branch is fine. - if (!isNextBlock(BBI.BB, *BBI2->BB->succ_begin())) { + if (!canFallThroughTo(BBI.BB, *BBI2->BB->succ_begin())) { InsertUncondBranch(BBI2->BB, *BBI2->BB->succ_begin(), TII); BBI2->hasFallThrough = false; } @@ -785,7 +813,7 @@ // 'True' and 'false' aren't combined, see if we need to add a unconditional // branch to the 'false' block. - if (NeedBr1 && !isNextBlock(BBI.BB, BBI2->BB)) { + if (NeedBr1 && !canFallThroughTo(BBI.BB, BBI2->BB)) { InsertUncondBranch(BBI.BB, BBI2->BB, TII); BBI1->hasFallThrough = false; } @@ -802,6 +830,8 @@ TailBBI.Kind = ICDead; } + RemoveExtraEdges(BBI); + // Update block info. BBI.Kind = ICDead; TrueBBI.Kind = ICDead; @@ -834,14 +864,6 @@ NumIfConvBBs++; } -static MachineBasicBlock *getNextBlock(MachineBasicBlock *BB) { - MachineFunction::iterator I = BB; - MachineFunction::iterator E = BB->getParent()->end(); - if (++I == E) - return NULL; - return I; -} - /// MergeBlocks - Move all instructions from FromBB to the end of ToBB. /// void IfConverter::MergeBlocks(BBInfo &ToBBI, BBInfo &FromBBI) { @@ -860,11 +882,12 @@ std::vector Succs(FromBBI.BB->succ_begin(), FromBBI.BB->succ_end()); - MachineBasicBlock *FallThrough = FromBBI.hasFallThrough - ? getNextBlock(FromBBI.BB) : NULL; + MachineBasicBlock *NBB = getNextBlock(FromBBI.BB); + MachineBasicBlock *FallThrough = FromBBI.hasFallThrough ? NBB : NULL; for (unsigned i = 0, e = Succs.size(); i != e; ++i) { MachineBasicBlock *Succ = Succs[i]; + // Fallthrough edge can't be transferred. if (Succ == FallThrough) continue; FromBBI.BB->removeSuccessor(Succ); @@ -872,6 +895,10 @@ ToBBI.BB->addSuccessor(Succ); } + // Now FromBBI always fall through to the next block! + if (NBB) + FromBBI.BB->addSuccessor(NBB); + ToBBI.NonPredSize += FromBBI.NonPredSize; FromBBI.NonPredSize = 0; From resistor at mac.com Fri Jun 8 17:02:58 2007 From: resistor at mac.com (Owen Anderson) Date: Fri, 8 Jun 2007 17:02:58 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706082202.l58M2wx4030720@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.26 -> 1.27 --- Log message: Collect statistics from GVN-PRE. --- Diffs of the changes: (+9 -0) GVNPRE.cpp | 9 +++++++++ 1 files changed, 9 insertions(+) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.26 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.27 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.26 Fri Jun 8 15:57:08 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Fri Jun 8 17:02:36 2007 @@ -114,6 +114,10 @@ "Global Value Numbering/Partial Redundancy Elimination"); +STATISTIC(NumInsertedVals, "Number of values inserted"); +STATISTIC(NumInsertedPhis, "Number of PHI nodes inserted"); +STATISTIC(NumEliminated, "Number of redundant instructions eliminated"); + bool GVNPRE::add(Value* V, uint32_t number) { std::pair ret = VN.insert(std::make_pair(V, number)); @@ -618,6 +622,8 @@ if (av != avail.end()) avail.erase(av); avail.insert(std::make_pair(*PI, newVal)); + + ++NumInsertedVals; } } @@ -655,6 +661,8 @@ DOUT << "\n\n"; new_set.insert(p); + + ++NumInsertedPhis; } } } @@ -688,6 +696,7 @@ if (Instr->getParent() != 0 && Instr != BI) { replace.push_back(std::make_pair(BI, leader)); erase.push_back(BI); + ++NumEliminated; } } } From dalej at apple.com Fri Jun 8 17:10:41 2007 From: dalej at apple.com (Dale Johannesen) Date: Fri, 8 Jun 2007 15:10:41 -0700 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp In-Reply-To: <200706082201.l58M1Tj1030678@zion.cs.uiuc.edu> References: <200706082201.l58M1Tj1030678@zion.cs.uiuc.edu> Message-ID: On Jun 8, 2007, at 3:01 PM, Evan Cheng wrote: > +/// RemoveExtraEdges - Remove true / false edges if either / both > are no longer > +/// successors. This does pretty much the same thing as CorrectExtraCFGEdges in BranchFolding.cpp, although I'm sure there are subtleties. Can we combine them? From evan.cheng at apple.com Fri Jun 8 20:04:05 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 8 Jun 2007 20:04:05 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706090104.l59145ks001871@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.41 -> 1.42 --- Log message: Don't change CFG during analysis stage. Do so during ifcvt and invalidate predecessors accordingly. --- Diffs of the changes: (+106 -56) IfConversion.cpp | 162 +++++++++++++++++++++++++++++++++++-------------------- 1 files changed, 106 insertions(+), 56 deletions(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.41 llvm/lib/CodeGen/IfConversion.cpp:1.42 --- llvm/lib/CodeGen/IfConversion.cpp:1.41 Fri Jun 8 17:01:07 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Fri Jun 8 20:03:43 2007 @@ -32,19 +32,25 @@ cl::opt IfCvtLimit("ifcvt-limit", cl::init(-1), cl::Hidden); cl::opt DisableSimple("disable-ifcvt-simple", cl::init(false), cl::Hidden); - cl::opt DisableSimpleFalse("disable-ifcvt-simple-false", - cl::init(false), cl::Hidden); + cl::opt DisableSimpleF("disable-ifcvt-simple-false", + cl::init(false), cl::Hidden); cl::opt DisableTriangle("disable-ifcvt-triangle", cl::init(false), cl::Hidden); + cl::opt DisableTriangleF("disable-ifcvt-triangle-false", + cl::init(false), cl::Hidden); + cl::opt DisableTriangleFR("disable-ifcvt-triangle-false-rev", + cl::init(false), cl::Hidden); cl::opt DisableDiamond("disable-ifcvt-diamond", cl::init(false), cl::Hidden); } -STATISTIC(NumSimple, "Number of simple if-conversions performed"); -STATISTIC(NumSimpleRev, "Number of simple (reversed) if-conversions performed"); -STATISTIC(NumTriangle, "Number of triangle if-conversions performed"); -STATISTIC(NumDiamonds, "Number of diamond if-conversions performed"); -STATISTIC(NumIfConvBBs, "Number of if-converted blocks"); +STATISTIC(NumSimple, "Number of simple if-conversions performed"); +STATISTIC(NumSimpleFalse, "Number of simple (F) if-conversions performed"); +STATISTIC(NumTriangle, "Number of triangle if-conversions performed"); +STATISTIC(NumTriangleFalse,"Number of triangle (F) if-conversions performed"); +STATISTIC(NumTriangleFRev, "Number of triangle (F/R) if-conversions performed"); +STATISTIC(NumDiamonds, "Number of diamond if-conversions performed"); +STATISTIC(NumIfConvBBs, "Number of if-converted blocks"); namespace { class IfConverter : public MachineFunctionPass { @@ -55,6 +61,8 @@ ICSimple, // BB is entry of an one split, no rejoin sub-CFG. ICSimpleFalse, // Same as ICSimple, but on the false path. ICTriangle, // BB is entry of a triangle sub-CFG. + ICTriangleFalse, // Same as ICTriangle, but on the false path. + ICTriangleFRev, // Same as ICTriangleFalse, but false path rev condition. ICDiamond, // BB is entry of a diamond sub-CFG. ICChild, // BB is part of the sub-CFG that'll be predicated. ICDead // BB cannot be if-converted again. @@ -80,7 +88,7 @@ BBICKind Kind; unsigned NonPredSize; bool IsAnalyzable; - bool hasFallThrough; + bool HasFallThrough; bool ModifyPredicate; MachineBasicBlock *BB; MachineBasicBlock *TrueBB; @@ -89,7 +97,7 @@ std::vector BrCond; std::vector Predicate; BBInfo() : Kind(ICNotAnalyzed), NonPredSize(0), - IsAnalyzable(false), hasFallThrough(false), + IsAnalyzable(false), HasFallThrough(false), ModifyPredicate(false), BB(0), TrueBB(0), FalseBB(0), TailBB(0) {} }; @@ -195,8 +203,8 @@ break; case ICSimple: case ICSimpleFalse: { - bool isRev = BBI.Kind == ICSimpleFalse; - if ((isRev && DisableSimpleFalse) || (!isRev && DisableSimple)) break; + bool isFalse = BBI.Kind == ICSimpleFalse; + if ((isFalse && DisableSimpleF) || (!isFalse && DisableSimple)) break; DOUT << "Ifcvt (Simple" << (BBI.Kind == ICSimpleFalse ? " false" : "") << "): BB#" << BBI.BB->getNumber() << " (" << ((BBI.Kind == ICSimpleFalse) @@ -204,18 +212,33 @@ RetVal = IfConvertSimple(BBI); DOUT << (RetVal ? "succeeded!" : "failed!") << "\n"; if (RetVal) - if (isRev) NumSimpleRev++; - else NumSimple++; + if (isFalse) NumSimpleFalse++; + else NumSimple++; break; } case ICTriangle: - if (DisableTriangle) break; - DOUT << "Ifcvt (Triangle): BB#" << BBI.BB->getNumber() << " (T:" + case ICTriangleFalse: + case ICTriangleFRev: + bool isFalse = BBI.Kind == ICTriangleFalse; + bool isFalseRev = BBI.Kind == ICTriangleFRev; + if (DisableTriangle && !isFalse && !isFalseRev) break; + if (DisableTriangleF && isFalse) break; + if (DisableTriangleFR && isFalseRev) break; + DOUT << "Ifcvt (Triangle"; + if (isFalse) + DOUT << " false"; + if (isFalseRev) + DOUT << " false/rev"; + DOUT << "): BB#" << BBI.BB->getNumber() << " (T:" << BBI.TrueBB->getNumber() << ",F:" << BBI.FalseBB->getNumber() << ") "; RetVal = IfConvertTriangle(BBI); DOUT << (RetVal ? "succeeded!" : "failed!") << "\n"; - if (RetVal) NumTriangle++; + if (RetVal) { + if (isFalseRev) NumTriangleFRev++; + else if (isFalse) NumTriangleFalse++; + else NumTriangle++; + } break; case ICDiamond: if (DisableDiamond) break; @@ -231,7 +254,7 @@ } Change |= RetVal; - if (IfCvtLimit != -1 && (int)NumIfConvBBs > IfCvtLimit) + if (IfCvtLimit != -1 && (int)NumIfConvBBs >= IfCvtLimit) break; } @@ -267,6 +290,16 @@ return false; } +/// getNextBlock - Returns the next block in the function blocks ordering. If +/// it is the end, returns NULL. +static inline MachineBasicBlock *getNextBlock(MachineBasicBlock *BB) { + MachineFunction::iterator I = BB; + MachineFunction::iterator E = BB->getParent()->end(); + if (++I == E) + return NULL; + return I; +} + /// ValidSimple - Returns true if the 'true' block (along with its /// predecessor) forms a valid simple shape for ifcvt. bool IfConverter::ValidSimple(BBInfo &TrueBBI) const { @@ -294,9 +327,19 @@ /// ValidDiamond - Returns true if the 'true' and 'false' blocks (along /// with their common predecessor) forms a valid diamond shape for ifcvt. bool IfConverter::ValidDiamond(BBInfo &TrueBBI, BBInfo &FalseBBI) const { - // FIXME: Also look for fallthrough - return (TrueBBI.TrueBB == FalseBBI.TrueBB && - TrueBBI.BB->pred_size() == 1 && + MachineBasicBlock *TT = TrueBBI.TrueBB; + MachineBasicBlock *FT = FalseBBI.TrueBB; + + if (!TT && blockAlwaysFallThrough(TrueBBI)) + TT = getNextBlock(TrueBBI.BB); + if (!FT && blockAlwaysFallThrough(FalseBBI)) + FT = getNextBlock(FalseBBI.BB); + if (TT != FT) + return false; + if (TT == NULL && (TrueBBI.IsAnalyzable || FalseBBI.IsAnalyzable)) + return false; + // FIXME: Allow false block to have an early exit? + return (TrueBBI.BB->pred_size() == 1 && FalseBBI.BB->pred_size() == 1 && !TrueBBI.FalseBB && !FalseBBI.FalseBB); } @@ -321,7 +364,7 @@ BBI.Kind = ICNotClassfied; BBI.IsAnalyzable = !TII->AnalyzeBranch(*BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond); - BBI.hasFallThrough = BBI.IsAnalyzable && BBI.FalseBB == NULL; + BBI.HasFallThrough = BBI.IsAnalyzable && BBI.FalseBB == NULL; // Unanalyable or ends with fallthrough or unconditional branch. if (!BBI.IsAnalyzable || BBI.BrCond.size() == 0) return; @@ -395,15 +438,11 @@ // Try the other path... if (ValidTriangle(FalseBBI, TrueBBI) && FeasibilityAnalysis(FalseBBI, RevCond, true)) { - // Reverse 'true' and 'false' paths. - ReverseBranchCondition(BBI); - BBI.Kind = ICTriangle; + BBI.Kind = ICTriangleFalse; FalseBBI.Kind = ICChild; } else if (ValidTriangle(FalseBBI, TrueBBI, true) && FeasibilityAnalysis(FalseBBI, RevCond, true, true)) { - ReverseBranchCondition(FalseBBI); - ReverseBranchCondition(BBI); - BBI.Kind = ICTriangle; + BBI.Kind = ICTriangleFRev; FalseBBI.Kind = ICChild; } else if (ValidSimple(FalseBBI) && FeasibilityAnalysis(FalseBBI, RevCond)) { @@ -556,16 +595,6 @@ return true; } -/// getNextBlock - Returns the next block in the function blocks ordering. If -/// it is the end, returns NULL. -static inline MachineBasicBlock *getNextBlock(MachineBasicBlock *BB) { - MachineFunction::iterator I = BB; - MachineFunction::iterator E = BB->getParent()->end(); - if (++I == E) - return NULL; - return I; -} - /// ReTryPreds - Invalidate predecessor BB info so it would be re-analyzed /// to determine if it can be if-converted. void IfConverter::ReTryPreds(MachineBasicBlock *BB) { @@ -625,7 +654,7 @@ bool IterIfcvt = true; if (!canFallThroughTo(BBI.BB, NextBBI->BB)) { InsertUncondBranch(BBI.BB, NextBBI->BB, TII); - BBI.hasFallThrough = false; + BBI.HasFallThrough = false; // Now ifcvt'd block will look like this: // BB: // ... @@ -657,40 +686,61 @@ /// bool IfConverter::IfConvertTriangle(BBInfo &BBI) { BBInfo &TrueBBI = BBAnalysis[BBI.TrueBB->getNumber()]; + BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; + BBInfo *CvtBBI = &TrueBBI; + BBInfo *NextBBI = &FalseBBI; + + std::vector Cond(BBI.BrCond); + if (BBI.Kind == ICTriangleFalse || BBI.Kind == ICTriangleFRev) { + if (BBI.Kind == ICTriangleFRev) { + ReverseBranchCondition(*NextBBI); + // False BB has been changed, modify its predecessors (except for this + // one) so they don't get ifcvt'ed based on bad intel. + for (MachineBasicBlock::pred_iterator PI = NextBBI->BB->pred_begin(), + E = NextBBI->BB->pred_end(); PI != E; ++PI) { + MachineBasicBlock *PBB = *PI; + if (PBB == BBI.BB) + continue; + BBInfo &PBBI = BBAnalysis[PBB->getNumber()]; + PBBI.Kind = ICReAnalyze; + } + } + std::swap(CvtBBI, NextBBI); + TII->ReverseBranchCondition(Cond); + } // Predicate the 'true' block after removing its branch. - TrueBBI.NonPredSize -= TII->RemoveBranch(*BBI.TrueBB); - PredicateBlock(TrueBBI, BBI.BrCond); + TrueBBI.NonPredSize -= TII->RemoveBranch(*CvtBBI->BB); + PredicateBlock(*CvtBBI, Cond); // If 'true' block has a 'false' successor, add an exit branch to it. - bool HasEarlyExit = TrueBBI.FalseBB != NULL; + bool HasEarlyExit = CvtBBI->FalseBB != NULL; if (HasEarlyExit) { - std::vector RevCond(TrueBBI.BrCond); + std::vector RevCond(CvtBBI->BrCond); if (TII->ReverseBranchCondition(RevCond)) assert(false && "Unable to reverse branch condition!"); - TII->InsertBranch(*BBI.TrueBB, TrueBBI.FalseBB, NULL, RevCond); + TII->InsertBranch(*CvtBBI->BB, CvtBBI->FalseBB, NULL, RevCond); } // Now merge the entry of the triangle with the true block. BBI.NonPredSize -= TII->RemoveBranch(*BBI.BB); - MergeBlocks(BBI, TrueBBI); + MergeBlocks(BBI, *CvtBBI); // Merge in the 'false' block if the 'false' block has no other // predecessors. Otherwise, add a unconditional branch from to 'false'. - BBInfo &FalseBBI = BBAnalysis[BBI.FalseBB->getNumber()]; bool FalseBBDead = false; bool IterIfcvt = true; - bool isFallThrough = canFallThroughTo(BBI.BB, FalseBBI.BB); + bool isFallThrough = canFallThroughTo(BBI.BB, NextBBI->BB); if (!isFallThrough) { // Only merge them if the true block does not fallthrough to the false // block. By not merging them, we make it possible to iteratively // ifcvt the blocks. - if (!HasEarlyExit && FalseBBI.BB->pred_size() == 1) { - MergeBlocks(BBI, FalseBBI); + if (!HasEarlyExit && NextBBI->BB->pred_size() == 1) { + MergeBlocks(BBI, *NextBBI); FalseBBDead = true; } else { - InsertUncondBranch(BBI.BB, FalseBBI.BB, TII); - TrueBBI.hasFallThrough = false; + InsertUncondBranch(BBI.BB, NextBBI->BB, TII); + BBI.HasFallThrough = false; } // Mixed predicated and unpredicated code. This cannot be iteratively // predicated. @@ -705,9 +755,9 @@ else BBI.Kind = ICDead; ReTryPreds(BBI.BB); - TrueBBI.Kind = ICDead; + CvtBBI->Kind = ICDead; if (FalseBBDead) - FalseBBI.Kind = ICDead; + NextBBI->Kind = ICDead; // FIXME: Must maintain LiveIns. return true; @@ -797,7 +847,7 @@ // or branch is fine. if (!canFallThroughTo(BBI.BB, *BBI2->BB->succ_begin())) { InsertUncondBranch(BBI2->BB, *BBI2->BB->succ_begin(), TII); - BBI2->hasFallThrough = false; + BBI2->HasFallThrough = false; } } @@ -815,7 +865,7 @@ // branch to the 'false' block. if (NeedBr1 && !canFallThroughTo(BBI.BB, BBI2->BB)) { InsertUncondBranch(BBI.BB, BBI2->BB, TII); - BBI1->hasFallThrough = false; + BBI1->HasFallThrough = false; } // If the if-converted block fallthrough or unconditionally branch into the @@ -883,7 +933,7 @@ std::vector Succs(FromBBI.BB->succ_begin(), FromBBI.BB->succ_end()); MachineBasicBlock *NBB = getNextBlock(FromBBI.BB); - MachineBasicBlock *FallThrough = FromBBI.hasFallThrough ? NBB : NULL; + MachineBasicBlock *FallThrough = FromBBI.HasFallThrough ? NBB : NULL; for (unsigned i = 0, e = Succs.size(); i != e; ++i) { MachineBasicBlock *Succ = Succs[i]; @@ -903,7 +953,7 @@ FromBBI.NonPredSize = 0; ToBBI.ModifyPredicate |= FromBBI.ModifyPredicate; - ToBBI.hasFallThrough = FromBBI.hasFallThrough; + ToBBI.HasFallThrough = FromBBI.HasFallThrough; std::copy(FromBBI.Predicate.begin(), FromBBI.Predicate.end(), std::back_inserter(ToBBI.Predicate)); From nicholas at mxc.ca Fri Jun 8 23:20:55 2007 From: nicholas at mxc.ca (Nick Lewycky) Date: Fri, 8 Jun 2007 23:20:55 -0500 Subject: [llvm-commits] CVS: llvm/lib/Support/ConstantRange.cpp Message-ID: <200706090420.l594Ktiu006165@zion.cs.uiuc.edu> Changes in directory llvm/lib/Support: ConstantRange.cpp updated: 1.45 -> 1.46 --- Log message: Fix edge case. --- Diffs of the changes: (+2 -2) ConstantRange.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/Support/ConstantRange.cpp diff -u llvm/lib/Support/ConstantRange.cpp:1.45 llvm/lib/Support/ConstantRange.cpp:1.46 --- llvm/lib/Support/ConstantRange.cpp:1.45 Thu Apr 26 11:40:25 2007 +++ llvm/lib/Support/ConstantRange.cpp Fri Jun 8 23:20:33 2007 @@ -108,7 +108,7 @@ APInt ConstantRange::getSignedMax() const { APInt SignedMax(APInt::getSignedMaxValue(getBitWidth())); if (!isWrappedSet()) { - if (getLower().slt(getUpper() - 1)) + if (getLower().sle(getUpper() - 1)) return getUpper() - 1; else return SignedMax; @@ -130,7 +130,7 @@ APInt ConstantRange::getSignedMin() const { APInt SignedMin(APInt::getSignedMinValue(getBitWidth())); if (!isWrappedSet()) { - if (getLower().slt(getUpper() - 1)) + if (getLower().sle(getUpper() - 1)) return getLower(); else return SignedMin; From sabre at nondot.org Sat Jun 9 00:02:12 2007 From: sabre at nondot.org (Chris Lattner) Date: Sat, 9 Jun 2007 00:02:12 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86ISelLowering.cpp Message-ID: <200706090502.l5952CvT006954@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86ISelLowering.cpp updated: 1.406 -> 1.407 --- Log message: fix mmx handling bug --- Diffs of the changes: (+4 -1) X86ISelLowering.cpp | 5 ++++- 1 files changed, 4 insertions(+), 1 deletion(-) Index: llvm/lib/Target/X86/X86ISelLowering.cpp diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.406 llvm/lib/Target/X86/X86ISelLowering.cpp:1.407 --- llvm/lib/Target/X86/X86ISelLowering.cpp:1.406 Thu May 24 09:33:05 2007 +++ llvm/lib/Target/X86/X86ISelLowering.cpp Sat Jun 9 00:01:50 2007 @@ -1183,7 +1183,10 @@ RC = X86::FR64RegisterClass; else { assert(MVT::isVector(RegVT)); - RC = X86::VR128RegisterClass; + if (MVT::getSizeInBits(RegVT) == 64) + RC = X86::VR64RegisterClass; + else + RC = X86::VR128RegisterClass; } unsigned Reg = AddLiveIn(DAG.getMachineFunction(), VA.getLocReg(), RC); From sabre at nondot.org Sat Jun 9 00:08:32 2007 From: sabre at nondot.org (Chris Lattner) Date: Sat, 9 Jun 2007 00:08:32 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/X86/X86ISelLowering.cpp Message-ID: <200706090508.l5958Wdx007130@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/X86: X86ISelLowering.cpp updated: 1.407 -> 1.408 --- Log message: fix x86-64 mmx calling convention for real, which passes in integer gprs. --- Diffs of the changes: (+9 -3) X86ISelLowering.cpp | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-) Index: llvm/lib/Target/X86/X86ISelLowering.cpp diff -u llvm/lib/Target/X86/X86ISelLowering.cpp:1.407 llvm/lib/Target/X86/X86ISelLowering.cpp:1.408 --- llvm/lib/Target/X86/X86ISelLowering.cpp:1.407 Sat Jun 9 00:01:50 2007 +++ llvm/lib/Target/X86/X86ISelLowering.cpp Sat Jun 9 00:08:10 2007 @@ -1183,9 +1183,10 @@ RC = X86::FR64RegisterClass; else { assert(MVT::isVector(RegVT)); - if (MVT::getSizeInBits(RegVT) == 64) - RC = X86::VR64RegisterClass; - else + if (MVT::getSizeInBits(RegVT) == 64) { + RC = X86::GR64RegisterClass; // MMX values are passed in GPRs. + RegVT = MVT::i64; + } else RC = X86::VR128RegisterClass; } @@ -1205,6 +1206,11 @@ if (VA.getLocInfo() != CCValAssign::Full) ArgValue = DAG.getNode(ISD::TRUNCATE, VA.getValVT(), ArgValue); + // Handle MMX values passed in GPRs. + if (RegVT != VA.getLocVT() && RC == X86::GR64RegisterClass && + MVT::getSizeInBits(RegVT) == 64) + ArgValue = DAG.getNode(ISD::BIT_CONVERT, VA.getLocVT(), ArgValue); + ArgValues.push_back(ArgValue); } else { assert(VA.isMemLoc()); From sabre at nondot.org Sat Jun 9 01:11:09 2007 From: sabre at nondot.org (Chris Lattner) Date: Sat, 9 Jun 2007 01:11:09 -0500 Subject: [llvm-commits] CVS: llvm/test/CFrontend/2007-04-24-bit-not-expr.c 2007-04-24-str-const.c 2007-05-11-str-const.c 2007-04-24-bit-not-expr.ll 2007-04-24-str-const.ll 2007-05-11-str-const.ll Message-ID: <200706090611.l596B9mo008485@zion.cs.uiuc.edu> Changes in directory llvm/test/CFrontend: 2007-04-24-bit-not-expr.c added (r1.1) 2007-04-24-str-const.c added (r1.1) 2007-05-11-str-const.c added (r1.1) 2007-04-24-bit-not-expr.ll (r1.1) removed 2007-04-24-str-const.ll (r1.1) removed 2007-05-11-str-const.ll (r1.1) removed --- Log message: rename C files to end with .c --- Diffs of the changes: (+29 -0) 2007-04-24-bit-not-expr.c | 7 +++++++ 2007-04-24-str-const.c | 17 +++++++++++++++++ 2007-05-11-str-const.c | 5 +++++ 3 files changed, 29 insertions(+) Index: llvm/test/CFrontend/2007-04-24-bit-not-expr.c diff -c /dev/null llvm/test/CFrontend/2007-04-24-bit-not-expr.c:1.1 *** /dev/null Sat Jun 9 01:10:57 2007 --- llvm/test/CFrontend/2007-04-24-bit-not-expr.c Sat Jun 9 01:10:47 2007 *************** *** 0 **** --- 1,7 ---- + // PR 1346 + // RUN: %llvmgcc -c %s -o /dev/null + extern bar(void *); + + void f(void *cd) { + bar(((void *)((unsigned long)(cd) ^ -1))); + } Index: llvm/test/CFrontend/2007-04-24-str-const.c diff -c /dev/null llvm/test/CFrontend/2007-04-24-str-const.c:1.1 *** /dev/null Sat Jun 9 01:11:09 2007 --- llvm/test/CFrontend/2007-04-24-str-const.c Sat Jun 9 01:10:47 2007 *************** *** 0 **** --- 1,17 ---- + // RUN: %llvmgcc -c %s -o /dev/null + static char *str; + + static const struct { + const char *name; + unsigned type; + } scan_special[] = { + {"shift", 1}, + {0, 0} + }; + + static void + sb(void) + { + while (*str == ' ' || *str == '\t') + str++; + } Index: llvm/test/CFrontend/2007-05-11-str-const.c diff -c /dev/null llvm/test/CFrontend/2007-05-11-str-const.c:1.1 *** /dev/null Sat Jun 9 01:11:09 2007 --- llvm/test/CFrontend/2007-05-11-str-const.c Sat Jun 9 01:10:47 2007 *************** *** 0 **** --- 1,5 ---- + // RUN: %llvmgcc -c -g %s -o /dev/null + + static unsigned char out[]={0,1}; + static const unsigned char str1[]="1"; + From baldrick at free.fr Sat Jun 9 09:21:23 2007 From: baldrick at free.fr (Duncan Sands) Date: Sat, 9 Jun 2007 16:21:23 +0200 Subject: [llvm-commits] Fix PR1224 differently Message-ID: <200706091621.23470.baldrick@free.fr> The fix that was applied for PR1224 stops the compiler crashing but breaks exception handling. The problem described in PR1224 is that invoke is a terminator that can produce a value. The value may be needed in other blocks. The code that writes to registers values needed in other blocks runs before terminators are lowered (in this case invoke) so asserted because the value was not yet available. The fix that was applied was to do invoke lowering earlier, before writing values to registers. The problem this causes is that the code to copy values to registers can be output after the invoke call. If an exception is raised and control is passed to the landing pad then this copy-code will never execute. If the value is needed in some code path reached via the landing pad then that code will get something bogus. The attached patch reverts the original fix and simply skips invoke values in the general copying to registers code. The invoke value is instead copied to a register in the invoke lowering code. I had a testcase but I accidentally deleted it... Ciao, Duncan. -------------- next part -------------- A non-text attachment was scrubbed... Name: invoke_order.diff Type: text/x-diff Size: 3640 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20070609/8a446572/attachment.bin From baldrick at free.fr Sat Jun 9 09:24:45 2007 From: baldrick at free.fr (Duncan Sands) Date: Sat, 9 Jun 2007 16:24:45 +0200 Subject: [llvm-commits] llvm-gcc: correct parameter attributes for nested functions Message-ID: <200706091624.45251.baldrick@free.fr> When I got rid of the inreg attribute for static chain parameters, I simply deleted the attribute adding code while I should have pushed a attribute of "none" - this results in attributes for other parameters being applied to the wrong parameters (off by one). Fixed by the attached patch. Ciao, Duncan. -------------- next part -------------- A non-text attachment was scrubbed... Name: chain_attr.diff Type: text/x-diff Size: 612 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20070609/5d9f571b/attachment.bin From resistor at mac.com Sat Jun 9 13:36:03 2007 From: resistor at mac.com (Owen Anderson) Date: Sat, 9 Jun 2007 13:36:03 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/GVNPRE.cpp Message-ID: <200706091836.l59Ia3BF001487@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: GVNPRE.cpp updated: 1.27 -> 1.28 --- Log message: Perform PRE of comparison operators. --- Diffs of the changes: (+155 -24) GVNPRE.cpp | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 155 insertions(+), 24 deletions(-) Index: llvm/lib/Transforms/Scalar/GVNPRE.cpp diff -u llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.27 llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.28 --- llvm/lib/Transforms/Scalar/GVNPRE.cpp:1.27 Fri Jun 8 17:02:36 2007 +++ llvm/lib/Transforms/Scalar/GVNPRE.cpp Sat Jun 9 13:35:31 2007 @@ -39,20 +39,43 @@ struct ExprLT { bool operator()(Value* left, Value* right) { - if (!isa(left) || !isa(right)) + if (BinaryOperator* leftBO = dyn_cast(left)) { + if (BinaryOperator* rightBO = dyn_cast(right)) + return cmpBinaryOperator(leftBO, rightBO); + else + return left < right; + } else if (CmpInst* leftCmp = dyn_cast(left)) { + if (CmpInst* rightCmp = dyn_cast(right)) + return cmpComparison(leftCmp, rightCmp); + else + return left < right; + } else { return left < right; - - BinaryOperator* BO1 = cast(left); - BinaryOperator* BO2 = cast(right); - - if (BO1->getOpcode() != BO2->getOpcode()) - return BO1->getOpcode() < BO2->getOpcode(); - else if ((*this)(BO1->getOperand(0), BO2->getOperand(0))) + } + } + + bool cmpBinaryOperator(BinaryOperator* left, BinaryOperator* right) { + if (left->getOpcode() != right->getOpcode()) + return left->getOpcode() < right->getOpcode(); + else if ((*this)(left->getOperand(0), right->getOperand(0))) + return true; + else if ((*this)(right->getOperand(0), left->getOperand(0))) + return false; + else + return (*this)(left->getOperand(1), right->getOperand(1)); + } + + bool cmpComparison(CmpInst* left, CmpInst* right) { + if (left->getOpcode() != right->getOpcode()) + return left->getOpcode() < right->getOpcode(); + else if (left->getPredicate() != right->getPredicate()) + return left->getPredicate() < right->getPredicate(); + else if ((*this)(left->getOperand(0), right->getOperand(0))) return true; - else if ((*this)(BO2->getOperand(0), BO1->getOperand(0))) + else if ((*this)(right->getOperand(0), left->getOperand(0))) return false; else - return (*this)(BO1->getOperand(1), BO2->getOperand(1)); + return (*this)(left->getOperand(1), right->getOperand(1)); } }; @@ -62,7 +85,7 @@ bool runOnFunction(Function &F); public: static char ID; // Pass identification, replacement for typeid - GVNPRE() : FunctionPass((intptr_t)&ID) { nextValueNumber = 0; } + GVNPRE() : FunctionPass((intptr_t)&ID) { nextValueNumber = 1; } private: uint32_t nextValueNumber; @@ -121,7 +144,7 @@ bool GVNPRE::add(Value* V, uint32_t number) { std::pair ret = VN.insert(std::make_pair(V, number)); - if (isa(V) || isa(V)) + if (isa(V) || isa(V) || isa(V)) MS.insert(V); return ret.second; } @@ -187,6 +210,48 @@ } else if (PHINode* P = dyn_cast(V)) { if (P->getParent() == pred->getTerminator()->getSuccessor(0)) return P->getIncomingValueForBlock(pred); + } else if (CmpInst* C = dyn_cast(V)) { + Value* newOp1 = isa(C->getOperand(0)) + ? phi_translate(set, + find_leader(set, C->getOperand(0)), + pred) + : C->getOperand(0); + if (newOp1 == 0) + return 0; + + Value* newOp2 = isa(C->getOperand(1)) + ? phi_translate(set, + find_leader(set, C->getOperand(1)), + pred) + : C->getOperand(1); + if (newOp2 == 0) + return 0; + + if (newOp1 != C->getOperand(0) || newOp2 != C->getOperand(1)) { + Instruction* newVal = CmpInst::create(C->getOpcode(), + C->getPredicate(), + newOp1, newOp2, + C->getName()+".gvnpre"); + + if (add(newVal, nextValueNumber)) + nextValueNumber++; + if (!find_leader(set, newVal)) { + DOUT << "Creating value: " << std::hex << newVal << std::dec << "\n"; + createdExpressions.insert(newVal); + return newVal; + } else { + ValueTable::iterator I = VN.find(newVal); + if (I->first == newVal) + VN.erase(newVal); + + std::set::iterator F = MS.find(newVal); + if (*F == newVal) + MS.erase(newVal); + + delete newVal; + return 0; + } + } } return V; @@ -231,6 +296,27 @@ if (!lhsValid || !rhsValid) set.erase(BO); + } else if (CmpInst* C = dyn_cast(v)) { + bool lhsValid = !isa(C->getOperand(0)); + if (!lhsValid) + for (std::set::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN[*I] == VN[C->getOperand(0)]) { + lhsValid = true; + break; + } + + bool rhsValid = !isa(C->getOperand(1)); + if (!rhsValid) + for (std::set::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN[*I] == VN[C->getOperand(1)]) { + rhsValid = true; + break; + } + + if (!lhsValid || !rhsValid) + set.erase(C); } } } @@ -246,7 +332,14 @@ VN[BO->getOperand(1)] == VN[*SI]) { toErase.insert(*SI); } - } + } + else if (CmpInst* C = dyn_cast(*I)) + for (std::set::iterator SI = set.begin(); SI != E; ++SI) { + if (VN[C->getOperand(0)] == VN[*SI] || + VN[C->getOperand(1)] == VN[*SI]) { + toErase.insert(*SI); + } + } } std::vector Q; @@ -275,6 +368,21 @@ visited.insert(e); Q.pop_back(); } + } else if (CmpInst* C = dyn_cast(e)) { + Value* l = find_leader(set, C->getOperand(0)); + Value* r = find_leader(set, C->getOperand(1)); + + if (l != 0 && isa(l) && + visited.find(l) == visited.end()) + Q.push_back(l); + else if (r != 0 && isa(r) && + visited.find(r) == visited.end()) + Q.push_back(r); + else { + vec.push_back(e); + visited.insert(e); + Q.pop_back(); + } } else { visited.insert(e); vec.push_back(e); @@ -340,6 +448,20 @@ currExps.insert(rightValue); currExps.insert(BO); + // Handle cmp ops... + } else if (CmpInst* C = dyn_cast(BI)) { + Value* leftValue = C->getOperand(0); + Value* rightValue = C->getOperand(1); + + if (add(C, nextValueNumber)) + nextValueNumber++; + + if (isa(leftValue)) + currExps.insert(leftValue); + if (isa(rightValue)) + currExps.insert(rightValue); + currExps.insert(C); + // Handle unsupported ops } else if (!BI->isTerminator()){ if (add(BI, nextValueNumber)) @@ -549,7 +671,7 @@ Value* e = workList.back(); workList.pop_back(); - if (isa(e)) { + if (isa(e) || isa(e)) { if (find_leader(availableOut[DI->getIDom()->getBlock()], e) != 0) continue; @@ -588,25 +710,34 @@ PI != PE; ++PI) { Value* e2 = avail[*PI]; if (!find_leader(availableOut[*PI], e2)) { - BinaryOperator* BO = cast(e2); + User* U = cast(e2); Value* s1 = 0; - if (isa(BO->getOperand(0))) - s1 = find_leader(availableOut[*PI], BO->getOperand(0)); + if (isa(U->getOperand(0))) + s1 = find_leader(availableOut[*PI], U->getOperand(0)); else - s1 = BO->getOperand(0); + s1 = U->getOperand(0); Value* s2 = 0; - if (isa(BO->getOperand(1))) - s2 = find_leader(availableOut[*PI], BO->getOperand(1)); + if (isa(U->getOperand(1))) + s2 = find_leader(availableOut[*PI], U->getOperand(1)); else - s2 = BO->getOperand(1); + s2 = U->getOperand(1); - Value* newVal = BinaryOperator::create(BO->getOpcode(), + Value* newVal = 0; + if (BinaryOperator* BO = dyn_cast(U)) + newVal = BinaryOperator::create(BO->getOpcode(), s1, s2, BO->getName()+".gvnpre", (*PI)->getTerminator()); - add(newVal, VN[BO]); + else if (CmpInst* C = dyn_cast(U)) + newVal = CmpInst::create(C->getOpcode(), + C->getPredicate(), + s1, s2, + C->getName()+".gvnpre", + (*PI)->getTerminator()); + + add(newVal, VN[U]); std::set& predAvail = availableOut[*PI]; Value* val = find_leader(predAvail, newVal); @@ -688,7 +819,7 @@ for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI) { - if (isa(BI)) { + if (isa(BI) || isa(BI)) { Value *leader = find_leader(availableOut[BB], BI); if (leader != 0) From evan.cheng at apple.com Sat Jun 9 14:07:32 2007 From: evan.cheng at apple.com (Evan Cheng) Date: Sat, 9 Jun 2007 12:07:32 -0700 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp In-Reply-To: References: <200706082201.l58M1Tj1030678@zion.cs.uiuc.edu> Message-ID: Perhaps. Will take a look. Thx. Evan On Jun 8, 2007, at 3:10 PM, Dale Johannesen wrote: > > On Jun 8, 2007, at 3:01 PM, Evan Cheng wrote: > >> +/// RemoveExtraEdges - Remove true / false edges if either / both >> are no longer >> +/// successors. > > This does pretty much the same thing as CorrectExtraCFGEdges in > BranchFolding.cpp, > although I'm sure there are subtleties. Can we combine them? > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From reid at x10sys.com Sat Jun 9 19:19:42 2007 From: reid at x10sys.com (Reid Spencer) Date: Sat, 9 Jun 2007 19:19:42 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/IfConversion.cpp Message-ID: <200706100019.l5A0Jgd1008525@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: IfConversion.cpp updated: 1.42 -> 1.43 --- Log message: Fix the build. --- Diffs of the changes: (+2 -1) IfConversion.cpp | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-) Index: llvm/lib/CodeGen/IfConversion.cpp diff -u llvm/lib/CodeGen/IfConversion.cpp:1.42 llvm/lib/CodeGen/IfConversion.cpp:1.43 --- llvm/lib/CodeGen/IfConversion.cpp:1.42 Fri Jun 8 20:03:43 2007 +++ llvm/lib/CodeGen/IfConversion.cpp Sat Jun 9 19:19:17 2007 @@ -218,7 +218,7 @@ } case ICTriangle: case ICTriangleFalse: - case ICTriangleFRev: + case ICTriangleFRev: { bool isFalse = BBI.Kind == ICTriangleFalse; bool isFalseRev = BBI.Kind == ICTriangleFRev; if (DisableTriangle && !isFalse && !isFalseRev) break; @@ -240,6 +240,7 @@ else NumTriangle++; } break; + } case ICDiamond: if (DisableDiamond) break; DOUT << "Ifcvt (Diamond): BB#" << BBI.BB->getNumber() << " (T:"