From lattner at cs.uiuc.edu Mon Oct 3 00:07:20 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 3 Oct 2005 00:07:20 -0500 Subject: [llvm-commits] CVS: llvm-test/MultiSource/Benchmarks/Olden/Makefile Message-ID: <200510030507.AAA24288@zion.cs.uiuc.edu> Changes in directory llvm-test/MultiSource/Benchmarks/Olden: Makefile updated: 1.7 -> 1.8 --- Log message: Fix typo, thanks to Vladimir Merzliakov for pointing this out! --- Diffs of the changes: (+2 -2) Makefile | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm-test/MultiSource/Benchmarks/Olden/Makefile diff -u llvm-test/MultiSource/Benchmarks/Olden/Makefile:1.7 llvm-test/MultiSource/Benchmarks/Olden/Makefile:1.8 --- llvm-test/MultiSource/Benchmarks/Olden/Makefile:1.7 Sun Oct 2 15:53:20 2005 +++ llvm-test/MultiSource/Benchmarks/Olden/Makefile Mon Oct 3 00:07:08 2005 @@ -2,8 +2,8 @@ LEVEL = ../../.. -## NOTE: This must remain in this oder, so that the labels in the nightly tester -## gnuplot scripts are correct. +## NOTE: This must remain in this order, so that the labels in the nightly +## tester gnuplot scripts are correct. PARALLEL_DIRS := bh em3d mst power tsp bisort health perimeter treeadd voronoi include $(LEVEL)/Makefile.programs From lattner at cs.uiuc.edu Mon Oct 3 02:08:48 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 3 Oct 2005 02:08:48 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PowerPCAsmPrinter.cpp Message-ID: <200510030708.CAA24688@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PowerPCAsmPrinter.cpp updated: 1.91 -> 1.92 --- Log message: Speed up the asm printer a lot by not printing formatted LLVM asm output for globals --- Diffs of the changes: (+3 -9) PowerPCAsmPrinter.cpp | 12 +++--------- 1 files changed, 3 insertions(+), 9 deletions(-) Index: llvm/lib/Target/PowerPC/PowerPCAsmPrinter.cpp diff -u llvm/lib/Target/PowerPC/PowerPCAsmPrinter.cpp:1.91 llvm/lib/Target/PowerPC/PowerPCAsmPrinter.cpp:1.92 --- llvm/lib/Target/PowerPC/PowerPCAsmPrinter.cpp:1.91 Thu Sep 1 18:08:50 2005 +++ llvm/lib/Target/PowerPC/PowerPCAsmPrinter.cpp Mon Oct 3 02:08:36 2005 @@ -465,9 +465,7 @@ O << ".lcomm " << name << "," << Size << "," << Align; else O << ".comm " << name << "," << Size; - O << "\t\t; "; - WriteAsOperand(O, I, true, true, &M); - O << '\n'; + O << "\t\t; '" << I->getName() << "'\n"; } else { switch (I->getLinkage()) { case GlobalValue::LinkOnceLinkage: @@ -497,11 +495,7 @@ } emitAlignment(Align); - O << name << ":\t\t\t\t; "; - WriteAsOperand(O, I, true, true, &M); - O << " = "; - WriteAsOperand(O, C, false, false, &M); - O << "\n"; + O << name << ":\t\t\t\t; '" << I->getName() << "'\n"; emitGlobalConstant(C); } } @@ -704,7 +698,7 @@ << "," << Log2_32((unsigned)TD.getTypeAlignment(I->getType())); } O << "\t\t# "; - WriteAsOperand(O, I, true, true, &M); + WriteAsOperand(O, I, false, true, &M); O << "\n"; } From lattner at cs.uiuc.edu Mon Oct 3 02:22:18 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 3 Oct 2005 02:22:18 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/PHIElimination.cpp Message-ID: <200510030722.CAA24775@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: PHIElimination.cpp updated: 1.38 -> 1.39 --- Log message: clean up this code a bit, no functionality change --- Diffs of the changes: (+117 -102) PHIElimination.cpp | 219 ++++++++++++++++++++++++++++------------------------- 1 files changed, 117 insertions(+), 102 deletions(-) Index: llvm/lib/CodeGen/PHIElimination.cpp diff -u llvm/lib/CodeGen/PHIElimination.cpp:1.38 llvm/lib/CodeGen/PHIElimination.cpp:1.39 --- llvm/lib/CodeGen/PHIElimination.cpp:1.38 Sun Oct 2 23:47:08 2005 +++ llvm/lib/CodeGen/PHIElimination.cpp Mon Oct 3 02:22:07 2005 @@ -22,10 +22,15 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Statistic.h" #include +#include using namespace llvm; namespace { + Statistic<> NumAtomic("phielim", "Number of atomic phis lowered"); + Statistic<> NumSimple("phielim", "Number of simple phis lowered"); + struct PNE : public MachineFunctionPass { bool runOnMachineFunction(MachineFunction &Fn) { bool Changed = false; @@ -49,8 +54,7 @@ bool EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB); void LowerAtomicPHINode(MachineBasicBlock &MBB, MachineBasicBlock::iterator AfterPHIsIt, - DenseMap &VUC, - unsigned BBIsSuccOfPreds); + DenseMap &VUC); }; RegisterPass X("phi-node-elimination", @@ -72,18 +76,15 @@ DenseMap VRegPHIUseCount; VRegPHIUseCount.grow(MF.getSSARegMap()->getLastVirtReg()); - unsigned BBIsSuccOfPreds = 0; // Number of times MBB is a succ of preds for (MachineBasicBlock::pred_iterator PI = MBB.pred_begin(), E = MBB.pred_end(); PI != E; ++PI) for (MachineBasicBlock::succ_iterator SI = (*PI)->succ_begin(), - E = (*PI)->succ_end(); SI != E; ++SI) { - BBIsSuccOfPreds += *SI == &MBB; - for (MachineBasicBlock::iterator BBI = (*SI)->begin(); BBI !=(*SI)->end() && - BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) - for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) - VRegPHIUseCount[BBI->getOperand(i).getReg()]++; - } - + E = (*PI)->succ_end(); SI != E; ++SI) + for (MachineBasicBlock::iterator BBI = (*SI)->begin(), E = (*SI)->end(); + BBI != E && BBI->getOpcode() == TargetInstrInfo::PHI; ++BBI) + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) + VRegPHIUseCount[BBI->getOperand(i).getReg()]++; + // Get an iterator to the first instruction after the last PHI node (this may // also be the end of the basic block). MachineBasicBlock::iterator AfterPHIsIt = MBB.begin(); @@ -92,7 +93,7 @@ ++AfterPHIsIt; // Skip over all of the PHI nodes... while (MBB.front().getOpcode() == TargetInstrInfo::PHI) { - LowerAtomicPHINode(MBB, AfterPHIsIt, VRegPHIUseCount, BBIsSuccOfPreds); + LowerAtomicPHINode(MBB, AfterPHIsIt, VRegPHIUseCount); } return true; } @@ -103,8 +104,7 @@ /// time. void PNE::LowerAtomicPHINode(MachineBasicBlock &MBB, MachineBasicBlock::iterator AfterPHIsIt, - DenseMap &VRegPHIUseCount, - unsigned BBIsSuccOfPreds) { + DenseMap &VRegPHIUseCount) { // Unlink the PHI node from the basic block, but don't delete the PHI yet. MachineInstr *MPhi = MBB.remove(MBB.begin()); @@ -140,124 +140,139 @@ // LV->removeVirtualRegistersKilled(MPhi); - std::pair - RKs = LV->dead_range(MPhi); - if (RKs.first != RKs.second) { - for (LiveVariables::killed_iterator I = RKs.first; I != RKs.second; ++I) - LV->addVirtualRegisterDead(*I, PHICopy); + // If the result is dead, update LV. + if (LV->RegisterDefIsDead(MPhi, DestReg)) { + LV->addVirtualRegisterDead(DestReg, PHICopy); LV->removeVirtualRegistersDead(MPhi); } } // Adjust the VRegPHIUseCount map to account for the removal of this PHI // node. + unsigned NumPreds = (MPhi->getNumOperands()-1)/2; for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) - VRegPHIUseCount[MPhi->getOperand(i).getReg()] -= BBIsSuccOfPreds; + VRegPHIUseCount[MPhi->getOperand(i).getReg()] -= NumPreds; // Now loop over all of the incoming arguments, changing them to copy into // the IncomingReg register in the corresponding predecessor basic block. // + std::set MBBsInsertedInto; for (int i = MPhi->getNumOperands() - 1; i >= 2; i-=2) { - MachineOperand &opVal = MPhi->getOperand(i-1); + unsigned SrcReg = MPhi->getOperand(i-1).getReg(); + assert(MRegisterInfo::isVirtualRegister(SrcReg) && + "Machine PHI Operands must all be virtual registers!"); // Get the MachineBasicBlock equivalent of the BasicBlock that is the // source path the PHI. MachineBasicBlock &opBlock = *MPhi->getOperand(i).getMachineBasicBlock(); - MachineBasicBlock::iterator I = opBlock.getFirstTerminator(); - // Check to make sure we haven't already emitted the copy for this block. // This can happen because PHI nodes may have multiple entries for the - // same basic block. It doesn't matter which entry we use though, because - // all incoming values are guaranteed to be the same for a particular bb. + // same basic block. + if (!MBBsInsertedInto.insert(&opBlock).second) + continue; // If the copy has already been emitted, we're done. + + // Get an iterator pointing to the first terminator in the block (or end()). + // This is the point where we can insert a copy if we'd like to. + MachineBasicBlock::iterator I = opBlock.getFirstTerminator(); + + // Insert the copy. + RegInfo->copyRegToReg(opBlock, I, IncomingReg, SrcReg, RC); + + // Now update live variable information if we have it. Otherwise we're done + if (!LV) continue; + + // We want to be able to insert a kill of the register if this PHI + // (aka, the copy we just inserted) is the last use of the source + // value. Live variable analysis conservatively handles this by + // saying that the value is live until the end of the block the PHI + // entry lives in. If the value really is dead at the PHI copy, there + // will be no successor blocks which have the value live-in. // - // If we emitted a copy for this basic block already, it will be right - // where we want to insert one now. Just check for a definition of the - // register we are interested in! - // - bool HaveNotEmitted = true; - - if (I != opBlock.begin()) { - MachineBasicBlock::iterator PrevInst = prior(I); - for (unsigned i = 0, e = PrevInst->getNumOperands(); i != e; ++i) { - MachineOperand &MO = PrevInst->getOperand(i); - if (MO.isRegister() && MO.getReg() == IncomingReg) - if (MO.isDef()) { - HaveNotEmitted = false; - break; - } + // Check to see if the copy is the last use, and if so, update the + // live variables information so that it knows the copy source + // instruction kills the incoming value. + // + LiveVariables::VarInfo &InRegVI = LV->getVarInfo(SrcReg); + + // Loop over all of the successors of the basic block, checking to see + // if the value is either live in the block, or if it is killed in the + // block. Also check to see if this register is in use by another PHI + // node which has not yet been eliminated. If so, it will be killed + // at an appropriate point later. + // + + // Is it used by any PHI instructions in this block? + bool ValueIsLive = VRegPHIUseCount[SrcReg] != 0; + + std::vector OpSuccBlocks; + + // Otherwise, scan successors, including the BB the PHI node lives in. + for (MachineBasicBlock::succ_iterator SI = opBlock.succ_begin(), + E = opBlock.succ_end(); SI != E && !ValueIsLive; ++SI) { + MachineBasicBlock *SuccMBB = *SI; + + // Is it alive in this successor? + unsigned SuccIdx = SuccMBB->getNumber(); + if (SuccIdx < InRegVI.AliveBlocks.size() && + InRegVI.AliveBlocks[SuccIdx]) { + ValueIsLive = true; + break; } + + OpSuccBlocks.push_back(SuccMBB); } - if (HaveNotEmitted) { // If the copy has not already been emitted, do it. - assert(MRegisterInfo::isVirtualRegister(opVal.getReg()) && - "Machine PHI Operands must all be virtual registers!"); - unsigned SrcReg = opVal.getReg(); - RegInfo->copyRegToReg(opBlock, I, IncomingReg, SrcReg, RC); - - // Now update live variable information if we have it. - if (LV) { - // We want to be able to insert a kill of the register if this PHI - // (aka, the copy we just inserted) is the last use of the source - // value. Live variable analysis conservatively handles this by - // saying that the value is live until the end of the block the PHI - // entry lives in. If the value really is dead at the PHI copy, there - // will be no successor blocks which have the value live-in. - // - // Check to see if the copy is the last use, and if so, update the - // live variables information so that it knows the copy source - // instruction kills the incoming value. - // - LiveVariables::VarInfo &InRegVI = LV->getVarInfo(SrcReg); - - // Loop over all of the successors of the basic block, checking to see - // if the value is either live in the block, or if it is killed in the - // block. Also check to see if this register is in use by another PHI - // node which has not yet been eliminated. If so, it will be killed - // at an appropriate point later. - // - bool ValueIsLive = false; - for (MachineBasicBlock::succ_iterator SI = opBlock.succ_begin(), - E = opBlock.succ_end(); SI != E && !ValueIsLive; ++SI) { - MachineBasicBlock *SuccMBB = *SI; - - // Is it alive in this successor? - unsigned SuccIdx = SuccMBB->getNumber(); - if (SuccIdx < InRegVI.AliveBlocks.size() && - InRegVI.AliveBlocks[SuccIdx]) { + // Check to see if this value is live because there is a use in a successor + // that kills it. + if (!ValueIsLive) { + switch (OpSuccBlocks.size()) { + case 1: { + MachineBasicBlock *MBB = OpSuccBlocks[0]; + for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i) + if (InRegVI.Kills[i]->getParent() == MBB) { ValueIsLive = true; break; } - - // Is it killed in this successor? - for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i) - if (InRegVI.Kills[i]->getParent() == SuccMBB) { - ValueIsLive = true; - break; - } - - // Is it used by any PHI instructions in this block? - if (!ValueIsLive) - ValueIsLive = VRegPHIUseCount[SrcReg] != 0; - } - - // Okay, if we now know that the value is not live out of the block, - // we can add a kill marker to the copy we inserted saying that it - // kills the incoming value! - // - if (!ValueIsLive) { - MachineBasicBlock::iterator Prev = prior(I); - LV->addVirtualRegisterKilled(SrcReg, Prev); - - // This vreg no longer lives all of the way through opBlock. - unsigned opBlockNum = opBlock.getNumber(); - if (opBlockNum < InRegVI.AliveBlocks.size()) - InRegVI.AliveBlocks[opBlockNum] = false; - } + break; + } + case 2: { + MachineBasicBlock *MBB1 = OpSuccBlocks[0], *MBB2 = OpSuccBlocks[1]; + for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i) + if (InRegVI.Kills[i]->getParent() == MBB1 || + InRegVI.Kills[i]->getParent() == MBB2) { + ValueIsLive = true; + break; + } + break; } + default: + std::sort(OpSuccBlocks.begin(), OpSuccBlocks.end()); + for (unsigned i = 0, e = InRegVI.Kills.size(); i != e; ++i) + if (std::binary_search(OpSuccBlocks.begin(), OpSuccBlocks.end(), + InRegVI.Kills[i]->getParent())) { + ValueIsLive = true; + break; + } + } + } + + // Okay, if we now know that the value is not live out of the block, + // we can add a kill marker to the copy we inserted saying that it + // kills the incoming value! + // + if (!ValueIsLive) { + MachineBasicBlock::iterator Prev = prior(I); + LV->addVirtualRegisterKilled(SrcReg, Prev); + + // This vreg no longer lives all of the way through opBlock. + unsigned opBlockNum = opBlock.getNumber(); + if (opBlockNum < InRegVI.AliveBlocks.size()) + InRegVI.AliveBlocks[opBlockNum] = false; } } // Really delete the PHI instruction now! delete MPhi; + ++NumAtomic; } From jlaskey at apple.com Mon Oct 3 07:30:43 2005 From: jlaskey at apple.com (Jim Laskey) Date: Mon, 3 Oct 2005 07:30:43 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Message-ID: <200510031230.HAA26115@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: ScheduleDAG.cpp updated: 1.32 -> 1.33 --- Log message: Refactor gathering node info and emission. --- Diffs of the changes: (+70 -238) ScheduleDAG.cpp | 308 ++++++++++++-------------------------------------------- 1 files changed, 70 insertions(+), 238 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp:1.32 llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp:1.33 --- llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp:1.32 Sun Oct 2 11:30:51 2005 +++ llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Mon Oct 3 07:30:32 2005 @@ -386,7 +386,6 @@ std::vector Ordering; // Emit ordering of nodes ResourceTally Tally; // Resource usage tally unsigned NSlots; // Total latency - std::map VRMap; // Node to VR map static const unsigned NotFound = ~0U; // Search marker public: @@ -427,7 +426,9 @@ void IncludeNode(NodeInfo *NI); void VisitAll(); void Schedule(); - void GatherNodeInfo(); + void IdentifyGroups(); + void GatherSchedulingInfo(); + void PrepareNodeInfo(); bool isStrongDependency(NodeInfo *A, NodeInfo *B); bool isWeakDependency(NodeInfo *A, NodeInfo *B); void ScheduleBackward(); @@ -635,28 +636,34 @@ } } -/// GatherNodeInfo - Get latency and resource information about each node. -/// -void SimpleSched::GatherNodeInfo() { - // Allocate node information - Info = new NodeInfo[NodeCount]; - // Get base of all nodes table - SelectionDAG::allnodes_iterator AllNodes = DAG.allnodes_begin(); - - // For each node being scheduled +/// IdentifyGroups - Put flagged nodes into groups. +/// +void SimpleSched::IdentifyGroups() { for (unsigned i = 0, N = NodeCount; i < N; i++) { - // Get next node from DAG all nodes table - SDNode *Node = AllNodes[i]; - // Fast reference to node schedule info NodeInfo* NI = &Info[i]; - // Set up map - Map[Node] = NI; - // Set node - NI->Node = Node; - // Set pending visit count - NI->setPending(Node->use_size()); - + SDNode *Node = NI->Node; + + // For each operand (in reverse to only look at flags) + for (unsigned N = Node->getNumOperands(); 0 < N--;) { + // Get operand + SDOperand Op = Node->getOperand(N); + // No more flags to walk + if (Op.getValueType() != MVT::Flag) break; + // Add to node group + NodeGroup::Add(getNI(Op.Val), NI); + } + } +} + +/// GatherSchedulingInfo - Get latency and resource information about each node. +/// +void SimpleSched::GatherSchedulingInfo() { + for (unsigned i = 0, N = NodeCount; i < N; i++) { + NodeInfo* NI = &Info[i]; + SDNode *Node = NI->Node; + MVT::ValueType VT = Node->getValueType(0); + if (Node->isTargetOpcode()) { MachineOpCode TOpc = Node->getTargetOpcode(); // FIXME: This is an ugly (but temporary!) hack to test the scheduler @@ -701,21 +708,28 @@ // Sum up all the latencies for max tally size NSlots += NI->Latency; } +} - // Put flagged nodes into groups +/// PrepareNodeInfo - Set up the basic minimum node info for scheduling. +/// +void SimpleSched::PrepareNodeInfo() { + // Allocate node information + Info = new NodeInfo[NodeCount]; + // Get base of all nodes table + SelectionDAG::allnodes_iterator AllNodes = DAG.allnodes_begin(); + + // For each node being scheduled for (unsigned i = 0, N = NodeCount; i < N; i++) { + // Get next node from DAG all nodes table + SDNode *Node = AllNodes[i]; + // Fast reference to node schedule info NodeInfo* NI = &Info[i]; - SDNode *Node = NI->Node; - - // For each operand (in reverse to only look at flags) - for (unsigned N = Node->getNumOperands(); 0 < N--;) { - // Get operand - SDOperand Op = Node->getOperand(N); - // No more flags to walk - if (Op.getValueType() != MVT::Flag) break; - // Add to node group - NodeGroup::Add(getNI(Op.Val), NI); - } + // Set up map + Map[Node] = NI; + // Set node + NI->Node = Node; + // Set pending visit count + NI->setPending(Node->use_size()); } } @@ -1054,215 +1068,33 @@ NI->VRBase = VRBase; } -/// EmitDag - Generate machine code for an operand and needed dependencies. -/// -unsigned SimpleSched::EmitDAG(SDOperand Op) { - std::map::iterator OpI = VRMap.lower_bound(Op.Val); - if (OpI != VRMap.end() && OpI->first == Op.Val) - return OpI->second + Op.ResNo; - unsigned &OpSlot = VRMap.insert(OpI, std::make_pair(Op.Val, 0))->second; - - unsigned ResultReg = 0; - if (Op.isTargetOpcode()) { - unsigned Opc = Op.getTargetOpcode(); - const TargetInstrDescriptor &II = TII.get(Opc); - - unsigned NumResults = CountResults(Op.Val); - unsigned NodeOperands = CountOperands(Op.Val); - unsigned NumMIOperands = NodeOperands + NumResults; -#ifndef NDEBUG - assert((unsigned(II.numOperands) == NumMIOperands || II.numOperands == -1)&& - "#operands for dag node doesn't match .td file!"); -#endif - - // Create the new machine instruction. - MachineInstr *MI = new MachineInstr(Opc, NumMIOperands, true, true); - - // Add result register values for things that are defined by this - // instruction. - if (NumResults) ResultReg = CreateVirtualRegisters(MI, NumResults, II); - - // If there is a token chain operand, emit it first, as a hack to get avoid - // really bad cases. - if (Op.getNumOperands() > NodeOperands && - Op.getOperand(NodeOperands).getValueType() == MVT::Other) { - EmitDAG(Op.getOperand(NodeOperands)); - } - - // Emit all of the actual operands of this instruction, adding them to the - // instruction as appropriate. - for (unsigned i = 0; i != NodeOperands; ++i) { - if (Op.getOperand(i).isTargetOpcode()) { - // Note that this case is redundant with the final else block, but we - // include it because it is the most common and it makes the logic - // simpler here. - assert(Op.getOperand(i).getValueType() != MVT::Other && - Op.getOperand(i).getValueType() != MVT::Flag && - "Chain and flag operands should occur at end of operand list!"); - - unsigned VReg = EmitDAG(Op.getOperand(i)); - MI->addRegOperand(VReg, MachineOperand::Use); - - // Verify that it is right. - assert(MRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?"); - assert(II.OpInfo[i+NumResults].RegClass && - "Don't have operand info for this instruction!"); -#ifndef NDEBUG - if (RegMap->getRegClass(VReg) != II.OpInfo[i+NumResults].RegClass) { - std::cerr << "OP: "; - Op.getOperand(i).Val->dump(&DAG); std::cerr << "\nUSE: "; - Op.Val->dump(&DAG); std::cerr << "\n"; - } -#endif - assert(RegMap->getRegClass(VReg) == II.OpInfo[i+NumResults].RegClass && - "Register class of operand and regclass of use don't agree!"); - } else if (ConstantSDNode *C = - dyn_cast(Op.getOperand(i))) { - MI->addZeroExtImm64Operand(C->getValue()); - } else if (RegisterSDNode*R =dyn_cast(Op.getOperand(i))) { - MI->addRegOperand(R->getReg(), MachineOperand::Use); - } else if (GlobalAddressSDNode *TGA = - dyn_cast(Op.getOperand(i))) { - MI->addGlobalAddressOperand(TGA->getGlobal(), false, 0); - } else if (BasicBlockSDNode *BB = - dyn_cast(Op.getOperand(i))) { - MI->addMachineBasicBlockOperand(BB->getBasicBlock()); - } else if (FrameIndexSDNode *FI = - dyn_cast(Op.getOperand(i))) { - MI->addFrameIndexOperand(FI->getIndex()); - } else if (ConstantPoolSDNode *CP = - dyn_cast(Op.getOperand(i))) { - unsigned Idx = ConstPool->getConstantPoolIndex(CP->get()); - MI->addConstantPoolIndexOperand(Idx); - } else if (ExternalSymbolSDNode *ES = - dyn_cast(Op.getOperand(i))) { - MI->addExternalSymbolOperand(ES->getSymbol(), false); - } else { - assert(Op.getOperand(i).getValueType() != MVT::Other && - Op.getOperand(i).getValueType() != MVT::Flag && - "Chain and flag operands should occur at end of operand list!"); - unsigned VReg = EmitDAG(Op.getOperand(i)); - MI->addRegOperand(VReg, MachineOperand::Use); - - // Verify that it is right. - assert(MRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?"); - assert(II.OpInfo[i+NumResults].RegClass && - "Don't have operand info for this instruction!"); - assert(RegMap->getRegClass(VReg) == II.OpInfo[i+NumResults].RegClass && - "Register class of operand and regclass of use don't agree!"); - } - } - - // Finally, if this node has any flag operands, we *must* emit them last, to - // avoid emitting operations that might clobber the flags. - if (Op.getNumOperands() > NodeOperands) { - unsigned i = NodeOperands; - if (Op.getOperand(i).getValueType() == MVT::Other) - ++i; // the chain is already selected. - for (unsigned N = Op.getNumOperands(); i < N; i++) { - assert(Op.getOperand(i).getValueType() == MVT::Flag && - "Must be flag operands!"); - EmitDAG(Op.getOperand(i)); - } - } - - // Now that we have emitted all operands, emit this instruction itself. - if ((II.Flags & M_USES_CUSTOM_DAG_SCHED_INSERTION) == 0) { - BB->insert(BB->end(), MI); - } else { - // Insert this instruction into the end of the basic block, potentially - // taking some custom action. - BB = DAG.getTargetLoweringInfo().InsertAtEndOfBasicBlock(MI, BB); - } - } else { - switch (Op.getOpcode()) { - default: - Op.Val->dump(); - assert(0 && "This target-independent node should have been selected!"); - case ISD::EntryToken: break; - case ISD::TokenFactor: - for (unsigned i = 0, N = Op.getNumOperands(); i < N; i++) { - EmitDAG(Op.getOperand(i)); - } - break; - case ISD::CopyToReg: { - SDOperand FlagOp; FlagOp.ResNo = 0; - if (Op.getNumOperands() == 4) { - FlagOp = Op.getOperand(3); - } - if (Op.getOperand(0).Val != FlagOp.Val) { - EmitDAG(Op.getOperand(0)); // Emit the chain. - } - unsigned Val = EmitDAG(Op.getOperand(2)); - if (FlagOp.Val) { - EmitDAG(FlagOp); - } - MRI.copyRegToReg(*BB, BB->end(), - cast(Op.getOperand(1))->getReg(), Val, - RegMap->getRegClass(Val)); - break; - } - case ISD::CopyFromReg: { - EmitDAG(Op.getOperand(0)); // Emit the chain. - unsigned SrcReg = cast(Op.getOperand(1))->getReg(); - - // Figure out the register class to create for the destreg. - const TargetRegisterClass *TRC = 0; - if (MRegisterInfo::isVirtualRegister(SrcReg)) { - TRC = RegMap->getRegClass(SrcReg); - } else { - // Pick the register class of the right type that contains this physreg. - for (MRegisterInfo::regclass_iterator I = MRI.regclass_begin(), - E = MRI.regclass_end(); I != E; ++I) - if ((*I)->getType() == Op.Val->getValueType(0) && - (*I)->contains(SrcReg)) { - TRC = *I; - break; - } - assert(TRC && "Couldn't find register class for reg copy!"); - } - - // Create the reg, emit the copy. - ResultReg = RegMap->createVirtualRegister(TRC); - MRI.copyRegToReg(*BB, BB->end(), ResultReg, SrcReg, TRC); - break; - } - } - } - - OpSlot = ResultReg; - return ResultReg+Op.ResNo; -} - /// Schedule - Order nodes according to selected style. /// void SimpleSched::Schedule() { - switch (ScheduleStyle) { - case simpleScheduling: - // Number the nodes - NodeCount = DAG.allnodes_size(); - // Don't waste time if is only entry and return - if (NodeCount > 3) { - // Get latency and resource requirements - GatherNodeInfo(); - // Breadth first walk of DAG - VisitAll(); - DEBUG(dump("Pre-")); - // Push back long instructions and critical path - ScheduleBackward(); - DEBUG(dump("Mid-")); - // Pack instructions to maximize resource utilization - ScheduleForward(); - DEBUG(dump("Post-")); - // Emit in scheduled order - EmitAll(); - break; - } // fall thru - case noScheduling: - // Emit instructions in using a DFS from the exit root - EmitDAG(DAG.getRoot()); - break; + // Number the nodes + NodeCount = DAG.allnodes_size(); + // Set up minimum info for scheduling. + PrepareNodeInfo(); + // Construct node groups for flagged nodes + IdentifyGroups(); + // Breadth first walk of DAG + VisitAll(); + + // Don't waste time if is only entry and return + if (ScheduleStyle != noScheduling && NodeCount > 3) { + // Get latency and resource requirements + GatherSchedulingInfo(); + DEBUG(dump("Pre-")); + // Push back long instructions and critical path + ScheduleBackward(); + DEBUG(dump("Mid-")); + // Pack instructions to maximize resource utilization + ScheduleForward(); } + + DEBUG(dump("Post-")); + // Emit in scheduled order + EmitAll(); } /// printSI - Print schedule info. From lattner at cs.uiuc.edu Mon Oct 3 16:27:05 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 3 Oct 2005 16:27:05 -0500 Subject: [llvm-commits] CVS: llvm/lib/Bytecode/Reader/Reader.cpp Reader.h Message-ID: <200510032127.QAA28727@zion.cs.uiuc.edu> Changes in directory llvm/lib/Bytecode/Reader: Reader.cpp updated: 1.166 -> 1.167 Reader.h updated: 1.24 -> 1.25 --- Log message: Use a map to cache the ModuleType information, so we can do logarithmic lookups instead of linear time lookups. This speeds up bc parsing of a large file from 137.834u 118.256s 4:27.96 to 132.611u 114.436s 4:08.53 with a release build. --- Diffs of the changes: (+47 -8) Reader.cpp | 49 +++++++++++++++++++++++++++++++++++++++++-------- Reader.h | 6 ++++++ 2 files changed, 47 insertions(+), 8 deletions(-) Index: llvm/lib/Bytecode/Reader/Reader.cpp diff -u llvm/lib/Bytecode/Reader/Reader.cpp:1.166 llvm/lib/Bytecode/Reader/Reader.cpp:1.167 --- llvm/lib/Bytecode/Reader/Reader.cpp:1.166 Wed Aug 17 14:22:05 2005 +++ llvm/lib/Bytecode/Reader/Reader.cpp Mon Oct 3 16:26:53 2005 @@ -347,11 +347,25 @@ return Type::FirstDerivedTyID + ModuleTypes.size() + (&*I - &FunctionTypes[0]); - // Check the module level types now... - I = std::find(ModuleTypes.begin(), ModuleTypes.end(), Ty); - if (I == ModuleTypes.end()) + // If we don't have our cache yet, build it now. + if (ModuleTypeIDCache.empty()) { + unsigned N = 0; + ModuleTypeIDCache.reserve(ModuleTypes.size()); + for (TypeListTy::iterator I = ModuleTypes.begin(), E = ModuleTypes.end(); + I != E; ++I, ++N) + ModuleTypeIDCache.push_back(std::make_pair(*I, N)); + + std::sort(ModuleTypeIDCache.begin(), ModuleTypeIDCache.end()); + } + + // Binary search the cache for the entry. + std::vector >::iterator IT = + std::lower_bound(ModuleTypeIDCache.begin(), ModuleTypeIDCache.end(), + std::make_pair(Ty, 0U)); + if (IT == ModuleTypeIDCache.end() || IT->first != Ty) error("Didn't find type in ModuleTypes."); - return Type::FirstDerivedTyID + (&*I - &ModuleTypes[0]); + + return Type::FirstDerivedTyID + IT->second; } /// This is just like getType, but when a compaction table is in use, it is @@ -375,11 +389,26 @@ unsigned BytecodeReader::getGlobalTableTypeSlot(const Type *Ty) { if (Ty->isPrimitiveType()) return Ty->getTypeID(); - TypeListTy::iterator I = std::find(ModuleTypes.begin(), - ModuleTypes.end(), Ty); - if (I == ModuleTypes.end()) + + // If we don't have our cache yet, build it now. + if (ModuleTypeIDCache.empty()) { + unsigned N = 0; + ModuleTypeIDCache.reserve(ModuleTypes.size()); + for (TypeListTy::iterator I = ModuleTypes.begin(), E = ModuleTypes.end(); + I != E; ++I, ++N) + ModuleTypeIDCache.push_back(std::make_pair(*I, N)); + + std::sort(ModuleTypeIDCache.begin(), ModuleTypeIDCache.end()); + } + + // Binary search the cache for the entry. + std::vector >::iterator IT = + std::lower_bound(ModuleTypeIDCache.begin(), ModuleTypeIDCache.end(), + std::make_pair(Ty, 0U)); + if (IT == ModuleTypeIDCache.end() || IT->first != Ty) error("Didn't find type in ModuleTypes."); - return Type::FirstDerivedTyID + (&*I - &ModuleTypes[0]); + + return Type::FirstDerivedTyID + IT->second; } /// Retrieve a value of a given type and slot number, possibly creating @@ -1309,6 +1338,10 @@ if (Handler) Handler->handleTypeList(NumEntries); + // If we are about to resolve types, make sure the type cache is clear. + if (NumEntries) + ModuleTypeIDCache.clear(); + // Loop through reading all of the types. Forward types will make use of the // opaque types just inserted. // Index: llvm/lib/Bytecode/Reader/Reader.h diff -u llvm/lib/Bytecode/Reader/Reader.h:1.24 llvm/lib/Bytecode/Reader/Reader.h:1.25 --- llvm/lib/Bytecode/Reader/Reader.h:1.24 Tue Aug 16 16:59:52 2005 +++ llvm/lib/Bytecode/Reader/Reader.h Mon Oct 3 16:26:53 2005 @@ -333,6 +333,12 @@ /// @brief This vector is used to deal with forward references to types in /// a module. TypeListTy ModuleTypes; + + /// @brief This is an inverse mapping of ModuleTypes from the type to an + /// index. Because refining types causes the index of this map to be + /// invalidated, any time we refine a type, we clear this cache and recompute + /// it next time we need it. These entries are ordered by the pointer value. + std::vector > ModuleTypeIDCache; /// @brief This vector is used to deal with forward references to types in /// a function. From lattner at cs.uiuc.edu Mon Oct 3 16:56:36 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 3 Oct 2005 16:56:36 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200510032156.QAA28832@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.129 -> 1.130 --- Log message: minor microoptimizations --- Diffs of the changes: (+21 -14) Constants.cpp | 35 +++++++++++++++++++++-------------- 1 files changed, 21 insertions(+), 14 deletions(-) Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.129 llvm/lib/VMCore/Constants.cpp:1.130 --- llvm/lib/VMCore/Constants.cpp:1.129 Tue Sep 27 01:09:08 2005 +++ llvm/lib/VMCore/Constants.cpp Mon Oct 3 16:56:24 2005 @@ -248,12 +248,14 @@ assert(V.size() == T->getNumElements() && "Invalid initializer vector for constant array"); Use *OL = OperandList; - for (unsigned i = 0, e = V.size(); i != e; ++i) { - assert((V[i]->getType() == T->getElementType() || + for (std::vector::const_iterator I = V.begin(), E = V.end(); + I != E; ++I, ++OL) { + Constant *E = *I; + assert((E->getType() == T->getElementType() || (T->isAbstract() && - V[i]->getType()->getTypeID()==T->getElementType()->getTypeID())) && + E->getType()->getTypeID() == T->getElementType()->getTypeID())) && "Initializer for array element doesn't match array element type!"); - OL[i].init(V[i], this); + OL->init(E, this); } } @@ -267,13 +269,16 @@ assert(V.size() == T->getNumElements() && "Invalid initializer vector for constant structure"); Use *OL = OperandList; - for (unsigned i = 0, e = V.size(); i != e; ++i) { - assert((V[i]->getType() == T->getElementType(i) || - ((T->getElementType(i)->isAbstract() || - V[i]->getType()->isAbstract()) && - T->getElementType(i)->getTypeID()==V[i]->getType()->getTypeID()))&& + for (std::vector::const_iterator I = V.begin(), E = V.end(); + I != E; ++I, ++OL) { + Constant *E = *I; + assert((E->getType() == T->getElementType(I-V.begin()) || + ((T->getElementType(I-V.begin())->isAbstract() || + E->getType()->isAbstract()) && + T->getElementType(I-V.begin())->getTypeID() == + E->getType()->getTypeID())) && "Initializer for struct element doesn't match struct element type!"); - OL[i].init(V[i], this); + OL->init(E, this); } } @@ -286,12 +291,14 @@ const std::vector &V) : Constant(T, ConstantPackedVal, new Use[V.size()], V.size()) { Use *OL = OperandList; - for (unsigned i = 0, e = V.size(); i != e; ++i) { - assert((V[i]->getType() == T->getElementType() || + for (std::vector::const_iterator I = V.begin(), E = V.end(); + I != E; ++I, ++OL) { + Constant *E = *I; + assert((E->getType() == T->getElementType() || (T->isAbstract() && - V[i]->getType()->getTypeID()==T->getElementType()->getTypeID())) && + E->getType()->getTypeID() == T->getElementType()->getTypeID())) && "Initializer for packed element doesn't match packed element type!"); - OL[i].init(V[i], this); + OL->init(E, this); } } From lattner at cs.uiuc.edu Mon Oct 3 16:58:47 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 3 Oct 2005 16:58:47 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200510032158.QAA28891@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.130 -> 1.131 --- Log message: move some methods, no other changes --- Diffs of the changes: (+132 -130) Constants.cpp | 262 +++++++++++++++++++++++++++++----------------------------- 1 files changed, 132 insertions(+), 130 deletions(-) Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.130 llvm/lib/VMCore/Constants.cpp:1.131 --- llvm/lib/VMCore/Constants.cpp:1.130 Mon Oct 3 16:56:24 2005 +++ llvm/lib/VMCore/Constants.cpp Mon Oct 3 16:58:36 2005 @@ -488,136 +488,6 @@ }; //===----------------------------------------------------------------------===// -// replaceUsesOfWithOnConstant implementations - -void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking) { - assert(isa(To) && "Cannot make Constant refer to non-constant!"); - - std::vector Values; - Values.reserve(getNumOperands()); // Build replacement array... - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { - Constant *Val = getOperand(i); - if (Val == From) Val = cast(To); - Values.push_back(Val); - } - - Constant *Replacement = ConstantArray::get(getType(), Values); - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement... - if (DisableChecking) - uncheckedReplaceAllUsesWith(Replacement); - else - replaceAllUsesWith(Replacement); - - // Delete the old constant! - destroyConstant(); -} - -void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking) { - assert(isa(To) && "Cannot make Constant refer to non-constant!"); - - std::vector Values; - Values.reserve(getNumOperands()); // Build replacement array... - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { - Constant *Val = getOperand(i); - if (Val == From) Val = cast(To); - Values.push_back(Val); - } - - Constant *Replacement = ConstantStruct::get(getType(), Values); - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement... - if (DisableChecking) - uncheckedReplaceAllUsesWith(Replacement); - else - replaceAllUsesWith(Replacement); - - // Delete the old constant! - destroyConstant(); -} - -void ConstantPacked::replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking) { - assert(isa(To) && "Cannot make Constant refer to non-constant!"); - - std::vector Values; - Values.reserve(getNumOperands()); // Build replacement array... - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { - Constant *Val = getOperand(i); - if (Val == From) Val = cast(To); - Values.push_back(Val); - } - - Constant *Replacement = ConstantPacked::get(getType(), Values); - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement... - if (DisableChecking) - uncheckedReplaceAllUsesWith(Replacement); - else - replaceAllUsesWith(Replacement); - - // Delete the old constant! - destroyConstant(); -} - -void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, - bool DisableChecking) { - assert(isa(ToV) && "Cannot make Constant refer to non-constant!"); - Constant *To = cast(ToV); - - Constant *Replacement = 0; - if (getOpcode() == Instruction::GetElementPtr) { - std::vector Indices; - Constant *Pointer = getOperand(0); - Indices.reserve(getNumOperands()-1); - if (Pointer == From) Pointer = To; - - for (unsigned i = 1, e = getNumOperands(); i != e; ++i) { - Constant *Val = getOperand(i); - if (Val == From) Val = To; - Indices.push_back(Val); - } - Replacement = ConstantExpr::getGetElementPtr(Pointer, Indices); - } else if (getOpcode() == Instruction::Cast) { - assert(getOperand(0) == From && "Cast only has one use!"); - Replacement = ConstantExpr::getCast(To, getType()); - } else if (getOpcode() == Instruction::Select) { - Constant *C1 = getOperand(0); - Constant *C2 = getOperand(1); - Constant *C3 = getOperand(2); - if (C1 == From) C1 = To; - if (C2 == From) C2 = To; - if (C3 == From) C3 = To; - Replacement = ConstantExpr::getSelect(C1, C2, C3); - } else if (getNumOperands() == 2) { - Constant *C1 = getOperand(0); - Constant *C2 = getOperand(1); - if (C1 == From) C1 = To; - if (C2 == From) C2 = To; - Replacement = ConstantExpr::get(getOpcode(), C1, C2); - } else { - assert(0 && "Unknown ConstantExpr type!"); - return; - } - - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement... - if (DisableChecking) - uncheckedReplaceAllUsesWith(Replacement); - else - replaceAllUsesWith(Replacement); - - // Delete the old constant! - destroyConstant(); -} - -//===----------------------------------------------------------------------===// // Factory Function Implementation // ConstantCreator - A class that is used to create constants by @@ -1454,6 +1324,138 @@ return Instruction::getOpcodeName(getOpcode()); } +//===----------------------------------------------------------------------===// +// replaceUsesOfWithOnConstant implementations + +void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, + bool DisableChecking) { + assert(isa(To) && "Cannot make Constant refer to non-constant!"); + + std::vector Values; + Values.reserve(getNumOperands()); // Build replacement array... + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + Constant *Val = getOperand(i); + if (Val == From) Val = cast(To); + Values.push_back(Val); + } + + Constant *Replacement = ConstantArray::get(getType(), Values); + assert(Replacement != this && "I didn't contain From!"); + + // Everyone using this now uses the replacement... + if (DisableChecking) + uncheckedReplaceAllUsesWith(Replacement); + else + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); +} + +void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, + bool DisableChecking) { + assert(isa(To) && "Cannot make Constant refer to non-constant!"); + + std::vector Values; + Values.reserve(getNumOperands()); // Build replacement array... + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + Constant *Val = getOperand(i); + if (Val == From) Val = cast(To); + Values.push_back(Val); + } + + Constant *Replacement = ConstantStruct::get(getType(), Values); + assert(Replacement != this && "I didn't contain From!"); + + // Everyone using this now uses the replacement... + if (DisableChecking) + uncheckedReplaceAllUsesWith(Replacement); + else + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); +} + +void ConstantPacked::replaceUsesOfWithOnConstant(Value *From, Value *To, + bool DisableChecking) { + assert(isa(To) && "Cannot make Constant refer to non-constant!"); + + std::vector Values; + Values.reserve(getNumOperands()); // Build replacement array... + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + Constant *Val = getOperand(i); + if (Val == From) Val = cast(To); + Values.push_back(Val); + } + + Constant *Replacement = ConstantPacked::get(getType(), Values); + assert(Replacement != this && "I didn't contain From!"); + + // Everyone using this now uses the replacement... + if (DisableChecking) + uncheckedReplaceAllUsesWith(Replacement); + else + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); +} + +void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, + bool DisableChecking) { + assert(isa(ToV) && "Cannot make Constant refer to non-constant!"); + Constant *To = cast(ToV); + + Constant *Replacement = 0; + if (getOpcode() == Instruction::GetElementPtr) { + std::vector Indices; + Constant *Pointer = getOperand(0); + Indices.reserve(getNumOperands()-1); + if (Pointer == From) Pointer = To; + + for (unsigned i = 1, e = getNumOperands(); i != e; ++i) { + Constant *Val = getOperand(i); + if (Val == From) Val = To; + Indices.push_back(Val); + } + Replacement = ConstantExpr::getGetElementPtr(Pointer, Indices); + } else if (getOpcode() == Instruction::Cast) { + assert(getOperand(0) == From && "Cast only has one use!"); + Replacement = ConstantExpr::getCast(To, getType()); + } else if (getOpcode() == Instruction::Select) { + Constant *C1 = getOperand(0); + Constant *C2 = getOperand(1); + Constant *C3 = getOperand(2); + if (C1 == From) C1 = To; + if (C2 == From) C2 = To; + if (C3 == From) C3 = To; + Replacement = ConstantExpr::getSelect(C1, C2, C3); + } else if (getNumOperands() == 2) { + Constant *C1 = getOperand(0); + Constant *C2 = getOperand(1); + if (C1 == From) C1 = To; + if (C2 == From) C2 = To; + Replacement = ConstantExpr::get(getOpcode(), C1, C2); + } else { + assert(0 && "Unknown ConstantExpr type!"); + return; + } + + assert(Replacement != this && "I didn't contain From!"); + + // Everyone using this now uses the replacement... + if (DisableChecking) + uncheckedReplaceAllUsesWith(Replacement); + else + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); +} + + + /// clearAllValueMaps - This method frees all internal memory used by the /// constant subsystem, which can be used in environments where this memory /// is otherwise reported as a leak. From lattner at cs.uiuc.edu Mon Oct 3 17:51:49 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 3 Oct 2005 17:51:49 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200510032251.RAA29123@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.131 -> 1.132 --- Log message: Change ConstantArray::replaceUsesOfWithOnConstant to attempt to update constant arrays in place instead of reallocating them and replaceAllUsesOf'ing the result. This speeds up a release build of the bcreader from: 136.987u 120.866s 4:24.38 to 49.790u 49.890s 1:40.14 ... a 2.6x speedup parsing a large python bc file. --- Diffs of the changes: (+58 -8) Constants.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 58 insertions(+), 8 deletions(-) Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.131 llvm/lib/VMCore/Constants.cpp:1.132 --- llvm/lib/VMCore/Constants.cpp:1.131 Mon Oct 3 16:58:36 2005 +++ llvm/lib/VMCore/Constants.cpp Mon Oct 3 17:51:37 2005 @@ -515,9 +515,11 @@ namespace { template class ValueMap : public AbstractTypeUser { + public: typedef std::pair MapKey; typedef std::map MapTy; typedef typename MapTy::iterator MapIterator; + private: MapTy Map; typedef std::map AbstractTypeMapTy; @@ -533,8 +535,22 @@ } public: - // getOrCreate - Return the specified constant from the map, creating it if - // necessary. + MapIterator map_end() { return Map.end(); } + + /// InsertOrGetItem - Return an iterator for the specified element. + /// If the element exists in the map, the returned iterator points to the + /// entry and Exists=true. If not, the iterator points to the newly + /// inserted entry and returns Exists=false. Newly inserted entries have + /// I->second == 0, and should be filled in. + MapIterator InsertOrGetItem(std::pair &InsertVal, + bool &Exists) { + std::pair IP = Map.insert(InsertVal); + Exists = !IP.second; + return IP.first; + } + + /// getOrCreate - Return the specified constant from the map, creating it if + /// necessary. ConstantClass *getOrCreate(const TypeClass *Ty, const ValType &V) { MapKey Lookup(Ty, V); MapIterator I = Map.lower_bound(Lookup); @@ -545,7 +561,6 @@ ConstantClass *Result = ConstantCreator::create(Ty, V); - /// FIXME: why does this assert fail when loading 176.gcc? //assert(Result->getType() == Ty && "Type specified is not correct!"); I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result)); @@ -784,8 +799,9 @@ return Elements; } -static ValueMap, ArrayType, - ConstantArray> ArrayConstants; +typedef ValueMap, ArrayType, + ConstantArray> ArrayConstantsTy; +static ArrayConstantsTy ArrayConstants; Constant *ConstantArray::get(const ArrayType *Ty, const std::vector &V) { @@ -1331,15 +1347,49 @@ bool DisableChecking) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); - std::vector Values; - Values.reserve(getNumOperands()); // Build replacement array... + std::pair Lookup; + Lookup.first.first = getType(); + Lookup.second = this; + std::vector &Values = Lookup.first.second; + Values.reserve(getNumOperands()); // Build replacement array. + + bool isAllZeros = false; // Does this turn into an all-zeros array? for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { Constant *Val = getOperand(i); if (Val == From) Val = cast(To); Values.push_back(Val); + if (isAllZeros) isAllZeros = Val->isNullValue(); } - Constant *Replacement = ConstantArray::get(getType(), Values); + Constant *Replacement = 0; + if (isAllZeros) { + Replacement = ConstantAggregateZero::get(getType()); + } else { + // Check to see if we have this array type already. + bool Exists; + ArrayConstantsTy::MapIterator I = + ArrayConstants.InsertOrGetItem(Lookup, Exists); + + if (Exists) { + Replacement = I->second; + } else { + // Okay, the new shape doesn't exist in the system yet. Instead of + // creating a new constant array, inserting it, replaceallusesof'ing the + // old with the new, then deleting the old... just update the current one + // in place! + if (I != ArrayConstants.map_end() && I->second == this) + ++I; // Do not invalidate iterator! + ArrayConstants.remove(this); // Remove old shape from the map. + + // Update to the new values. + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (getOperand(i) == From) + setOperand(i, cast(To)); + return; + } + } + + // Otherwise, I do need to replace this with an existing value. assert(Replacement != this && "I didn't contain From!"); // Everyone using this now uses the replacement... From lattner at cs.uiuc.edu Mon Oct 3 18:43:06 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 3 Oct 2005 18:43:06 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll Message-ID: <200510032343.SAA29380@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/Transforms/SimplifyCFG: 2005-10-02-InvokeSimplify.ll added (r1.1) --- Log message: new testcase for PR635: http://llvm.cs.uiuc.edu/PR635 --- Diffs of the changes: (+13 -0) 2005-10-02-InvokeSimplify.ll | 13 +++++++++++++ 1 files changed, 13 insertions(+) Index: llvm/test/Regression/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll diff -c /dev/null llvm/test/Regression/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll:1.1 *** /dev/null Mon Oct 3 18:43:04 2005 --- llvm/test/Regression/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll Mon Oct 3 18:42:54 2005 *************** *** 0 **** --- 1,13 ---- + ; RUN: llvm-as < %s | opt -simplifycfg -disable-output + + bool %foo() { + %X = invoke bool %foo() to label %N unwind label %F + F: + ret bool false + N: + br bool %X, label %A, label %B + A: + ret bool true + B: + ret bool true + } From lattner at cs.uiuc.edu Mon Oct 3 18:43:55 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 3 Oct 2005 18:43:55 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/SimplifyCFG.cpp Message-ID: <200510032343.SAA29415@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: SimplifyCFG.cpp updated: 1.91 -> 1.92 --- Log message: Clean up the code a bit. Use isInstructionTriviallyDead to be more aggressive and more correct than use_empty(). This fixes PR635: http://llvm.cs.uiuc.edu/PR635 and SimplifyCFG/2005-10-02-InvokeSimplify.ll --- Diffs of the changes: (+8 -4) SimplifyCFG.cpp | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp diff -u llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.91 llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.92 --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.91 Fri Sep 23 13:49:09 2005 +++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp Mon Oct 3 18:43:43 2005 @@ -1284,12 +1284,16 @@ FalseValue, "retval", BI); else NewRetVal = TrueValue; + + DEBUG(std::cerr << "\nCHANGING BRANCH TO TWO RETURNS INTO SELECT:" + << "\n " << *BI << "Select = " << *NewRetVal + << "TRUEBLOCK: " << *TrueSucc << "FALSEBLOCK: "<< *FalseSucc); new ReturnInst(NewRetVal, BI); - BI->getParent()->getInstList().erase(BI); - if (BrCond->use_empty()) - if (Instruction *BrCondI = dyn_cast(BrCond)) - BrCondI->getParent()->getInstList().erase(BrCondI); + BI->eraseFromParent(); + if (Instruction *BrCondI = dyn_cast(BrCond)) + if (isInstructionTriviallyDead(BrCondI)) + BrCondI->eraseFromParent(); return true; } } From natebegeman at mac.com Mon Oct 3 19:37:49 2005 From: natebegeman at mac.com (Nate Begeman) Date: Mon, 3 Oct 2005 19:37:49 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Message-ID: <200510040037.TAA29604@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: LegalizeDAG.cpp updated: 1.189 -> 1.190 --- Log message: Add back a workaround that fixes some breakages from chris's last change. Neither of us have yet figured out why this code is necessary, but stuff breaks if its not there. Still tracking this down... --- Diffs of the changes: (+13 -2) LegalizeDAG.cpp | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.189 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.190 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.189 Sun Oct 2 12:49:46 2005 +++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Mon Oct 3 19:37:37 2005 @@ -623,9 +623,20 @@ Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. // Do not try to legalize the target-specific arguments (#1+) Tmp2 = Node->getOperand(0); - if (Tmp1 != Tmp2) + if (Tmp1 != Tmp2) { Node->setAdjCallChain(Tmp1); - + + // If moving the operand from pointing to Tmp2 dropped its use count to 1, + // this will cause the maps used to memoize results to get confused. + // Create and add a dummy use, just to increase its use count. This will + // be removed at the end of legalize when dead nodes are removed. + if (Tmp2.Val->hasOneUse()) { + // FIXME: find out why this code is necessary + DAG.getNode(ISD::PCMARKER, MVT::Other, Tmp2, + DAG.getConstant(0, MVT::i32)); + } + } + // Note that we do not create new CALLSEQ_DOWN/UP nodes here. These // nodes are treated specially and are mutated in place. This makes the dag // legalization process more efficient and also makes libcall insertion From lattner at cs.uiuc.edu Mon Oct 3 19:44:12 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 3 Oct 2005 19:44:12 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Utils/DemoteRegToStack.cpp Message-ID: <200510040044.TAA29669@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Utils: DemoteRegToStack.cpp updated: 1.14 -> 1.15 --- Log message: Fix DemoteRegToStack on an invoke. This fixes PR634: http://llvm.cs.uiuc.edu/PR634 . --- Diffs of the changes: (+2 -1) DemoteRegToStack.cpp | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-) Index: llvm/lib/Transforms/Utils/DemoteRegToStack.cpp diff -u llvm/lib/Transforms/Utils/DemoteRegToStack.cpp:1.14 llvm/lib/Transforms/Utils/DemoteRegToStack.cpp:1.15 --- llvm/lib/Transforms/Utils/DemoteRegToStack.cpp:1.14 Tue Sep 27 14:39:00 2005 +++ llvm/lib/Transforms/Utils/DemoteRegToStack.cpp Mon Oct 3 19:44:01 2005 @@ -77,6 +77,7 @@ BasicBlock::iterator InsertPt; if (!isa(I)) { InsertPt = &I; + ++InsertPt; } else { // We cannot demote invoke instructions to the stack if their normal edge // is critical. @@ -86,7 +87,7 @@ InsertPt = II.getNormalDest()->begin(); } - for (++InsertPt; isa(InsertPt); ++InsertPt) + for (; isa(InsertPt); ++InsertPt) /* empty */; // Don't insert before any PHI nodes. new StoreInst(&I, Slot, InsertPt); From lattner at cs.uiuc.edu Mon Oct 3 20:18:02 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Mon, 3 Oct 2005 20:18:02 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200510040118.UAA29880@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.132 -> 1.133 --- Log message: implement the struct version of the array speedup, speeding up the testcase a bit more from 1:48 -> 1.40. --- Diffs of the changes: (+49 -9) Constants.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 49 insertions(+), 9 deletions(-) Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.132 llvm/lib/VMCore/Constants.cpp:1.133 --- llvm/lib/VMCore/Constants.cpp:1.132 Mon Oct 3 17:51:37 2005 +++ llvm/lib/VMCore/Constants.cpp Mon Oct 3 20:17:50 2005 @@ -889,8 +889,9 @@ }; } -static ValueMap, StructType, - ConstantStruct> StructConstants; +typedef ValueMap, StructType, + ConstantStruct> StructConstantsTy; +static StructConstantsTy StructConstants; static std::vector getValType(ConstantStruct *CS) { std::vector Elements; @@ -1346,6 +1347,7 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, bool DisableChecking) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); + Constant *ToC = cast(To); std::pair Lookup; Lookup.first.first = getType(); @@ -1353,10 +1355,12 @@ std::vector &Values = Lookup.first.second; Values.reserve(getNumOperands()); // Build replacement array. - bool isAllZeros = false; // Does this turn into an all-zeros array? + // Fill values with the modified operands of the constant array. Also, + // compute whether this turns into an all-zeros array. + bool isAllZeros = ToC->isNullValue(); for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { Constant *Val = getOperand(i); - if (Val == From) Val = cast(To); + if (Val == From) Val = ToC; Values.push_back(Val); if (isAllZeros) isAllZeros = Val->isNullValue(); } @@ -1384,7 +1388,7 @@ // Update to the new values. for (unsigned i = 0, e = getNumOperands(); i != e; ++i) if (getOperand(i) == From) - setOperand(i, cast(To)); + setOperand(i, ToC); return; } } @@ -1405,16 +1409,52 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, bool DisableChecking) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); + Constant *ToC = cast(To); + + std::pair Lookup; + Lookup.first.first = getType(); + Lookup.second = this; + std::vector &Values = Lookup.first.second; + Values.reserve(getNumOperands()); // Build replacement struct. - std::vector Values; - Values.reserve(getNumOperands()); // Build replacement array... + // Fill values with the modified operands of the constant struct. Also, + // compute whether this turns into an all-zeros struct. + bool isAllZeros = ToC->isNullValue(); for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { Constant *Val = getOperand(i); - if (Val == From) Val = cast(To); + if (Val == From) Val = ToC; Values.push_back(Val); + if (isAllZeros) isAllZeros = Val->isNullValue(); + } + + Constant *Replacement = 0; + if (isAllZeros) { + Replacement = ConstantAggregateZero::get(getType()); + } else { + // Check to see if we have this array type already. + bool Exists; + StructConstantsTy::MapIterator I = + StructConstants.InsertOrGetItem(Lookup, Exists); + + if (Exists) { + Replacement = I->second; + } else { + // Okay, the new shape doesn't exist in the system yet. Instead of + // creating a new constant struct, inserting it, replaceallusesof'ing the + // old with the new, then deleting the old... just update the current one + // in place! + if (I != StructConstants.map_end() && I->second == this) + ++I; // Do not invalidate iterator! + StructConstants.remove(this); // Remove old shape from the map. + + // Update to the new values. + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (getOperand(i) == From) + setOperand(i, ToC); + return; + } } - Constant *Replacement = ConstantStruct::get(getType(), Values); assert(Replacement != this && "I didn't contain From!"); // Everyone using this now uses the replacement... From natebegeman at mac.com Mon Oct 3 21:11:08 2005 From: natebegeman at mac.com (Nate Begeman) Date: Mon, 3 Oct 2005 21:11:08 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Message-ID: <200510040211.VAA30029@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: LegalizeDAG.cpp updated: 1.190 -> 1.191 --- Log message: Fix some faulty logic in the libcall inserter. Since calls return more than one value, don't bail if one of their uses happens to be a node that's not an MVT::Other when following the chain from CALLSEQ_START to CALLSEQ_END. Once we've found a CALLSEQ_START, we can just return; there's no need to tail-recurse further up the graph. Most importantly, just because something only has one use doesn't mean we should use it's one use to follow from start to end. This faulty logic caused us to follow a chain of one-use FP operations back to a much earlier call, putting a cycle in the graph from a later start to an earlier end. This is a better fix that reverting to the workaround committed earlier today. --- Diffs of the changes: (+11 -19) LegalizeDAG.cpp | 30 +++++++++++------------------- 1 files changed, 11 insertions(+), 19 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.190 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.191 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.190 Mon Oct 3 19:37:37 2005 +++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Mon Oct 3 21:10:55 2005 @@ -623,20 +623,9 @@ Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain. // Do not try to legalize the target-specific arguments (#1+) Tmp2 = Node->getOperand(0); - if (Tmp1 != Tmp2) { + if (Tmp1 != Tmp2) Node->setAdjCallChain(Tmp1); - // If moving the operand from pointing to Tmp2 dropped its use count to 1, - // this will cause the maps used to memoize results to get confused. - // Create and add a dummy use, just to increase its use count. This will - // be removed at the end of legalize when dead nodes are removed. - if (Tmp2.Val->hasOneUse()) { - // FIXME: find out why this code is necessary - DAG.getNode(ISD::PCMARKER, MVT::Other, Tmp2, - DAG.getConstant(0, MVT::i32)); - } - } - // Note that we do not create new CALLSEQ_DOWN/UP nodes here. These // nodes are treated specially and are mutated in place. This makes the dag // legalization process more efficient and also makes libcall insertion @@ -2630,8 +2619,11 @@ // Otherwise, scan the operands of Node to see if any of them is a call. assert(Node->getNumOperands() != 0 && "All leaves should have depth equal to the entry node!"); - for (unsigned i = 0, e = Node->getNumOperands()-1; i != e; ++i) + for (unsigned i = 0, e = Node->getNumOperands()-1; i != e; ++i) { FindLatestCallSeqStart(Node->getOperand(i).Val, Found); + if (Found->getOpcode() == ISD::CALLSEQ_START) + return; + } // Tail recurse for the last iteration. FindLatestCallSeqStart(Node->getOperand(Node->getNumOperands()-1).Val, @@ -2672,13 +2664,11 @@ if (Node->use_empty()) return 0; // No CallSeqEnd - if (Node->hasOneUse()) // Simple case, only has one user to check. - return FindCallSeqEnd(*Node->use_begin()); - SDOperand TheChain(Node, Node->getNumValues()-1); if (TheChain.getValueType() != MVT::Other) TheChain = SDOperand(Node, 0); - assert(TheChain.getValueType() == MVT::Other && "Is not a token chain!"); + if (TheChain.getValueType() != MVT::Other) + return 0; for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end(); UI != E; ++UI) { @@ -2722,10 +2712,12 @@ // previous call in the function. LatestCallStackDown may in that case be // the entry node itself. Do not attempt to find a matching CALLSEQ_END // unless LatestCallStackDown is an CALLSEQ_START. - if (LatestCallSeqStart->getOpcode() == ISD::CALLSEQ_START) + if (LatestCallSeqStart->getOpcode() == ISD::CALLSEQ_START) { LatestCallSeqEnd = FindCallSeqEnd(LatestCallSeqStart); - else + //std::cerr<<"Found end node: "; LatestCallSeqEnd->dump(); std::cerr <<"\n"; + } else { LatestCallSeqEnd = Entry.Val; + } assert(LatestCallSeqEnd && "NULL return from FindCallSeqEnd"); // Finally, find the first call that this must come before, first we find the From lattner at cs.uiuc.edu Tue Oct 4 00:09:32 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 4 Oct 2005 00:09:32 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Target.td Message-ID: <200510040509.AAA30800@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target: Target.td updated: 1.50 -> 1.51 --- Log message: Add a forward def --- Diffs of the changes: (+2 -1) Target.td | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-) Index: llvm/lib/Target/Target.td diff -u llvm/lib/Target/Target.td:1.50 llvm/lib/Target/Target.td:1.51 --- llvm/lib/Target/Target.td:1.50 Thu Sep 29 23:13:23 2005 +++ llvm/lib/Target/Target.td Tue Oct 4 00:09:20 2005 @@ -41,8 +41,9 @@ //===----------------------------------------------------------------------===// // Register file description - These classes are used to fill in the target -// description classes in llvm/Target/MRegisterInfo.h +// description classes. +class RegisterClass; // Forward def // Register - You should define one instance of this class for each register // in the target machine. String n will become the "name" of the register. From jlaskey at apple.com Tue Oct 4 11:42:03 2005 From: jlaskey at apple.com (Jim Laskey) Date: Tue, 4 Oct 2005 11:42:03 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Message-ID: <200510041642.LAA01538@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: ScheduleDAG.cpp updated: 1.33 -> 1.34 --- Log message: Reverting to version - until problem isolated. --- Diffs of the changes: (+238 -70) ScheduleDAG.cpp | 308 +++++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 238 insertions(+), 70 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp:1.33 llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp:1.34 --- llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp:1.33 Mon Oct 3 07:30:32 2005 +++ llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Tue Oct 4 11:41:51 2005 @@ -386,6 +386,7 @@ std::vector Ordering; // Emit ordering of nodes ResourceTally Tally; // Resource usage tally unsigned NSlots; // Total latency + std::map VRMap; // Node to VR map static const unsigned NotFound = ~0U; // Search marker public: @@ -426,9 +427,7 @@ void IncludeNode(NodeInfo *NI); void VisitAll(); void Schedule(); - void IdentifyGroups(); - void GatherSchedulingInfo(); - void PrepareNodeInfo(); + void GatherNodeInfo(); bool isStrongDependency(NodeInfo *A, NodeInfo *B); bool isWeakDependency(NodeInfo *A, NodeInfo *B); void ScheduleBackward(); @@ -636,34 +635,28 @@ } } -/// IdentifyGroups - Put flagged nodes into groups. -/// -void SimpleSched::IdentifyGroups() { - for (unsigned i = 0, N = NodeCount; i < N; i++) { - NodeInfo* NI = &Info[i]; - SDNode *Node = NI->Node; - - // For each operand (in reverse to only look at flags) - for (unsigned N = Node->getNumOperands(); 0 < N--;) { - // Get operand - SDOperand Op = Node->getOperand(N); - // No more flags to walk - if (Op.getValueType() != MVT::Flag) break; - // Add to node group - NodeGroup::Add(getNI(Op.Val), NI); - } - } -} - -/// GatherSchedulingInfo - Get latency and resource information about each node. -/// -void SimpleSched::GatherSchedulingInfo() { +/// GatherNodeInfo - Get latency and resource information about each node. +/// +void SimpleSched::GatherNodeInfo() { + // Allocate node information + Info = new NodeInfo[NodeCount]; + // Get base of all nodes table + SelectionDAG::allnodes_iterator AllNodes = DAG.allnodes_begin(); + + // For each node being scheduled for (unsigned i = 0, N = NodeCount; i < N; i++) { + // Get next node from DAG all nodes table + SDNode *Node = AllNodes[i]; + // Fast reference to node schedule info NodeInfo* NI = &Info[i]; - SDNode *Node = NI->Node; - - MVT::ValueType VT = Node->getValueType(0); + // Set up map + Map[Node] = NI; + // Set node + NI->Node = Node; + // Set pending visit count + NI->setPending(Node->use_size()); + MVT::ValueType VT = Node->getValueType(0); if (Node->isTargetOpcode()) { MachineOpCode TOpc = Node->getTargetOpcode(); // FIXME: This is an ugly (but temporary!) hack to test the scheduler @@ -708,28 +701,21 @@ // Sum up all the latencies for max tally size NSlots += NI->Latency; } -} -/// PrepareNodeInfo - Set up the basic minimum node info for scheduling. -/// -void SimpleSched::PrepareNodeInfo() { - // Allocate node information - Info = new NodeInfo[NodeCount]; - // Get base of all nodes table - SelectionDAG::allnodes_iterator AllNodes = DAG.allnodes_begin(); - - // For each node being scheduled + // Put flagged nodes into groups for (unsigned i = 0, N = NodeCount; i < N; i++) { - // Get next node from DAG all nodes table - SDNode *Node = AllNodes[i]; - // Fast reference to node schedule info NodeInfo* NI = &Info[i]; - // Set up map - Map[Node] = NI; - // Set node - NI->Node = Node; - // Set pending visit count - NI->setPending(Node->use_size()); + SDNode *Node = NI->Node; + + // For each operand (in reverse to only look at flags) + for (unsigned N = Node->getNumOperands(); 0 < N--;) { + // Get operand + SDOperand Op = Node->getOperand(N); + // No more flags to walk + if (Op.getValueType() != MVT::Flag) break; + // Add to node group + NodeGroup::Add(getNI(Op.Val), NI); + } } } @@ -1068,33 +1054,215 @@ NI->VRBase = VRBase; } +/// EmitDag - Generate machine code for an operand and needed dependencies. +/// +unsigned SimpleSched::EmitDAG(SDOperand Op) { + std::map::iterator OpI = VRMap.lower_bound(Op.Val); + if (OpI != VRMap.end() && OpI->first == Op.Val) + return OpI->second + Op.ResNo; + unsigned &OpSlot = VRMap.insert(OpI, std::make_pair(Op.Val, 0))->second; + + unsigned ResultReg = 0; + if (Op.isTargetOpcode()) { + unsigned Opc = Op.getTargetOpcode(); + const TargetInstrDescriptor &II = TII.get(Opc); + + unsigned NumResults = CountResults(Op.Val); + unsigned NodeOperands = CountOperands(Op.Val); + unsigned NumMIOperands = NodeOperands + NumResults; +#ifndef NDEBUG + assert((unsigned(II.numOperands) == NumMIOperands || II.numOperands == -1)&& + "#operands for dag node doesn't match .td file!"); +#endif + + // Create the new machine instruction. + MachineInstr *MI = new MachineInstr(Opc, NumMIOperands, true, true); + + // Add result register values for things that are defined by this + // instruction. + if (NumResults) ResultReg = CreateVirtualRegisters(MI, NumResults, II); + + // If there is a token chain operand, emit it first, as a hack to get avoid + // really bad cases. + if (Op.getNumOperands() > NodeOperands && + Op.getOperand(NodeOperands).getValueType() == MVT::Other) { + EmitDAG(Op.getOperand(NodeOperands)); + } + + // Emit all of the actual operands of this instruction, adding them to the + // instruction as appropriate. + for (unsigned i = 0; i != NodeOperands; ++i) { + if (Op.getOperand(i).isTargetOpcode()) { + // Note that this case is redundant with the final else block, but we + // include it because it is the most common and it makes the logic + // simpler here. + assert(Op.getOperand(i).getValueType() != MVT::Other && + Op.getOperand(i).getValueType() != MVT::Flag && + "Chain and flag operands should occur at end of operand list!"); + + unsigned VReg = EmitDAG(Op.getOperand(i)); + MI->addRegOperand(VReg, MachineOperand::Use); + + // Verify that it is right. + assert(MRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?"); + assert(II.OpInfo[i+NumResults].RegClass && + "Don't have operand info for this instruction!"); +#ifndef NDEBUG + if (RegMap->getRegClass(VReg) != II.OpInfo[i+NumResults].RegClass) { + std::cerr << "OP: "; + Op.getOperand(i).Val->dump(&DAG); std::cerr << "\nUSE: "; + Op.Val->dump(&DAG); std::cerr << "\n"; + } +#endif + assert(RegMap->getRegClass(VReg) == II.OpInfo[i+NumResults].RegClass && + "Register class of operand and regclass of use don't agree!"); + } else if (ConstantSDNode *C = + dyn_cast(Op.getOperand(i))) { + MI->addZeroExtImm64Operand(C->getValue()); + } else if (RegisterSDNode*R =dyn_cast(Op.getOperand(i))) { + MI->addRegOperand(R->getReg(), MachineOperand::Use); + } else if (GlobalAddressSDNode *TGA = + dyn_cast(Op.getOperand(i))) { + MI->addGlobalAddressOperand(TGA->getGlobal(), false, 0); + } else if (BasicBlockSDNode *BB = + dyn_cast(Op.getOperand(i))) { + MI->addMachineBasicBlockOperand(BB->getBasicBlock()); + } else if (FrameIndexSDNode *FI = + dyn_cast(Op.getOperand(i))) { + MI->addFrameIndexOperand(FI->getIndex()); + } else if (ConstantPoolSDNode *CP = + dyn_cast(Op.getOperand(i))) { + unsigned Idx = ConstPool->getConstantPoolIndex(CP->get()); + MI->addConstantPoolIndexOperand(Idx); + } else if (ExternalSymbolSDNode *ES = + dyn_cast(Op.getOperand(i))) { + MI->addExternalSymbolOperand(ES->getSymbol(), false); + } else { + assert(Op.getOperand(i).getValueType() != MVT::Other && + Op.getOperand(i).getValueType() != MVT::Flag && + "Chain and flag operands should occur at end of operand list!"); + unsigned VReg = EmitDAG(Op.getOperand(i)); + MI->addRegOperand(VReg, MachineOperand::Use); + + // Verify that it is right. + assert(MRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?"); + assert(II.OpInfo[i+NumResults].RegClass && + "Don't have operand info for this instruction!"); + assert(RegMap->getRegClass(VReg) == II.OpInfo[i+NumResults].RegClass && + "Register class of operand and regclass of use don't agree!"); + } + } + + // Finally, if this node has any flag operands, we *must* emit them last, to + // avoid emitting operations that might clobber the flags. + if (Op.getNumOperands() > NodeOperands) { + unsigned i = NodeOperands; + if (Op.getOperand(i).getValueType() == MVT::Other) + ++i; // the chain is already selected. + for (unsigned N = Op.getNumOperands(); i < N; i++) { + assert(Op.getOperand(i).getValueType() == MVT::Flag && + "Must be flag operands!"); + EmitDAG(Op.getOperand(i)); + } + } + + // Now that we have emitted all operands, emit this instruction itself. + if ((II.Flags & M_USES_CUSTOM_DAG_SCHED_INSERTION) == 0) { + BB->insert(BB->end(), MI); + } else { + // Insert this instruction into the end of the basic block, potentially + // taking some custom action. + BB = DAG.getTargetLoweringInfo().InsertAtEndOfBasicBlock(MI, BB); + } + } else { + switch (Op.getOpcode()) { + default: + Op.Val->dump(); + assert(0 && "This target-independent node should have been selected!"); + case ISD::EntryToken: break; + case ISD::TokenFactor: + for (unsigned i = 0, N = Op.getNumOperands(); i < N; i++) { + EmitDAG(Op.getOperand(i)); + } + break; + case ISD::CopyToReg: { + SDOperand FlagOp; FlagOp.ResNo = 0; + if (Op.getNumOperands() == 4) { + FlagOp = Op.getOperand(3); + } + if (Op.getOperand(0).Val != FlagOp.Val) { + EmitDAG(Op.getOperand(0)); // Emit the chain. + } + unsigned Val = EmitDAG(Op.getOperand(2)); + if (FlagOp.Val) { + EmitDAG(FlagOp); + } + MRI.copyRegToReg(*BB, BB->end(), + cast(Op.getOperand(1))->getReg(), Val, + RegMap->getRegClass(Val)); + break; + } + case ISD::CopyFromReg: { + EmitDAG(Op.getOperand(0)); // Emit the chain. + unsigned SrcReg = cast(Op.getOperand(1))->getReg(); + + // Figure out the register class to create for the destreg. + const TargetRegisterClass *TRC = 0; + if (MRegisterInfo::isVirtualRegister(SrcReg)) { + TRC = RegMap->getRegClass(SrcReg); + } else { + // Pick the register class of the right type that contains this physreg. + for (MRegisterInfo::regclass_iterator I = MRI.regclass_begin(), + E = MRI.regclass_end(); I != E; ++I) + if ((*I)->getType() == Op.Val->getValueType(0) && + (*I)->contains(SrcReg)) { + TRC = *I; + break; + } + assert(TRC && "Couldn't find register class for reg copy!"); + } + + // Create the reg, emit the copy. + ResultReg = RegMap->createVirtualRegister(TRC); + MRI.copyRegToReg(*BB, BB->end(), ResultReg, SrcReg, TRC); + break; + } + } + } + + OpSlot = ResultReg; + return ResultReg+Op.ResNo; +} + /// Schedule - Order nodes according to selected style. /// void SimpleSched::Schedule() { - // Number the nodes - NodeCount = DAG.allnodes_size(); - // Set up minimum info for scheduling. - PrepareNodeInfo(); - // Construct node groups for flagged nodes - IdentifyGroups(); - // Breadth first walk of DAG - VisitAll(); - - // Don't waste time if is only entry and return - if (ScheduleStyle != noScheduling && NodeCount > 3) { - // Get latency and resource requirements - GatherSchedulingInfo(); - DEBUG(dump("Pre-")); - // Push back long instructions and critical path - ScheduleBackward(); - DEBUG(dump("Mid-")); - // Pack instructions to maximize resource utilization - ScheduleForward(); + switch (ScheduleStyle) { + case simpleScheduling: + // Number the nodes + NodeCount = DAG.allnodes_size(); + // Don't waste time if is only entry and return + if (NodeCount > 3) { + // Get latency and resource requirements + GatherNodeInfo(); + // Breadth first walk of DAG + VisitAll(); + DEBUG(dump("Pre-")); + // Push back long instructions and critical path + ScheduleBackward(); + DEBUG(dump("Mid-")); + // Pack instructions to maximize resource utilization + ScheduleForward(); + DEBUG(dump("Post-")); + // Emit in scheduled order + EmitAll(); + break; + } // fall thru + case noScheduling: + // Emit instructions in using a DFS from the exit root + EmitDAG(DAG.getRoot()); + break; } - - DEBUG(dump("Post-")); - // Emit in scheduled order - EmitAll(); } /// printSI - Print schedule info. From lattner at cs.uiuc.edu Tue Oct 4 11:52:58 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 4 Oct 2005 11:52:58 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200510041652.LAA01671@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.133 -> 1.134 --- Log message: minor cleanup/fastpath for the bcreader. This speeds up the bcreader from 1:41 -> 1:39 on the large python .bc file in a release build. --- Diffs of the changes: (+23 -2) Constants.cpp | 25 +++++++++++++++++++++++-- 1 files changed, 23 insertions(+), 2 deletions(-) Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.133 llvm/lib/VMCore/Constants.cpp:1.134 --- llvm/lib/VMCore/Constants.cpp:1.133 Mon Oct 3 20:17:50 2005 +++ llvm/lib/VMCore/Constants.cpp Tue Oct 4 11:52:46 2005 @@ -520,6 +520,9 @@ typedef std::map MapTy; typedef typename MapTy::iterator MapIterator; private: + /// Map - This is the main map from the element descriptor to the Constants. + /// This is the primary way we avoid creating two of the same shape + /// constant. MapTy Map; typedef std::map AbstractTypeMapTy; @@ -548,6 +551,24 @@ Exists = !IP.second; return IP.first; } + + /// SimpleRemove - This method removes the specified constant from the map, + /// without updating type information. This should only be used when we're + /// changing an element in the map, making this the second half of a 'move' + /// operation. + void SimpleRemove(ConstantClass *CP) { + MapIterator I = Map.find(MapKey((TypeClass*)CP->getRawType(), + getValType(CP))); + if (I == Map.end() || I->second != CP) { + // FIXME: This should not use a linear scan. If this gets to be a + // performance problem, someone should look at this. + for (I = Map.begin(); I != Map.end() && I->second != CP; ++I) + /* empty */; + } + assert(I != Map.end() && "Constant not found in constant table!"); + assert(I->second == CP && "Didn't find correct element?"); + Map.erase(I); + } /// getOrCreate - Return the specified constant from the map, creating it if /// necessary. @@ -1383,7 +1404,7 @@ // in place! if (I != ArrayConstants.map_end() && I->second == this) ++I; // Do not invalidate iterator! - ArrayConstants.remove(this); // Remove old shape from the map. + ArrayConstants.SimpleRemove(this); // Remove old shape from the map. // Update to the new values. for (unsigned i = 0, e = getNumOperands(); i != e; ++i) @@ -1445,7 +1466,7 @@ // in place! if (I != StructConstants.map_end() && I->second == this) ++I; // Do not invalidate iterator! - StructConstants.remove(this); // Remove old shape from the map. + StructConstants.SimpleRemove(this); // Remove old shape from the map. // Update to the new values. for (unsigned i = 0, e = getNumOperands(); i != e; ++i) From lattner at cs.uiuc.edu Tue Oct 4 12:48:58 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 4 Oct 2005 12:48:58 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200510041748.MAA01884@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.134 -> 1.135 --- Log message: For large constants (e.g. arrays and structs with many elements) just creating the keys and doing comparisons to index into 'Map' takes a lot of time. For these large constants, keep an inverse map so that 'remove' and move operations are much faster. This speeds up a release build of the bc reader on Eric's nasty python bytecode file from 1:39 to 1:00s. --- Diffs of the changes: (+56 -23) Constants.cpp | 79 +++++++++++++++++++++++++++++++++++++++++----------------- 1 files changed, 56 insertions(+), 23 deletions(-) Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.134 llvm/lib/VMCore/Constants.cpp:1.135 --- llvm/lib/VMCore/Constants.cpp:1.134 Tue Oct 4 11:52:46 2005 +++ llvm/lib/VMCore/Constants.cpp Tue Oct 4 12:48:46 2005 @@ -513,7 +513,8 @@ } namespace { - template + template class ValueMap : public AbstractTypeUser { public: typedef std::pair MapKey; @@ -524,6 +525,12 @@ /// This is the primary way we avoid creating two of the same shape /// constant. MapTy Map; + + /// InverseMap - If "HasLargeKey" is true, this contains an inverse mapping + /// from the constants to their element in Map. This is important for + /// removal of constants from the array, which would otherwise have to scan + /// through the map with very large keys. + std::map InverseMap; typedef std::map AbstractTypeMapTy; AbstractTypeMapTy AbstractTypeMap; @@ -535,11 +542,19 @@ Constants.push_back(I->second); Map.clear(); AbstractTypeMap.clear(); + InverseMap.clear(); } public: MapIterator map_end() { return Map.end(); } + void UpdateInverseMap(ConstantClass *C, MapIterator I) { + if (HasLargeKey) { + assert(I->second == C && "Bad inversemap entry!"); + InverseMap[C] = I; + } + } + /// InsertOrGetItem - Return an iterator for the specified element. /// If the element exists in the map, the returned iterator points to the /// entry and Exists=true. If not, the iterator points to the newly @@ -552,19 +567,35 @@ return IP.first; } - /// SimpleRemove - This method removes the specified constant from the map, - /// without updating type information. This should only be used when we're - /// changing an element in the map, making this the second half of a 'move' - /// operation. - void SimpleRemove(ConstantClass *CP) { - MapIterator I = Map.find(MapKey((TypeClass*)CP->getRawType(), - getValType(CP))); +private: + MapIterator FindExistingElement(ConstantClass *CP) { + if (HasLargeKey) { + typename std::map::iterator + IMI = InverseMap.find(CP); + assert(IMI != InverseMap.end() && IMI->second != Map.end() && + IMI->second->second == CP && + "InverseMap corrupt!"); + return IMI->second; + } + + MapIterator I = + Map.find(MapKey((TypeClass*)CP->getRawType(), getValType(CP))); if (I == Map.end() || I->second != CP) { // FIXME: This should not use a linear scan. If this gets to be a // performance problem, someone should look at this. for (I = Map.begin(); I != Map.end() && I->second != CP; ++I) /* empty */; } + return I; + } +public: + + /// SimpleRemove - This method removes the specified constant from the map, + /// without updating type information. This should only be used when we're + /// changing an element in the map, making this the second half of a 'move' + /// operation. + void SimpleRemove(ConstantClass *CP) { + MapIterator I = FindExistingElement(CP); assert(I != Map.end() && "Constant not found in constant table!"); assert(I->second == CP && "Didn't find correct element?"); Map.erase(I); @@ -586,6 +617,9 @@ //assert(Result->getType() == Ty && "Type specified is not correct!"); I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result)); + if (HasLargeKey) // Remember the reverse mapping if needed. + InverseMap.insert(std::make_pair(Result, I)); + // If the type of the constant is abstract, make sure that an entry exists // for it in the AbstractTypeMap. if (Ty->isAbstract()) { @@ -603,18 +637,13 @@ } void remove(ConstantClass *CP) { - MapIterator I = Map.find(MapKey((TypeClass*)CP->getRawType(), - getValType(CP))); - if (I == Map.end() || I->second != CP) { - // FIXME: This should not use a linear scan. If this gets to be a - // performance problem, someone should look at this. - for (I = Map.begin(); I != Map.end() && I->second != CP; ++I) - /* empty */; - } - + MapIterator I = FindExistingElement(CP); assert(I != Map.end() && "Constant not found in constant table!"); assert(I->second == CP && "Didn't find correct element?"); + if (HasLargeKey) // Remember the reverse mapping if needed. + InverseMap.erase(CP); + // Now that we found the entry, make sure this isn't the entry that // the AbstractTypeMap points to. const TypeClass *Ty = I->first.first; @@ -821,7 +850,7 @@ } typedef ValueMap, ArrayType, - ConstantArray> ArrayConstantsTy; + ConstantArray, true /*largekey*/> ArrayConstantsTy; static ArrayConstantsTy ArrayConstants; Constant *ConstantArray::get(const ArrayType *Ty, @@ -911,7 +940,7 @@ } typedef ValueMap, StructType, - ConstantStruct> StructConstantsTy; + ConstantStruct, true /*largekey*/> StructConstantsTy; static StructConstantsTy StructConstants; static std::vector getValType(ConstantStruct *CS) { @@ -1402,9 +1431,11 @@ // creating a new constant array, inserting it, replaceallusesof'ing the // old with the new, then deleting the old... just update the current one // in place! - if (I != ArrayConstants.map_end() && I->second == this) - ++I; // Do not invalidate iterator! ArrayConstants.SimpleRemove(this); // Remove old shape from the map. + + // Update the inverse map so that we know that this constant is now + // located at descriptor I. + ArrayConstants.UpdateInverseMap(this, I); // Update to the new values. for (unsigned i = 0, e = getNumOperands(); i != e; ++i) @@ -1464,9 +1495,11 @@ // creating a new constant struct, inserting it, replaceallusesof'ing the // old with the new, then deleting the old... just update the current one // in place! - if (I != StructConstants.map_end() && I->second == this) - ++I; // Do not invalidate iterator! StructConstants.SimpleRemove(this); // Remove old shape from the map. + + // Update the inverse map so that we know that this constant is now + // located at descriptor I. + StructConstants.UpdateInverseMap(this, I); // Update to the new values. for (unsigned i = 0, e = getNumOperands(); i != e; ++i) From lattner at cs.uiuc.edu Tue Oct 4 13:12:25 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 4 Oct 2005 13:12:25 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Constant.h Constants.h GlobalVariable.h Message-ID: <200510041812.NAA02110@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm: Constant.h updated: 1.24 -> 1.25 Constants.h updated: 1.74 -> 1.75 GlobalVariable.h updated: 1.34 -> 1.35 --- Log message: Change the signature of replaceUsesOfWithOnConstant to take a Use* and not take the bool. The bool is always true dynamically. --- Diffs of the changes: (+6 -14) Constant.h | 3 +-- Constants.h | 14 ++++---------- GlobalVariable.h | 3 +-- 3 files changed, 6 insertions(+), 14 deletions(-) Index: llvm/include/llvm/Constant.h diff -u llvm/include/llvm/Constant.h:1.24 llvm/include/llvm/Constant.h:1.25 --- llvm/include/llvm/Constant.h:1.24 Tue Sep 27 01:08:32 2005 +++ llvm/include/llvm/Constant.h Tue Oct 4 13:12:13 2005 @@ -75,8 +75,7 @@ /// use Value::replaceAllUsesWith, which automatically dispatches to this /// method as needed. /// - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking = false) { + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { // Provide a default implementation for constants (like integers) that // cannot use any other values. This cannot be called at runtime, but needs // to be here to avoid link errors. Index: llvm/include/llvm/Constants.h diff -u llvm/include/llvm/Constants.h:1.74 llvm/include/llvm/Constants.h:1.75 --- llvm/include/llvm/Constants.h:1.74 Tue Sep 27 01:08:32 2005 +++ llvm/include/llvm/Constants.h Tue Oct 4 13:12:13 2005 @@ -323,8 +323,6 @@ virtual bool isNullValue() const { return true; } virtual void destroyConstant(); - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking = false); /// Methods for support type inquiry through isa, cast, and dyn_cast: /// @@ -372,8 +370,7 @@ virtual bool isNullValue() const { return false; } virtual void destroyConstant(); - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking = false); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ConstantArray *) { return true; } @@ -413,8 +410,7 @@ } virtual void destroyConstant(); - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking = false); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ConstantStruct *) { return true; } @@ -451,8 +447,7 @@ virtual bool isNullValue() const { return false; } virtual void destroyConstant(); - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking = false); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ConstantPacked *) { return true; } @@ -604,8 +599,7 @@ const char *getOpcodeName() const; virtual void destroyConstant(); - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking = false); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); /// Override methods to provide more type information... inline Constant *getOperand(unsigned i) { Index: llvm/include/llvm/GlobalVariable.h diff -u llvm/include/llvm/GlobalVariable.h:1.34 llvm/include/llvm/GlobalVariable.h:1.35 --- llvm/include/llvm/GlobalVariable.h:1.34 Thu Apr 21 22:20:18 2005 +++ llvm/include/llvm/GlobalVariable.h Tue Oct 4 13:12:13 2005 @@ -113,8 +113,7 @@ /// Override Constant's implementation of this method so we can /// replace constant initializers. - virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking = false); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); virtual void print(std::ostream &OS) const; From lattner at cs.uiuc.edu Tue Oct 4 13:13:16 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 4 Oct 2005 13:13:16 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Globals.cpp Value.cpp Message-ID: <200510041813.NAA02176@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.135 -> 1.136 Globals.cpp updated: 1.11 -> 1.12 Value.cpp updated: 1.57 -> 1.58 --- Log message: Change the signature of replaceUsesOfWithOnConstant. The bool was always true dynamically. Finally, pass the Use* that replaceAllUsesWith has into the method for future use. --- Diffs of the changes: (+14 -37) Constants.cpp | 44 ++++++++++++-------------------------------- Globals.cpp | 5 +---- Value.cpp | 2 +- 3 files changed, 14 insertions(+), 37 deletions(-) Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.135 llvm/lib/VMCore/Constants.cpp:1.136 --- llvm/lib/VMCore/Constants.cpp:1.135 Tue Oct 4 12:48:46 2005 +++ llvm/lib/VMCore/Constants.cpp Tue Oct 4 13:13:04 2005 @@ -815,14 +815,6 @@ destroyConstantImpl(); } -void ConstantAggregateZero::replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking) { - assert(0 && "No uses!"); - abort(); -} - - - //---- ConstantArray::get() implementation... // namespace llvm { @@ -1395,7 +1387,7 @@ // replaceUsesOfWithOnConstant implementations void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking) { + Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(To); @@ -1448,18 +1440,15 @@ // Otherwise, I do need to replace this with an existing value. assert(Replacement != this && "I didn't contain From!"); - // Everyone using this now uses the replacement... - if (DisableChecking) - uncheckedReplaceAllUsesWith(Replacement); - else - replaceAllUsesWith(Replacement); + // Everyone using this now uses the replacement. + uncheckedReplaceAllUsesWith(Replacement); // Delete the old constant! destroyConstant(); } void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking) { + Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(To); @@ -1511,18 +1500,15 @@ assert(Replacement != this && "I didn't contain From!"); - // Everyone using this now uses the replacement... - if (DisableChecking) - uncheckedReplaceAllUsesWith(Replacement); - else - replaceAllUsesWith(Replacement); + // Everyone using this now uses the replacement. + uncheckedReplaceAllUsesWith(Replacement); // Delete the old constant! destroyConstant(); } void ConstantPacked::replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking) { + Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); std::vector Values; @@ -1536,18 +1522,15 @@ Constant *Replacement = ConstantPacked::get(getType(), Values); assert(Replacement != this && "I didn't contain From!"); - // Everyone using this now uses the replacement... - if (DisableChecking) - uncheckedReplaceAllUsesWith(Replacement); - else - replaceAllUsesWith(Replacement); + // Everyone using this now uses the replacement. + uncheckedReplaceAllUsesWith(Replacement); // Delete the old constant! destroyConstant(); } void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, - bool DisableChecking) { + Use *U) { assert(isa(ToV) && "Cannot make Constant refer to non-constant!"); Constant *To = cast(ToV); @@ -1588,11 +1571,8 @@ assert(Replacement != this && "I didn't contain From!"); - // Everyone using this now uses the replacement... - if (DisableChecking) - uncheckedReplaceAllUsesWith(Replacement); - else - replaceAllUsesWith(Replacement); + // Everyone using this now uses the replacement. + uncheckedReplaceAllUsesWith(Replacement); // Delete the old constant! destroyConstant(); Index: llvm/lib/VMCore/Globals.cpp diff -u llvm/lib/VMCore/Globals.cpp:1.11 llvm/lib/VMCore/Globals.cpp:1.12 --- llvm/lib/VMCore/Globals.cpp:1.11 Thu Apr 21 18:46:51 2005 +++ llvm/lib/VMCore/Globals.cpp Tue Oct 4 13:13:04 2005 @@ -108,7 +108,7 @@ } void GlobalVariable::replaceUsesOfWithOnConstant(Value *From, Value *To, - bool DisableChecking) { + Use *U) { // If you call this, then you better know this GVar has a constant // initializer worth replacing. Enforce that here. assert(getNumOperands() == 1 && @@ -126,6 +126,3 @@ // Okay, preconditions out of the way, replace the constant initializer. this->setOperand(0, cast(To)); } - -// vim: sw=2 ai - Index: llvm/lib/VMCore/Value.cpp diff -u llvm/lib/VMCore/Value.cpp:1.57 llvm/lib/VMCore/Value.cpp:1.58 --- llvm/lib/VMCore/Value.cpp:1.57 Thu Apr 21 18:46:51 2005 +++ llvm/lib/VMCore/Value.cpp Tue Oct 4 13:13:04 2005 @@ -141,7 +141,7 @@ // constant! if (Constant *C = dyn_cast(U.getUser())) { if (!isa(C)) - C->replaceUsesOfWithOnConstant(this, New, true); + C->replaceUsesOfWithOnConstant(this, New, &U); else U.set(New); } else { From lattner at cs.uiuc.edu Tue Oct 4 13:47:21 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 4 Oct 2005 13:47:21 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200510041847.NAA02362@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.136 -> 1.137 --- Log message: Minor speedup to avoid array searches given a Use*. This speeds up bc reading of the python test from 1:00 to 54s. --- Diffs of the changes: (+39 -23) Constants.cpp | 62 ++++++++++++++++++++++++++++++++++++---------------------- 1 files changed, 39 insertions(+), 23 deletions(-) Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.136 llvm/lib/VMCore/Constants.cpp:1.137 --- llvm/lib/VMCore/Constants.cpp:1.136 Tue Oct 4 13:13:04 2005 +++ llvm/lib/VMCore/Constants.cpp Tue Oct 4 13:47:09 2005 @@ -1390,22 +1390,32 @@ Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(To); - + + unsigned OperandToUpdate = U-OperandList; + assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!"); + std::pair Lookup; Lookup.first.first = getType(); Lookup.second = this; + std::vector &Values = Lookup.first.second; Values.reserve(getNumOperands()); // Build replacement array. - + // Fill values with the modified operands of the constant array. Also, // compute whether this turns into an all-zeros array. - bool isAllZeros = ToC->isNullValue(); - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { - Constant *Val = getOperand(i); - if (Val == From) Val = ToC; - Values.push_back(Val); - if (isAllZeros) isAllZeros = Val->isNullValue(); + bool isAllZeros = false; + if (!ToC->isNullValue()) { + for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) + Values.push_back(cast(O->get())); + } else { + isAllZeros = true; + for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) { + Constant *Val = cast(O->get()); + Values.push_back(Val); + if (isAllZeros) isAllZeros = Val->isNullValue(); + } } + Values[OperandToUpdate] = ToC; Constant *Replacement = 0; if (isAllZeros) { @@ -1429,10 +1439,8 @@ // located at descriptor I. ArrayConstants.UpdateInverseMap(this, I); - // Update to the new values. - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (getOperand(i) == From) - setOperand(i, ToC); + // Update to the new value. + setOperand(OperandToUpdate, ToC); return; } } @@ -1452,22 +1460,32 @@ assert(isa(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(To); + unsigned OperandToUpdate = U-OperandList; + assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!"); + std::pair Lookup; Lookup.first.first = getType(); Lookup.second = this; std::vector &Values = Lookup.first.second; Values.reserve(getNumOperands()); // Build replacement struct. + // Fill values with the modified operands of the constant struct. Also, // compute whether this turns into an all-zeros struct. - bool isAllZeros = ToC->isNullValue(); - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { - Constant *Val = getOperand(i); - if (Val == From) Val = ToC; - Values.push_back(Val); - if (isAllZeros) isAllZeros = Val->isNullValue(); + bool isAllZeros = false; + if (!ToC->isNullValue()) { + for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) + Values.push_back(cast(O->get())); + } else { + isAllZeros = true; + for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) { + Constant *Val = cast(O->get()); + Values.push_back(Val); + if (isAllZeros) isAllZeros = Val->isNullValue(); + } } - + Values[OperandToUpdate] = ToC; + Constant *Replacement = 0; if (isAllZeros) { Replacement = ConstantAggregateZero::get(getType()); @@ -1490,10 +1508,8 @@ // located at descriptor I. StructConstants.UpdateInverseMap(this, I); - // Update to the new values. - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (getOperand(i) == From) - setOperand(i, ToC); + // Update to the new value. + setOperand(OperandToUpdate, ToC); return; } } From lattner at cs.uiuc.edu Tue Oct 4 16:36:03 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 4 Oct 2005 16:36:03 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200510042136.QAA03582@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.137 -> 1.138 --- Log message: refactor a bit of code. When moving constant entries in 'Map' if the entry is the representative constant for the abstractypemap, make sure to update it as well. This fixes the bcreader failures from last night on several C++ apps. --- Diffs of the changes: (+35 -29) Constants.cpp | 64 +++++++++++++++++++++++++++++++--------------------------- 1 files changed, 35 insertions(+), 29 deletions(-) Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.137 llvm/lib/VMCore/Constants.cpp:1.138 --- llvm/lib/VMCore/Constants.cpp:1.137 Tue Oct 4 13:47:09 2005 +++ llvm/lib/VMCore/Constants.cpp Tue Oct 4 16:35:50 2005 @@ -548,13 +548,6 @@ public: MapIterator map_end() { return Map.end(); } - void UpdateInverseMap(ConstantClass *C, MapIterator I) { - if (HasLargeKey) { - assert(I->second == C && "Bad inversemap entry!"); - InverseMap[C] = I; - } - } - /// InsertOrGetItem - Return an iterator for the specified element. /// If the element exists in the map, the returned iterator points to the /// entry and Exists=true. If not, the iterator points to the newly @@ -590,17 +583,6 @@ } public: - /// SimpleRemove - This method removes the specified constant from the map, - /// without updating type information. This should only be used when we're - /// changing an element in the map, making this the second half of a 'move' - /// operation. - void SimpleRemove(ConstantClass *CP) { - MapIterator I = FindExistingElement(CP); - assert(I != Map.end() && "Constant not found in constant table!"); - assert(I->second == CP && "Didn't find correct element?"); - Map.erase(I); - } - /// getOrCreate - Return the specified constant from the map, creating it if /// necessary. ConstantClass *getOrCreate(const TypeClass *Ty, const ValType &V) { @@ -686,6 +668,38 @@ Map.erase(I); } + + /// MoveConstantToNewSlot - If we are about to change C to be the element + /// specified by I, update our internal data structures to reflect this + /// fact. + void MoveConstantToNewSlot(ConstantClass *C, MapIterator I) { + // First, remove the old location of the specified constant in the map. + MapIterator OldI = FindExistingElement(C); + assert(OldI != Map.end() && "Constant not found in constant table!"); + assert(OldI->second == C && "Didn't find correct element?"); + + // If this constant is the representative element for its abstract type, + // update the AbstractTypeMap so that the representative element is I. + if (C->getType()->isAbstract()) { + typename AbstractTypeMapTy::iterator ATI = + AbstractTypeMap.find(C->getType()); + assert(ATI != AbstractTypeMap.end() && + "Abstract type not in AbstractTypeMap?"); + if (ATI->second == OldI) + ATI->second = I; + } + + // Remove the old entry from the map. + Map.erase(OldI); + + // Update the inverse map so that we know that this constant is now + // located at descriptor I. + if (HasLargeKey) { + assert(I->second == C && "Bad inversemap entry!"); + InverseMap[C] = I; + } + } + void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) { typename AbstractTypeMapTy::iterator I = AbstractTypeMap.find(cast(OldTy)); @@ -1433,11 +1447,7 @@ // creating a new constant array, inserting it, replaceallusesof'ing the // old with the new, then deleting the old... just update the current one // in place! - ArrayConstants.SimpleRemove(this); // Remove old shape from the map. - - // Update the inverse map so that we know that this constant is now - // located at descriptor I. - ArrayConstants.UpdateInverseMap(this, I); + ArrayConstants.MoveConstantToNewSlot(this, I); // Update to the new value. setOperand(OperandToUpdate, ToC); @@ -1493,7 +1503,7 @@ // Check to see if we have this array type already. bool Exists; StructConstantsTy::MapIterator I = - StructConstants.InsertOrGetItem(Lookup, Exists); + StructConstants.InsertOrGetItem(Lookup, Exists); if (Exists) { Replacement = I->second; @@ -1502,11 +1512,7 @@ // creating a new constant struct, inserting it, replaceallusesof'ing the // old with the new, then deleting the old... just update the current one // in place! - StructConstants.SimpleRemove(this); // Remove old shape from the map. - - // Update the inverse map so that we know that this constant is now - // located at descriptor I. - StructConstants.UpdateInverseMap(this, I); + StructConstants.MoveConstantToNewSlot(this, I); // Update to the new value. setOperand(OperandToUpdate, ToC); From lattner at cs.uiuc.edu Tue Oct 4 19:28:54 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 4 Oct 2005 19:28:54 -0500 Subject: [llvm-commits] CVS: llvm/Makefile.rules Message-ID: <200510050028.TAA04123@zion.cs.uiuc.edu> Changes in directory llvm: Makefile.rules updated: 1.325 -> 1.326 --- Log message: Add some rules for building preprocessed files --- Diffs of the changes: (+17 -0) Makefile.rules | 17 +++++++++++++++++ 1 files changed, 17 insertions(+) Index: llvm/Makefile.rules diff -u llvm/Makefile.rules:1.325 llvm/Makefile.rules:1.326 --- llvm/Makefile.rules:1.325 Fri Sep 2 20:15:25 2005 +++ llvm/Makefile.rules Tue Oct 4 19:28:41 2005 @@ -359,10 +359,13 @@ LTCompile.C = $(LIBTOOL) $(LibTool.Flags) --mode=compile $(Compile.C) BCCompile.C = $(LLVMGCCWITHPATH) $(CPP.Flags) $(CompileCommonOpts) \ $(C.Flags) -c +Preprocess.C = $(CC) $(CPP.Flags) $(CompileCommonOpts) -E $(C.Flags) + Compile.CXX = $(CXX) $(CPP.Flags) $(CompileCommonOpts) $(CXX.Flags) -c LTCompile.CXX = $(LIBTOOL) $(LibTool.Flags) --mode=compile $(Compile.CXX) BCCompile.CXX = $(LLVMGXXWITHPATH) $(CPP.Flags) $(CompileCommonOpts) \ $(CXX.Flags) -c +Preprocess.CXX= $(CXX) $(CPP.Flags) $(CompileCommonOpts) $(CXX.Flags) -E Link = $(LIBTOOL) $(LibTool.Flags) --mode=link $(CXX) $(CPP.Flags) \ $(CompileCommonOpts) $(LD.Flags) $(Strip) Relink = $(LIBTOOL) $(LibTool.Flags) --mode=link $(CXX) $(CPP.Flags) \ @@ -1002,6 +1005,20 @@ endif +## Rules for building preprocessed (.i/.ii) outputs. +$(BuildMode)/%.ii: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cpp for $(BuildMode) build to .ii file" + $(Verb) $(Preprocess.CXX) $< -o $@ + +$(BuildMode)/%.ii: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.cc for $(BuildMode) build to .ii file" + $(Verb) $(Preprocess.CXX) $< -o $@ + + $(BuildMode)/%.i: %.c $(ObjDir)/.dir $(BUILT_SOURCES) + $(Echo) "Compiling $*.c for $(BuildMode) build to .i file" + $(Verb) $(Preprocess.C) $< -o $@ + + #--------------------------------------------------------- # Create .bc files in the ObjDir directory from .cpp .cc and .c files... #--------------------------------------------------------- From lattner at cs.uiuc.edu Tue Oct 4 23:45:55 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Tue, 4 Oct 2005 23:45:55 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <200510050445.XAA05223@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: DAGCombiner.cpp updated: 1.14 -> 1.15 --- Log message: Fix a crash compiling Olden/tsp --- Diffs of the changes: (+4 -6) DAGCombiner.cpp | 10 ++++------ 1 files changed, 4 insertions(+), 6 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.14 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.15 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.14 Wed Sep 28 17:28:18 2005 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Tue Oct 4 23:45:43 2005 @@ -1069,18 +1069,16 @@ // Determine if the condition we're dealing with is constant SDOperand SCC = SimplifySetCC(TLI.getSetCCResultTy(), N0, N1, CC); - ConstantSDNode *SCCC = dyn_cast(SCC); - bool constTrue = SCCC && SCCC->getValue() == 1; - bool constFalse = SCCC && SCCC->isNullValue(); - + ConstantSDNode *SCCC = dyn_cast_or_null(SCC.Val); + // fold select_cc lhs, rhs, x, x, cc -> x if (N2 == N3) return N2; // fold select_cc true, x, y -> x - if (constTrue) + if (SCCC && SCCC->getValue()) return N2; // fold select_cc false, x, y -> y - if (constFalse) + if (SCCC && SCCC->getValue() == 0) return N3; // fold select_cc into other things, such as min/max/abs return SimplifySelectCC(N0, N1, N2, N3, CC); From lattner at cs.uiuc.edu Wed Oct 5 01:09:25 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 5 Oct 2005 01:09:25 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Message-ID: <200510050609.BAA05512@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAGISel.cpp updated: 1.86 -> 1.87 --- Log message: make sure that -view-isel-dags is the input to the isel, not the input to the second phase of dag combining --- Diffs of the changes: (+2 -2) SelectionDAGISel.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.86 llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.87 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1.86 Fri Sep 30 22:57:14 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Wed Oct 5 01:09:10 2005 @@ -1302,11 +1302,11 @@ DEBUG(std::cerr << "Legalized selection DAG:\n"); DEBUG(DAG.dump()); - if (ViewDAGs) DAG.viewGraph(); - // Run the DAG combiner in post-legalize mode, if we are told to do so if (CombinerEnabled) DAG.Combine(true); + if (ViewDAGs) DAG.viewGraph(); + // Third, instruction select all of the operations to machine code, adding the // code to the MachineBasicBlock. InstructionSelectBasicBlock(DAG); From lattner at cs.uiuc.edu Wed Oct 5 01:11:19 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 5 Oct 2005 01:11:19 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <200510050611.BAA05622@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: DAGCombiner.cpp updated: 1.15 -> 1.16 --- Log message: Implement the code for PowerPC/inverted-bool-compares.ll, even though it that testcase still does not pass with the dag combiner. This is because not all forms of br* are folded yet. Also, when we combine a node into another one, delete the node immediately instead of waiting for the node to potentially come up in the future. --- Diffs of the changes: (+16 -1) DAGCombiner.cpp | 17 ++++++++++++++++- 1 files changed, 16 insertions(+), 1 deletion(-) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.15 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.16 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.15 Tue Oct 4 23:45:43 2005 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Wed Oct 5 01:11:08 2005 @@ -313,6 +313,9 @@ // Nodes can end up on the worklist more than once. Make sure we do // not process a node that has been replaced. removeFromWorkList(N); + + // Finally, since the node is now dead, remove it from the graph. + DAG.DeleteNode(N); } } } @@ -1546,7 +1549,7 @@ ExtDstTy), Cond); } - + uint64_t MinVal, MaxVal; unsigned OperandBitSize = MVT::getSizeInBits(N1C->getValueType(0)); if (ISD::isSignedIntSetCC(Cond)) { @@ -1682,6 +1685,18 @@ } } + // Turn (X^C1) == C2 into X == C1^C2 iff X&~C1 = 0. Common for condcodes. + if (N0.getOpcode() == ISD::XOR) + if (ConstantSDNode *XORC = dyn_cast(N0.getOperand(1))) + if (ConstantSDNode *RHSC = dyn_cast(N1)) { + // If we know that all of the inverted bits are zero, don't bother + // performing the inversion. + if (MaskedValueIsZero(N0.getOperand(0), ~XORC->getValue(), TLI)) + return DAG.getSetCC(VT, N0.getOperand(0), + DAG.getConstant(XORC->getValue()^RHSC->getValue(), + N0.getValueType()), Cond); + } + // Simplify (X+Z) == X --> Z == 0 if (N0.getOperand(0) == N1) return DAG.getSetCC(VT, N0.getOperand(1), From lattner at cs.uiuc.edu Wed Oct 5 01:34:46 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 5 Oct 2005 01:34:46 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/CodeGen/SelectionDAGNodes.h Message-ID: <200510050634.BAA05746@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/CodeGen: SelectionDAGNodes.h updated: 1.68 -> 1.69 --- Log message: add a helper class --- Diffs of the changes: (+17 -0) SelectionDAGNodes.h | 17 +++++++++++++++++ 1 files changed, 17 insertions(+) Index: llvm/include/llvm/CodeGen/SelectionDAGNodes.h diff -u llvm/include/llvm/CodeGen/SelectionDAGNodes.h:1.68 llvm/include/llvm/CodeGen/SelectionDAGNodes.h:1.69 --- llvm/include/llvm/CodeGen/SelectionDAGNodes.h:1.68 Wed Sep 28 17:26:50 2005 +++ llvm/include/llvm/CodeGen/SelectionDAGNodes.h Wed Oct 5 01:34:34 2005 @@ -309,6 +309,9 @@ // other operands match the intrinsic. These produce a token chain in // addition to a value (if any). READPORT, WRITEPORT, READIO, WRITEIO, + + // HANDLENODE node - Used as a handle for various purposes. + HANDLENODE, // BUILTIN_OP_END - This must be the last enum value in this list. BUILTIN_OP_END, @@ -751,6 +754,20 @@ return Val->hasNUsesOfValue(1, ResNo); } +/// HandleSDNode - This class is used to form a handle around another node that +/// is persistant and is updated across invocations of replaceAllUsesWith on its +/// operand. This node should be directly created by end-users and not added to +/// the AllNodes list. +class HandleSDNode : public SDNode { +public: + HandleSDNode(SDOperand X) : SDNode(ISD::HANDLENODE, X) {} + ~HandleSDNode() { + MorphNodeTo(ISD::HANDLENODE); // Drops operand uses. + } + + SDOperand getValue() const { return getOperand(0); } +}; + class ConstantSDNode : public SDNode { uint64_t Value; From lattner at cs.uiuc.edu Wed Oct 5 01:35:40 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 5 Oct 2005 01:35:40 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp SelectionDAG.cpp Message-ID: <200510050635.BAA05784@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: DAGCombiner.cpp updated: 1.16 -> 1.17 SelectionDAG.cpp updated: 1.194 -> 1.195 --- Log message: Add a new HandleNode class, which is used to handle (haha) cases in the dead node elim and dag combiner passes where the root is potentially updated. This fixes a fixme in the dag combiner. --- Diffs of the changes: (+17 -11) DAGCombiner.cpp | 17 ++++++++++++----- SelectionDAG.cpp | 11 +++++------ 2 files changed, 17 insertions(+), 11 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.16 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.17 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.16 Wed Oct 5 01:11:08 2005 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Wed Oct 5 01:35:28 2005 @@ -274,6 +274,11 @@ // Add all the dag nodes to the worklist. WorkList.insert(WorkList.end(), DAG.allnodes_begin(), DAG.allnodes_end()); + // Create a dummy node (which is not added to allnodes), that adds a reference + // to the root node, preventing it from being deleted, and tracking any + // changes of the root. + HandleSDNode Dummy(DAG.getRoot()); + // while the worklist isn't empty, inspect the node on the end of it and // try and combine it. while (!WorkList.empty()) { @@ -281,15 +286,14 @@ WorkList.pop_back(); // If N has no uses, it is dead. Make sure to revisit all N's operands once - // N is deleted from the DAG, since they too may now be dead. - // FIXME: is there a better way to keep from deleting the dag root because - // we think it has no uses? This works for now... - if (N->use_empty() && N != DAG.getRoot().Val) { + // N is deleted from the DAG, since they too may now be dead or may have a + // reduced number of uses, allowing other xforms. + if (N->use_empty() && N != &Dummy) { for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) WorkList.push_back(N->getOperand(i).Val); - DAG.DeleteNode(N); removeFromWorkList(N); + DAG.DeleteNode(N); continue; } @@ -319,6 +323,9 @@ } } } + + // If the root changed (e.g. it was a dead load, update the root). + DAG.setRoot(Dummy.getValue()); } SDOperand DAGCombiner::visit(SDNode *N) { Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.194 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.195 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.194 Wed Sep 28 17:28:18 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Wed Oct 5 01:35:28 2005 @@ -176,7 +176,7 @@ // Create a dummy node (which is not added to allnodes), that adds a reference // to the root node, preventing it from being deleted. - SDNode *DummyNode = new SDNode(ISD::EntryToken, getRoot()); + HandleSDNode Dummy(getRoot()); // If we have a hint to start from, use it. if (N) DeleteNodeIfDead(N, &AllNodeSet); @@ -199,11 +199,7 @@ AllNodes.assign(AllNodeSet.begin(), AllNodeSet.end()); // If the root changed (e.g. it was a dead load, update the root). - setRoot(DummyNode->getOperand(0)); - - // Now that we are done with the dummy node, delete it. - DummyNode->getOperand(0).Val->removeUser(DummyNode); - delete DummyNode; + setRoot(Dummy.getValue()); } @@ -276,6 +272,7 @@ void SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) { bool Erased = false; switch (N->getOpcode()) { + case ISD::HANDLENODE: return; // noop. case ISD::Constant: Erased = Constants.erase(std::make_pair(cast(N)->getValue(), N->getValueType(0))); @@ -397,6 +394,8 @@ N->getValueType(0)))]; if (L) return L; L = N; + } else if (N->getOpcode() == ISD::HANDLENODE) { + return 0; // never add it. } else if (N->getNumOperands() == 1) { SDNode *&U = UnaryOps[std::make_pair(N->getOpcode(), std::make_pair(N->getOperand(0), From lattner at cs.uiuc.edu Wed Oct 5 01:37:34 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 5 Oct 2005 01:37:34 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200510050637.BAA05841@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAG.cpp updated: 1.195 -> 1.196 --- Log message: fix some pastos --- Diffs of the changes: (+2 -2) SelectionDAG.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.195 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.196 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.195 Wed Oct 5 01:35:28 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Wed Oct 5 01:37:22 2005 @@ -1947,7 +1947,7 @@ break; } case ISD::SELECT_CC: { - assert(Ops.size() == 5 && "TRUNCSTORE takes 5 operands!"); + assert(Ops.size() == 5 && "SELECT_CC takes 5 operands!"); assert(Ops[0].getValueType() == Ops[1].getValueType() && "LHS and RHS of condition must have same type!"); assert(Ops[2].getValueType() == Ops[3].getValueType() && @@ -1960,7 +1960,7 @@ break; } case ISD::BR_CC: { - assert(Ops.size() == 5 && "TRUNCSTORE takes 5 operands!"); + assert(Ops.size() == 5 && "BR_CC takes 5 operands!"); assert(Ops[2].getValueType() == Ops[3].getValueType() && "LHS/RHS of comparison should match types!"); // Use SimplifySetCC to simplify SETCC's. From lattner at cs.uiuc.edu Wed Oct 5 01:48:00 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 5 Oct 2005 01:48:00 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp SelectionDAG.cpp Message-ID: <200510050648.BAA05919@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: DAGCombiner.cpp updated: 1.17 -> 1.18 SelectionDAG.cpp updated: 1.196 -> 1.197 --- Log message: implement visitBR_CC so that PowerPC/inverted-bool-compares.ll passes with the dag combiner. This speeds up espresso by 8%, reaching performance parity with the dag-combiner-disabled llc. --- Diffs of the changes: (+25 -2) DAGCombiner.cpp | 24 ++++++++++++++++++++++-- SelectionDAG.cpp | 3 +++ 2 files changed, 25 insertions(+), 2 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.17 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.18 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.17 Wed Oct 5 01:35:28 2005 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Wed Oct 5 01:47:48 2005 @@ -1425,9 +1425,29 @@ return SDOperand(); } +// Operand List for BR_CC: Chain, CondCC, CondLHS, CondRHS, DestBB. +// SDOperand DAGCombiner::visitBR_CC(SDNode *N) { - // FIXME: come up with a common way between br_cc, brtwoway_cc, and select_cc - // to canonicalize the condition without calling getnode a bazillion times. + CondCodeSDNode *CC = cast(N->getOperand(1)); + SDOperand CondLHS = N->getOperand(2), CondRHS = N->getOperand(3); + + // Use SimplifySetCC to simplify SETCC's. + SDOperand Simp = SimplifySetCC(MVT::i1, CondLHS, CondRHS, CC->get()); + if (Simp.Val) { + if (ConstantSDNode *C = dyn_cast(Simp)) { + if (C->getValue() & 1) // Unconditional branch + return DAG.getNode(ISD::BR, MVT::Other, N->getOperand(0), + N->getOperand(4)); + else + return N->getOperand(0); // Unconditional Fall through + } else if (Simp.Val->getOpcode() == ISD::SETCC) { + // Folded to a simpler setcc + return DAG.getNode(ISD::BR_CC, MVT::Other, N->getOperand(0), + Simp.getOperand(2), Simp.getOperand(0), + Simp.getOperand(1), N->getOperand(4)); + } + } + return SDOperand(); } Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.196 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.197 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.196 Wed Oct 5 01:37:22 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Wed Oct 5 01:47:48 2005 @@ -1963,6 +1963,9 @@ assert(Ops.size() == 5 && "BR_CC takes 5 operands!"); assert(Ops[2].getValueType() == Ops[3].getValueType() && "LHS/RHS of comparison should match types!"); + + if (CombinerEnabled) break; // xforms moved to dag combine. + // Use SimplifySetCC to simplify SETCC's. SDOperand Simp = SimplifySetCC(MVT::i1, Ops[2], Ops[3], cast(Ops[1])->get()); From lattner at cs.uiuc.edu Wed Oct 5 12:15:21 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 5 Oct 2005 12:15:21 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/SparcV8/FPMover.cpp Message-ID: <200510051715.MAA16757@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/SparcV8: FPMover.cpp updated: 1.6 -> 1.7 --- Log message: silence some warnings --- Diffs of the changes: (+1 -1) FPMover.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Target/SparcV8/FPMover.cpp diff -u llvm/lib/Target/SparcV8/FPMover.cpp:1.6 llvm/lib/Target/SparcV8/FPMover.cpp:1.7 --- llvm/lib/Target/SparcV8/FPMover.cpp:1.6 Wed Jul 27 01:12:33 2005 +++ llvm/lib/Target/SparcV8/FPMover.cpp Wed Oct 5 12:15:09 2005 @@ -82,7 +82,7 @@ bool Changed = false; for (MachineBasicBlock::iterator I = MBB.begin (); I != MBB.end (); ++I) if (V8::FpMOVD == I->getOpcode ()) { - unsigned NewSrcReg0, NewSrcReg1, NewDestReg0, NewDestReg1; + unsigned NewSrcReg0 = 0, NewSrcReg1 = 0, NewDestReg0 = 0, NewDestReg1 = 0; doubleToSingleRegPair (I->getOperand (0).getReg (), NewDestReg0, NewDestReg1); doubleToSingleRegPair (I->getOperand (1).getReg (), NewSrcReg0, From lattner at cs.uiuc.edu Wed Oct 5 13:31:24 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 5 Oct 2005 13:31:24 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/VirtRegMap.cpp Message-ID: <200510051831.NAA03849@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: VirtRegMap.cpp updated: 1.40 -> 1.41 --- Log message: Fix a bug in the local spiller, where we could take code like this: store r12 -> [ss#2] R3 = load [ss#1] use R3 R3 = load [ss#2] R4 = load [ss#1] and turn it into this code: store R12 -> [ss#2] R3 = load [ss#1] use R3 R3 = R12 R4 = R3 <- oops! The problem was that promoting R3 = load[ss#2] to a copy missed the fact that the instruction invalidated R3 at that point. --- Diffs of the changes: (+5 -5) VirtRegMap.cpp | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) Index: llvm/lib/CodeGen/VirtRegMap.cpp diff -u llvm/lib/CodeGen/VirtRegMap.cpp:1.40 llvm/lib/CodeGen/VirtRegMap.cpp:1.41 --- llvm/lib/CodeGen/VirtRegMap.cpp:1.40 Thu Sep 29 20:29:00 2005 +++ llvm/lib/CodeGen/VirtRegMap.cpp Wed Oct 5 13:30:19 2005 @@ -490,11 +490,11 @@ if (DestReg != It->second) { MRI->copyRegToReg(MBB, &MI, DestReg, It->second, MF.getSSARegMap()->getRegClass(VirtReg)); - // Revisit the copy if the destination is a vreg. - if (MRegisterInfo::isVirtualRegister(DestReg)) { - NextMII = &MI; - --NextMII; // backtrack to the copy. - } + // Revisit the copy so we make sure to notice the effects of the + // operation on the destreg (either needing to RA it if it's + // virtual or needing to clobber any values if it's physical). + NextMII = &MI; + --NextMII; // backtrack to the copy. } MBB.erase(&MI); goto ProcessNextInst; From natebegeman at mac.com Wed Oct 5 16:43:58 2005 From: natebegeman at mac.com (Nate Begeman) Date: Wed, 5 Oct 2005 16:43:58 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <200510052143.QAA06125@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: DAGCombiner.cpp updated: 1.18 -> 1.19 --- Log message: Check in some more DAGCombiner pieces --- Diffs of the changes: (+45 -23) DAGCombiner.cpp | 68 +++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 45 insertions(+), 23 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.18 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.19 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.18 Wed Oct 5 01:47:48 2005 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Wed Oct 5 16:43:42 2005 @@ -139,7 +139,7 @@ SDOperand SimplifySelectCC(SDOperand N0, SDOperand N1, SDOperand N2, SDOperand N3, ISD::CondCode CC); SDOperand SimplifySetCC(MVT::ValueType VT, SDOperand N0, SDOperand N1, - ISD::CondCode Cond); + ISD::CondCode Cond, bool foldBooleans = true); public: DAGCombiner(SelectionDAG &D) : DAG(D), TLI(D.getTargetLoweringInfo()), AfterLegalize(false) {} @@ -1078,7 +1078,7 @@ ISD::CondCode CC = cast(N4)->get(); // Determine if the condition we're dealing with is constant - SDOperand SCC = SimplifySetCC(TLI.getSetCCResultTy(), N0, N1, CC); + SDOperand SCC = SimplifySetCC(TLI.getSetCCResultTy(), N0, N1, CC, false); ConstantSDNode *SCCC = dyn_cast_or_null(SCC.Val); // fold select_cc lhs, rhs, x, x, cc -> x @@ -1404,7 +1404,7 @@ if (N1C && N1C->isNullValue()) return Chain; // unconditional branch - if (N1C && !N1C->isNullValue()) + if (N1C && N1C->getValue() == 1) return DAG.getNode(ISD::BR, MVT::Other, Chain, N2); return SDOperand(); } @@ -1432,28 +1432,49 @@ SDOperand CondLHS = N->getOperand(2), CondRHS = N->getOperand(3); // Use SimplifySetCC to simplify SETCC's. - SDOperand Simp = SimplifySetCC(MVT::i1, CondLHS, CondRHS, CC->get()); - if (Simp.Val) { - if (ConstantSDNode *C = dyn_cast(Simp)) { - if (C->getValue() & 1) // Unconditional branch - return DAG.getNode(ISD::BR, MVT::Other, N->getOperand(0), - N->getOperand(4)); - else - return N->getOperand(0); // Unconditional Fall through - } else if (Simp.Val->getOpcode() == ISD::SETCC) { - // Folded to a simpler setcc - return DAG.getNode(ISD::BR_CC, MVT::Other, N->getOperand(0), - Simp.getOperand(2), Simp.getOperand(0), - Simp.getOperand(1), N->getOperand(4)); - } - } - + SDOperand Simp = SimplifySetCC(MVT::i1, CondLHS, CondRHS, CC->get(), false); + ConstantSDNode *SCCC = dyn_cast_or_null(Simp.Val); + + // fold br_cc true, dest -> br dest (unconditional branch) + if (SCCC && SCCC->getValue()) + return DAG.getNode(ISD::BR, MVT::Other, N->getOperand(0), + N->getOperand(4)); + // fold br_cc false, dest -> unconditional fall through + if (SCCC && SCCC->isNullValue()) + return N->getOperand(0); + // fold to a simpler setcc + if (Simp.Val && Simp.getOpcode() == ISD::SETCC) + return DAG.getNode(ISD::BR_CC, MVT::Other, N->getOperand(0), + Simp.getOperand(2), Simp.getOperand(0), + Simp.getOperand(1), N->getOperand(4)); return SDOperand(); } SDOperand DAGCombiner::visitBRTWOWAY_CC(SDNode *N) { - // FIXME: come up with a common way between br_cc, brtwoway_cc, and select_cc - // to canonicalize the condition without calling getnode a bazillion times. + SDOperand Chain = N->getOperand(0); + SDOperand CCN = N->getOperand(1); + SDOperand LHS = N->getOperand(2); + SDOperand RHS = N->getOperand(3); + SDOperand N4 = N->getOperand(4); + SDOperand N5 = N->getOperand(5); + + SDOperand SCC = SimplifySetCC(TLI.getSetCCResultTy(), LHS, RHS, + cast(CCN)->get(), false); + ConstantSDNode *SCCC = dyn_cast_or_null(SCC.Val); + + // fold select_cc lhs, rhs, x, x, cc -> x + if (N4 == N5) + return DAG.getNode(ISD::BR, MVT::Other, Chain, N4); + // fold select_cc true, x, y -> x + if (SCCC && SCCC->getValue()) + return DAG.getNode(ISD::BR, MVT::Other, Chain, N4); + // fold select_cc false, x, y -> y + if (SCCC && SCCC->isNullValue()) + return DAG.getNode(ISD::BR, MVT::Other, Chain, N5); + // fold to a simpler setcc + if (SCC.Val && SCC.getOpcode() == ISD::SETCC) + return DAG.getBR2Way_CC(Chain, SCC.getOperand(2), SCC.getOperand(0), + SCC.getOperand(1), N4, N5); return SDOperand(); } @@ -1468,7 +1489,8 @@ } SDOperand DAGCombiner::SimplifySetCC(MVT::ValueType VT, SDOperand N0, - SDOperand N1, ISD::CondCode Cond) { + SDOperand N1, ISD::CondCode Cond, + bool foldBooleans) { // These setcc operations always fold. switch (Cond) { default: break; @@ -1768,7 +1790,7 @@ // Fold away ALL boolean setcc's. SDOperand Temp; - if (N0.getValueType() == MVT::i1) { + if (N0.getValueType() == MVT::i1 && foldBooleans) { switch (Cond) { default: assert(0 && "Unknown integer setcc!"); case ISD::SETEQ: // X == Y -> (X^Y)^1 From natebegeman at mac.com Wed Oct 5 16:44:21 2005 From: natebegeman at mac.com (Nate Begeman) Date: Wed, 5 Oct 2005 16:44:21 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Message-ID: <200510052144.QAA06138@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: LegalizeDAG.cpp updated: 1.191 -> 1.192 --- Log message: Remove some bad code from Legalize --- Diffs of the changes: (+1 -4) LegalizeDAG.cpp | 5 +---- 1 files changed, 1 insertion(+), 4 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.191 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.192 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.191 Mon Oct 3 21:10:55 2005 +++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Wed Oct 5 16:44:10 2005 @@ -2619,11 +2619,8 @@ // Otherwise, scan the operands of Node to see if any of them is a call. assert(Node->getNumOperands() != 0 && "All leaves should have depth equal to the entry node!"); - for (unsigned i = 0, e = Node->getNumOperands()-1; i != e; ++i) { + for (unsigned i = 0, e = Node->getNumOperands()-1; i != e; ++i) FindLatestCallSeqStart(Node->getOperand(i).Val, Found); - if (Found->getOpcode() == ISD::CALLSEQ_START) - return; - } // Tail recurse for the last iteration. FindLatestCallSeqStart(Node->getOperand(Node->getNumOperands()-1).Val, From natebegeman at mac.com Wed Oct 5 16:44:54 2005 From: natebegeman at mac.com (Nate Begeman) Date: Wed, 5 Oct 2005 16:44:54 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200510052144.QAA06150@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAG.cpp updated: 1.197 -> 1.198 --- Log message: Let the combiner handle more cases --- Diffs of the changes: (+4 -1) SelectionDAG.cpp | 5 ++++- 1 files changed, 4 insertions(+), 1 deletion(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.197 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.198 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.197 Wed Oct 5 01:47:48 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Wed Oct 5 16:44:43 2005 @@ -854,6 +854,7 @@ return getSetCC(VT, N2, N1, ISD::getSetCCSwappedOperands(Cond)); } + if (!CombinerEnabled) { if (N1 == N2) { // We can always fold X == Y for integer setcc's. if (MVT::isInteger(N1.getValueType())) @@ -979,7 +980,7 @@ N1 = getNode(ISD::ZERO_EXTEND, VT, N1); return N1; } - + } // Could not fold it. return SDOperand(); } @@ -1807,6 +1808,7 @@ if (N2 == N3) return N2; // select C, X, X -> X + if (!CombinerEnabled) { if (VT == MVT::i1) { // Boolean SELECT if (N2C) { if (N2C->getValue()) // select C, 1, X -> C | X @@ -1834,6 +1836,7 @@ N3, cast(N1.getOperand(2))->get()); if (Simp.Val) return Simp; } + } break; case ISD::BRCOND: if (N2C) From lattner at cs.uiuc.edu Wed Oct 5 20:20:38 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Wed, 5 Oct 2005 20:20:38 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Message-ID: <200510060120.UAA09395@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: LegalizeDAG.cpp updated: 1.192 -> 1.193 --- Log message: Make the legalizer completely non-recursive --- Diffs of the changes: (+63 -28) LegalizeDAG.cpp | 91 ++++++++++++++++++++++++++++++++++++++------------------ 1 files changed, 63 insertions(+), 28 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.192 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.193 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.192 Wed Oct 5 16:44:10 2005 +++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Wed Oct 5 20:20:27 2005 @@ -378,46 +378,74 @@ DAG.getNode(OpToUse, NewOutTy, LegalOp)); } +/// ComputeTopDownOrdering - Add the specified node to the Order list if it has +/// not been visited yet and if all of its operands have already been visited. +static void ComputeTopDownOrdering(SDNode *N, std::vector &Order, + std::map &Visited) { + if (++Visited[N] != N->getNumOperands()) + return; // Haven't visited all operands yet + + Order.push_back(N); + + if (N->hasOneUse()) { // Tail recurse in common case. + ComputeTopDownOrdering(*N->use_begin(), Order, Visited); + return; + } + + // Now that we have N in, add anything that uses it if all of their operands + // are now done. + + for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end(); UI != E;++UI) + ComputeTopDownOrdering(*UI, Order, Visited); +} + void SelectionDAGLegalize::LegalizeDAG() { // The legalize process is inherently a bottom-up recursive process (users // legalize their uses before themselves). Given infinite stack space, we // could just start legalizing on the root and traverse the whole graph. In // practice however, this causes us to run out of stack space on large basic - // blocks. To avoid this problem, legalize the entry node, then all its uses - // iteratively instead of recursively. - std::vector Worklist; - Worklist.push_back(DAG.getEntryNode()); + // blocks. To avoid this problem, compute an ordering of the nodes where each + // node is only legalized after all of its operands are legalized. + std::map Visited; + std::vector Order; - while (!Worklist.empty()) { - SDOperand Node = Worklist.back(); - Worklist.pop_back(); - - if (LegalizedNodes.count(Node)) continue; - - for (SDNode::use_iterator UI = Node.Val->use_begin(), - E = Node.Val->use_end(); UI != E; ++UI) { - // Scan the values. If this use has a value that is a token chain, add it - // to the worklist. - SDNode *User = *UI; - for (unsigned i = 0, e = User->getNumValues(); i != e; ++i) - if (User->getValueType(i) == MVT::Other) { - Worklist.push_back(SDOperand(User, i)); - break; - } + // Compute ordering from all of the leaves in the graphs, those (like the + // entry node) that have no operands. + for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(), + E = DAG.allnodes_end(); I != E; ++I) { + if ((*I)->getNumOperands() == 0) { + Visited[*I] = 0 - 1U; + ComputeTopDownOrdering(*I, Order, Visited); } - - // Finally, legalize this node. - LegalizeOp(Node); } + assert(Order.size() == Visited.size() && Order.size() == DAG.allnodes_size()&& + "Error: DAG is cyclic!"); + Visited.clear(); - // Finally, legalize from the root up, to make sure we have legalized - // everything possible. + for (unsigned i = 0, e = Order.size(); i != e; ++i) { + SDNode *N = Order[i]; + switch (getTypeAction(N->getValueType(0))) { + default: assert(0 && "Bad type action!"); + case Legal: + LegalizeOp(SDOperand(N, 0)); + break; + case Promote: + PromoteOp(SDOperand(N, 0)); + break; + case Expand: { + SDOperand X, Y; + ExpandOp(SDOperand(N, 0), X, Y); + break; + } + } + } + + // Finally, it's possible the root changed. Get the new root. SDOperand OldRoot = DAG.getRoot(); - SDOperand NewRoot = LegalizeOp(OldRoot); - - DAG.setRoot(NewRoot); + assert(LegalizedNodes.count(OldRoot) && "Root didn't get legalized?"); + DAG.setRoot(LegalizedNodes[OldRoot]); ExpandedNodes.clear(); LegalizedNodes.clear(); @@ -492,9 +520,16 @@ abort(); case ISD::EntryToken: case ISD::FrameIndex: + case ISD::TargetFrameIndex: + case ISD::Register: + case ISD::TargetConstant: case ISD::GlobalAddress: case ISD::ExternalSymbol: case ISD::ConstantPool: // Nothing to do. + case ISD::BasicBlock: + case ISD::CONDCODE: + case ISD::VALUETYPE: + case ISD::SRCVALUE: assert(isTypeLegal(Node->getValueType(0)) && "This must be legal!"); break; case ISD::AssertSext: From alenhar2 at cs.uiuc.edu Thu Oct 6 11:53:49 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Thu, 6 Oct 2005 11:53:49 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaInstrInfo.td Message-ID: <200510061653.LAA12856@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Alpha: AlphaInstrInfo.td updated: 1.58 -> 1.59 --- Log message: remove VAX compatibility instruction, we will never use this --- Diffs of the changes: (+0 -2) AlphaInstrInfo.td | 2 -- 1 files changed, 2 deletions(-) Index: llvm/lib/Target/Alpha/AlphaInstrInfo.td diff -u llvm/lib/Target/Alpha/AlphaInstrInfo.td:1.58 llvm/lib/Target/Alpha/AlphaInstrInfo.td:1.59 --- llvm/lib/Target/Alpha/AlphaInstrInfo.td:1.58 Thu Aug 18 19:51:37 2005 +++ llvm/lib/Target/Alpha/AlphaInstrInfo.td Thu Oct 6 11:53:32 2005 @@ -397,9 +397,7 @@ //LDQ_L Mem 2B Load quadword locked //LDQ_U Mem 0B Load unaligned quadword //MB Mfc 18.4000 Memory barrier -//RC Mfc 18.E000 Read and clear //RPCC Mfc 18.C000 Read process cycle counter -//RS Mfc 18.F000 Read and set //STL_C Mem 2E Store longword conditional //STQ_C Mem 2F Store quadword conditional From alenhar2 at cs.uiuc.edu Thu Oct 6 11:54:40 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Thu, 6 Oct 2005 11:54:40 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaISelLowering.cpp AlphaISelPattern.cpp Message-ID: <200510061654.LAA12886@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Alpha: AlphaISelLowering.cpp updated: 1.6 -> 1.7 AlphaISelPattern.cpp updated: 1.172 -> 1.173 --- Log message: This is suppose to work now --- Diffs of the changes: (+2 -1) AlphaISelLowering.cpp | 2 ++ AlphaISelPattern.cpp | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) Index: llvm/lib/Target/Alpha/AlphaISelLowering.cpp diff -u llvm/lib/Target/Alpha/AlphaISelLowering.cpp:1.6 llvm/lib/Target/Alpha/AlphaISelLowering.cpp:1.7 --- llvm/lib/Target/Alpha/AlphaISelLowering.cpp:1.6 Thu Sep 29 17:54:56 2005 +++ llvm/lib/Target/Alpha/AlphaISelLowering.cpp Thu Oct 6 11:54:29 2005 @@ -66,6 +66,8 @@ setOperationAction(ISD::SEXTLOAD, MVT::i8, Expand); setOperationAction(ISD::SEXTLOAD, MVT::i16, Expand); + setOperationAction(ISD::TRUNCSTORE, MVT::i1, Promote); + setOperationAction(ISD::FREM, MVT::f32, Expand); setOperationAction(ISD::FREM, MVT::f64, Expand); Index: llvm/lib/Target/Alpha/AlphaISelPattern.cpp diff -u llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.172 llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.173 --- llvm/lib/Target/Alpha/AlphaISelPattern.cpp:1.172 Thu Sep 29 17:54:56 2005 +++ llvm/lib/Target/Alpha/AlphaISelPattern.cpp Thu Oct 6 11:54:29 2005 @@ -1822,7 +1822,6 @@ } else { //ISD::TRUNCSTORE switch(cast(Node->getOperand(4))->getVT()) { default: assert(0 && "unknown Type in store"); - case MVT::i1: //FIXME: DAG does not promote this load case MVT::i8: Opc = Alpha::STB; break; case MVT::i16: Opc = Alpha::STW; break; case MVT::i32: Opc = Alpha::STL; break; From lattner at cs.uiuc.edu Thu Oct 6 12:19:17 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 6 Oct 2005 12:19:17 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/VirtRegMap.cpp Message-ID: <200510061719.MAA14512@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen: VirtRegMap.cpp updated: 1.41 -> 1.42 --- Log message: Fix the LLC regressions on X86 last night. In particular, when undoing previous copy elisions and we discover we need to reload a register, make sure to use the regclass of the original register for the reload, not the class of the current register. This avoid using 16-bit loads to reload 32-bit values. --- Diffs of the changes: (+12 -5) VirtRegMap.cpp | 17 ++++++++++++----- 1 files changed, 12 insertions(+), 5 deletions(-) Index: llvm/lib/CodeGen/VirtRegMap.cpp diff -u llvm/lib/CodeGen/VirtRegMap.cpp:1.41 llvm/lib/CodeGen/VirtRegMap.cpp:1.42 --- llvm/lib/CodeGen/VirtRegMap.cpp:1.41 Wed Oct 5 13:30:19 2005 +++ llvm/lib/CodeGen/VirtRegMap.cpp Thu Oct 6 12:19:06 2005 @@ -266,9 +266,14 @@ // AssignedPhysReg - The physreg that was assigned for use by the reload. unsigned AssignedPhysReg; - - ReusedOp(unsigned o, unsigned ss, unsigned prr, unsigned apr) - : Operand(o), StackSlot(ss), PhysRegReused(prr), AssignedPhysReg(apr) {} + + // VirtReg - The virtual register itself. + unsigned VirtReg; + + ReusedOp(unsigned o, unsigned ss, unsigned prr, unsigned apr, + unsigned vreg) + : Operand(o), StackSlot(ss), PhysRegReused(prr), AssignedPhysReg(apr), + VirtReg(vreg) {} }; } @@ -381,7 +386,7 @@ // case, we actually insert a reload for V1 in R1, ensuring that // we can get at R0 or its alias. ReusedOperands.push_back(ReusedOp(i, StackSlot, PhysReg, - VRM.getPhys(VirtReg))); + VRM.getPhys(VirtReg), VirtReg)); ++NumReused; continue; } @@ -409,8 +414,10 @@ // Okay, we found out that an alias of a reused register // was used. This isn't good because it means we have // to undo a previous reuse. + const TargetRegisterClass *AliasRC = + MBB.getParent()->getSSARegMap()->getRegClass(Op.VirtReg); MRI->loadRegFromStackSlot(MBB, &MI, Op.AssignedPhysReg, - Op.StackSlot, RC); + Op.StackSlot, AliasRC); ClobberPhysReg(Op.AssignedPhysReg, SpillSlotsAvailable, PhysRegsAvailable); From lattner at cs.uiuc.edu Thu Oct 6 12:39:21 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 6 Oct 2005 12:39:21 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Message-ID: <200510061739.MAA16702@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: LegalizeDAG.cpp updated: 1.193 -> 1.194 --- Log message: silence a bogus GCC warning --- Diffs of the changes: (+1 -1) LegalizeDAG.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.193 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.194 --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.193 Wed Oct 5 20:20:27 2005 +++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Thu Oct 6 12:39:10 2005 @@ -2455,7 +2455,7 @@ // FIXME: this should be moved to the dag combiner someday. assert(NodeOp == ISD::ADD_PARTS || NodeOp == ISD::SUB_PARTS); if (LHSL.getValueType() == MVT::i32) { - SDOperand LowEl; + SDOperand LowEl = SDOperand(0,0); if (ConstantSDNode *C = dyn_cast(LHSL)) if (C->getValue() == 0) LowEl = RHSL; From lattner at cs.uiuc.edu Thu Oct 6 13:46:03 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 6 Oct 2005 13:46:03 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Message-ID: <200510061846.NAA04104@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelDAGToDAG.cpp updated: 1.93 -> 1.94 --- Log message: Add a recursive-iterative hybrid stage to attempt to reduce stack space, this helps but not enough. Start pulling cases out of PPC32DAGToDAGISel::Select. With GCC 4, this function required 8512 bytes of stack space for each invocation (GCC 3 required less than 700 bytes). Pulling this first function out gets us down to 8224. More to come :( --- Diffs of the changes: (+94 -45) PPC32ISelDAGToDAG.cpp | 139 +++++++++++++++++++++++++++++++++----------------- 1 files changed, 94 insertions(+), 45 deletions(-) Index: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.93 llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.94 --- llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.93 Sun Oct 2 02:07:49 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Thu Oct 6 13:45:51 2005 @@ -83,26 +83,70 @@ /// InstructionSelectBasicBlock - This callback is invoked by /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. - virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) { - DEBUG(BB->dump()); - // Select target instructions for the DAG. - DAG.setRoot(Select(DAG.getRoot())); - CodeGenMap.clear(); - DAG.RemoveDeadNodes(); - - // Emit machine code to BB. - ScheduleAndEmitDAG(DAG); - } - + virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); + virtual const char *getPassName() const { return "PowerPC DAG->DAG Pattern Instruction Selection"; } // Include the pieces autogenerated from the target description. #include "PPC32GenDAGISel.inc" + +private: + SDOperand SelectDYNAMIC_STACKALLOC(SDOperand N); }; } +/// InstructionSelectBasicBlock - This callback is invoked by +/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. +void PPC32DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { + DEBUG(BB->dump()); + + // The selection process is inherently a bottom-up recursive process (users + // select their uses before themselves). Given infinite stack space, we + // could just start selecting on the root and traverse the whole graph. In + // practice however, this causes us to run out of stack space on large basic + // blocks. To avoid this problem, select the entry node, then all its uses, + // iteratively instead of recursively. + std::vector Worklist; + Worklist.push_back(DAG.getEntryNode()); + + // Note that we can do this in the PPC target (scanning forward across token + // chain edges) because no nodes ever get folded across these edges. On a + // target like X86 which supports load/modify/store operations, this would + // have to be more careful. + while (!Worklist.empty()) { + SDOperand Node = Worklist.back(); + Worklist.pop_back(); + + if ((Node.Val->getOpcode() >= ISD::BUILTIN_OP_END && + Node.Val->getOpcode() < PPCISD::FIRST_NUMBER) || + CodeGenMap.count(Node)) continue; + + for (SDNode::use_iterator UI = Node.Val->use_begin(), + E = Node.Val->use_end(); UI != E; ++UI) { + // Scan the values. If this use has a value that is a token chain, add it + // to the worklist. + SDNode *User = *UI; + for (unsigned i = 0, e = User->getNumValues(); i != e; ++i) + if (User->getValueType(i) == MVT::Other) { + Worklist.push_back(SDOperand(User, i)); + break; + } + } + + // Finally, legalize this node. + Select(Node); + } + + // Select target instructions for the DAG. + DAG.setRoot(Select(DAG.getRoot())); + CodeGenMap.clear(); + DAG.RemoveDeadNodes(); + + // Emit machine code to BB. + ScheduleAndEmitDAG(DAG); +} /// getGlobalBaseReg - Output the instructions required to put the /// base address to use for accessing globals into a register. @@ -632,6 +676,43 @@ } } +SDOperand PPC32DAGToDAGISel::SelectDYNAMIC_STACKALLOC(SDOperand Op) { + SDNode *N = Op.Val; + + // FIXME: We are currently ignoring the requested alignment for handling + // greater than the stack alignment. This will need to be revisited at some + // point. Align = N.getOperand(2); + if (!isa(N->getOperand(2)) || + cast(N->getOperand(2))->getValue() != 0) { + std::cerr << "Cannot allocate stack object with greater alignment than" + << " the stack alignment yet!"; + abort(); + } + SDOperand Chain = Select(N->getOperand(0)); + SDOperand Amt = Select(N->getOperand(1)); + + SDOperand R1Reg = CurDAG->getRegister(PPC::R1, MVT::i32); + + SDOperand R1Val = CurDAG->getCopyFromReg(Chain, PPC::R1, MVT::i32); + Chain = R1Val.getValue(1); + + // Subtract the amount (guaranteed to be a multiple of the stack alignment) + // from the stack pointer, giving us the result pointer. + SDOperand Result = CurDAG->getTargetNode(PPC::SUBF, MVT::i32, Amt, R1Val); + + // Copy this result back into R1. + Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R1Reg, Result); + + // Copy this result back out of R1 to make sure we're not using the stack + // space without decrementing the stack pointer. + Result = CurDAG->getCopyFromReg(Chain, PPC::R1, MVT::i32); + + // Finally, replace the DYNAMIC_STACKALLOC with the copyfromreg. + CodeGenMap[Op.getValue(0)] = Result; + CodeGenMap[Op.getValue(1)] = Result.getValue(1); + return SDOperand(Result.Val, Op.ResNo); +} + // Select - Convert the specified operand from a target-independent to a // target-specific node if it hasn't already been changed. SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { @@ -718,40 +799,8 @@ CurDAG->SelectNodeTo(N, PPC::LA, MVT::i32, Tmp, GA); return SDOperand(N, 0); } - case ISD::DYNAMIC_STACKALLOC: { - // FIXME: We are currently ignoring the requested alignment for handling - // greater than the stack alignment. This will need to be revisited at some - // point. Align = N.getOperand(2); - if (!isa(N->getOperand(2)) || - cast(N->getOperand(2))->getValue() != 0) { - std::cerr << "Cannot allocate stack object with greater alignment than" - << " the stack alignment yet!"; - abort(); - } - SDOperand Chain = Select(N->getOperand(0)); - SDOperand Amt = Select(N->getOperand(1)); - - SDOperand R1Reg = CurDAG->getRegister(PPC::R1, MVT::i32); - - SDOperand R1Val = CurDAG->getCopyFromReg(Chain, PPC::R1, MVT::i32); - Chain = R1Val.getValue(1); - - // Subtract the amount (guaranteed to be a multiple of the stack alignment) - // from the stack pointer, giving us the result pointer. - SDOperand Result = CurDAG->getTargetNode(PPC::SUBF, MVT::i32, Amt, R1Val); - - // Copy this result back into R1. - Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R1Reg, Result); - - // Copy this result back out of R1 to make sure we're not using the stack - // space without decrementing the stack pointer. - Result = CurDAG->getCopyFromReg(Chain, PPC::R1, MVT::i32); - - // Finally, replace the DYNAMIC_STACKALLOC with the copyfromreg. - CodeGenMap[Op.getValue(0)] = Result; - CodeGenMap[Op.getValue(1)] = Result.getValue(1); - return SDOperand(Result.Val, Op.ResNo); - } + case ISD::DYNAMIC_STACKALLOC: + return SelectDYNAMIC_STACKALLOC(Op); case PPCISD::FSEL: { SDOperand Comparison = Select(N->getOperand(0)); // Extend the comparison to 64-bits. From lattner at cs.uiuc.edu Thu Oct 6 13:56:21 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 6 Oct 2005 13:56:21 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Message-ID: <200510061856.NAA05013@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelDAGToDAG.cpp updated: 1.94 -> 1.95 --- Log message: Pull two more methods out, reducing stack frame size from 8224 -> 7520 bytes --- Diffs of the changes: (+65 -58) PPC32ISelDAGToDAG.cpp | 123 ++++++++++++++++++++++++++------------------------ 1 files changed, 65 insertions(+), 58 deletions(-) Index: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.94 llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.95 --- llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.94 Thu Oct 6 13:45:51 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Thu Oct 6 13:56:10 2005 @@ -94,6 +94,8 @@ private: SDOperand SelectDYNAMIC_STACKALLOC(SDOperand N); + SDOperand SelectADD_PARTS(SDOperand N); + SDOperand SelectSUB_PARTS(SDOperand N); }; } @@ -713,6 +715,67 @@ return SDOperand(Result.Val, Op.ResNo); } +SDOperand PPC32DAGToDAGISel::SelectADD_PARTS(SDOperand Op) { + SDNode *N = Op.Val; + SDOperand LHSL = Select(N->getOperand(0)); + SDOperand LHSH = Select(N->getOperand(1)); + + unsigned Imm; + bool ME = false, ZE = false; + if (isIntImmediate(N->getOperand(3), Imm)) { + ME = (signed)Imm == -1; + ZE = Imm == 0; + } + + std::vector Result; + SDOperand CarryFromLo; + if (isIntImmediate(N->getOperand(2), Imm) && + ((signed)Imm >= -32768 || (signed)Imm < 32768)) { + // Codegen the low 32 bits of the add. Interestingly, there is no + // shifted form of add immediate carrying. + CarryFromLo = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, + LHSL, getI32Imm(Imm)); + } else { + CarryFromLo = CurDAG->getTargetNode(PPC::ADDC, MVT::i32, MVT::Flag, + LHSL, Select(N->getOperand(2))); + } + CarryFromLo = CarryFromLo.getValue(1); + + // Codegen the high 32 bits, adding zero, minus one, or the full value + // along with the carry flag produced by addc/addic. + SDOperand ResultHi; + if (ZE) + ResultHi = CurDAG->getTargetNode(PPC::ADDZE, MVT::i32, LHSH, CarryFromLo); + else if (ME) + ResultHi = CurDAG->getTargetNode(PPC::ADDME, MVT::i32, LHSH, CarryFromLo); + else + ResultHi = CurDAG->getTargetNode(PPC::ADDE, MVT::i32, LHSH, + Select(N->getOperand(3)), CarryFromLo); + Result.push_back(CarryFromLo.getValue(0)); + Result.push_back(ResultHi); + + CodeGenMap[Op.getValue(0)] = Result[0]; + CodeGenMap[Op.getValue(1)] = Result[1]; + return Result[Op.ResNo]; +} +SDOperand PPC32DAGToDAGISel::SelectSUB_PARTS(SDOperand Op) { + SDNode *N = Op.Val; + SDOperand LHSL = Select(N->getOperand(0)); + SDOperand LHSH = Select(N->getOperand(1)); + SDOperand RHSL = Select(N->getOperand(2)); + SDOperand RHSH = Select(N->getOperand(3)); + + std::vector Result; + Result.push_back(CurDAG->getTargetNode(PPC::SUBFC, MVT::i32, MVT::Flag, + RHSL, LHSL)); + Result.push_back(CurDAG->getTargetNode(PPC::SUBFE, MVT::i32, RHSH, LHSH, + Result[0].getValue(1))); + CodeGenMap[Op.getValue(0)] = Result[0]; + CodeGenMap[Op.getValue(1)] = Result[1]; + return Result[Op.ResNo]; +} + + // Select - Convert the specified operand from a target-independent to a // target-specific node if it hasn't already been changed. SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { @@ -1069,64 +1132,8 @@ Select(N->getOperand(0))); return SDOperand(N, 0); } - - case ISD::ADD_PARTS: { - SDOperand LHSL = Select(N->getOperand(0)); - SDOperand LHSH = Select(N->getOperand(1)); - - unsigned Imm; - bool ME = false, ZE = false; - if (isIntImmediate(N->getOperand(3), Imm)) { - ME = (signed)Imm == -1; - ZE = Imm == 0; - } - - std::vector Result; - SDOperand CarryFromLo; - if (isIntImmediate(N->getOperand(2), Imm) && - ((signed)Imm >= -32768 || (signed)Imm < 32768)) { - // Codegen the low 32 bits of the add. Interestingly, there is no - // shifted form of add immediate carrying. - CarryFromLo = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, - LHSL, getI32Imm(Imm)); - } else { - CarryFromLo = CurDAG->getTargetNode(PPC::ADDC, MVT::i32, MVT::Flag, - LHSL, Select(N->getOperand(2))); - } - CarryFromLo = CarryFromLo.getValue(1); - - // Codegen the high 32 bits, adding zero, minus one, or the full value - // along with the carry flag produced by addc/addic. - SDOperand ResultHi; - if (ZE) - ResultHi = CurDAG->getTargetNode(PPC::ADDZE, MVT::i32, LHSH, CarryFromLo); - else if (ME) - ResultHi = CurDAG->getTargetNode(PPC::ADDME, MVT::i32, LHSH, CarryFromLo); - else - ResultHi = CurDAG->getTargetNode(PPC::ADDE, MVT::i32, LHSH, - Select(N->getOperand(3)), CarryFromLo); - Result.push_back(CarryFromLo.getValue(0)); - Result.push_back(ResultHi); - - CodeGenMap[Op.getValue(0)] = Result[0]; - CodeGenMap[Op.getValue(1)] = Result[1]; - return Result[Op.ResNo]; - } - case ISD::SUB_PARTS: { - SDOperand LHSL = Select(N->getOperand(0)); - SDOperand LHSH = Select(N->getOperand(1)); - SDOperand RHSL = Select(N->getOperand(2)); - SDOperand RHSH = Select(N->getOperand(3)); - - std::vector Result; - Result.push_back(CurDAG->getTargetNode(PPC::SUBFC, MVT::i32, MVT::Flag, - RHSL, LHSL)); - Result.push_back(CurDAG->getTargetNode(PPC::SUBFE, MVT::i32, RHSH, LHSH, - Result[0].getValue(1))); - CodeGenMap[Op.getValue(0)] = Result[0]; - CodeGenMap[Op.getValue(1)] = Result[1]; - return Result[Op.ResNo]; - } + case ISD::ADD_PARTS: return SelectADD_PARTS(Op); + case ISD::SUB_PARTS: return SelectSUB_PARTS(Op); case ISD::LOAD: case ISD::EXTLOAD: From lattner at cs.uiuc.edu Thu Oct 6 14:03:47 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 6 Oct 2005 14:03:47 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Message-ID: <200510061903.OAA05150@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelDAGToDAG.cpp updated: 1.95 -> 1.96 --- Log message: Pull out setcc, this reduces stack frame size from 7520 to 6032 bytes --- Diffs of the changes: (+117 -115) PPC32ISelDAGToDAG.cpp | 232 +++++++++++++++++++++++++------------------------- 1 files changed, 117 insertions(+), 115 deletions(-) Index: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.95 llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.96 --- llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.95 Thu Oct 6 13:56:10 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Thu Oct 6 14:03:35 2005 @@ -93,9 +93,10 @@ #include "PPC32GenDAGISel.inc" private: - SDOperand SelectDYNAMIC_STACKALLOC(SDOperand N); - SDOperand SelectADD_PARTS(SDOperand N); - SDOperand SelectSUB_PARTS(SDOperand N); + SDOperand SelectDYNAMIC_STACKALLOC(SDOperand Op); + SDOperand SelectADD_PARTS(SDOperand Op); + SDOperand SelectSUB_PARTS(SDOperand Op); + SDOperand SelectSETCC(SDOperand Op); }; } @@ -775,6 +776,113 @@ return Result[Op.ResNo]; } +SDOperand PPC32DAGToDAGISel::SelectSETCC(SDOperand Op) { + SDNode *N = Op.Val; + unsigned Imm; + ISD::CondCode CC = cast(N->getOperand(2))->get(); + if (isIntImmediate(N->getOperand(1), Imm)) { + // We can codegen setcc op, imm very efficiently compared to a brcond. + // Check for those cases here. + // setcc op, 0 + if (Imm == 0) { + SDOperand Op = Select(N->getOperand(0)); + switch (CC) { + default: assert(0 && "Unhandled SetCC condition"); abort(); + case ISD::SETEQ: + Op = CurDAG->getTargetNode(PPC::CNTLZW, MVT::i32, Op); + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(27), + getI32Imm(5), getI32Imm(31)); + break; + case ISD::SETNE: { + SDOperand AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, + Op, getI32Imm(~0U)); + CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, AD.getValue(1)); + break; + } + case ISD::SETLT: + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(1), + getI32Imm(31), getI32Imm(31)); + break; + case ISD::SETGT: { + SDOperand T = CurDAG->getTargetNode(PPC::NEG, MVT::i32, Op); + T = CurDAG->getTargetNode(PPC::ANDC, MVT::i32, T, Op);; + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, T, getI32Imm(1), + getI32Imm(31), getI32Imm(31)); + break; + } + } + return SDOperand(N, 0); + } else if (Imm == ~0U) { // setcc op, -1 + SDOperand Op = Select(N->getOperand(0)); + switch (CC) { + default: assert(0 && "Unhandled SetCC condition"); abort(); + case ISD::SETEQ: + Op = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, + Op, getI32Imm(1)); + CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32, + CurDAG->getTargetNode(PPC::LI, MVT::i32, + getI32Imm(0)), + Op.getValue(1)); + break; + case ISD::SETNE: { + Op = CurDAG->getTargetNode(PPC::NOR, MVT::i32, Op, Op); + SDOperand AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, + Op, getI32Imm(~0U)); + CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, AD.getValue(1)); + break; + } + case ISD::SETLT: { + SDOperand AD = CurDAG->getTargetNode(PPC::ADDI, MVT::i32, Op, + getI32Imm(1)); + SDOperand AN = CurDAG->getTargetNode(PPC::AND, MVT::i32, AD, Op); + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, AN, getI32Imm(1), + getI32Imm(31), getI32Imm(31)); + break; + } + case ISD::SETGT: + Op = CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Op, getI32Imm(1), + getI32Imm(31), getI32Imm(31)); + CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Op, getI32Imm(1)); + break; + } + return SDOperand(N, 0); + } + } + + bool Inv; + unsigned Idx = getCRIdxForSetCC(CC, Inv); + SDOperand CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC); + SDOperand IntCR; + + // Force the ccreg into CR7. + SDOperand CR7Reg = CurDAG->getRegister(PPC::CR7, MVT::i32); + + std::vector VTs; + VTs.push_back(MVT::Other); + VTs.push_back(MVT::Flag); // NONSTANDARD CopyToReg node: defines a flag + std::vector Ops; + Ops.push_back(CurDAG->getEntryNode()); + Ops.push_back(CR7Reg); + Ops.push_back(CCReg); + CCReg = CurDAG->getNode(ISD::CopyToReg, VTs, Ops).getValue(1); + + if (TLI.getTargetMachine().getSubtarget().isGigaProcessor()) + IntCR = CurDAG->getTargetNode(PPC::MFOCRF, MVT::i32, CR7Reg, CCReg); + else + IntCR = CurDAG->getTargetNode(PPC::MFCR, MVT::i32, CCReg); + + if (!Inv) { + CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, IntCR, + getI32Imm(32-(3-Idx)), getI32Imm(31), getI32Imm(31)); + } else { + SDOperand Tmp = + CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, IntCR, + getI32Imm(32-(3-Idx)), getI32Imm(31),getI32Imm(31)); + CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Tmp, getI32Imm(1)); + } + + return SDOperand(N, 0); +} // Select - Convert the specified operand from a target-independent to a // target-specific node if it hasn't already been changed. @@ -790,6 +898,10 @@ switch (N->getOpcode()) { default: break; + case ISD::DYNAMIC_STACKALLOC: return SelectDYNAMIC_STACKALLOC(Op); + case ISD::ADD_PARTS: return SelectADD_PARTS(Op); + case ISD::SUB_PARTS: return SelectSUB_PARTS(Op); + case ISD::SETCC: return SelectSETCC(Op); case ISD::TokenFactor: { SDOperand New; if (N->getNumOperands() == 2) { @@ -862,8 +974,7 @@ CurDAG->SelectNodeTo(N, PPC::LA, MVT::i32, Tmp, GA); return SDOperand(N, 0); } - case ISD::DYNAMIC_STACKALLOC: - return SelectDYNAMIC_STACKALLOC(Op); + case PPCISD::FSEL: { SDOperand Comparison = Select(N->getOperand(0)); // Extend the comparison to 64-bits. @@ -1132,9 +1243,7 @@ Select(N->getOperand(0))); return SDOperand(N, 0); } - case ISD::ADD_PARTS: return SelectADD_PARTS(Op); - case ISD::SUB_PARTS: return SelectSUB_PARTS(Op); - + case ISD::LOAD: case ISD::EXTLOAD: case ISD::ZEXTLOAD: @@ -1209,113 +1318,6 @@ return SDOperand(N, 0); } - case ISD::SETCC: { - unsigned Imm; - ISD::CondCode CC = cast(N->getOperand(2))->get(); - if (isIntImmediate(N->getOperand(1), Imm)) { - // We can codegen setcc op, imm very efficiently compared to a brcond. - // Check for those cases here. - // setcc op, 0 - if (Imm == 0) { - SDOperand Op = Select(N->getOperand(0)); - switch (CC) { - default: assert(0 && "Unhandled SetCC condition"); abort(); - case ISD::SETEQ: - Op = CurDAG->getTargetNode(PPC::CNTLZW, MVT::i32, Op); - CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(27), - getI32Imm(5), getI32Imm(31)); - break; - case ISD::SETNE: { - SDOperand AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, - Op, getI32Imm(~0U)); - CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, AD.getValue(1)); - break; - } - case ISD::SETLT: - CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(1), - getI32Imm(31), getI32Imm(31)); - break; - case ISD::SETGT: { - SDOperand T = CurDAG->getTargetNode(PPC::NEG, MVT::i32, Op); - T = CurDAG->getTargetNode(PPC::ANDC, MVT::i32, T, Op);; - CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, T, getI32Imm(1), - getI32Imm(31), getI32Imm(31)); - break; - } - } - return SDOperand(N, 0); - } else if (Imm == ~0U) { // setcc op, -1 - SDOperand Op = Select(N->getOperand(0)); - switch (CC) { - default: assert(0 && "Unhandled SetCC condition"); abort(); - case ISD::SETEQ: - Op = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, - Op, getI32Imm(1)); - CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32, - CurDAG->getTargetNode(PPC::LI, MVT::i32, - getI32Imm(0)), - Op.getValue(1)); - break; - case ISD::SETNE: { - Op = CurDAG->getTargetNode(PPC::NOR, MVT::i32, Op, Op); - SDOperand AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, - Op, getI32Imm(~0U)); - CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, AD.getValue(1)); - break; - } - case ISD::SETLT: { - SDOperand AD = CurDAG->getTargetNode(PPC::ADDI, MVT::i32, Op, - getI32Imm(1)); - SDOperand AN = CurDAG->getTargetNode(PPC::AND, MVT::i32, AD, Op); - CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, AN, getI32Imm(1), - getI32Imm(31), getI32Imm(31)); - break; - } - case ISD::SETGT: - Op = CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Op, getI32Imm(1), - getI32Imm(31), getI32Imm(31)); - CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Op, getI32Imm(1)); - break; - } - return SDOperand(N, 0); - } - } - - bool Inv; - unsigned Idx = getCRIdxForSetCC(CC, Inv); - SDOperand CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC); - SDOperand IntCR; - - // Force the ccreg into CR7. - SDOperand CR7Reg = CurDAG->getRegister(PPC::CR7, MVT::i32); - - std::vector VTs; - VTs.push_back(MVT::Other); - VTs.push_back(MVT::Flag); // NONSTANDARD CopyToReg node: defines a flag - std::vector Ops; - Ops.push_back(CurDAG->getEntryNode()); - Ops.push_back(CR7Reg); - Ops.push_back(CCReg); - CCReg = CurDAG->getNode(ISD::CopyToReg, VTs, Ops).getValue(1); - - if (TLI.getTargetMachine().getSubtarget().isGigaProcessor()) - IntCR = CurDAG->getTargetNode(PPC::MFOCRF, MVT::i32, CR7Reg, CCReg); - else - IntCR = CurDAG->getTargetNode(PPC::MFCR, MVT::i32, CCReg); - - if (!Inv) { - CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, IntCR, - getI32Imm(32-(3-Idx)), getI32Imm(31), getI32Imm(31)); - } else { - SDOperand Tmp = - CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, IntCR, - getI32Imm(32-(3-Idx)), getI32Imm(31),getI32Imm(31)); - CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Tmp, getI32Imm(1)); - } - - return SDOperand(N, 0); - } - case ISD::SELECT_CC: { ISD::CondCode CC = cast(N->getOperand(4))->get(); From lattner at cs.uiuc.edu Thu Oct 6 14:07:57 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 6 Oct 2005 14:07:57 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Message-ID: <200510061907.OAA05189@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelDAGToDAG.cpp updated: 1.96 -> 1.97 --- Log message: Pull out Call, reducing stack frame size from 6032 bytes to 5184 bytes. --- Diffs of the changes: (+111 -106) PPC32ISelDAGToDAG.cpp | 217 +++++++++++++++++++++++++------------------------- 1 files changed, 111 insertions(+), 106 deletions(-) Index: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.96 llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.97 --- llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.96 Thu Oct 6 14:03:35 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Thu Oct 6 14:07:45 2005 @@ -97,6 +97,7 @@ SDOperand SelectADD_PARTS(SDOperand Op); SDOperand SelectSUB_PARTS(SDOperand Op); SDOperand SelectSETCC(SDOperand Op); + SDOperand SelectCALL(SDOperand Op); }; } @@ -884,6 +885,113 @@ return SDOperand(N, 0); } +SDOperand PPC32DAGToDAGISel::SelectCALL(SDOperand Op) { + SDNode *N = Op.Val; + SDOperand Chain = Select(N->getOperand(0)); + + unsigned CallOpcode; + std::vector CallOperands; + + if (GlobalAddressSDNode *GASD = + dyn_cast(N->getOperand(1))) { + CallOpcode = PPC::CALLpcrel; + CallOperands.push_back(CurDAG->getTargetGlobalAddress(GASD->getGlobal(), + MVT::i32)); + } else if (ExternalSymbolSDNode *ESSDN = + dyn_cast(N->getOperand(1))) { + CallOpcode = PPC::CALLpcrel; + CallOperands.push_back(N->getOperand(1)); + } else { + // Copy the callee address into the CTR register. + SDOperand Callee = Select(N->getOperand(1)); + Chain = CurDAG->getTargetNode(PPC::MTCTR, MVT::Other, Callee, Chain); + + // Copy the callee address into R12 on darwin. + SDOperand R12 = CurDAG->getRegister(PPC::R12, MVT::i32); + Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R12, Callee); + + CallOperands.push_back(getI32Imm(20)); // Information to encode indcall + CallOperands.push_back(getI32Imm(0)); // Information to encode indcall + CallOperands.push_back(R12); + CallOpcode = PPC::CALLindirect; + } + + unsigned GPR_idx = 0, FPR_idx = 0; + static const unsigned GPR[] = { + PPC::R3, PPC::R4, PPC::R5, PPC::R6, + PPC::R7, PPC::R8, PPC::R9, PPC::R10, + }; + static const unsigned FPR[] = { + PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, + PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13 + }; + + SDOperand InFlag; // Null incoming flag value. + + for (unsigned i = 2, e = N->getNumOperands(); i != e; ++i) { + unsigned DestReg = 0; + MVT::ValueType RegTy = N->getOperand(i).getValueType(); + if (RegTy == MVT::i32) { + assert(GPR_idx < 8 && "Too many int args"); + DestReg = GPR[GPR_idx++]; + } else { + assert(MVT::isFloatingPoint(N->getOperand(i).getValueType()) && + "Unpromoted integer arg?"); + assert(FPR_idx < 13 && "Too many fp args"); + DestReg = FPR[FPR_idx++]; + } + + if (N->getOperand(i).getOpcode() != ISD::UNDEF) { + SDOperand Val = Select(N->getOperand(i)); + Chain = CurDAG->getCopyToReg(Chain, DestReg, Val, InFlag); + InFlag = Chain.getValue(1); + CallOperands.push_back(CurDAG->getRegister(DestReg, RegTy)); + } + } + + // Finally, once everything is in registers to pass to the call, emit the + // call itself. + if (InFlag.Val) + CallOperands.push_back(InFlag); // Strong dep on register copies. + else + CallOperands.push_back(Chain); // Weak dep on whatever occurs before + Chain = CurDAG->getTargetNode(CallOpcode, MVT::Other, MVT::Flag, + CallOperands); + + std::vector CallResults; + + // If the call has results, copy the values out of the ret val registers. + switch (N->getValueType(0)) { + default: assert(0 && "Unexpected ret value!"); + case MVT::Other: break; + case MVT::i32: + if (N->getValueType(1) == MVT::i32) { + Chain = CurDAG->getCopyFromReg(Chain, PPC::R4, MVT::i32, + Chain.getValue(1)).getValue(1); + CallResults.push_back(Chain.getValue(0)); + Chain = CurDAG->getCopyFromReg(Chain, PPC::R3, MVT::i32, + Chain.getValue(2)).getValue(1); + CallResults.push_back(Chain.getValue(0)); + } else { + Chain = CurDAG->getCopyFromReg(Chain, PPC::R3, MVT::i32, + Chain.getValue(1)).getValue(1); + CallResults.push_back(Chain.getValue(0)); + } + break; + case MVT::f32: + case MVT::f64: + Chain = CurDAG->getCopyFromReg(Chain, PPC::F1, N->getValueType(0), + Chain.getValue(1)).getValue(1); + CallResults.push_back(Chain.getValue(0)); + break; + } + + CallResults.push_back(Chain); + for (unsigned i = 0, e = CallResults.size(); i != e; ++i) + CodeGenMap[Op.getValue(i)] = CallResults[i]; + return CallResults[Op.ResNo]; +} + // Select - Convert the specified operand from a target-independent to a // target-specific node if it hasn't already been changed. SDOperand PPC32DAGToDAGISel::Select(SDOperand Op) { @@ -902,6 +1010,9 @@ case ISD::ADD_PARTS: return SelectADD_PARTS(Op); case ISD::SUB_PARTS: return SelectSUB_PARTS(Op); case ISD::SETCC: return SelectSETCC(Op); + case ISD::CALL: return SelectCALL(Op); + case ISD::TAILCALL: return SelectCALL(Op); + case ISD::TokenFactor: { SDOperand New; if (N->getNumOperands() == 2) { @@ -1362,112 +1473,6 @@ getI32Imm(Amt), Select(N->getOperand(0))); return SDOperand(N, 0); } - case ISD::CALL: - case ISD::TAILCALL: { - SDOperand Chain = Select(N->getOperand(0)); - - unsigned CallOpcode; - std::vector CallOperands; - - if (GlobalAddressSDNode *GASD = - dyn_cast(N->getOperand(1))) { - CallOpcode = PPC::CALLpcrel; - CallOperands.push_back(CurDAG->getTargetGlobalAddress(GASD->getGlobal(), - MVT::i32)); - } else if (ExternalSymbolSDNode *ESSDN = - dyn_cast(N->getOperand(1))) { - CallOpcode = PPC::CALLpcrel; - CallOperands.push_back(N->getOperand(1)); - } else { - // Copy the callee address into the CTR register. - SDOperand Callee = Select(N->getOperand(1)); - Chain = CurDAG->getTargetNode(PPC::MTCTR, MVT::Other, Callee, Chain); - - // Copy the callee address into R12 on darwin. - SDOperand R12 = CurDAG->getRegister(PPC::R12, MVT::i32); - Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R12, Callee); - - CallOperands.push_back(getI32Imm(20)); // Information to encode indcall - CallOperands.push_back(getI32Imm(0)); // Information to encode indcall - CallOperands.push_back(R12); - CallOpcode = PPC::CALLindirect; - } - - unsigned GPR_idx = 0, FPR_idx = 0; - static const unsigned GPR[] = { - PPC::R3, PPC::R4, PPC::R5, PPC::R6, - PPC::R7, PPC::R8, PPC::R9, PPC::R10, - }; - static const unsigned FPR[] = { - PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, - PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13 - }; - - SDOperand InFlag; // Null incoming flag value. - - for (unsigned i = 2, e = N->getNumOperands(); i != e; ++i) { - unsigned DestReg = 0; - MVT::ValueType RegTy = N->getOperand(i).getValueType(); - if (RegTy == MVT::i32) { - assert(GPR_idx < 8 && "Too many int args"); - DestReg = GPR[GPR_idx++]; - } else { - assert(MVT::isFloatingPoint(N->getOperand(i).getValueType()) && - "Unpromoted integer arg?"); - assert(FPR_idx < 13 && "Too many fp args"); - DestReg = FPR[FPR_idx++]; - } - - if (N->getOperand(i).getOpcode() != ISD::UNDEF) { - SDOperand Val = Select(N->getOperand(i)); - Chain = CurDAG->getCopyToReg(Chain, DestReg, Val, InFlag); - InFlag = Chain.getValue(1); - CallOperands.push_back(CurDAG->getRegister(DestReg, RegTy)); - } - } - - // Finally, once everything is in registers to pass to the call, emit the - // call itself. - if (InFlag.Val) - CallOperands.push_back(InFlag); // Strong dep on register copies. - else - CallOperands.push_back(Chain); // Weak dep on whatever occurs before - Chain = CurDAG->getTargetNode(CallOpcode, MVT::Other, MVT::Flag, - CallOperands); - - std::vector CallResults; - - // If the call has results, copy the values out of the ret val registers. - switch (N->getValueType(0)) { - default: assert(0 && "Unexpected ret value!"); - case MVT::Other: break; - case MVT::i32: - if (N->getValueType(1) == MVT::i32) { - Chain = CurDAG->getCopyFromReg(Chain, PPC::R4, MVT::i32, - Chain.getValue(1)).getValue(1); - CallResults.push_back(Chain.getValue(0)); - Chain = CurDAG->getCopyFromReg(Chain, PPC::R3, MVT::i32, - Chain.getValue(2)).getValue(1); - CallResults.push_back(Chain.getValue(0)); - } else { - Chain = CurDAG->getCopyFromReg(Chain, PPC::R3, MVT::i32, - Chain.getValue(1)).getValue(1); - CallResults.push_back(Chain.getValue(0)); - } - break; - case MVT::f32: - case MVT::f64: - Chain = CurDAG->getCopyFromReg(Chain, PPC::F1, N->getValueType(0), - Chain.getValue(1)).getValue(1); - CallResults.push_back(Chain.getValue(0)); - break; - } - - CallResults.push_back(Chain); - for (unsigned i = 0, e = CallResults.size(); i != e; ++i) - CodeGenMap[Op.getValue(i)] = CallResults[i]; - return CallResults[Op.ResNo]; - } case ISD::RET: { SDOperand Chain = Select(N->getOperand(0)); // Token chain. From lattner at cs.uiuc.edu Thu Oct 6 23:49:12 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 6 Oct 2005 23:49:12 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/CodeGen/Generic/bool-to-double.ll Message-ID: <200510070449.XAA13691@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/CodeGen/Generic: bool-to-double.ll added (r1.1) --- Log message: test broken in the IA64 backend. --- Diffs of the changes: (+5 -0) bool-to-double.ll | 5 +++++ 1 files changed, 5 insertions(+) Index: llvm/test/Regression/CodeGen/Generic/bool-to-double.ll diff -c /dev/null llvm/test/Regression/CodeGen/Generic/bool-to-double.ll:1.1 *** /dev/null Thu Oct 6 23:49:10 2005 --- llvm/test/Regression/CodeGen/Generic/bool-to-double.ll Thu Oct 6 23:49:00 2005 *************** *** 0 **** --- 1,5 ---- + ; RUN: llvm-as < %s | llc + double %test(bool %X) { + %Y = cast bool %X to double + ret double %Y + } From lattner at cs.uiuc.edu Thu Oct 6 23:51:00 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 6 Oct 2005 23:51:00 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/IA64/IA64ISelPattern.cpp Message-ID: <200510070451.XAA13757@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/IA64: IA64ISelPattern.cpp updated: 1.65 -> 1.66 --- Log message: Fix CodeGen/Generic/bool-to-double.ll --- Diffs of the changes: (+3 -0) IA64ISelPattern.cpp | 3 +++ 1 files changed, 3 insertions(+) Index: llvm/lib/Target/IA64/IA64ISelPattern.cpp diff -u llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.65 llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.66 --- llvm/lib/Target/IA64/IA64ISelPattern.cpp:1.65 Wed Sep 28 17:29:17 2005 +++ llvm/lib/Target/IA64/IA64ISelPattern.cpp Thu Oct 6 23:50:48 2005 @@ -81,6 +81,9 @@ setOperationAction(ISD::MEMMOVE , MVT::Other, Expand); setOperationAction(ISD::MEMSET , MVT::Other, Expand); setOperationAction(ISD::MEMCPY , MVT::Other, Expand); + + setOperationAction(ISD::SINT_TO_FP , MVT::i1 , Promote); + setOperationAction(ISD::UINT_TO_FP , MVT::i1 , Promote); // We don't support sin/cos/sqrt setOperationAction(ISD::FSIN , MVT::f64, Expand); From lattner at cs.uiuc.edu Thu Oct 6 23:59:53 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Thu, 6 Oct 2005 23:59:53 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/CodeGen/PowerPC/fpcopy.ll Message-ID: <200510070459.XAA13860@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/CodeGen/PowerPC: fpcopy.ll added (r1.1) --- Log message: double to float casts should nto result in an fmr --- Diffs of the changes: (+7 -0) fpcopy.ll | 7 +++++++ 1 files changed, 7 insertions(+) Index: llvm/test/Regression/CodeGen/PowerPC/fpcopy.ll diff -c /dev/null llvm/test/Regression/CodeGen/PowerPC/fpcopy.ll:1.1 *** /dev/null Thu Oct 6 23:59:51 2005 --- llvm/test/Regression/CodeGen/PowerPC/fpcopy.ll Thu Oct 6 23:59:41 2005 *************** *** 0 **** --- 1,7 ---- + ; RUN: llvm-as < %s | llc -march=ppc32 && + ; RUN: llvm-as < %s | llc -march=ppc32 | not grep fmr + + double %test(float %F) { + %F = cast float %F to double + ret double %F + } From lattner at cs.uiuc.edu Fri Oct 7 00:01:03 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 7 Oct 2005 00:01:03 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32InstrInfo.cpp Message-ID: <200510070501.AAA13952@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32InstrInfo.cpp updated: 1.6 -> 1.7 --- Log message: Fix a CQ regression from my patch to split F32/F64 into seperate register classes on PPC. We were emitting fmr instructions to do fp extensions, which weren't getting coallesced. This fixes Regression/CodeGen/PowerPC/fpcopy.ll --- Diffs of the changes: (+2 -1) PPC32InstrInfo.cpp | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-) Index: llvm/lib/Target/PowerPC/PPC32InstrInfo.cpp diff -u llvm/lib/Target/PowerPC/PPC32InstrInfo.cpp:1.6 llvm/lib/Target/PowerPC/PPC32InstrInfo.cpp:1.7 --- llvm/lib/Target/PowerPC/PPC32InstrInfo.cpp:1.6 Fri Sep 30 20:34:18 2005 +++ llvm/lib/Target/PowerPC/PPC32InstrInfo.cpp Fri Oct 7 00:00:52 2005 @@ -57,7 +57,8 @@ destReg = MI.getOperand(0).getReg(); return true; } - } else if (oc == PPC::FMRS || oc == PPC::FMRD) { // fmr r1, r2 + } else if (oc == PPC::FMRS || oc == PPC::FMRD || + oc == PPC::FMRSD) { // fmr r1, r2 assert(MI.getNumOperands() == 2 && MI.getOperand(0).isRegister() && MI.getOperand(1).isRegister() && From lattner at cs.uiuc.edu Fri Oct 7 00:23:47 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 7 Oct 2005 00:23:47 -0500 Subject: [llvm-commits] CVS: llvm/lib/VMCore/Constants.cpp Message-ID: <200510070523.AAA14041@zion.cs.uiuc.edu> Changes in directory llvm/lib/VMCore: Constants.cpp updated: 1.138 -> 1.139 --- Log message: add a hack to work around broken VC++ scoping rules. Thx to JeffC for pointing this out to me --- Diffs of the changes: (+13 -13) Constants.cpp | 26 +++++++++++++------------- 1 files changed, 13 insertions(+), 13 deletions(-) Index: llvm/lib/VMCore/Constants.cpp diff -u llvm/lib/VMCore/Constants.cpp:1.138 llvm/lib/VMCore/Constants.cpp:1.139 --- llvm/lib/VMCore/Constants.cpp:1.138 Tue Oct 4 16:35:50 2005 +++ llvm/lib/VMCore/Constants.cpp Fri Oct 7 00:23:36 2005 @@ -250,12 +250,12 @@ Use *OL = OperandList; for (std::vector::const_iterator I = V.begin(), E = V.end(); I != E; ++I, ++OL) { - Constant *E = *I; - assert((E->getType() == T->getElementType() || + Constant *C = *I; + assert((C->getType() == T->getElementType() || (T->isAbstract() && - E->getType()->getTypeID() == T->getElementType()->getTypeID())) && + C->getType()->getTypeID() == T->getElementType()->getTypeID())) && "Initializer for array element doesn't match array element type!"); - OL->init(E, this); + OL->init(C, this); } } @@ -271,14 +271,14 @@ Use *OL = OperandList; for (std::vector::const_iterator I = V.begin(), E = V.end(); I != E; ++I, ++OL) { - Constant *E = *I; - assert((E->getType() == T->getElementType(I-V.begin()) || + Constant *C = *I; + assert((C->getType() == T->getElementType(I-V.begin()) || ((T->getElementType(I-V.begin())->isAbstract() || - E->getType()->isAbstract()) && + C->getType()->isAbstract()) && T->getElementType(I-V.begin())->getTypeID() == - E->getType()->getTypeID())) && + C->getType()->getTypeID())) && "Initializer for struct element doesn't match struct element type!"); - OL->init(E, this); + OL->init(C, this); } } @@ -293,12 +293,12 @@ Use *OL = OperandList; for (std::vector::const_iterator I = V.begin(), E = V.end(); I != E; ++I, ++OL) { - Constant *E = *I; - assert((E->getType() == T->getElementType() || + Constant *C = *I; + assert((C->getType() == T->getElementType() || (T->isAbstract() && - E->getType()->getTypeID() == T->getElementType()->getTypeID())) && + C->getType()->getTypeID() == T->getElementType()->getTypeID())) && "Initializer for packed element doesn't match packed element type!"); - OL->init(E, this); + OL->init(C, this); } } From jeffc at jolt-lang.org Fri Oct 7 00:28:40 2005 From: jeffc at jolt-lang.org (Jeff Cohen) Date: Fri, 7 Oct 2005 00:28:40 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200510070528.AAA14070@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.382 -> 1.383 --- Log message: Remove useless variable. --- Diffs of the changes: (+1 -1) InstructionCombining.cpp | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.382 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.383 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.382 Mon Sep 26 00:28:06 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Fri Oct 7 00:28:29 2005 @@ -3444,7 +3444,7 @@ if (BinaryOperator *Op0BO = dyn_cast(Op0)) { // Turn ((X >> C) + Y) << C -> (X + (Y << C)) & (~0 << C) - Value *V1, *V2, *V3; + Value *V1, *V2; ConstantInt *CC; switch (Op0BO->getOpcode()) { default: break; From jeffc at jolt-lang.org Fri Oct 7 00:29:37 2005 From: jeffc at jolt-lang.org (Jeff Cohen) Date: Fri, 7 Oct 2005 00:29:37 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Support/MathExtras.h Message-ID: <200510070529.AAA14082@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm/Support: MathExtras.h updated: 1.26 -> 1.27 --- Log message: Remove prolific source of VC++ truncation warnings. --- Diffs of the changes: (+2 -1) MathExtras.h | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-) Index: llvm/include/llvm/Support/MathExtras.h diff -u llvm/include/llvm/Support/MathExtras.h:1.26 llvm/include/llvm/Support/MathExtras.h:1.27 --- llvm/include/llvm/Support/MathExtras.h:1.26 Tue Aug 30 19:25:01 2005 +++ llvm/include/llvm/Support/MathExtras.h Fri Oct 7 00:29:25 2005 @@ -184,7 +184,8 @@ // CountPopulation_64 - this function counts the number of set bits in a value, // (64 bit edition.) inline unsigned CountPopulation_64(uint64_t Value) { - return CountPopulation_32(Value >> 32) + CountPopulation_32(Value); + return CountPopulation_32(unsigned(Value >> 32)) + + CountPopulation_32(unsigned(Value)); } // Log2_32 - This function returns the floor log base 2 of the specified value, From lattner at cs.uiuc.edu Fri Oct 7 01:10:14 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 7 Oct 2005 01:10:14 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/CodeGen/PowerPC/div-2.ll Message-ID: <200510070610.BAA14299@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/CodeGen/PowerPC: div-2.ll added (r1.1) --- Log message: New testcase, should turn into a ushr --- Diffs of the changes: (+8 -0) div-2.ll | 8 ++++++++ 1 files changed, 8 insertions(+) Index: llvm/test/Regression/CodeGen/PowerPC/div-2.ll diff -c /dev/null llvm/test/Regression/CodeGen/PowerPC/div-2.ll:1.1 *** /dev/null Fri Oct 7 01:10:13 2005 --- llvm/test/Regression/CodeGen/PowerPC/div-2.ll Fri Oct 7 01:10:03 2005 *************** *** 0 **** --- 1,8 ---- + ; RUN: llvm-as < %s | llc -march=ppc32 | not grep srawi && + ; RUN: llvm-as < %s | llc -march=ppc32 | grep blr + + int %test(int %X) { + %Y = and int %X, 15 + %Z = div int %Y, 4 + ret int %Z + } From lattner at cs.uiuc.edu Fri Oct 7 01:10:58 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 7 Oct 2005 01:10:58 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp SelectionDAG.cpp Message-ID: <200510070610.BAA14335@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: DAGCombiner.cpp updated: 1.19 -> 1.20 SelectionDAG.cpp updated: 1.198 -> 1.199 --- Log message: Turn sdivs into udivs when we can prove the sign bits are clear. This implements CodeGen/PowerPC/div-2.ll --- Diffs of the changes: (+21 -0) DAGCombiner.cpp | 10 ++++++++++ SelectionDAG.cpp | 11 +++++++++++ 2 files changed, 21 insertions(+) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.19 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.20 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.19 Wed Oct 5 16:43:42 2005 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Fri Oct 7 01:10:46 2005 @@ -501,6 +501,7 @@ SDOperand DAGCombiner::visitSDIV(SDNode *N) { SDOperand N0 = N->getOperand(0); SDOperand N1 = N->getOperand(1); + MVT::ValueType VT = N->getValueType(0); ConstantSDNode *N0C = dyn_cast(N0.Val); ConstantSDNode *N1C = dyn_cast(N1.Val); @@ -508,6 +509,15 @@ if (N0C && N1C && !N1C->isNullValue()) return DAG.getConstant(N0C->getSignExtended() / N1C->getSignExtended(), N->getValueType(0)); + + // If we know the sign bits of both operands are zero, strength reduce to a + // udiv instead. Handles (X&15) /s 4 -> X&15 >> 2 + uint64_t SignBit = 1ULL << (MVT::getSizeInBits(VT)-1); + if (MaskedValueIsZero(N1, SignBit, TLI) && + MaskedValueIsZero(N0, SignBit, TLI)) + return DAG.getNode(ISD::UDIV, N1.getValueType(), N0, N1); + + return SDOperand(); } Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.198 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.199 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.198 Wed Oct 5 16:44:43 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Fri Oct 7 01:10:46 2005 @@ -1556,6 +1556,17 @@ return N1; } break; + case ISD::SDIV: { + if (CombinerEnabled) break; + + // If we know the sign bits of both operands are zero, strength reduce to a + // udiv instead. Handles (X&15) /s 4 -> X&15 >> 2 + uint64_t SignBit = 1ULL << (MVT::getSizeInBits(VT)-1); + if (MaskedValueIsZero(N2, SignBit, TLI) && + MaskedValueIsZero(N1, SignBit, TLI)) + return getNode(ISD::UDIV, VT, N1, N2); + break; + } case ISD::AND: case ISD::OR: From lattner at cs.uiuc.edu Fri Oct 7 01:37:14 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 7 Oct 2005 01:37:14 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200510070637.BAA14471@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAG.cpp updated: 1.199 -> 1.200 --- Log message: fix indentation --- Diffs of the changes: (+57 -57) SelectionDAG.cpp | 114 +++++++++++++++++++++++++++---------------------------- 1 files changed, 57 insertions(+), 57 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.199 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.200 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.199 Fri Oct 7 01:10:46 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Fri Oct 7 01:37:02 2005 @@ -591,63 +591,63 @@ // If we know the result of a setcc has the top bits zero, use this info. switch (Op.getOpcode()) { - case ISD::Constant: - return (cast(Op)->getValue() & Mask) == 0; - - case ISD::SETCC: - return ((Mask & 1) == 0) && - TLI.getSetCCResultContents() == TargetLowering::ZeroOrOneSetCCResult; - - case ISD::ZEXTLOAD: - SrcBits = MVT::getSizeInBits(cast(Op.getOperand(3))->getVT()); - return (Mask & ((1ULL << SrcBits)-1)) == 0; // Returning only the zext bits. - case ISD::ZERO_EXTEND: - SrcBits = MVT::getSizeInBits(Op.getOperand(0).getValueType()); - return MaskedValueIsZero(Op.getOperand(0),Mask & ((1ULL << SrcBits)-1),TLI); - case ISD::AssertZext: - SrcBits = MVT::getSizeInBits(cast(Op.getOperand(1))->getVT()); - return (Mask & ((1ULL << SrcBits)-1)) == 0; // Returning only the zext bits. - case ISD::AND: - // (X & C1) & C2 == 0 iff C1 & C2 == 0. - if (ConstantSDNode *AndRHS = dyn_cast(Op.getOperand(1))) - return MaskedValueIsZero(Op.getOperand(0),AndRHS->getValue() & Mask, TLI); - - // FALL THROUGH - case ISD::OR: - case ISD::XOR: - return MaskedValueIsZero(Op.getOperand(0), Mask, TLI) && - MaskedValueIsZero(Op.getOperand(1), Mask, TLI); - case ISD::SELECT: - return MaskedValueIsZero(Op.getOperand(1), Mask, TLI) && - MaskedValueIsZero(Op.getOperand(2), Mask, TLI); - case ISD::SELECT_CC: - return MaskedValueIsZero(Op.getOperand(2), Mask, TLI) && - MaskedValueIsZero(Op.getOperand(3), Mask, TLI); - case ISD::SRL: - // (ushr X, C1) & C2 == 0 iff X & (C2 << C1) == 0 - if (ConstantSDNode *ShAmt = dyn_cast(Op.getOperand(1))) { - uint64_t NewVal = Mask << ShAmt->getValue(); - SrcBits = MVT::getSizeInBits(Op.getValueType()); - if (SrcBits != 64) NewVal &= (1ULL << SrcBits)-1; - return MaskedValueIsZero(Op.getOperand(0), NewVal, TLI); - } - return false; - case ISD::SHL: - // (ushl X, C1) & C2 == 0 iff X & (C2 >> C1) == 0 - if (ConstantSDNode *ShAmt = dyn_cast(Op.getOperand(1))) { - uint64_t NewVal = Mask >> ShAmt->getValue(); - return MaskedValueIsZero(Op.getOperand(0), NewVal, TLI); - } - return false; - case ISD::CTTZ: - case ISD::CTLZ: - case ISD::CTPOP: - // Bit counting instructions can not set the high bits of the result - // register. The max number of bits sets depends on the input. - return (Mask & (MVT::getSizeInBits(Op.getValueType())*2-1)) == 0; - - // TODO we could handle some SRA cases here. - default: break; + case ISD::Constant: + return (cast(Op)->getValue() & Mask) == 0; + + case ISD::SETCC: + return ((Mask & 1) == 0) && + TLI.getSetCCResultContents() == TargetLowering::ZeroOrOneSetCCResult; + + case ISD::ZEXTLOAD: + SrcBits = MVT::getSizeInBits(cast(Op.getOperand(3))->getVT()); + return (Mask & ((1ULL << SrcBits)-1)) == 0; // Returning only the zext bits. + case ISD::ZERO_EXTEND: + SrcBits = MVT::getSizeInBits(Op.getOperand(0).getValueType()); + return MaskedValueIsZero(Op.getOperand(0),Mask & ((1ULL << SrcBits)-1),TLI); + case ISD::AssertZext: + SrcBits = MVT::getSizeInBits(cast(Op.getOperand(1))->getVT()); + return (Mask & ((1ULL << SrcBits)-1)) == 0; // Returning only the zext bits. + case ISD::AND: + // (X & C1) & C2 == 0 iff C1 & C2 == 0. + if (ConstantSDNode *AndRHS = dyn_cast(Op.getOperand(1))) + return MaskedValueIsZero(Op.getOperand(0),AndRHS->getValue() & Mask, TLI); + + // FALL THROUGH + case ISD::OR: + case ISD::XOR: + return MaskedValueIsZero(Op.getOperand(0), Mask, TLI) && + MaskedValueIsZero(Op.getOperand(1), Mask, TLI); + case ISD::SELECT: + return MaskedValueIsZero(Op.getOperand(1), Mask, TLI) && + MaskedValueIsZero(Op.getOperand(2), Mask, TLI); + case ISD::SELECT_CC: + return MaskedValueIsZero(Op.getOperand(2), Mask, TLI) && + MaskedValueIsZero(Op.getOperand(3), Mask, TLI); + case ISD::SRL: + // (ushr X, C1) & C2 == 0 iff X & (C2 << C1) == 0 + if (ConstantSDNode *ShAmt = dyn_cast(Op.getOperand(1))) { + uint64_t NewVal = Mask << ShAmt->getValue(); + SrcBits = MVT::getSizeInBits(Op.getValueType()); + if (SrcBits != 64) NewVal &= (1ULL << SrcBits)-1; + return MaskedValueIsZero(Op.getOperand(0), NewVal, TLI); + } + return false; + case ISD::SHL: + // (ushl X, C1) & C2 == 0 iff X & (C2 >> C1) == 0 + if (ConstantSDNode *ShAmt = dyn_cast(Op.getOperand(1))) { + uint64_t NewVal = Mask >> ShAmt->getValue(); + return MaskedValueIsZero(Op.getOperand(0), NewVal, TLI); + } + return false; + case ISD::CTTZ: + case ISD::CTLZ: + case ISD::CTPOP: + // Bit counting instructions can not set the high bits of the result + // register. The max number of bits sets depends on the input. + return (Mask & (MVT::getSizeInBits(Op.getValueType())*2-1)) == 0; + + // TODO we could handle some SRA cases here. + default: break; } return false; From lattner at cs.uiuc.edu Fri Oct 7 10:27:29 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 7 Oct 2005 10:27:29 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/CodeGen/PowerPC/div-2.ll Message-ID: <200510071527.KAA15550@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/CodeGen/PowerPC: div-2.ll updated: 1.1 -> 1.2 --- Log message: These don't need to be sdivs. --- Diffs of the changes: (+22 -1) div-2.ll | 23 ++++++++++++++++++++++- 1 files changed, 22 insertions(+), 1 deletion(-) Index: llvm/test/Regression/CodeGen/PowerPC/div-2.ll diff -u llvm/test/Regression/CodeGen/PowerPC/div-2.ll:1.1 llvm/test/Regression/CodeGen/PowerPC/div-2.ll:1.2 --- llvm/test/Regression/CodeGen/PowerPC/div-2.ll:1.1 Fri Oct 7 01:10:03 2005 +++ llvm/test/Regression/CodeGen/PowerPC/div-2.ll Fri Oct 7 10:27:12 2005 @@ -1,8 +1,29 @@ ; RUN: llvm-as < %s | llc -march=ppc32 | not grep srawi && ; RUN: llvm-as < %s | llc -march=ppc32 | grep blr -int %test(int %X) { +int %test1(int %X) { %Y = and int %X, 15 %Z = div int %Y, 4 ret int %Z } + +int %test2(int %W) { + %X = and int %W, 15 + %Y = sub int 16, %X + %Z = div int %Y, 4 + ret int %Z +} + +int %test3(int %W) { + %X = and int %W, 15 + %Y = sub int 15, %X + %Z = div int %Y, 4 + ret int %Z +} + +int %test4(int %W) { + %X = and int %W, 2 + %Y = sub int 5, %X + %Z = div int %Y, 2 + ret int %Z +} From lattner at cs.uiuc.edu Fri Oct 7 10:29:53 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 7 Oct 2005 10:29:53 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200510071529.KAA15583@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAG.cpp updated: 1.200 -> 1.201 --- Log message: implement CodeGen/PowerPC/div-2.ll:test2-4 by propagating zero bits through C-X's --- Diffs of the changes: (+23 -1) SelectionDAG.cpp | 24 +++++++++++++++++++++++- 1 files changed, 23 insertions(+), 1 deletion(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.200 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.201 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.200 Fri Oct 7 01:37:02 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Fri Oct 7 10:29:41 2005 @@ -639,6 +639,24 @@ return MaskedValueIsZero(Op.getOperand(0), NewVal, TLI); } return false; + case ISD::SUB: + if (ConstantSDNode *CLHS = dyn_cast(Op.getOperand(0))) { + // We know that the top bits of C-X are clear if X contains less bits + // than C (i.e. no wrap-around can happen). For example, 20-X is + // positive if we can prove that X is >= 0 and < 16. + unsigned Bits = MVT::getSizeInBits(CLHS->getValueType(0)); + if ((CLHS->getValue() & (1 << (Bits-1))) == 0) { // sign bit clear + unsigned NLZ = CountLeadingZeros_64(CLHS->getValue()+1); + uint64_t MaskV = (1ULL << (63-NLZ))-1; + if (MaskedValueIsZero(Op.getOperand(1), ~MaskV, TLI)) { + // High bits are clear this value is known to be >= C. + unsigned NLZ2 = CountLeadingZeros_64(CLHS->getValue()); + if ((Mask & ((1ULL << (64-NLZ2))-1)) == 0) + return true; + } + } + } + break; case ISD::CTTZ: case ISD::CTLZ: case ISD::CTPOP: @@ -1563,8 +1581,12 @@ // udiv instead. Handles (X&15) /s 4 -> X&15 >> 2 uint64_t SignBit = 1ULL << (MVT::getSizeInBits(VT)-1); if (MaskedValueIsZero(N2, SignBit, TLI) && - MaskedValueIsZero(N1, SignBit, TLI)) + MaskedValueIsZero(N1, SignBit, TLI)) { + std::cerr << "SDIV [["; + N1.Val->dump(); std::cerr << "]] [["; + N2.Val->dump(); std::cerr << "]] -> udiv\n"; return getNode(ISD::UDIV, VT, N1, N2); + } break; } From lattner at cs.uiuc.edu Fri Oct 7 10:30:43 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 7 Oct 2005 10:30:43 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <200510071530.KAA15624@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: DAGCombiner.cpp updated: 1.20 -> 1.21 --- Log message: implement CodeGen/PowerPC/div-2.ll:test2-4 by propagating zero bits through C-X's --- Diffs of the changes: (+18 -0) DAGCombiner.cpp | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.20 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.21 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.20 Fri Oct 7 01:10:46 2005 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Fri Oct 7 10:30:32 2005 @@ -205,6 +205,24 @@ return MaskedValueIsZero(Op.getOperand(0), NewVal, TLI); } return false; + case ISD::SUB: + if (ConstantSDNode *CLHS = dyn_cast(Op.getOperand(0))) { + // We know that the top bits of C-X are clear if X contains less bits + // than C (i.e. no wrap-around can happen). For example, 20-X is + // positive if we can prove that X is >= 0 and < 16. + unsigned Bits = MVT::getSizeInBits(CLHS->getValueType(0)); + if ((CLHS->getValue() & (1 << (Bits-1))) == 0) { // sign bit clear + unsigned NLZ = CountLeadingZeros_64(CLHS->getValue()+1); + uint64_t MaskV = (1ULL << (63-NLZ))-1; + if (MaskedValueIsZero(Op.getOperand(1), ~MaskV, TLI)) { + // High bits are clear this value is known to be >= C. + unsigned NLZ2 = CountLeadingZeros_64(CLHS->getValue()); + if ((Mask & ((1ULL << (64-NLZ2))-1)) == 0) + return true; + } + } + } + break; case ISD::CTTZ: case ISD::CTLZ: case ISD::CTPOP: From lattner at cs.uiuc.edu Fri Oct 7 10:31:37 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 7 Oct 2005 10:31:37 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200510071531.KAA15657@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAG.cpp updated: 1.201 -> 1.202 --- Log message: remove debugging code --- Diffs of the changes: (+1 -5) SelectionDAG.cpp | 6 +----- 1 files changed, 1 insertion(+), 5 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.201 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.202 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.201 Fri Oct 7 10:29:41 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Fri Oct 7 10:31:26 2005 @@ -1581,12 +1581,8 @@ // udiv instead. Handles (X&15) /s 4 -> X&15 >> 2 uint64_t SignBit = 1ULL << (MVT::getSizeInBits(VT)-1); if (MaskedValueIsZero(N2, SignBit, TLI) && - MaskedValueIsZero(N1, SignBit, TLI)) { - std::cerr << "SDIV [["; - N1.Val->dump(); std::cerr << "]] [["; - N2.Val->dump(); std::cerr << "]] -> udiv\n"; + MaskedValueIsZero(N1, SignBit, TLI)) return getNode(ISD::UDIV, VT, N1, N2); - } break; } From lattner at cs.uiuc.edu Fri Oct 7 17:10:39 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 7 Oct 2005 17:10:39 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Message-ID: <200510072210.RAA31012@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelDAGToDAG.cpp updated: 1.97 -> 1.98 --- Log message: When preselecting, favor things that have low depth to select first. This is faster and uses less stack space. This reduces our stack requirement enough to compile sixtrack, and though it's a hack, should be enough until we switch to iterative isel --- Diffs of the changes: (+8 -5) PPC32ISelDAGToDAG.cpp | 13 ++++++++----- 1 files changed, 8 insertions(+), 5 deletions(-) Index: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.97 llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.98 --- llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.97 Thu Oct 6 14:07:45 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Fri Oct 7 17:10:27 2005 @@ -123,6 +123,11 @@ SDOperand Node = Worklist.back(); Worklist.pop_back(); + // Chose from the least deep of the top two nodes. + if (!Worklist.empty() && + Worklist.back().Val->getNodeDepth() < Node.Val->getNodeDepth()) + std::swap(Worklist.back(), Node); + if ((Node.Val->getOpcode() >= ISD::BUILTIN_OP_END && Node.Val->getOpcode() < PPCISD::FIRST_NUMBER) || CodeGenMap.count(Node)) continue; @@ -142,7 +147,7 @@ // Finally, legalize this node. Select(Node); } - + // Select target instructions for the DAG. DAG.setRoot(Select(DAG.getRoot())); CodeGenMap.clear(); @@ -1026,7 +1031,7 @@ New = CurDAG->getNode(ISD::TokenFactor, MVT::Other, Ops); } - if (!N->hasOneUse()) CodeGenMap[Op] = New; + CodeGenMap[Op] = New; return New; } case ISD::CopyFromReg: { @@ -1042,7 +1047,7 @@ SDOperand Val = Select(N->getOperand(2)); SDOperand New = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, Reg, Val); - if (!N->hasOneUse()) CodeGenMap[Op] = New; + CodeGenMap[Op] = New; return New; } case ISD::UNDEF: @@ -1354,7 +1359,6 @@ Select(N->getOperand(0))); return SDOperand(N, 0); } - case ISD::LOAD: case ISD::EXTLOAD: case ISD::ZEXTLOAD: @@ -1402,7 +1406,6 @@ return Ext; } } - case ISD::TRUNCSTORE: case ISD::STORE: { SDOperand AddrOp1, AddrOp2; From natebegeman at mac.com Fri Oct 7 19:29:55 2005 From: natebegeman at mac.com (Nate Begeman) Date: Fri, 7 Oct 2005 19:29:55 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <200510080029.TAA28256@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: DAGCombiner.cpp updated: 1.21 -> 1.22 --- Log message: Lo and behold, the last bits of SelectionDAG.cpp have been moved over. --- Diffs of the changes: (+150 -6) DAGCombiner.cpp | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 150 insertions(+), 6 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.21 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.22 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.21 Fri Oct 7 10:30:32 2005 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Fri Oct 7 19:29:44 2005 @@ -39,6 +39,7 @@ // is >= to that of the extend. // FIXME: divide by zero is currently left unfolded. do we want to turn this // into an undef? +// FIXME: select ne (select cc, 1, 0), 0, true, false -> select cc, true, false // //===----------------------------------------------------------------------===// @@ -1112,12 +1113,6 @@ // fold select_cc lhs, rhs, x, x, cc -> x if (N2 == N3) return N2; - // fold select_cc true, x, y -> x - if (SCCC && SCCC->getValue()) - return N2; - // fold select_cc false, x, y -> y - if (SCCC && SCCC->getValue() == 0) - return N3; // fold select_cc into other things, such as min/max/abs return SimplifySelectCC(N0, N1, N2, N3, CC); } @@ -1507,12 +1502,161 @@ } SDOperand DAGCombiner::SimplifySelect(SDOperand N0, SDOperand N1, SDOperand N2){ + assert(N0.getOpcode() ==ISD::SETCC && "First argument must be a SetCC node!"); + + SDOperand SCC = SimplifySelectCC(N0.getOperand(0), N0.getOperand(1), N1, N2, + cast(N0.getOperand(2))->get()); + // If we got a simplified select_cc node back from SimplifySelectCC, then + // break it down into a new SETCC node, and a new SELECT node, and then return + // the SELECT node, since we were called with a SELECT node. + if (SCC.Val) { + // Check to see if we got a select_cc back (to turn into setcc/select). + // Otherwise, just return whatever node we got back, like fabs. + if (SCC.getOpcode() == ISD::SELECT_CC) { + SDOperand SETCC = DAG.getNode(ISD::SETCC, N0.getValueType(), + SCC.getOperand(0), SCC.getOperand(1), + SCC.getOperand(4)); + WorkList.push_back(SETCC.Val); + return DAG.getNode(ISD::SELECT, SCC.getValueType(), SCC.getOperand(2), + SCC.getOperand(3), SETCC); + } + return SCC; + } return SDOperand(); } SDOperand DAGCombiner::SimplifySelectCC(SDOperand N0, SDOperand N1, SDOperand N2, SDOperand N3, ISD::CondCode CC) { + + MVT::ValueType VT = N2.getValueType(); + ConstantSDNode *N0C = dyn_cast(N0.Val); + ConstantSDNode *N1C = dyn_cast(N1.Val); + ConstantSDNode *N2C = dyn_cast(N2.Val); + ConstantSDNode *N3C = dyn_cast(N3.Val); + + // Determine if the condition we're dealing with is constant + SDOperand SCC = SimplifySetCC(TLI.getSetCCResultTy(), N0, N1, CC, false); + ConstantSDNode *SCCC = dyn_cast_or_null(SCC.Val); + + // fold select_cc true, x, y -> x + if (SCCC && SCCC->getValue()) + return N2; + // fold select_cc false, x, y -> y + if (SCCC && SCCC->getValue() == 0) + return N3; + + // Check to see if we can simplify the select into an fabs node + if (ConstantFPSDNode *CFP = dyn_cast(N1)) { + // Allow either -0.0 or 0.0 + if (CFP->getValue() == 0.0) { + // select (setg[te] X, +/-0.0), X, fneg(X) -> fabs + if ((CC == ISD::SETGE || CC == ISD::SETGT) && + N0 == N2 && N3.getOpcode() == ISD::FNEG && + N2 == N3.getOperand(0)) + return DAG.getNode(ISD::FABS, VT, N0); + + // select (setl[te] X, +/-0.0), fneg(X), X -> fabs + if ((CC == ISD::SETLT || CC == ISD::SETLE) && + N0 == N3 && N2.getOpcode() == ISD::FNEG && + N2.getOperand(0) == N3) + return DAG.getNode(ISD::FABS, VT, N3); + } + } + + // Check to see if we can perform the "gzip trick", transforming + // select_cc setlt X, 0, A, 0 -> and (sra X, size(X)-1), A + if (N1C && N1C->isNullValue() && N3C && N3C->isNullValue() && + MVT::isInteger(N0.getValueType()) && + MVT::isInteger(N2.getValueType()) && CC == ISD::SETLT) { + MVT::ValueType XType = N0.getValueType(); + MVT::ValueType AType = N2.getValueType(); + if (XType >= AType) { + // and (sra X, size(X)-1, A) -> "and (srl X, C2), A" iff A is a + // single-bit constant. FIXME: remove once the dag combiner + // exists. + if (N2C && ((N2C->getValue() & (N2C->getValue()-1)) == 0)) { + unsigned ShCtV = Log2_64(N2C->getValue()); + ShCtV = MVT::getSizeInBits(XType)-ShCtV-1; + SDOperand ShCt = DAG.getConstant(ShCtV, TLI.getShiftAmountTy()); + SDOperand Shift = DAG.getNode(ISD::SRL, XType, N0, ShCt); + WorkList.push_back(Shift.Val); + if (XType > AType) { + Shift = DAG.getNode(ISD::TRUNCATE, AType, Shift); + WorkList.push_back(Shift.Val); + } + return DAG.getNode(ISD::AND, AType, Shift, N2); + } + SDOperand Shift = DAG.getNode(ISD::SRA, XType, N0, + DAG.getConstant(MVT::getSizeInBits(XType)-1, + TLI.getShiftAmountTy())); + WorkList.push_back(Shift.Val); + if (XType > AType) { + Shift = DAG.getNode(ISD::TRUNCATE, AType, Shift); + WorkList.push_back(Shift.Val); + } + return DAG.getNode(ISD::AND, AType, Shift, N2); + } + } + + // Check to see if this is the equivalent of setcc + // FIXME: Turn all of these into setcc if setcc if setcc is legal + // otherwise, go ahead with the folds. + if (0 && N3C && N3C->isNullValue() && N2C && (N2C->getValue() == 1ULL)) { + MVT::ValueType XType = N0.getValueType(); + if (TLI.isOperationLegal(ISD::SETCC, TLI.getSetCCResultTy())) { + SDOperand Res = DAG.getSetCC(TLI.getSetCCResultTy(), N0, N1, CC); + if (Res.getValueType() != VT) + Res = DAG.getNode(ISD::ZERO_EXTEND, VT, Res); + return Res; + } + + // seteq X, 0 -> srl (ctlz X, log2(size(X))) + if (N1C && N1C->isNullValue() && CC == ISD::SETEQ && + TLI.isOperationLegal(ISD::CTLZ, XType)) { + SDOperand Ctlz = DAG.getNode(ISD::CTLZ, XType, N0); + return DAG.getNode(ISD::SRL, XType, Ctlz, + DAG.getConstant(Log2_32(MVT::getSizeInBits(XType)), + TLI.getShiftAmountTy())); + } + // setgt X, 0 -> srl (and (-X, ~X), size(X)-1) + if (N1C && N1C->isNullValue() && CC == ISD::SETGT) { + SDOperand NegN0 = DAG.getNode(ISD::SUB, XType, DAG.getConstant(0, XType), + N0); + SDOperand NotN0 = DAG.getNode(ISD::XOR, XType, N0, + DAG.getConstant(~0ULL, XType)); + return DAG.getNode(ISD::SRL, XType, + DAG.getNode(ISD::AND, XType, NegN0, NotN0), + DAG.getConstant(MVT::getSizeInBits(XType)-1, + TLI.getShiftAmountTy())); + } + // setgt X, -1 -> xor (srl (X, size(X)-1), 1) + if (N1C && N1C->isAllOnesValue() && CC == ISD::SETGT) { + SDOperand Sign = DAG.getNode(ISD::SRL, XType, N0, + DAG.getConstant(MVT::getSizeInBits(XType)-1, + TLI.getShiftAmountTy())); + return DAG.getNode(ISD::XOR, XType, Sign, DAG.getConstant(1, XType)); + } + } + + // Check to see if this is an integer abs. select_cc setl[te] X, 0, -X, X -> + // Y = sra (X, size(X)-1); xor (add (X, Y), Y) + if (N1C && N1C->isNullValue() && (CC == ISD::SETLT || CC == ISD::SETLE) && + N0 == N3 && N2.getOpcode() == ISD::SUB && N0 == N2.getOperand(1)) { + if (ConstantSDNode *SubC = dyn_cast(N2.getOperand(0))) { + MVT::ValueType XType = N0.getValueType(); + if (SubC->isNullValue() && MVT::isInteger(XType)) { + SDOperand Shift = DAG.getNode(ISD::SRA, XType, N0, + DAG.getConstant(MVT::getSizeInBits(XType)-1, + TLI.getShiftAmountTy())); + SDOperand Add = DAG.getNode(ISD::ADD, XType, N0, Shift); + WorkList.push_back(Shift.Val); + WorkList.push_back(Add.Val); + return DAG.getNode(ISD::XOR, XType, Add, Shift); + } + } + } + return SDOperand(); } From llvm at cs.uiuc.edu Fri Oct 7 20:21:38 2005 From: llvm at cs.uiuc.edu (LLVM) Date: Fri, 7 Oct 2005 20:21:38 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC64RegisterInfo.td Message-ID: <200510080121.UAA28380@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC64RegisterInfo.td (r1.6) removed --- Log message: Remove a file that is no longer used --- Diffs of the changes: (+0 -0) 0 files changed From lattner at cs.uiuc.edu Fri Oct 7 20:24:31 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Fri, 7 Oct 2005 20:24:31 -0500 Subject: [llvm-commits] CVS: llvm/include/llvm/Value.h Message-ID: <200510080124.UAA28438@zion.cs.uiuc.edu> Changes in directory llvm/include/llvm: Value.h updated: 1.78 -> 1.79 --- Log message: remove a comma to compile with pedantic gcc --- Diffs of the changes: (+1 -1) Value.h | 2 +- 1 files changed, 1 insertion(+), 1 deletion(-) Index: llvm/include/llvm/Value.h diff -u llvm/include/llvm/Value.h:1.78 llvm/include/llvm/Value.h:1.79 --- llvm/include/llvm/Value.h:1.78 Tue Sep 27 01:08:32 2005 +++ llvm/include/llvm/Value.h Fri Oct 7 20:24:19 2005 @@ -158,7 +158,7 @@ // Markers: ConstantFirstVal = FunctionVal, - ConstantLastVal = ConstantPointerNullVal, + ConstantLastVal = ConstantPointerNullVal }; unsigned getValueType() const { return SubclassID; From llvm at cs.uiuc.edu Fri Oct 7 20:32:46 2005 From: llvm at cs.uiuc.edu (LLVM) Date: Fri, 7 Oct 2005 20:32:46 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC64.td Message-ID: <200510080132.UAA28462@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC64.td (r1.5) removed --- Log message: Remove another unused file. Preparing for the great "enable i64 on ppc32" merge, and using subtarget info for ptr size. --- Diffs of the changes: (+0 -0) 0 files changed From lattner at cs.uiuc.edu Sun Oct 9 00:31:58 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 9 Oct 2005 00:31:58 -0500 Subject: [llvm-commits] CVS: llvm/test/Regression/CodeGen/PowerPC/2005-10-08-ArithmeticRotate.ll Message-ID: <200510090531.AAA00689@zion.cs.uiuc.edu> Changes in directory llvm/test/Regression/CodeGen/PowerPC: 2005-10-08-ArithmeticRotate.ll added (r1.1) --- Log message: Testcase that is miscompiled by the ppc backend --- Diffs of the changes: (+9 -0) 2005-10-08-ArithmeticRotate.ll | 9 +++++++++ 1 files changed, 9 insertions(+) Index: llvm/test/Regression/CodeGen/PowerPC/2005-10-08-ArithmeticRotate.ll diff -c /dev/null llvm/test/Regression/CodeGen/PowerPC/2005-10-08-ArithmeticRotate.ll:1.1 *** /dev/null Sun Oct 9 00:31:57 2005 --- llvm/test/Regression/CodeGen/PowerPC/2005-10-08-ArithmeticRotate.ll Sun Oct 9 00:31:47 2005 *************** *** 0 **** --- 1,9 ---- + ; This was erroneously being turned into an rlwinm instruction. + ; The sign bit does matter in this case. + + ; RUN: llvm-as < %s | llc -march=ppc32 | grep srawi + int %test(int %X) { + %Y = and int %X, -2 + %Z = shr int %Y, ubyte 11 + ret int %Z + } From lattner at cs.uiuc.edu Sun Oct 9 00:36:28 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 9 Oct 2005 00:36:28 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Message-ID: <200510090536.AAA00781@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/PowerPC: PPC32ISelDAGToDAG.cpp updated: 1.98 -> 1.99 --- Log message: Disable formation of rlwinm instructions from SRA bases. This fixes the 177.mesa failure from last night, and fixes the CodeGen/PowerPC/2005-10-08-ArithmeticRotate.ll regression test I added. If this code cannot be fixed, it should be removed for good, but I'll leave it to Nate to decide its fate. --- Diffs of the changes: (+2 -2) PPC32ISelDAGToDAG.cpp | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) Index: llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp diff -u llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.98 llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.99 --- llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp:1.98 Fri Oct 7 17:10:27 2005 +++ llvm/lib/Target/PowerPC/PPC32ISelDAGToDAG.cpp Sun Oct 9 00:36:17 2005 @@ -217,7 +217,7 @@ return false; } -// isRotateAndMask - Returns true if Mask and Shift can be folded in to a rotate +// isRotateAndMask - Returns true if Mask and Shift can be folded into a rotate // and mask opcode and mask operation. static bool isRotateAndMask(SDNode *N, unsigned Mask, bool IsShiftMask, unsigned &SH, unsigned &MB, unsigned &ME) { @@ -1278,7 +1278,7 @@ } case ISD::SRA: { unsigned Imm, SH, MB, ME; - if (isOpcWithIntImmediate(N->getOperand(0).Val, ISD::AND, Imm) && + if (0 &&isOpcWithIntImmediate(N->getOperand(0).Val, ISD::AND, Imm) && isRotateAndMask(N, Imm, true, SH, MB, ME)) CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Select(N->getOperand(0).getOperand(0)), From lattner at cs.uiuc.edu Sun Oct 9 00:59:08 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 9 Oct 2005 00:59:08 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Message-ID: <200510090559.AAA00986@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: ScheduleDAG.cpp updated: 1.34 -> 1.35 --- Log message: When emiting a CopyFromReg and the source is already a vreg, do not bother creating a new vreg and inserting a copy: just use the input vreg directly. This speeds up the compile (e.g. about 5% on mesa with a debug build of llc) by not adding a bunch of copies and vregs to be coallesced away. On mesa, for example, this reduces the number of intervals from 168601 to 129040 going into the coallescer. --- Diffs of the changes: (+31 -27) ScheduleDAG.cpp | 58 +++++++++++++++++++++++++++++--------------------------- 1 files changed, 31 insertions(+), 27 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp:1.34 llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp:1.35 --- llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp:1.34 Tue Oct 4 11:41:51 2005 +++ llvm/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Sun Oct 9 00:58:56 2005 @@ -1025,22 +1025,23 @@ } case ISD::CopyFromReg: { unsigned SrcReg = cast(Node->getOperand(1))->getReg(); - - // Figure out the register class to create for the destreg. - const TargetRegisterClass *TRC = 0; if (MRegisterInfo::isVirtualRegister(SrcReg)) { - TRC = RegMap->getRegClass(SrcReg); - } else { - // Pick the register class of the right type that contains this physreg. - for (MRegisterInfo::regclass_iterator I = MRI.regclass_begin(), - E = MRI.regclass_end(); I != E; ++I) - if ((*I)->getType() == Node->getValueType(0) && - (*I)->contains(SrcReg)) { - TRC = *I; - break; - } - assert(TRC && "Couldn't find register class for reg copy!"); + VRBase = SrcReg; // Just use the input register directly! + break; } + + // Figure out the register class to create for the destreg. + const TargetRegisterClass *TRC = 0; + + // Pick the register class of the right type that contains this physreg. + for (MRegisterInfo::regclass_iterator I = MRI.regclass_begin(), + E = MRI.regclass_end(); I != E; ++I) + if ((*I)->getType() == Node->getValueType(0) && + (*I)->contains(SrcReg)) { + TRC = *I; + break; + } + assert(TRC && "Couldn't find register class for reg copy!"); // Create the reg, emit the copy. VRBase = RegMap->createVirtualRegister(TRC); @@ -1206,21 +1207,24 @@ EmitDAG(Op.getOperand(0)); // Emit the chain. unsigned SrcReg = cast(Op.getOperand(1))->getReg(); + // If the input is already a virtual register, just use it. + if (MRegisterInfo::isVirtualRegister(SrcReg)) { + ResultReg = SrcReg; + break; + } + // Figure out the register class to create for the destreg. const TargetRegisterClass *TRC = 0; - if (MRegisterInfo::isVirtualRegister(SrcReg)) { - TRC = RegMap->getRegClass(SrcReg); - } else { - // Pick the register class of the right type that contains this physreg. - for (MRegisterInfo::regclass_iterator I = MRI.regclass_begin(), - E = MRI.regclass_end(); I != E; ++I) - if ((*I)->getType() == Op.Val->getValueType(0) && - (*I)->contains(SrcReg)) { - TRC = *I; - break; - } - assert(TRC && "Couldn't find register class for reg copy!"); - } + + // Pick the register class of the right type that contains this physreg. + for (MRegisterInfo::regclass_iterator I = MRI.regclass_begin(), + E = MRI.regclass_end(); I != E; ++I) + if ((*I)->getType() == Op.Val->getValueType(0) && + (*I)->contains(SrcReg)) { + TRC = *I; + break; + } + assert(TRC && "Couldn't find register class for reg copy!"); // Create the reg, emit the copy. ResultReg = RegMap->createVirtualRegister(TRC); From lattner at cs.uiuc.edu Sun Oct 9 01:21:07 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 9 Oct 2005 01:21:07 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200510090621.BAA01114@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopStrengthReduce.cpp updated: 1.63 -> 1.64 --- Log message: Fix a source of non-determinism in the backend: the order of processing IV strides dependend on the pointer order of the strides in memory. Non-determinism is bad. --- Diffs of the changes: (+25 -6) LoopStrengthReduce.cpp | 31 +++++++++++++++++++++++++------ 1 files changed, 25 insertions(+), 6 deletions(-) Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp diff -u llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.63 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.64 --- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.63 Sun Oct 2 21:50:05 2005 +++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Sun Oct 9 01:20:55 2005 @@ -91,6 +91,11 @@ /// are interested in. The key of the map is the stride of the access. std::map IVUsesByStride; + /// StrideOrder - An ordering of the keys in IVUsesByStride that is stable: + /// We use this to iterate over the IVUsesByStride collection without being + /// dependent on random ordering of pointers in the process. + std::vector StrideOrder; + /// CastedValues - As we need to cast values to uintptr_t, this keeps track /// of the casted version of each value. This is accessed by /// getCastedVersionOf. @@ -402,6 +407,10 @@ } if (AddUserToIVUsers) { + IVUsersOfOneStride &StrideUses = IVUsesByStride[Stride]; + if (StrideUses.Users.empty()) // First occurance of this stride? + StrideOrder.push_back(Stride); + // 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. @@ -409,11 +418,11 @@ // The value used will be incremented by the stride more than we are // expecting, so subtract this off. SCEVHandle NewStart = SCEV::getMinusSCEV(Start, Stride); - IVUsesByStride[Stride].addUser(NewStart, User, I); - IVUsesByStride[Stride].Users.back().isUseOfPostIncrementedValue = true; + StrideUses.addUser(NewStart, User, I); + StrideUses.Users.back().isUseOfPostIncrementedValue = true; DEBUG(std::cerr << " USING POSTINC SCEV, START=" << *NewStart<< "\n"); } else { - IVUsesByStride[Stride].addUser(Start, User, I); + StrideUses.addUser(Start, User, I); } } } @@ -1039,12 +1048,21 @@ // If we only have one stride, we can more aggressively eliminate some things. bool HasOneStride = IVUsesByStride.size() == 1; + + if (IVUsesByStride.size() == 123) + std::cerr << "FOO!\n"; // Note: this processes each stride/type pair individually. All users passed - // into StrengthReduceStridedIVUsers have the same type AND stride. - for (std::map::iterator SI - = IVUsesByStride.begin(), E = IVUsesByStride.end(); SI != E; ++SI) + // into StrengthReduceStridedIVUsers have the same type AND stride. Also, + // node that we iterate over IVUsesByStride indirectly by using StrideOrder. + // This extra layer of indirection makes the ordering of strides deterministic + // - not dependent on map order. + for (unsigned Stride = 0, e = StrideOrder.size(); Stride != e; ++Stride) { + std::map::iterator SI = + IVUsesByStride.find(StrideOrder[Stride]); + assert(SI != IVUsesByStride.end() && "Stride doesn't exist!"); StrengthReduceStridedIVUsers(SI->first, SI->second, L, HasOneStride); + } // Clean up after ourselves if (!DeadInsts.empty()) { @@ -1085,5 +1103,6 @@ CastedPointers.clear(); IVUsesByStride.clear(); + StrideOrder.clear(); return; } From lattner at cs.uiuc.edu Sun Oct 9 01:24:14 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 9 Oct 2005 01:24:14 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200510090624.BAA01159@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: LoopStrengthReduce.cpp updated: 1.64 -> 1.65 --- Log message: Hrm, you didn't see this. --- Diffs of the changes: (+0 -3) LoopStrengthReduce.cpp | 3 --- 1 files changed, 3 deletions(-) Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp diff -u llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.64 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.65 --- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.64 Sun Oct 9 01:20:55 2005 +++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp Sun Oct 9 01:24:02 2005 @@ -1049,9 +1049,6 @@ // If we only have one stride, we can more aggressively eliminate some things. bool HasOneStride = IVUsesByStride.size() == 1; - if (IVUsesByStride.size() == 123) - std::cerr << "FOO!\n"; - // Note: this processes each stride/type pair individually. All users passed // into StrengthReduceStridedIVUsers have the same type AND stride. Also, // node that we iterate over IVUsesByStride indirectly by using StrideOrder. From lattner at cs.uiuc.edu Sun Oct 9 01:36:46 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 9 Oct 2005 01:36:46 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200510090636.BAA01251@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.383 -> 1.384 --- Log message: Fix funky xcode indentation --- Diffs of the changes: (+50 -50) InstructionCombining.cpp | 100 +++++++++++++++++++++++------------------------ 1 files changed, 50 insertions(+), 50 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.383 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.384 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.383 Fri Oct 7 00:28:29 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sun Oct 9 01:36:35 2005 @@ -402,59 +402,59 @@ if (Instruction *I = dyn_cast(V)) { switch (I->getOpcode()) { - case Instruction::And: - // (X & C1) & C2 == 0 iff C1 & C2 == 0. - if (ConstantIntegral *CI = dyn_cast(I->getOperand(1))) - if (ConstantExpr::getAnd(CI, Mask)->isNullValue()) - return true; - break; - case Instruction::Or: - // If the LHS and the RHS are MaskedValueIsZero, the result is also zero. - return MaskedValueIsZero(I->getOperand(1), Mask) && - MaskedValueIsZero(I->getOperand(0), Mask); - case Instruction::Select: - // If the T and F values are MaskedValueIsZero, the result is also zero. - return MaskedValueIsZero(I->getOperand(2), Mask) && - MaskedValueIsZero(I->getOperand(1), Mask); - case Instruction::Cast: { - const Type *SrcTy = I->getOperand(0)->getType(); - if (SrcTy == Type::BoolTy) - return (Mask->getRawValue() & 1) == 0; + case Instruction::And: + // (X & C1) & C2 == 0 iff C1 & C2 == 0. + if (ConstantIntegral *CI = dyn_cast(I->getOperand(1))) + if (ConstantExpr::getAnd(CI, Mask)->isNullValue()) + return true; + break; + case Instruction::Or: + // If the LHS and the RHS are MaskedValueIsZero, the result is also zero. + return MaskedValueIsZero(I->getOperand(1), Mask) && + MaskedValueIsZero(I->getOperand(0), Mask); + case Instruction::Select: + // If the T and F values are MaskedValueIsZero, the result is also zero. + return MaskedValueIsZero(I->getOperand(2), Mask) && + MaskedValueIsZero(I->getOperand(1), Mask); + case Instruction::Cast: { + const Type *SrcTy = I->getOperand(0)->getType(); + if (SrcTy == Type::BoolTy) + return (Mask->getRawValue() & 1) == 0; + + if (SrcTy->isInteger()) { + // (cast X to int) & C2 == 0 iff could not have contained C2. + if (SrcTy->isUnsigned() && // Only handle zero ext. + ConstantExpr::getCast(Mask, SrcTy)->isNullValue()) + return true; - if (SrcTy->isInteger()) { - // (cast X to int) & C2 == 0 iff could not have contained C2. - if (SrcTy->isUnsigned() && // Only handle zero ext. - ConstantExpr::getCast(Mask, SrcTy)->isNullValue()) - return true; - - // If this is a noop cast, recurse. - if ((SrcTy->isSigned() && SrcTy->getUnsignedVersion() == I->getType())|| - SrcTy->getSignedVersion() == I->getType()) { - Constant *NewMask = - ConstantExpr::getCast(Mask, I->getOperand(0)->getType()); - return MaskedValueIsZero(I->getOperand(0), - cast(NewMask)); - } + // If this is a noop cast, recurse. + if ((SrcTy->isSigned() && SrcTy->getUnsignedVersion() == I->getType())|| + SrcTy->getSignedVersion() == I->getType()) { + Constant *NewMask = + ConstantExpr::getCast(Mask, I->getOperand(0)->getType()); + return MaskedValueIsZero(I->getOperand(0), + cast(NewMask)); } - break; } - case Instruction::Shl: - // (shl X, C1) & C2 == 0 iff (X & C2 >>u C1) == 0 - if (ConstantUInt *SA = dyn_cast(I->getOperand(1))) - return MaskedValueIsZero(I->getOperand(0), - cast(ConstantExpr::getUShr(Mask, SA))); - break; - case Instruction::Shr: - // (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0 - if (ConstantUInt *SA = dyn_cast(I->getOperand(1))) - if (I->getType()->isUnsigned()) { - Constant *C1 = ConstantIntegral::getAllOnesValue(I->getType()); - C1 = ConstantExpr::getShr(C1, SA); - C1 = ConstantExpr::getAnd(C1, Mask); - if (C1->isNullValue()) - return true; - } - break; + break; + } + case Instruction::Shl: + // (shl X, C1) & C2 == 0 iff (X & C2 >>u C1) == 0 + if (ConstantUInt *SA = dyn_cast(I->getOperand(1))) + return MaskedValueIsZero(I->getOperand(0), + cast(ConstantExpr::getUShr(Mask, SA))); + break; + case Instruction::Shr: + // (ushr X, C1) & C2 == 0 iff (-1 >> C1) & C2 == 0 + if (ConstantUInt *SA = dyn_cast(I->getOperand(1))) + if (I->getType()->isUnsigned()) { + Constant *C1 = ConstantIntegral::getAllOnesValue(I->getType()); + C1 = ConstantExpr::getShr(C1, SA); + C1 = ConstantExpr::getAnd(C1, Mask); + if (C1->isNullValue()) + return true; + } + break; } } From lattner at cs.uiuc.edu Sun Oct 9 02:11:45 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 9 Oct 2005 02:11:45 -0500 Subject: [llvm-commits] CVS: llvm-test/Makefile.programs Message-ID: <200510090711.CAA01398@zion.cs.uiuc.edu> Changes in directory llvm-test: Makefile.programs updated: 1.171 -> 1.172 --- Log message: enable the dag combiner for tonight --- Diffs of the changes: (+2 -1) Makefile.programs | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-) Index: llvm-test/Makefile.programs diff -u llvm-test/Makefile.programs:1.171 llvm-test/Makefile.programs:1.172 --- llvm-test/Makefile.programs:1.171 Tue Sep 27 17:51:20 2005 +++ llvm-test/Makefile.programs Sun Oct 9 02:11:33 2005 @@ -187,7 +187,8 @@ endif#DISABLE_DIFFS ifeq ($(ARCH),PowerPC) -LLCBETAOPTION := -sched=simple +LLCBETAOPTION := -enable-dag-combiner +#-sched=simple endif ifeq ($(ARCH),Alpha) LLCBETAOPTION := -enable-alpha-FTOI -enable-lsr-for-alpha From alenhar2 at cs.uiuc.edu Sun Oct 9 15:11:47 2005 From: alenhar2 at cs.uiuc.edu (Andrew Lenharth) Date: Sun, 9 Oct 2005 15:11:47 -0500 Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp AlphaRegisterInfo.h Message-ID: <200510092011.PAA10228@zion.cs.uiuc.edu> Changes in directory llvm/lib/Target/Alpha: AlphaRegisterInfo.cpp updated: 1.27 -> 1.28 AlphaRegisterInfo.h updated: 1.6 -> 1.7 --- Log message: This seems useful from the original patch that added the function. If there is a reason it is not useful on a RISC type target, let me know and I will pull it out --- Diffs of the changes: (+21 -0) AlphaRegisterInfo.cpp | 19 +++++++++++++++++++ AlphaRegisterInfo.h | 2 ++ 2 files changed, 21 insertions(+) Index: llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp diff -u llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp:1.27 llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp:1.28 --- llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp:1.27 Thu Sep 29 20:29:42 2005 +++ llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp Sun Oct 9 15:11:35 2005 @@ -107,6 +107,25 @@ abort(); } +unsigned +AlphaRegisterInfo::isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const +{ + switch (MI->getOpcode()) { + case Alpha::LDL: + case Alpha::LDQ: + case Alpha::LDBU: + case Alpha::LDWU: + case Alpha::LDS: + case Alpha::LDT: + if (MI->getOperand(1).isFrameIndex()) { + FrameIndex = MI->getOperand(1).getFrameIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + return 0; +} + void AlphaRegisterInfo::copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, unsigned SrcReg, Index: llvm/lib/Target/Alpha/AlphaRegisterInfo.h diff -u llvm/lib/Target/Alpha/AlphaRegisterInfo.h:1.6 llvm/lib/Target/Alpha/AlphaRegisterInfo.h:1.7 --- llvm/lib/Target/Alpha/AlphaRegisterInfo.h:1.6 Thu Sep 29 20:29:42 2005 +++ llvm/lib/Target/Alpha/AlphaRegisterInfo.h Sun Oct 9 15:11:35 2005 @@ -34,6 +34,8 @@ MachineBasicBlock::iterator MBBI, unsigned DestReg, int FrameIndex, const TargetRegisterClass *RC) const; + + virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const; void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, unsigned SrcReg, From sabre at nondot.org Sun Oct 9 15:38:07 2005 From: sabre at nondot.org (Chris Lattner) Date: Sun, 9 Oct 2005 15:38:07 -0500 (CDT) Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp AlphaRegisterInfo.h In-Reply-To: <200510092011.PAA10228@zion.cs.uiuc.edu> References: <200510092011.PAA10228@zion.cs.uiuc.edu> Message-ID: On Sun, 9 Oct 2005, Andrew Lenharth wrote: > This seems useful from the original patch that added the function. If > there is a reason it is not useful on a RISC type target, let me know > and I will pull it out Sounds good. All targets should implement it if they can. It improves spill code generation. -Chris > --- > Diffs of the changes: (+21 -0) > > AlphaRegisterInfo.cpp | 19 +++++++++++++++++++ > AlphaRegisterInfo.h | 2 ++ > 2 files changed, 21 insertions(+) > > > Index: llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp > diff -u llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp:1.27 llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp:1.28 > --- llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp:1.27 Thu Sep 29 20:29:42 2005 > +++ llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp Sun Oct 9 15:11:35 2005 > @@ -107,6 +107,25 @@ > abort(); > } > > +unsigned > +AlphaRegisterInfo::isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const > +{ > + switch (MI->getOpcode()) { > + case Alpha::LDL: > + case Alpha::LDQ: > + case Alpha::LDBU: > + case Alpha::LDWU: > + case Alpha::LDS: > + case Alpha::LDT: > + if (MI->getOperand(1).isFrameIndex()) { > + FrameIndex = MI->getOperand(1).getFrameIndex(); > + return MI->getOperand(0).getReg(); > + } > + break; > + } > + return 0; > +} > + > void AlphaRegisterInfo::copyRegToReg(MachineBasicBlock &MBB, > MachineBasicBlock::iterator MI, > unsigned DestReg, unsigned SrcReg, > > > Index: llvm/lib/Target/Alpha/AlphaRegisterInfo.h > diff -u llvm/lib/Target/Alpha/AlphaRegisterInfo.h:1.6 llvm/lib/Target/Alpha/AlphaRegisterInfo.h:1.7 > --- llvm/lib/Target/Alpha/AlphaRegisterInfo.h:1.6 Thu Sep 29 20:29:42 2005 > +++ llvm/lib/Target/Alpha/AlphaRegisterInfo.h Sun Oct 9 15:11:35 2005 > @@ -34,6 +34,8 @@ > MachineBasicBlock::iterator MBBI, > unsigned DestReg, int FrameIndex, > const TargetRegisterClass *RC) const; > + > + virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const; > > void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, > unsigned DestReg, unsigned SrcReg, > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > -Chris -- http://nondot.org/sabre/ http://llvm.org/ From sabre at nondot.org Sun Oct 9 16:58:07 2005 From: sabre at nondot.org (Chris Lattner) Date: Sun, 9 Oct 2005 16:58:07 -0500 (CDT) Subject: [llvm-commits] CVS: llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp AlphaRegisterInfo.h In-Reply-To: References: <200510092011.PAA10228@zion.cs.uiuc.edu> Message-ID: On Sun, 9 Oct 2005, Chris Lattner wrote: > On Sun, 9 Oct 2005, Andrew Lenharth wrote: > >> This seems useful from the original patch that added the function. If >> there is a reason it is not useful on a RISC type target, let me know and I >> will pull it out > > Sounds good. All targets should implement it if they can. It improves spill > code generation. Note, something else worth implementing is MRegisterInfo::foldMemoryOperand. In particular, folding a load/store is possible for copy instructions: turning it into a or load/store :). If you're interested, see PPC as an example. -Chris >> --- >> Diffs of the changes: (+21 -0) >> >> AlphaRegisterInfo.cpp | 19 +++++++++++++++++++ >> AlphaRegisterInfo.h | 2 ++ >> 2 files changed, 21 insertions(+) >> >> >> Index: llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp >> diff -u llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp:1.27 >> llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp:1.28 >> --- llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp:1.27 Thu Sep 29 20:29:42 >> 2005 >> +++ llvm/lib/Target/Alpha/AlphaRegisterInfo.cpp Sun Oct 9 15:11:35 >> 2005 >> @@ -107,6 +107,25 @@ >> abort(); >> } >> >> +unsigned >> +AlphaRegisterInfo::isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) >> const >> +{ >> + switch (MI->getOpcode()) { >> + case Alpha::LDL: >> + case Alpha::LDQ: >> + case Alpha::LDBU: >> + case Alpha::LDWU: >> + case Alpha::LDS: >> + case Alpha::LDT: >> + if (MI->getOperand(1).isFrameIndex()) { >> + FrameIndex = MI->getOperand(1).getFrameIndex(); >> + return MI->getOperand(0).getReg(); >> + } >> + break; >> + } >> + return 0; >> +} >> + >> void AlphaRegisterInfo::copyRegToReg(MachineBasicBlock &MBB, >> MachineBasicBlock::iterator MI, >> unsigned DestReg, unsigned SrcReg, >> >> >> Index: llvm/lib/Target/Alpha/AlphaRegisterInfo.h >> diff -u llvm/lib/Target/Alpha/AlphaRegisterInfo.h:1.6 >> llvm/lib/Target/Alpha/AlphaRegisterInfo.h:1.7 >> --- llvm/lib/Target/Alpha/AlphaRegisterInfo.h:1.6 Thu Sep 29 20:29:42 >> 2005 >> +++ llvm/lib/Target/Alpha/AlphaRegisterInfo.h Sun Oct 9 15:11:35 2005 >> @@ -34,6 +34,8 @@ >> MachineBasicBlock::iterator MBBI, >> unsigned DestReg, int FrameIndex, >> const TargetRegisterClass *RC) const; >> + >> + virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) >> const; >> >> void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator >> MBBI, >> unsigned DestReg, unsigned SrcReg, >> >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> > > -Chris > > -Chris -- http://nondot.org/sabre/ http://llvm.org/ From lattner at cs.uiuc.edu Sun Oct 9 17:09:01 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 9 Oct 2005 17:09:01 -0500 Subject: [llvm-commits] CVS: llvm/lib/Transforms/Scalar/InstructionCombining.cpp Message-ID: <200510092209.RAA10750@zion.cs.uiuc.edu> Changes in directory llvm/lib/Transforms/Scalar: InstructionCombining.cpp updated: 1.384 -> 1.385 --- Log message: Make MaskedValueIsZero a bit more aggressive --- Diffs of the changes: (+9 -3) InstructionCombining.cpp | 12 +++++++++--- 1 files changed, 9 insertions(+), 3 deletions(-) Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.384 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.385 --- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.384 Sun Oct 9 01:36:35 2005 +++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp Sun Oct 9 17:08:50 2005 @@ -404,11 +404,17 @@ switch (I->getOpcode()) { case Instruction::And: // (X & C1) & C2 == 0 iff C1 & C2 == 0. - if (ConstantIntegral *CI = dyn_cast(I->getOperand(1))) - if (ConstantExpr::getAnd(CI, Mask)->isNullValue()) + if (ConstantIntegral *CI = dyn_cast(I->getOperand(1))) { + ConstantIntegral *C1C2 = + cast(ConstantExpr::getAnd(CI, Mask)); + if (MaskedValueIsZero(I->getOperand(0), C1C2)) return true; - break; + } + // If either the LHS or the RHS are MaskedValueIsZero, the result is zero. + return MaskedValueIsZero(I->getOperand(1), Mask) || + MaskedValueIsZero(I->getOperand(0), Mask); case Instruction::Or: + case Instruction::Xor: // If the LHS and the RHS are MaskedValueIsZero, the result is also zero. return MaskedValueIsZero(I->getOperand(1), Mask) && MaskedValueIsZero(I->getOperand(0), Mask); From lattner at cs.uiuc.edu Sun Oct 9 17:10:01 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 9 Oct 2005 17:10:01 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Message-ID: <200510092210.RAA10818@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: SelectionDAG.cpp updated: 1.202 -> 1.203 --- Log message: (X & Y) & C == 0 if either X&C or Y&C are zero --- Diffs of the changes: (+6 -2) SelectionDAG.cpp | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp diff -u llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.202 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.203 --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1.202 Fri Oct 7 10:31:26 2005 +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Sun Oct 9 17:09:50 2005 @@ -608,11 +608,15 @@ SrcBits = MVT::getSizeInBits(cast(Op.getOperand(1))->getVT()); return (Mask & ((1ULL << SrcBits)-1)) == 0; // Returning only the zext bits. case ISD::AND: + // If either of the operands has zero bits, the result will too. + if (MaskedValueIsZero(Op.getOperand(1), Mask, TLI) || + MaskedValueIsZero(Op.getOperand(0), Mask, TLI)) + return true; + // (X & C1) & C2 == 0 iff C1 & C2 == 0. if (ConstantSDNode *AndRHS = dyn_cast(Op.getOperand(1))) return MaskedValueIsZero(Op.getOperand(0),AndRHS->getValue() & Mask, TLI); - - // FALL THROUGH + return false; case ISD::OR: case ISD::XOR: return MaskedValueIsZero(Op.getOperand(0), Mask, TLI) && From lattner at cs.uiuc.edu Sun Oct 9 17:12:48 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 9 Oct 2005 17:12:48 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <200510092212.RAA10885@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: DAGCombiner.cpp updated: 1.22 -> 1.23 --- Log message: (X & Y) & C == 0 if either X&C or Y&C are zero --- Diffs of the changes: (+6 -1) DAGCombiner.cpp | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletion(-) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.22 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.23 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.22 Fri Oct 7 19:29:44 2005 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Sun Oct 9 17:12:36 2005 @@ -176,10 +176,15 @@ SrcBits = MVT::getSizeInBits(cast(Op.getOperand(1))->getVT()); return (Mask & ((1ULL << SrcBits)-1)) == 0; // Returning only the zext bits. case ISD::AND: + // If either of the operands has zero bits, the result will too. + if (MaskedValueIsZero(Op.getOperand(1), Mask, TLI) || + MaskedValueIsZero(Op.getOperand(0), Mask, TLI)) + return true; + // (X & C1) & C2 == 0 iff C1 & C2 == 0. if (ConstantSDNode *AndRHS = dyn_cast(Op.getOperand(1))) return MaskedValueIsZero(Op.getOperand(0),AndRHS->getValue() & Mask, TLI); - // FALL THROUGH + return false; case ISD::OR: case ISD::XOR: return MaskedValueIsZero(Op.getOperand(0), Mask, TLI) && From lattner at cs.uiuc.edu Sun Oct 9 17:59:19 2005 From: lattner at cs.uiuc.edu (Chris Lattner) Date: Sun, 9 Oct 2005 17:59:19 -0500 Subject: [llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <200510092259.RAA11104@zion.cs.uiuc.edu> Changes in directory llvm/lib/CodeGen/SelectionDAG: DAGCombiner.cpp updated: 1.23 -> 1.24 --- Log message: add a todo for something I noticed --- Diffs of the changes: (+4 -0) DAGCombiner.cpp | 4 ++++ 1 files changed, 4 insertions(+) Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.23 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.24 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.23 Sun Oct 9 17:12:36 2005 +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Sun Oct 9 17:59:08 2005 @@ -40,6 +40,10 @@ // FIXME: divide by zero is currently left unfolded. do we want to turn this // into an undef? // FIXME: select ne (select cc, 1, 0), 0, true, false -> select cc, true, false +// FIXME: sext_inreg(SRL) -> SRA: +// int %simple(uint %X) { %tmp.4 = shr uint %X, ubyte 16 +// %tmp.5 = cast uint %tmp.4 to short %tmp.6 = cast short %tmp.5 to int +// ret int %tmp.6 } // //===----------------------------------------------------------------------===//