From lhames at gmail.com Mon Dec 14 00:49:42 2009 From: lhames at gmail.com (Lang Hames) Date: Mon, 14 Dec 2009 06:49:42 -0000 Subject: [llvm-commits] [llvm] r91273 - in /llvm/trunk: include/llvm/CodeGen/CalcSpillWeights.h lib/CodeGen/CalcSpillWeights.cpp lib/CodeGen/PreAllocSplitting.cpp lib/CodeGen/RegAllocLinearScan.cpp lib/CodeGen/RegAllocPBQP.cpp lib/CodeGen/SimpleRegisterCoalescing.cpp lib/CodeGen/SimpleRegisterCoalescing.h Message-ID: <200912140649.nBE6ngqC000877@zion.cs.uiuc.edu> Author: lhames Date: Mon Dec 14 00:49:42 2009 New Revision: 91273 URL: http://llvm.org/viewvc/llvm-project?rev=91273&view=rev Log: Moved spill weight calculation out of SimpleRegisterCoalescing and into its own pass: CalculateSpillWeights. Added: llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h llvm/trunk/lib/CodeGen/CalcSpillWeights.cpp Modified: llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.h Added: llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h?rev=91273&view=auto ============================================================================== --- llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h (added) +++ llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h Mon Dec 14 00:49:42 2009 @@ -0,0 +1,39 @@ +//===---------------- lib/CodeGen/CalcSpillWeights.h ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_CALCSPILLWEIGHTS_H +#define LLVM_CODEGEN_CALCSPILLWEIGHTS_H + +#include "llvm/CodeGen/MachineFunctionPass.h" + +namespace llvm { + + class LiveInterval; + + /// CalculateSpillWeights - Compute spill weights for all virtual register + /// live intervals. + class CalculateSpillWeights : public MachineFunctionPass { + public: + static char ID; + + CalculateSpillWeights() : MachineFunctionPass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &au) const; + + virtual bool runOnMachineFunction(MachineFunction &fn); + + private: + /// Returns true if the given live interval is zero length. + bool isZeroLengthInterval(LiveInterval *li) const; + }; + +} + +#endif // LLVM_CODEGEN_CALCSPILLWEIGHTS_H Added: llvm/trunk/lib/CodeGen/CalcSpillWeights.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CalcSpillWeights.cpp?rev=91273&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/CalcSpillWeights.cpp (added) +++ llvm/trunk/lib/CodeGen/CalcSpillWeights.cpp Mon Dec 14 00:49:42 2009 @@ -0,0 +1,154 @@ +//===------------------------ CalcSpillWeights.cpp ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "calcspillweights" + +#include "llvm/Function.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/CodeGen/CalcSpillWeights.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" + +using namespace llvm; + +char CalculateSpillWeights::ID = 0; +static RegisterPass X("calcspillweights", + "Calculate spill weights"); + +void CalculateSpillWeights::getAnalysisUsage(AnalysisUsage &au) const { + au.addRequired(); + au.addRequired(); + au.setPreservesAll(); + MachineFunctionPass::getAnalysisUsage(au); +} + +bool CalculateSpillWeights::runOnMachineFunction(MachineFunction &fn) { + + DEBUG(errs() << "********** Compute Spill Weights **********\n" + << "********** Function: " + << fn.getFunction()->getName() << '\n'); + + LiveIntervals *lis = &getAnalysis(); + MachineLoopInfo *loopInfo = &getAnalysis(); + const TargetInstrInfo *tii = fn.getTarget().getInstrInfo(); + MachineRegisterInfo *mri = &fn.getRegInfo(); + + SmallSet processed; + for (MachineFunction::iterator mbbi = fn.begin(), mbbe = fn.end(); + mbbi != mbbe; ++mbbi) { + MachineBasicBlock* mbb = mbbi; + SlotIndex mbbEnd = lis->getMBBEndIdx(mbb); + MachineLoop* loop = loopInfo->getLoopFor(mbb); + unsigned loopDepth = loop ? loop->getLoopDepth() : 0; + bool isExiting = loop ? loop->isLoopExiting(mbb) : false; + + for (MachineBasicBlock::const_iterator mii = mbb->begin(), mie = mbb->end(); + mii != mie; ++mii) { + const MachineInstr *mi = mii; + if (tii->isIdentityCopy(*mi)) + continue; + + if (mi->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) + continue; + + for (unsigned i = 0, e = mi->getNumOperands(); i != e; ++i) { + const MachineOperand &mopi = mi->getOperand(i); + if (!mopi.isReg() || mopi.getReg() == 0) + continue; + unsigned reg = mopi.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(mopi.getReg())) + continue; + // Multiple uses of reg by the same instruction. It should not + // contribute to spill weight again. + if (!processed.insert(reg)) + continue; + + bool hasDef = mopi.isDef(); + bool hasUse = !hasDef; + for (unsigned j = i+1; j != e; ++j) { + const MachineOperand &mopj = mi->getOperand(j); + if (!mopj.isReg() || mopj.getReg() != reg) + continue; + hasDef |= mopj.isDef(); + hasUse |= mopj.isUse(); + if (hasDef && hasUse) + break; + } + + LiveInterval ®Int = lis->getInterval(reg); + float weight = lis->getSpillWeight(hasDef, hasUse, loopDepth); + if (hasDef && isExiting) { + // Looks like this is a loop count variable update. + SlotIndex defIdx = lis->getInstructionIndex(mi).getDefIndex(); + const LiveRange *dlr = + lis->getInterval(reg).getLiveRangeContaining(defIdx); + if (dlr->end > mbbEnd) + weight *= 3.0F; + } + regInt.weight += weight; + } + processed.clear(); + } + } + + for (LiveIntervals::iterator I = lis->begin(), E = lis->end(); I != E; ++I) { + LiveInterval &li = *I->second; + if (TargetRegisterInfo::isVirtualRegister(li.reg)) { + // If the live interval length is essentially zero, i.e. in every live + // range the use follows def immediately, it doesn't make sense to spill + // it and hope it will be easier to allocate for this li. + if (isZeroLengthInterval(&li)) { + li.weight = HUGE_VALF; + continue; + } + + bool isLoad = false; + SmallVector spillIs; + if (lis->isReMaterializable(li, spillIs, isLoad)) { + // If all of the definitions of the interval are re-materializable, + // it is a preferred candidate for spilling. If non of the defs are + // loads, then it's potentially very cheap to re-materialize. + // FIXME: this gets much more complicated once we support non-trivial + // re-materialization. + if (isLoad) + li.weight *= 0.9F; + else + li.weight *= 0.5F; + } + + // Slightly prefer live interval that has been assigned a preferred reg. + std::pair Hint = mri->getRegAllocationHint(li.reg); + if (Hint.first || Hint.second) + li.weight *= 1.01F; + + // Divide the weight of the interval by its size. This encourages + // spilling of intervals that are large and have few uses, and + // discourages spilling of small intervals with many uses. + li.weight /= lis->getApproximateInstructionCount(li) * SlotIndex::NUM; + } + } + + return false; +} + +/// Returns true if the given live interval is zero length. +bool CalculateSpillWeights::isZeroLengthInterval(LiveInterval *li) const { + for (LiveInterval::Ranges::const_iterator + i = li->ranges.begin(), e = li->ranges.end(); i != e; ++i) + if (i->end.getPrevIndex() > i->start) + return false; + return true; +} Modified: llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp?rev=91273&r1=91272&r2=91273&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp (original) +++ llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp Mon Dec 14 00:49:42 2009 @@ -16,6 +16,7 @@ #define DEBUG_TYPE "pre-alloc-split" #include "VirtRegMap.h" +#include "llvm/CodeGen/CalcSpillWeights.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/LiveStackAnalysis.h" #include "llvm/CodeGen/MachineDominators.h" @@ -104,6 +105,7 @@ AU.addRequired(); AU.addPreserved(); AU.addPreserved(); + AU.addPreserved(); if (StrongPHIElim) AU.addPreservedID(StrongPHIEliminationID); else Modified: llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp?rev=91273&r1=91272&r2=91273&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp Mon Dec 14 00:49:42 2009 @@ -16,6 +16,7 @@ #include "VirtRegRewriter.h" #include "Spiller.h" #include "llvm/Function.h" +#include "llvm/CodeGen/CalcSpillWeights.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/LiveStackAnalysis.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -187,6 +188,7 @@ // Make sure PassManager knows which analyses to make available // to coalescing and which analyses coalescing invalidates. AU.addRequiredTransitive(); + AU.addRequired(); if (PreSplitIntervals) AU.addRequiredID(PreAllocSplittingID); AU.addRequired(); Modified: llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp?rev=91273&r1=91272&r2=91273&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp Mon Dec 14 00:49:42 2009 @@ -36,6 +36,7 @@ #include "PBQP/Heuristics/Briggs.h" #include "VirtRegMap.h" #include "VirtRegRewriter.h" +#include "llvm/CodeGen/CalcSpillWeights.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/LiveStackAnalysis.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -90,6 +91,7 @@ au.addRequired(); //au.addRequiredID(SplitCriticalEdgesID); au.addRequired(); + au.addRequired(); au.addRequired(); au.addPreserved(); au.addRequired(); Modified: llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp?rev=91273&r1=91272&r2=91273&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp (original) +++ llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp Mon Dec 14 00:49:42 2009 @@ -2622,114 +2622,6 @@ ReMatDefs.clear(); } -/// Returns true if the given live interval is zero length. -static bool isZeroLengthInterval(LiveInterval *li, LiveIntervals *li_) { - for (LiveInterval::Ranges::const_iterator - i = li->ranges.begin(), e = li->ranges.end(); i != e; ++i) - if (i->end.getPrevIndex() > i->start) - return false; - return true; -} - - -void SimpleRegisterCoalescing::CalculateSpillWeights() { - SmallSet Processed; - for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); - mbbi != mbbe; ++mbbi) { - MachineBasicBlock* MBB = mbbi; - SlotIndex MBBEnd = li_->getMBBEndIdx(MBB); - MachineLoop* loop = loopInfo->getLoopFor(MBB); - unsigned loopDepth = loop ? loop->getLoopDepth() : 0; - bool isExiting = loop ? loop->isLoopExiting(MBB) : false; - - for (MachineBasicBlock::const_iterator mii = MBB->begin(), mie = MBB->end(); - mii != mie; ++mii) { - const MachineInstr *MI = mii; - if (tii_->isIdentityCopy(*MI)) - continue; - - if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) - continue; - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &mopi = MI->getOperand(i); - if (!mopi.isReg() || mopi.getReg() == 0) - continue; - unsigned Reg = mopi.getReg(); - if (!TargetRegisterInfo::isVirtualRegister(mopi.getReg())) - continue; - // Multiple uses of reg by the same instruction. It should not - // contribute to spill weight again. - if (!Processed.insert(Reg)) - continue; - - bool HasDef = mopi.isDef(); - bool HasUse = !HasDef; - for (unsigned j = i+1; j != e; ++j) { - const MachineOperand &mopj = MI->getOperand(j); - if (!mopj.isReg() || mopj.getReg() != Reg) - continue; - HasDef |= mopj.isDef(); - HasUse |= mopj.isUse(); - if (HasDef && HasUse) - break; - } - - LiveInterval &RegInt = li_->getInterval(Reg); - float Weight = li_->getSpillWeight(HasDef, HasUse, loopDepth); - if (HasDef && isExiting) { - // Looks like this is a loop count variable update. - SlotIndex DefIdx = li_->getInstructionIndex(MI).getDefIndex(); - const LiveRange *DLR = - li_->getInterval(Reg).getLiveRangeContaining(DefIdx); - if (DLR->end > MBBEnd) - Weight *= 3.0F; - } - RegInt.weight += Weight; - } - Processed.clear(); - } - } - - for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); I != E; ++I) { - LiveInterval &LI = *I->second; - if (TargetRegisterInfo::isVirtualRegister(LI.reg)) { - // If the live interval length is essentially zero, i.e. in every live - // range the use follows def immediately, it doesn't make sense to spill - // it and hope it will be easier to allocate for this li. - if (isZeroLengthInterval(&LI, li_)) { - LI.weight = HUGE_VALF; - continue; - } - - bool isLoad = false; - SmallVector SpillIs; - if (li_->isReMaterializable(LI, SpillIs, isLoad)) { - // If all of the definitions of the interval are re-materializable, - // it is a preferred candidate for spilling. If non of the defs are - // loads, then it's potentially very cheap to re-materialize. - // FIXME: this gets much more complicated once we support non-trivial - // re-materialization. - if (isLoad) - LI.weight *= 0.9F; - else - LI.weight *= 0.5F; - } - - // Slightly prefer live interval that has been assigned a preferred reg. - std::pair Hint = mri_->getRegAllocationHint(LI.reg); - if (Hint.first || Hint.second) - LI.weight *= 1.01F; - - // Divide the weight of the interval by its size. This encourages - // spilling of intervals that are large and have few uses, and - // discourages spilling of small intervals with many uses. - LI.weight /= li_->getApproximateInstructionCount(LI) * InstrSlots::NUM; - } - } -} - - bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { mf_ = &fn; mri_ = &fn.getRegInfo(); @@ -2860,8 +2752,6 @@ } } - CalculateSpillWeights(); - DEBUG(dump()); return true; } Modified: llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.h?rev=91273&r1=91272&r2=91273&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.h (original) +++ llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.h Mon Dec 14 00:49:42 2009 @@ -244,10 +244,6 @@ MachineOperand *lastRegisterUse(SlotIndex Start, SlotIndex End, unsigned Reg, SlotIndex &LastUseIdx) const; - /// CalculateSpillWeights - Compute spill weights for all virtual register - /// live intervals. - void CalculateSpillWeights(); - void printRegName(unsigned reg) const; }; From isanbard at gmail.com Mon Dec 14 00:51:20 2009 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 14 Dec 2009 06:51:20 -0000 Subject: [llvm-commits] [llvm] r91274 - in /llvm/trunk: include/llvm/Target/TargetInstrInfo.h lib/CodeGen/MachineBasicBlock.cpp lib/Target/X86/X86InstrInfo.cpp Message-ID: <200912140651.nBE6pKcZ000938@zion.cs.uiuc.edu> Author: void Date: Mon Dec 14 00:51:19 2009 New Revision: 91274 URL: http://llvm.org/viewvc/llvm-project?rev=91274&view=rev Log: Whitespace changes, comment clarification. No functional changes. Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetInstrInfo.h?rev=91274&r1=91273&r2=91274&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/TargetInstrInfo.h (original) +++ llvm/trunk/include/llvm/Target/TargetInstrInfo.h Mon Dec 14 00:51:19 2009 @@ -286,11 +286,10 @@ /// just return false, leaving TBB/FBB null. /// 2. If this block ends with only an unconditional branch, it sets TBB to be /// the destination block. - /// 3. If this block ends with an conditional branch and it falls through to - /// a successor block, it sets TBB to be the branch destination block and - /// a list of operands that evaluate the condition. These - /// operands can be passed to other TargetInstrInfo methods to create new - /// branches. + /// 3. If this block ends with a conditional branch and it falls through to a + /// successor block, it sets TBB to be the branch destination block and a + /// list of operands that evaluate the condition. These operands can be + /// passed to other TargetInstrInfo methods to create new branches. /// 4. If this block ends with a conditional branch followed by an /// unconditional branch, it returns the 'true' destination in TBB, the /// 'false' destination in FBB, and a list of operands that evaluate the Modified: llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp?rev=91274&r1=91273&r2=91274&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp (original) +++ llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp Mon Dec 14 00:51:19 2009 @@ -483,16 +483,16 @@ MachineFunction::iterator FallThru = llvm::next(MachineFunction::iterator(this)); - // If this block ends with a conditional branch that falls through to its - // successor, set DestB as the successor. if (isCond) { + // If this block ends with a conditional branch that falls through to its + // successor, set DestB as the successor. if (DestB == 0 && FallThru != getParent()->end()) { DestB = FallThru; AddedFallThrough = true; } } else { // If this is an unconditional branch with no explicit dest, it must just be - // a fallthrough into DestB. + // a fallthrough into DestA. if (DestA == 0 && FallThru != getParent()->end()) { DestA = FallThru; AddedFallThrough = true; Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=91274&r1=91273&r2=91274&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Mon Dec 14 00:51:19 2009 @@ -1624,14 +1624,17 @@ MachineBasicBlock::iterator I = MBB.end(); while (I != MBB.begin()) { --I; - // Working from the bottom, when we see a non-terminator - // instruction, we're done. + + // Working from the bottom, when we see a non-terminator instruction, we're + // done. if (!isBrAnalysisUnpredicatedTerminator(I, *this)) break; - // A terminator that isn't a branch can't easily be handled - // by this analysis. + + // A terminator that isn't a branch can't easily be handled by this + // analysis. if (!I->getDesc().isBranch()) return true; + // Handle unconditional branches. if (I->getOpcode() == X86::JMP) { if (!AllowModify) { @@ -1642,8 +1645,10 @@ // If the block has any instructions after a JMP, delete them. while (llvm::next(I) != MBB.end()) llvm::next(I)->eraseFromParent(); + Cond.clear(); FBB = 0; + // Delete the JMP if it's equivalent to a fall-through. if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { TBB = 0; @@ -1651,14 +1656,17 @@ I = MBB.end(); continue; } + // TBB is used to indicate the unconditinal destination. TBB = I->getOperand(0).getMBB(); continue; } + // Handle conditional branches. X86::CondCode BranchCode = GetCondFromBranchOpc(I->getOpcode()); if (BranchCode == X86::COND_INVALID) return true; // Can't handle indirect branch. + // Working from the bottom, handle the first conditional branch. if (Cond.empty()) { FBB = TBB; @@ -1666,24 +1674,26 @@ Cond.push_back(MachineOperand::CreateImm(BranchCode)); continue; } - // Handle subsequent conditional branches. Only handle the case - // where all conditional branches branch to the same destination - // and their condition opcodes fit one of the special - // multi-branch idioms. + + // Handle subsequent conditional branches. Only handle the case where all + // conditional branches branch to the same destination and their condition + // opcodes fit one of the special multi-branch idioms. assert(Cond.size() == 1); assert(TBB); - // Only handle the case where all conditional branches branch to - // the same destination. + + // Only handle the case where all conditional branches branch to the same + // destination. if (TBB != I->getOperand(0).getMBB()) return true; - X86::CondCode OldBranchCode = (X86::CondCode)Cond[0].getImm(); + // If the conditions are the same, we can leave them alone. + X86::CondCode OldBranchCode = (X86::CondCode)Cond[0].getImm(); if (OldBranchCode == BranchCode) continue; - // If they differ, see if they fit one of the known patterns. - // Theoretically we could handle more patterns here, but - // we shouldn't expect to see them if instruction selection - // has done a reasonable job. + + // If they differ, see if they fit one of the known patterns. Theoretically, + // we could handle more patterns here, but we shouldn't expect to see them + // if instruction selection has done a reasonable job. if ((OldBranchCode == X86::COND_NP && BranchCode == X86::COND_E) || (OldBranchCode == X86::COND_E && @@ -1696,6 +1706,7 @@ BranchCode = X86::COND_NE_OR_P; else return true; + // Update the MachineOperand. Cond[0].setImm(BranchCode); } From lhames at gmail.com Mon Dec 14 01:43:26 2009 From: lhames at gmail.com (Lang Hames) Date: Mon, 14 Dec 2009 07:43:26 -0000 Subject: [llvm-commits] [llvm] r91275 - /llvm/trunk/lib/CodeGen/CMakeLists.txt Message-ID: <200912140743.nBE7hQ3W002834@zion.cs.uiuc.edu> Author: lhames Date: Mon Dec 14 01:43:25 2009 New Revision: 91275 URL: http://llvm.org/viewvc/llvm-project?rev=91275&view=rev Log: Added CalcSpillWeights to CMakeLists. Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=91275&r1=91274&r2=91275&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/CMakeLists.txt (original) +++ llvm/trunk/lib/CodeGen/CMakeLists.txt Mon Dec 14 01:43:25 2009 @@ -1,6 +1,7 @@ add_llvm_library(LLVMCodeGen AggressiveAntiDepBreaker.cpp BranchFolding.cpp + CalcSpillWeights.cpp CodePlacementOpt.cpp CriticalAntiDepBreaker.cpp DeadMachineInstructionElim.cpp From edwintorok at gmail.com Mon Dec 14 06:38:19 2009 From: edwintorok at gmail.com (Torok Edwin) Date: Mon, 14 Dec 2009 12:38:19 -0000 Subject: [llvm-commits] [llvm] r91276 - /llvm/trunk/lib/System/Host.cpp Message-ID: <200912141238.nBECcJlE028673@zion.cs.uiuc.edu> Author: edwin Date: Mon Dec 14 06:38:18 2009 New Revision: 91276 URL: http://llvm.org/viewvc/llvm-project?rev=91276&view=rev Log: Add "generic" fallback. gcc warned that the function may not have a return value, indeed for non-intel and non-amd X86 CPUs it is right (VIA, etc.). Modified: llvm/trunk/lib/System/Host.cpp Modified: llvm/trunk/lib/System/Host.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Host.cpp?rev=91276&r1=91275&r2=91276&view=diff ============================================================================== --- llvm/trunk/lib/System/Host.cpp (original) +++ llvm/trunk/lib/System/Host.cpp Mon Dec 14 06:38:18 2009 @@ -292,6 +292,7 @@ return "generic"; } } + return "generic"; } #else std::string sys::getHostCPUName() { From ssen at apple.com Mon Dec 14 08:15:15 2009 From: ssen at apple.com (Shantonu Sen) Date: Mon, 14 Dec 2009 14:15:15 -0000 Subject: [llvm-commits] [llvm] r91277 - /llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll Message-ID: <200912141415.nBEEFFpr031877@zion.cs.uiuc.edu> Author: ssen Date: Mon Dec 14 08:15:15 2009 New Revision: 91277 URL: http://llvm.org/viewvc/llvm-project?rev=91277&view=rev Log: Remove empty file completely Removed: llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll Removed: llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll?rev=91276&view=auto ============================================================================== (empty) From ssen at apple.com Mon Dec 14 08:18:23 2009 From: ssen at apple.com (Shantonu Sen) Date: Mon, 14 Dec 2009 06:18:23 -0800 Subject: [llvm-commits] [llvm] r91268 - in /llvm/trunk: lib/Transforms/Scalar/ScalarReplAggregates.cpp test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll In-Reply-To: <200912140511.nBE5B3Uj029684@zion.cs.uiuc.edu> References: <200912140511.nBE5B3Uj029684@zion.cs.uiuc.edu> Message-ID: <05B54FC2-9B70-4DF6-94D2-9AB0B370F05D@apple.com> There was a 0-byte test case left, which caused a test suite error. File completely removed in r91277 Shantonu Sent from my MacBook UNRESOLVED: LLVM::Transforms/ScalarRepl/2009-12-11-NeonTypes.ll (4776 of 4969) ******************** TEST 'LLVM::Transforms/ScalarRepl/2009-12-11-NeonTypes.ll' FAILED ******************** Test has no run line! ******************** On Dec 13, 2009, at 9:11 PM, Chris Lattner wrote: > Author: lattner > Date: Sun Dec 13 23:11:02 2009 > New Revision: 91268 > > URL: http://llvm.org/viewvc/llvm-project?rev=91268&view=rev > Log: > revert r91184, because it causes a crash on a .bc file I just > sent to Bob. > > Modified: > llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp > llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll > > Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=91268&r1=91267&r2=91268&view=diff > > ============================================================================== > --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original) > +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Sun Dec 13 23:11:02 2009 > @@ -102,27 +102,25 @@ > > int isSafeAllocaToScalarRepl(AllocaInst *AI); > > - void isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, > - uint64_t ArrayOffset, AllocaInfo &Info); > - void isSafeGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t &Offset, > - uint64_t &ArrayOffset, AllocaInfo &Info); > - void isSafeMemAccess(AllocaInst *AI, uint64_t Offset, uint64_t ArrayOffset, > - uint64_t MemSize, const Type *MemOpType, bool isStore, > - AllocaInfo &Info); > - bool TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size); > - unsigned FindElementAndOffset(const Type *&T, uint64_t &Offset); > + void isSafeUseOfAllocation(Instruction *User, AllocaInst *AI, > + AllocaInfo &Info); > + void isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI, > + AllocaInfo &Info); > + void isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI, > + unsigned OpNo, AllocaInfo &Info); > + void isSafeUseOfBitCastedAllocation(BitCastInst *User, AllocaInst *AI, > + AllocaInfo &Info); > > void DoScalarReplacement(AllocaInst *AI, > std::vector &WorkList); > void CleanupGEP(GetElementPtrInst *GEP); > - void CleanupAllocaUsers(Value *V); > + void CleanupAllocaUsers(AllocaInst *AI); > AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocaInst *Base); > > - void RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, > - SmallVector &NewElts); > - void RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset, > - SmallVector &NewElts); > - void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, > + void RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocaInst *AI, > + SmallVector &NewElts); > + > + void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst, > AllocaInst *AI, > SmallVector &NewElts); > void RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI, > @@ -362,12 +360,176 @@ > } > } > > - // Now that we have created the new alloca instructions, rewrite all the > - // uses of the old alloca. > - RewriteForScalarRepl(AI, AI, 0, ElementAllocas); > + // Now that we have created the alloca instructions that we want to use, > + // expand the getelementptr instructions to use them. > + while (!AI->use_empty()) { > + Instruction *User = cast(AI->use_back()); > + if (BitCastInst *BCInst = dyn_cast(User)) { > + RewriteBitCastUserOfAlloca(BCInst, AI, ElementAllocas); > + BCInst->eraseFromParent(); > + continue; > + } > + > + // Replace: > + // %res = load { i32, i32 }* %alloc > + // with: > + // %load.0 = load i32* %alloc.0 > + // %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0 > + // %load.1 = load i32* %alloc.1 > + // %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 > + // (Also works for arrays instead of structs) > + if (LoadInst *LI = dyn_cast(User)) { > + Value *Insert = UndefValue::get(LI->getType()); > + for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) { > + Value *Load = new LoadInst(ElementAllocas[i], "load", LI); > + Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI); > + } > + LI->replaceAllUsesWith(Insert); > + LI->eraseFromParent(); > + continue; > + } > + > + // Replace: > + // store { i32, i32 } %val, { i32, i32 }* %alloc > + // with: > + // %val.0 = extractvalue { i32, i32 } %val, 0 > + // store i32 %val.0, i32* %alloc.0 > + // %val.1 = extractvalue { i32, i32 } %val, 1 > + // store i32 %val.1, i32* %alloc.1 > + // (Also works for arrays instead of structs) > + if (StoreInst *SI = dyn_cast(User)) { > + Value *Val = SI->getOperand(0); > + for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) { > + Value *Extract = ExtractValueInst::Create(Val, i, Val->getName(), SI); > + new StoreInst(Extract, ElementAllocas[i], SI); > + } > + SI->eraseFromParent(); > + continue; > + } > + > + GetElementPtrInst *GEPI = cast(User); > + // We now know that the GEP is of the form: GEP , 0, > + unsigned Idx = > + (unsigned)cast(GEPI->getOperand(2))->getZExtValue(); > + > + assert(Idx < ElementAllocas.size() && "Index out of range?"); > + AllocaInst *AllocaToUse = ElementAllocas[Idx]; > + > + Value *RepValue; > + if (GEPI->getNumOperands() == 3) { > + // Do not insert a new getelementptr instruction with zero indices, only > + // to have it optimized out later. > + RepValue = AllocaToUse; > + } else { > + // We are indexing deeply into the structure, so we still need a > + // getelement ptr instruction to finish the indexing. This may be > + // expanded itself once the worklist is rerun. > + // > + SmallVector NewArgs; > + NewArgs.push_back(Constant::getNullValue( > + Type::getInt32Ty(AI->getContext()))); > + NewArgs.append(GEPI->op_begin()+3, GEPI->op_end()); > + RepValue = GetElementPtrInst::Create(AllocaToUse, NewArgs.begin(), > + NewArgs.end(), "", GEPI); > + RepValue->takeName(GEPI); > + } > + > + // If this GEP is to the start of the aggregate, check for memcpys. > + if (Idx == 0 && GEPI->hasAllZeroIndices()) > + RewriteBitCastUserOfAlloca(GEPI, AI, ElementAllocas); > + > + // Move all of the users over to the new GEP. > + GEPI->replaceAllUsesWith(RepValue); > + // Delete the old GEP > + GEPI->eraseFromParent(); > + } > + > + // Finally, delete the Alloca instruction > + AI->eraseFromParent(); > NumReplaced++; > } > - > + > +/// isSafeElementUse - Check to see if this use is an allowed use for a > +/// getelementptr instruction of an array aggregate allocation. isFirstElt > +/// indicates whether Ptr is known to the start of the aggregate. > +void SROA::isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI, > + AllocaInfo &Info) { > + for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); > + I != E; ++I) { > + Instruction *User = cast(*I); > + switch (User->getOpcode()) { > + case Instruction::Load: break; > + case Instruction::Store: > + // Store is ok if storing INTO the pointer, not storing the pointer > + if (User->getOperand(0) == Ptr) return MarkUnsafe(Info); > + break; > + case Instruction::GetElementPtr: { > + GetElementPtrInst *GEP = cast(User); > + bool AreAllZeroIndices = isFirstElt; > + if (GEP->getNumOperands() > 1 && > + (!isa(GEP->getOperand(1)) || > + !cast(GEP->getOperand(1))->isZero())) > + // Using pointer arithmetic to navigate the array. > + return MarkUnsafe(Info); > + > + // Verify that any array subscripts are in range. > + for (gep_type_iterator GEPIt = gep_type_begin(GEP), > + E = gep_type_end(GEP); GEPIt != E; ++GEPIt) { > + // Ignore struct elements, no extra checking needed for these. > + if (isa(*GEPIt)) > + continue; > + > + // This GEP indexes an array. Verify that this is an in-range > + // constant integer. Specifically, consider A[0][i]. We cannot know that > + // the user isn't doing invalid things like allowing i to index an > + // out-of-range subscript that accesses A[1]. Because of this, we have > + // to reject SROA of any accesses into structs where any of the > + // components are variables. > + ConstantInt *IdxVal = dyn_cast(GEPIt.getOperand()); > + if (!IdxVal) return MarkUnsafe(Info); > + > + // Are all indices still zero? > + AreAllZeroIndices &= IdxVal->isZero(); > + > + if (const ArrayType *AT = dyn_cast(*GEPIt)) { > + if (IdxVal->getZExtValue() >= AT->getNumElements()) > + return MarkUnsafe(Info); > + } else if (const VectorType *VT = dyn_cast(*GEPIt)) { > + if (IdxVal->getZExtValue() >= VT->getNumElements()) > + return MarkUnsafe(Info); > + } > + } > + > + isSafeElementUse(GEP, AreAllZeroIndices, AI, Info); > + if (Info.isUnsafe) return; > + break; > + } > + case Instruction::BitCast: > + if (isFirstElt) { > + isSafeUseOfBitCastedAllocation(cast(User), AI, Info); > + if (Info.isUnsafe) return; > + break; > + } > + DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); > + return MarkUnsafe(Info); > + case Instruction::Call: > + if (MemIntrinsic *MI = dyn_cast(User)) { > + if (isFirstElt) { > + isSafeMemIntrinsicOnAllocation(MI, AI, I.getOperandNo(), Info); > + if (Info.isUnsafe) return; > + break; > + } > + } > + DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); > + return MarkUnsafe(Info); > + default: > + DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); > + return MarkUnsafe(Info); > + } > + } > + return; // All users look ok :) > +} > + > /// AllUsersAreLoads - Return true if all users of this value are loads. > static bool AllUsersAreLoads(Value *Ptr) { > for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); > @@ -377,116 +539,72 @@ > return true; > } > > -/// isSafeForScalarRepl - Check if instruction I is a safe use with regard to > -/// performing scalar replacement of alloca AI. The results are flagged in > -/// the Info parameter. Offset and ArrayOffset indicate the position within > -/// AI that is referenced by this instruction. > -void SROA::isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, > - uint64_t ArrayOffset, AllocaInfo &Info) { > - for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI!=E; ++UI) { > - Instruction *User = cast(*UI); > - > - if (BitCastInst *BC = dyn_cast(User)) { > - isSafeForScalarRepl(BC, AI, Offset, ArrayOffset, Info); > - } else if (GetElementPtrInst *GEPI = dyn_cast(User)) { > - uint64_t GEPArrayOffset = ArrayOffset; > - uint64_t GEPOffset = Offset; > - isSafeGEP(GEPI, AI, GEPOffset, GEPArrayOffset, Info); > - if (!Info.isUnsafe) > - isSafeForScalarRepl(GEPI, AI, GEPOffset, GEPArrayOffset, Info); > - } else if (MemIntrinsic *MI = dyn_cast(UI)) { > - ConstantInt *Length = dyn_cast(MI->getLength()); > - if (Length) > - isSafeMemAccess(AI, Offset, ArrayOffset, Length->getZExtValue(), 0, > - UI.getOperandNo() == 1, Info); > - else > - MarkUnsafe(Info); > - } else if (LoadInst *LI = dyn_cast(User)) { > - if (!LI->isVolatile()) { > - const Type *LIType = LI->getType(); > - isSafeMemAccess(AI, Offset, ArrayOffset, TD->getTypeAllocSize(LIType), > - LIType, false, Info); > - } else > - MarkUnsafe(Info); > - } else if (StoreInst *SI = dyn_cast(User)) { > - // Store is ok if storing INTO the pointer, not storing the pointer > - if (!SI->isVolatile() && SI->getOperand(0) != I) { > - const Type *SIType = SI->getOperand(0)->getType(); > - isSafeMemAccess(AI, Offset, ArrayOffset, TD->getTypeAllocSize(SIType), > - SIType, true, Info); > - } else > - MarkUnsafe(Info); > - } else if (isa(UI)) { > - // If one user is DbgInfoIntrinsic then check if all users are > - // DbgInfoIntrinsics. > - if (OnlyUsedByDbgInfoIntrinsics(I)) { > - Info.needsCleanup = true; > - return; > - } > - MarkUnsafe(Info); > - } else { > - DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); > - MarkUnsafe(Info); > - } > - if (Info.isUnsafe) return; > - } > -} > +/// isSafeUseOfAllocation - Check if this user is an allowed use for an > +/// aggregate allocation. > +void SROA::isSafeUseOfAllocation(Instruction *User, AllocaInst *AI, > + AllocaInfo &Info) { > + if (BitCastInst *C = dyn_cast(User)) > + return isSafeUseOfBitCastedAllocation(C, AI, Info); > + > + if (LoadInst *LI = dyn_cast(User)) > + if (!LI->isVolatile()) > + return;// Loads (returning a first class aggregrate) are always rewritable > + > + if (StoreInst *SI = dyn_cast(User)) > + if (!SI->isVolatile() && SI->getOperand(0) != AI) > + return;// Store is ok if storing INTO the pointer, not storing the pointer > + > + GetElementPtrInst *GEPI = dyn_cast(User); > + if (GEPI == 0) > + return MarkUnsafe(Info); > > -/// isSafeGEP - Check if a GEP instruction can be handled for scalar > -/// replacement. It is safe when all the indices are constant, in-bounds > -/// references, and when the resulting offset corresponds to an element within > -/// the alloca type. The results are flagged in the Info parameter. Upon > -/// return, Offset is adjusted as specified by the GEP indices. For the > -/// special case of a variable index to a 2-element array, ArrayOffset is set > -/// to the array element size. > -void SROA::isSafeGEP(GetElementPtrInst *GEPI, AllocaInst *AI, > - uint64_t &Offset, uint64_t &ArrayOffset, > - AllocaInfo &Info) { > - gep_type_iterator GEPIt = gep_type_begin(GEPI), E = gep_type_end(GEPI); > - if (GEPIt == E) > - return; > + gep_type_iterator I = gep_type_begin(GEPI), E = gep_type_end(GEPI); > > - // The first GEP index must be zero. > - if (!isa(GEPIt.getOperand()) || > - !cast(GEPIt.getOperand())->isZero()) > + // The GEP is not safe to transform if not of the form "GEP , 0, ". > + if (I == E || > + I.getOperand() != Constant::getNullValue(I.getOperand()->getType())) { > return MarkUnsafe(Info); > - if (++GEPIt == E) > - return; > + } > + > + ++I; > + if (I == E) return MarkUnsafe(Info); // ran out of GEP indices?? > > + bool IsAllZeroIndices = true; > + > // If the first index is a non-constant index into an array, see if we can > // handle it as a special case. > - const Type *ArrayEltTy = 0; > - if (ArrayOffset == 0 && Offset == 0) { > - if (const ArrayType *AT = dyn_cast(*GEPIt)) { > - if (!isa(GEPIt.getOperand())) { > - uint64_t NumElements = AT->getNumElements(); > - > - // If this is an array index and the index is not constant, we cannot > - // promote... that is unless the array has exactly one or two elements > - // in it, in which case we CAN promote it, but we have to canonicalize > - // this out if this is the only problem. > - if ((NumElements != 1 && NumElements != 2) || !AllUsersAreLoads(GEPI)) > - return MarkUnsafe(Info); > + if (const ArrayType *AT = dyn_cast(*I)) { > + if (!isa(I.getOperand())) { > + IsAllZeroIndices = 0; > + uint64_t NumElements = AT->getNumElements(); > + > + // If this is an array index and the index is not constant, we cannot > + // promote... that is unless the array has exactly one or two elements in > + // it, in which case we CAN promote it, but we have to canonicalize this > + // out if this is the only problem. > + if ((NumElements == 1 || NumElements == 2) && > + AllUsersAreLoads(GEPI)) { > Info.needsCleanup = true; > - ArrayOffset = TD->getTypeAllocSizeInBits(AT->getElementType()); > - ArrayEltTy = AT->getElementType(); > - ++GEPIt; > + return; // Canonicalization required! > } > + return MarkUnsafe(Info); > } > } > - > + > // Walk through the GEP type indices, checking the types that this indexes > // into. > - for (; GEPIt != E; ++GEPIt) { > + for (; I != E; ++I) { > // Ignore struct elements, no extra checking needed for these. > - if (isa(*GEPIt)) > + if (isa(*I)) > continue; > + > + ConstantInt *IdxVal = dyn_cast(I.getOperand()); > + if (!IdxVal) return MarkUnsafe(Info); > > - ConstantInt *IdxVal = dyn_cast(GEPIt.getOperand()); > - if (!IdxVal) > - return MarkUnsafe(Info); > - > - if (const ArrayType *AT = dyn_cast(*GEPIt)) { > + // Are all indices still zero? > + IsAllZeroIndices &= IdxVal->isZero(); > + > + if (const ArrayType *AT = dyn_cast(*I)) { > // This GEP indexes an array. Verify that this is an in-range constant > // integer. Specifically, consider A[0][i]. We cannot know that the user > // isn't doing invalid things like allowing i to index an out-of-range > @@ -494,254 +612,144 @@ > // of any accesses into structs where any of the components are variables. > if (IdxVal->getZExtValue() >= AT->getNumElements()) > return MarkUnsafe(Info); > - } else { > - const VectorType *VT = dyn_cast(*GEPIt); > - assert(VT && "unexpected type in GEP type iterator"); > + } else if (const VectorType *VT = dyn_cast(*I)) { > if (IdxVal->getZExtValue() >= VT->getNumElements()) > return MarkUnsafe(Info); > } > } > - > - // All the indices are safe. Now compute the offset due to this GEP and > - // check if the alloca has a component element at that offset. > - if (ArrayOffset == 0) { > - SmallVector Indices(GEPI->op_begin() + 1, GEPI->op_end()); > - Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(), > - &Indices[0], Indices.size()); > - } else { > - // Both array elements have the same type, so it suffices to check one of > - // them. Copy the GEP indices starting from the array index, but replace > - // that variable index with a constant zero. > - SmallVector Indices(GEPI->op_begin() + 2, GEPI->op_end()); > - Indices[0] = Constant::getNullValue(Type::getInt32Ty(GEPI->getContext())); > - const Type *ArrayEltPtr = PointerType::getUnqual(ArrayEltTy); > - Offset += TD->getIndexedOffset(ArrayEltPtr, &Indices[0], Indices.size()); > - } > - if (!TypeHasComponent(AI->getAllocatedType(), Offset, 0)) > - MarkUnsafe(Info); > -} > - > -/// isSafeMemAccess - Check if a load/store/memcpy operates on the entire AI > -/// alloca or has an offset and size that corresponds to a component element > -/// within it. The offset checked here may have been formed from a GEP with a > -/// pointer bitcasted to a different type. > -void SROA::isSafeMemAccess(AllocaInst *AI, uint64_t Offset, > - uint64_t ArrayOffset, uint64_t MemSize, > - const Type *MemOpType, bool isStore, > - AllocaInfo &Info) { > - // Check if this is a load/store of the entire alloca. > - if (Offset == 0 && ArrayOffset == 0 && > - MemSize == TD->getTypeAllocSize(AI->getAllocatedType())) { > - bool UsesAggregateType = (MemOpType == AI->getAllocatedType()); > - // This is safe for MemIntrinsics (where MemOpType is 0), integer types > - // (which are essentially the same as the MemIntrinsics, especially with > - // regard to copying padding between elements), or references using the > - // aggregate type of the alloca. > - if (!MemOpType || isa(MemOpType) || UsesAggregateType) { > - if (!UsesAggregateType) { > - if (isStore) > - Info.isMemCpyDst = true; > - else > - Info.isMemCpySrc = true; > - } > - return; > - } > - } > - // Check if the offset/size correspond to a component within the alloca type. > - const Type *T = AI->getAllocatedType(); > - if (TypeHasComponent(T, Offset, MemSize) && > - (ArrayOffset == 0 || TypeHasComponent(T, Offset + ArrayOffset, MemSize))) > - return; > - > - return MarkUnsafe(Info); > + > + // If there are any non-simple uses of this getelementptr, make sure to reject > + // them. > + return isSafeElementUse(GEPI, IsAllZeroIndices, AI, Info); > } > > -/// TypeHasComponent - Return true if T has a component type with the > -/// specified offset and size. If Size is zero, do not check the size. > -bool SROA::TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size) { > - const Type *EltTy; > - uint64_t EltSize; > - if (const StructType *ST = dyn_cast(T)) { > - const StructLayout *Layout = TD->getStructLayout(ST); > - unsigned EltIdx = Layout->getElementContainingOffset(Offset); > - EltTy = ST->getContainedType(EltIdx); > - EltSize = TD->getTypeAllocSize(EltTy); > - Offset -= Layout->getElementOffset(EltIdx); > - } else if (const ArrayType *AT = dyn_cast(T)) { > - EltTy = AT->getElementType(); > - EltSize = TD->getTypeAllocSize(EltTy); > - Offset %= EltSize; > - } else { > - return false; > +/// isSafeMemIntrinsicOnAllocation - Check if the specified memory > +/// intrinsic can be promoted by SROA. At this point, we know that the operand > +/// of the memintrinsic is a pointer to the beginning of the allocation. > +void SROA::isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI, > + unsigned OpNo, AllocaInfo &Info) { > + // If not constant length, give up. > + ConstantInt *Length = dyn_cast(MI->getLength()); > + if (!Length) return MarkUnsafe(Info); > + > + // If not the whole aggregate, give up. > + if (Length->getZExtValue() != > + TD->getTypeAllocSize(AI->getType()->getElementType())) > + return MarkUnsafe(Info); > + > + // We only know about memcpy/memset/memmove. > + if (!isa(MI)) > + return MarkUnsafe(Info); > + > + // Otherwise, we can transform it. Determine whether this is a memcpy/set > + // into or out of the aggregate. > + if (OpNo == 1) > + Info.isMemCpyDst = true; > + else { > + assert(OpNo == 2); > + Info.isMemCpySrc = true; > } > - if (Offset == 0 && (Size == 0 || EltSize == Size)) > - return true; > - // Check if the component spans multiple elements. > - if (Offset + Size > EltSize) > - return false; > - return TypeHasComponent(EltTy, Offset, Size); > } > > -/// RewriteForScalarRepl - Alloca AI is being split into NewElts, so rewrite > -/// the instruction I, which references it, to use the separate elements. > -/// Offset indicates the position within AI that is referenced by this > -/// instruction. > -void SROA::RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, > - SmallVector &NewElts) { > - for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; ) { > - Instruction *User = cast(*UI++); > +/// isSafeUseOfBitCastedAllocation - Check if all users of this bitcast > +/// from an alloca are safe for SROA of that alloca. > +void SROA::isSafeUseOfBitCastedAllocation(BitCastInst *BC, AllocaInst *AI, > + AllocaInfo &Info) { > + for (Value::use_iterator UI = BC->use_begin(), E = BC->use_end(); > + UI != E; ++UI) { > + if (BitCastInst *BCU = dyn_cast(UI)) { > + isSafeUseOfBitCastedAllocation(BCU, AI, Info); > + } else if (MemIntrinsic *MI = dyn_cast(UI)) { > + isSafeMemIntrinsicOnAllocation(MI, AI, UI.getOperandNo(), Info); > + } else if (StoreInst *SI = dyn_cast(UI)) { > + if (SI->isVolatile()) > + return MarkUnsafe(Info); > + > + // If storing the entire alloca in one chunk through a bitcasted pointer > + // to integer, we can transform it. This happens (for example) when you > + // cast a {i32,i32}* to i64* and store through it. This is similar to the > + // memcpy case and occurs in various "byval" cases and emulated memcpys. > + if (isa(SI->getOperand(0)->getType()) && > + TD->getTypeAllocSize(SI->getOperand(0)->getType()) == > + TD->getTypeAllocSize(AI->getType()->getElementType())) { > + Info.isMemCpyDst = true; > + continue; > + } > + return MarkUnsafe(Info); > + } else if (LoadInst *LI = dyn_cast(UI)) { > + if (LI->isVolatile()) > + return MarkUnsafe(Info); > > - if (BitCastInst *BC = dyn_cast(User)) { > - if (BC->getOperand(0) == AI) > - BC->setOperand(0, NewElts[0]); > - // If the bitcast type now matches the operand type, it will be removed > - // after processing its uses. > - RewriteForScalarRepl(BC, AI, Offset, NewElts); > - } else if (GetElementPtrInst *GEPI = dyn_cast(User)) { > - RewriteGEP(GEPI, AI, Offset, NewElts); > - } else if (MemIntrinsic *MI = dyn_cast(User)) { > - ConstantInt *Length = dyn_cast(MI->getLength()); > - uint64_t MemSize = Length->getZExtValue(); > - if (Offset == 0 && > - MemSize == TD->getTypeAllocSize(AI->getAllocatedType())) > - RewriteMemIntrinUserOfAlloca(MI, I, AI, NewElts); > - } else if (LoadInst *LI = dyn_cast(User)) { > - const Type *LIType = LI->getType(); > - if (LIType == AI->getAllocatedType()) { > - // Replace: > - // %res = load { i32, i32 }* %alloc > - // with: > - // %load.0 = load i32* %alloc.0 > - // %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0 > - // %load.1 = load i32* %alloc.1 > - // %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 > - // (Also works for arrays instead of structs) > - Value *Insert = UndefValue::get(LIType); > - for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { > - Value *Load = new LoadInst(NewElts[i], "load", LI); > - Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI); > - } > - LI->replaceAllUsesWith(Insert); > - LI->eraseFromParent(); > - } else if (isa(LIType) && > - TD->getTypeAllocSize(LIType) == > - TD->getTypeAllocSize(AI->getAllocatedType())) { > - // If this is a load of the entire alloca to an integer, rewrite it. > - RewriteLoadUserOfWholeAlloca(LI, AI, NewElts); > + // If loading the entire alloca in one chunk through a bitcasted pointer > + // to integer, we can transform it. This happens (for example) when you > + // cast a {i32,i32}* to i64* and load through it. This is similar to the > + // memcpy case and occurs in various "byval" cases and emulated memcpys. > + if (isa(LI->getType()) && > + TD->getTypeAllocSize(LI->getType()) == > + TD->getTypeAllocSize(AI->getType()->getElementType())) { > + Info.isMemCpySrc = true; > + continue; > } > - } else if (StoreInst *SI = dyn_cast(User)) { > - Value *Val = SI->getOperand(0); > - const Type *SIType = Val->getType(); > - if (SIType == AI->getAllocatedType()) { > - // Replace: > - // store { i32, i32 } %val, { i32, i32 }* %alloc > - // with: > - // %val.0 = extractvalue { i32, i32 } %val, 0 > - // store i32 %val.0, i32* %alloc.0 > - // %val.1 = extractvalue { i32, i32 } %val, 1 > - // store i32 %val.1, i32* %alloc.1 > - // (Also works for arrays instead of structs) > - for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { > - Value *Extract = ExtractValueInst::Create(Val, i, Val->getName(), SI); > - new StoreInst(Extract, NewElts[i], SI); > - } > - SI->eraseFromParent(); > - } else if (isa(SIType) && > - TD->getTypeAllocSize(SIType) == > - TD->getTypeAllocSize(AI->getAllocatedType())) { > - // If this is a store of the entire alloca from an integer, rewrite it. > - RewriteStoreUserOfWholeAlloca(SI, AI, NewElts); > + return MarkUnsafe(Info); > + } else if (isa(UI)) { > + // If one user is DbgInfoIntrinsic then check if all users are > + // DbgInfoIntrinsics. > + if (OnlyUsedByDbgInfoIntrinsics(BC)) { > + Info.needsCleanup = true; > + return; > } > + else > + MarkUnsafe(Info); > } > - } > - // Delete unused instructions and identity bitcasts. > - if (I->use_empty()) > - I->eraseFromParent(); > - else if (BitCastInst *BC = dyn_cast(I)) { > - if (BC->getDestTy() == BC->getSrcTy()) { > - BC->replaceAllUsesWith(BC->getOperand(0)); > - BC->eraseFromParent(); > + else { > + return MarkUnsafe(Info); > } > + if (Info.isUnsafe) return; > } > } > > -/// FindElementAndOffset - Return the index of the element containing Offset > -/// within the specified type, which must be either a struct or an array. > -/// Sets T to the type of the element and Offset to the offset within that > -/// element. > -unsigned SROA::FindElementAndOffset(const Type *&T, uint64_t &Offset) { > - unsigned Idx = 0; > - if (const StructType *ST = dyn_cast(T)) { > - const StructLayout *Layout = TD->getStructLayout(ST); > - Idx = Layout->getElementContainingOffset(Offset); > - T = ST->getContainedType(Idx); > - Offset -= Layout->getElementOffset(Idx); > - } else { > - const ArrayType *AT = dyn_cast(T); > - assert(AT && "unexpected type for scalar replacement"); > - T = AT->getElementType(); > - uint64_t EltSize = TD->getTypeAllocSize(T); > - Idx = (unsigned)(Offset / EltSize); > - Offset -= Idx * EltSize; > - } > - return Idx; > -} > - > -/// RewriteGEP - Check if this GEP instruction moves the pointer across > -/// elements of the alloca that are being split apart, and if so, rewrite > -/// the GEP to be relative to the new element. > -void SROA::RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset, > - SmallVector &NewElts) { > - Instruction *Val = GEPI; > - > - uint64_t OldOffset = Offset; > - SmallVector Indices(GEPI->op_begin() + 1, GEPI->op_end()); > - Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(), > - &Indices[0], Indices.size()); > - > - const Type *T = AI->getAllocatedType(); > - unsigned OldIdx = FindElementAndOffset(T, OldOffset); > - if (GEPI->getOperand(0) == AI) > - OldIdx = ~0U; // Force the GEP to be rewritten. > - > - T = AI->getAllocatedType(); > - uint64_t EltOffset = Offset; > - unsigned Idx = FindElementAndOffset(T, EltOffset); > - > - // If this GEP moves the pointer across elements of the alloca that are > - // being split, then it needs to be rewritten. > - if (Idx != OldIdx) { > - const Type *i32Ty = Type::getInt32Ty(AI->getContext()); > - SmallVector NewArgs; > - NewArgs.push_back(Constant::getNullValue(i32Ty)); > - while (EltOffset != 0) { > - unsigned EltIdx = FindElementAndOffset(T, EltOffset); > - NewArgs.push_back(ConstantInt::get(i32Ty, EltIdx)); > - } > - if (NewArgs.size() > 1) { > - Val = GetElementPtrInst::CreateInBounds(NewElts[Idx], NewArgs.begin(), > - NewArgs.end(), "", GEPI); > - Val->takeName(GEPI); > - if (Val->getType() != GEPI->getType()) > - Val = new BitCastInst(Val, GEPI->getType(), Val->getNameStr(), GEPI); > - } else { > - Val = NewElts[Idx]; > - // Insert a new bitcast. If the types match, it will be removed after > - // handling all of its uses. > - Val = new BitCastInst(Val, GEPI->getType(), Val->getNameStr(), GEPI); > - Val->takeName(GEPI); > +/// RewriteBitCastUserOfAlloca - BCInst (transitively) bitcasts AI, or indexes > +/// to its first element. Transform users of the cast to use the new values > +/// instead. > +void SROA::RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocaInst *AI, > + SmallVector &NewElts) { > + Value::use_iterator UI = BCInst->use_begin(), UE = BCInst->use_end(); > + while (UI != UE) { > + Instruction *User = cast(*UI++); > + if (BitCastInst *BCU = dyn_cast(User)) { > + RewriteBitCastUserOfAlloca(BCU, AI, NewElts); > + if (BCU->use_empty()) BCU->eraseFromParent(); > + continue; > } > > - GEPI->replaceAllUsesWith(Val); > - GEPI->eraseFromParent(); > - } > + if (MemIntrinsic *MI = dyn_cast(User)) { > + // This must be memcpy/memmove/memset of the entire aggregate. > + // Split into one per element. > + RewriteMemIntrinUserOfAlloca(MI, BCInst, AI, NewElts); > + continue; > + } > + > + if (StoreInst *SI = dyn_cast(User)) { > + // If this is a store of the entire alloca from an integer, rewrite it. > + RewriteStoreUserOfWholeAlloca(SI, AI, NewElts); > + continue; > + } > > - RewriteForScalarRepl(Val, AI, Offset, NewElts); > + if (LoadInst *LI = dyn_cast(User)) { > + // If this is a load of the entire alloca to an integer, rewrite it. > + RewriteLoadUserOfWholeAlloca(LI, AI, NewElts); > + continue; > + } > + > + // Otherwise it must be some other user of a gep of the first pointer. Just > + // leave these alone. > + continue; > + } > } > > /// RewriteMemIntrinUserOfAlloca - MI is a memcpy/memset/memmove from or to AI. > /// Rewrite it to copy or set the elements of the scalarized memory. > -void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, > +void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst, > AllocaInst *AI, > SmallVector &NewElts) { > > @@ -753,10 +761,10 @@ > LLVMContext &Context = MI->getContext(); > unsigned MemAlignment = MI->getAlignment(); > if (MemTransferInst *MTI = dyn_cast(MI)) { // memmove/memcopy > - if (Inst == MTI->getRawDest()) > + if (BCInst == MTI->getRawDest()) > OtherPtr = MTI->getRawSource(); > else { > - assert(Inst == MTI->getRawSource()); > + assert(BCInst == MTI->getRawSource()); > OtherPtr = MTI->getRawDest(); > } > } > @@ -790,7 +798,7 @@ > // Process each element of the aggregate. > Value *TheFn = MI->getOperand(0); > const Type *BytePtrTy = MI->getRawDest()->getType(); > - bool SROADest = MI->getRawDest() == Inst; > + bool SROADest = MI->getRawDest() == BCInst; > > Constant *Zero = Constant::getNullValue(Type::getInt32Ty(MI->getContext())); > > @@ -802,9 +810,9 @@ > if (OtherPtr) { > Value *Idx[2] = { Zero, > ConstantInt::get(Type::getInt32Ty(MI->getContext()), i) }; > - OtherElt = GetElementPtrInst::CreateInBounds(OtherPtr, Idx, Idx + 2, > + OtherElt = GetElementPtrInst::Create(OtherPtr, Idx, Idx + 2, > OtherPtr->getNameStr()+"."+Twine(i), > - MI); > + MI); > uint64_t EltOffset; > const PointerType *OtherPtrTy = cast(OtherPtr->getType()); > if (const StructType *ST = > @@ -929,9 +937,15 @@ > // Extract each element out of the integer according to its structure offset > // and store the element value to the individual alloca. > Value *SrcVal = SI->getOperand(0); > - const Type *AllocaEltTy = AI->getAllocatedType(); > + const Type *AllocaEltTy = AI->getType()->getElementType(); > uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy); > > + // If this isn't a store of an integer to the whole alloca, it may be a store > + // to the first element. Just ignore the store in this case and normal SROA > + // will handle it. > + if (!isa(SrcVal->getType()) || > + TD->getTypeAllocSizeInBits(SrcVal->getType()) != AllocaSizeBits) > + return; > // Handle tail padding by extending the operand > if (TD->getTypeSizeInBits(SrcVal->getType()) != AllocaSizeBits) > SrcVal = new ZExtInst(SrcVal, > @@ -1045,9 +1059,16 @@ > SmallVector &NewElts) { > // Extract each element out of the NewElts according to its structure offset > // and form the result value. > - const Type *AllocaEltTy = AI->getAllocatedType(); > + const Type *AllocaEltTy = AI->getType()->getElementType(); > uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy); > > + // If this isn't a load of the whole alloca to an integer, it may be a load > + // of the first element. Just ignore the load in this case and normal SROA > + // will handle it. > + if (!isa(LI->getType()) || > + TD->getTypeAllocSizeInBits(LI->getType()) != AllocaSizeBits) > + return; > + > DEBUG(errs() << "PROMOTING LOAD OF WHOLE ALLOCA: " << *AI << '\n' << *LI > << '\n'); > > @@ -1121,6 +1142,7 @@ > LI->eraseFromParent(); > } > > + > /// HasPadding - Return true if the specified type has any structure or > /// alignment padding, false otherwise. > static bool HasPadding(const Type *Ty, const TargetData &TD) { > @@ -1170,10 +1192,14 @@ > // the users are safe to transform. > AllocaInfo Info; > > - isSafeForScalarRepl(AI, AI, 0, 0, Info); > - if (Info.isUnsafe) { > - DEBUG(errs() << "Cannot transform: " << *AI << '\n'); > - return 0; > + for (Value::use_iterator I = AI->use_begin(), E = AI->use_end(); > + I != E; ++I) { > + isSafeUseOfAllocation(cast(*I), AI, Info); > + if (Info.isUnsafe) { > + DEBUG(errs() << "Cannot transform: " << *AI << "\n due to user: " > + << **I << '\n'); > + return 0; > + } > } > > // Okay, we know all the users are promotable. If the aggregate is a memcpy > @@ -1182,7 +1208,7 @@ > // types, but may actually be used. In these cases, we refuse to promote the > // struct. > if (Info.isMemCpySrc && Info.isMemCpyDst && > - HasPadding(AI->getAllocatedType(), *TD)) > + HasPadding(AI->getType()->getElementType(), *TD)) > return 0; > > // If we require cleanup, return 1, otherwise return 3. > @@ -1219,15 +1245,15 @@ > // Insert the new GEP instructions, which are properly indexed. > SmallVector Indices(GEPI->op_begin()+1, GEPI->op_end()); > Indices[1] = Constant::getNullValue(Type::getInt32Ty(GEPI->getContext())); > - Value *ZeroIdx = GetElementPtrInst::CreateInBounds(GEPI->getOperand(0), > - Indices.begin(), > - Indices.end(), > - GEPI->getName()+".0",GEPI); > + Value *ZeroIdx = GetElementPtrInst::Create(GEPI->getOperand(0), > + Indices.begin(), > + Indices.end(), > + GEPI->getName()+".0", GEPI); > Indices[1] = ConstantInt::get(Type::getInt32Ty(GEPI->getContext()), 1); > - Value *OneIdx = GetElementPtrInst::CreateInBounds(GEPI->getOperand(0), > - Indices.begin(), > - Indices.end(), > - GEPI->getName()+".1", GEPI); > + Value *OneIdx = GetElementPtrInst::Create(GEPI->getOperand(0), > + Indices.begin(), > + Indices.end(), > + GEPI->getName()+".1", GEPI); > // Replace all loads of the variable index GEP with loads from both > // indexes and a select. > while (!GEPI->use_empty()) { > @@ -1238,24 +1264,22 @@ > LI->replaceAllUsesWith(R); > LI->eraseFromParent(); > } > + GEPI->eraseFromParent(); > } > > + > /// CleanupAllocaUsers - If SROA reported that it can promote the specified > /// allocation, but only if cleaned up, perform the cleanups required. > -void SROA::CleanupAllocaUsers(Value *V) { > +void SROA::CleanupAllocaUsers(AllocaInst *AI) { > // At this point, we know that the end result will be SROA'd and promoted, so > // we can insert ugly code if required so long as sroa+mem2reg will clean it > // up. > - for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); > + for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); > UI != E; ) { > User *U = *UI++; > - if (isa(U)) { > - CleanupAllocaUsers(U); > - } else if (GetElementPtrInst *GEPI = dyn_cast(U)) { > + if (GetElementPtrInst *GEPI = dyn_cast(U)) > CleanupGEP(GEPI); > - CleanupAllocaUsers(GEPI); > - if (GEPI->use_empty()) GEPI->eraseFromParent(); > - } else { > + else { > Instruction *I = cast(U); > SmallVector DbgInUses; > if (!isa(I) && OnlyUsedByDbgInfoIntrinsics(I, &DbgInUses)) { > @@ -1371,7 +1395,7 @@ > > // Compute the offset that this GEP adds to the pointer. > SmallVector Indices(GEP->op_begin()+1, GEP->op_end()); > - uint64_t GEPOffset = TD->getIndexedOffset(GEP->getPointerOperandType(), > + uint64_t GEPOffset = TD->getIndexedOffset(GEP->getOperand(0)->getType(), > &Indices[0], Indices.size()); > // See if all uses can be converted. > if (!CanConvertToScalar(GEP, IsNotTrivial, VecTy, SawVec,Offset+GEPOffset, > @@ -1433,7 +1457,7 @@ > if (GetElementPtrInst *GEP = dyn_cast(User)) { > // Compute the offset that this GEP adds to the pointer. > SmallVector Indices(GEP->op_begin()+1, GEP->op_end()); > - uint64_t GEPOffset = TD->getIndexedOffset(GEP->getPointerOperandType(), > + uint64_t GEPOffset = TD->getIndexedOffset(GEP->getOperand(0)->getType(), > &Indices[0], Indices.size()); > ConvertUsesToScalar(GEP, NewAI, Offset+GEPOffset*8); > GEP->eraseFromParent(); > > Modified: llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll?rev=91268&r1=91267&r2=91268&view=diff > > ============================================================================== > --- llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll (original) > +++ llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll Sun Dec 13 23:11:02 2009 > @@ -1,68 +0,0 @@ > -; RUN: opt < %s -scalarrepl -S | FileCheck %s > -; Radar 7441282 > - > -target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32" > -target triple = "thumbv7-apple-darwin10" > - > -%struct.__neon_int16x8x2_t = type { <8 x i16>, <8 x i16> } > -%struct.int16x8_t = type { <8 x i16> } > -%struct.int16x8x2_t = type { [2 x %struct.int16x8_t] } > -%union..0anon = type { %struct.int16x8x2_t } > - > -define arm_apcscc void @test(<8 x i16> %tmp.0, %struct.int16x8x2_t* %dst) nounwind { > -; CHECK: @test > -; CHECK-NOT: alloca > -; CHECK: "alloca point" > -entry: > - %tmp_addr = alloca %struct.int16x8_t ; <%struct.int16x8_t*> [#uses=3] > - %dst_addr = alloca %struct.int16x8x2_t* ; <%struct.int16x8x2_t**> [#uses=2] > - %__rv = alloca %union..0anon ; <%union..0anon*> [#uses=2] > - %__bx = alloca %struct.int16x8_t ; <%struct.int16x8_t*> [#uses=2] > - %__ax = alloca %struct.int16x8_t ; <%struct.int16x8_t*> [#uses=2] > - %tmp2 = alloca %struct.int16x8x2_t ; <%struct.int16x8x2_t*> [#uses=2] > - %0 = alloca %struct.int16x8x2_t ; <%struct.int16x8x2_t*> [#uses=2] > - %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] > - %1 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] > - store <8 x i16> %tmp.0, <8 x i16>* %1 > - store %struct.int16x8x2_t* %dst, %struct.int16x8x2_t** %dst_addr > - %2 = getelementptr inbounds %struct.int16x8_t* %__ax, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] > - %3 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] > - %4 = load <8 x i16>* %3, align 16 ; <<8 x i16>> [#uses=1] > - store <8 x i16> %4, <8 x i16>* %2, align 16 > - %5 = getelementptr inbounds %struct.int16x8_t* %__bx, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] > - %6 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] > - %7 = load <8 x i16>* %6, align 16 ; <<8 x i16>> [#uses=1] > - store <8 x i16> %7, <8 x i16>* %5, align 16 > - %8 = getelementptr inbounds %struct.int16x8_t* %__ax, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] > - %9 = load <8 x i16>* %8, align 16 ; <<8 x i16>> [#uses=2] > - %10 = getelementptr inbounds %struct.int16x8_t* %__bx, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] > - %11 = load <8 x i16>* %10, align 16 ; <<8 x i16>> [#uses=2] > - %12 = getelementptr inbounds %union..0anon* %__rv, i32 0, i32 0 ; <%struct.int16x8x2_t*> [#uses=1] > - %13 = bitcast %struct.int16x8x2_t* %12 to %struct.__neon_int16x8x2_t* ; <%struct.__neon_int16x8x2_t*> [#uses=2] > - %14 = shufflevector <8 x i16> %9, <8 x i16> %11, <8 x i32> ; <<8 x i16>> [#uses=1] > - %15 = getelementptr inbounds %struct.__neon_int16x8x2_t* %13, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] > - store <8 x i16> %14, <8 x i16>* %15 > - %16 = shufflevector <8 x i16> %9, <8 x i16> %11, <8 x i32> ; <<8 x i16>> [#uses=1] > - %17 = getelementptr inbounds %struct.__neon_int16x8x2_t* %13, i32 0, i32 1 ; <<8 x i16>*> [#uses=1] > - store <8 x i16> %16, <8 x i16>* %17 > - %18 = getelementptr inbounds %union..0anon* %__rv, i32 0, i32 0 ; <%struct.int16x8x2_t*> [#uses=1] > - %19 = bitcast %struct.int16x8x2_t* %0 to i8* ; [#uses=1] > - %20 = bitcast %struct.int16x8x2_t* %18 to i8* ; [#uses=1] > - call void @llvm.memcpy.i32(i8* %19, i8* %20, i32 32, i32 16) > - %tmp21 = bitcast %struct.int16x8x2_t* %tmp2 to i8* ; [#uses=1] > - %21 = bitcast %struct.int16x8x2_t* %0 to i8* ; [#uses=1] > - call void @llvm.memcpy.i32(i8* %tmp21, i8* %21, i32 32, i32 16) > - %22 = load %struct.int16x8x2_t** %dst_addr, align 4 ; <%struct.int16x8x2_t*> [#uses=1] > - %23 = bitcast %struct.int16x8x2_t* %22 to i8* ; [#uses=1] > - %tmp22 = bitcast %struct.int16x8x2_t* %tmp2 to i8* ; [#uses=1] > - call void @llvm.memcpy.i32(i8* %23, i8* %tmp22, i32 32, i32 16) > - br label %return > - > -; CHECK: store <8 x i16> > -; CHECK: store <8 x i16> > - > -return: ; preds = %entry > - ret void > -} > - > -declare void @llvm.memcpy.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20091214/b1afe358/attachment.html From stoklund at 2pi.dk Mon Dec 14 09:48:46 2009 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 14 Dec 2009 07:48:46 -0800 Subject: [llvm-commits] [llvm] r91273 - in /llvm/trunk: include/llvm/CodeGen/CalcSpillWeights.h lib/CodeGen/CalcSpillWeights.cpp lib/CodeGen/PreAllocSplitting.cpp lib/CodeGen/RegAllocLinearScan.cpp lib/CodeGen/RegAllocPBQP.cpp lib/CodeGen/SimpleRegisterCoalescing.cpp lib/CodeGen/SimpleRegisterCoalescing.h In-Reply-To: <200912140649.nBE6ngqC000877@zion.cs.uiuc.edu> References: <200912140649.nBE6ngqC000877@zion.cs.uiuc.edu> Message-ID: <949F384C-AAE3-4C80-959E-1DE703DB7CED@2pi.dk> On Dec 13, 2009, at 10:49 PM, Lang Hames wrote: > Author: lhames > Date: Mon Dec 14 00:49:42 2009 > New Revision: 91273 > > URL: http://llvm.org/viewvc/llvm-project?rev=91273&view=rev > Log: > Moved spill weight calculation out of SimpleRegisterCoalescing and into its own pass: CalculateSpillWeights. Very nice! I was wondering what that method was doing in the coalescer. > ============================================================================== > --- llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h (added) > +++ llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h Mon Dec 14 00:49:42 2009 I think you can do without the header file. Just put a CalculateSpillWeightsID in Passes.h instead. > +/// Returns true if the given live interval is zero length. > +bool CalculateSpillWeights::isZeroLengthInterval(LiveInterval *li) const { Should this be a method on LiveInterval instead? /jakob -------------- next part -------------- A non-text attachment was scrubbed... Name: smime.p7s Type: application/pkcs7-signature Size: 1929 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20091214/b8f1c7e5/attachment.bin From dpatel at apple.com Mon Dec 14 10:18:46 2009 From: dpatel at apple.com (Devang Patel) Date: Mon, 14 Dec 2009 16:18:46 -0000 Subject: [llvm-commits] [llvm] r91278 - in /llvm/trunk/lib/CodeGen/AsmPrinter: DwarfDebug.cpp DwarfDebug.h Message-ID: <200912141618.nBEGIkvN004012@zion.cs.uiuc.edu> Author: dpatel Date: Mon Dec 14 10:18:45 2009 New Revision: 91278 URL: http://llvm.org/viewvc/llvm-project?rev=91278&view=rev Log: Use DW_AT_specification to point to DIE describing function declaration. Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=91278&r1=91277&r2=91278&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Mon Dec 14 10:18:45 2009 @@ -906,7 +906,7 @@ continue; DIE *ElemDie = NULL; if (Element.getTag() == dwarf::DW_TAG_subprogram) - ElemDie = createMemberSubprogramDIE(DISubprogram(Element.getNode())); + ElemDie = createSubprogramDIE(DISubprogram(Element.getNode())); else ElemDie = createMemberDIE(DIDerivedType(Element.getNode())); Buffer.addChild(ElemDie); @@ -1098,11 +1098,13 @@ return MemberDie; } -/// createRawSubprogramDIE - Create new partially incomplete DIE. This is -/// a helper routine used by createMemberSubprogramDIE and -/// createSubprogramDIE. -DIE *DwarfDebug::createRawSubprogramDIE(const DISubprogram &SP) { - DIE *SPDie = new DIE(dwarf::DW_TAG_subprogram); +/// createSubprogramDIE - Create new DIE using SP. +DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) { + DIE *SPDie = ModuleCU->getDIE(SP.getNode()); + if (SPDie) + return SPDie; + + SPDie = new DIE(dwarf::DW_TAG_subprogram); addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName()); StringRef LinkageName = SP.getLinkageName(); @@ -1144,52 +1146,7 @@ ContainingTypeMap.insert(std::make_pair(SPDie, WeakVH(SP.getContainingType().getNode()))); } - return SPDie; -} - -/// createMemberSubprogramDIE - Create new member DIE using SP. This routine -/// always returns a die with DW_AT_declaration attribute. -DIE *DwarfDebug::createMemberSubprogramDIE(const DISubprogram &SP) { - DIE *SPDie = ModuleCU->getDIE(SP.getNode()); - if (!SPDie) - SPDie = createSubprogramDIE(SP); - - // If SPDie has DW_AT_declaration then reuse it. - if (!SP.isDefinition()) - return SPDie; - - // Otherwise create new DIE for the declaration. First push definition - // DIE at the top level. - if (TopLevelDIEs.insert(SPDie)) - TopLevelDIEsVector.push_back(SPDie); - - SPDie = createRawSubprogramDIE(SP); - - // Add arguments. - DICompositeType SPTy = SP.getType(); - DIArray Args = SPTy.getTypeArray(); - unsigned SPTag = SPTy.getTag(); - if (SPTag == dwarf::DW_TAG_subroutine_type) - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - addType(Arg, DIType(Args.getElement(i).getNode())); - addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ?? - SPDie->addChild(Arg); - } - - addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - return SPDie; -} - -/// createSubprogramDIE - Create new DIE using SP. -DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP) { - DIE *SPDie = ModuleCU->getDIE(SP.getNode()); - if (SPDie) - return SPDie; - - SPDie = createRawSubprogramDIE(SP); - - if (!SP.isDefinition()) { + if (MakeDecl || !SP.isDefinition()) { addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); // Add arguments. Do not add arguments for subprogram definition. They will @@ -1310,6 +1267,28 @@ DIE *SPDie = ModuleCU->getDIE(SPNode); assert (SPDie && "Unable to find subprogram DIE!"); + DISubprogram SP(SPNode); + if (SP.isDefinition() && !SP.getContext().isCompileUnit()) { + addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + // Add arguments. + DICompositeType SPTy = SP.getType(); + DIArray Args = SPTy.getTypeArray(); + unsigned SPTag = SPTy.getTag(); + if (SPTag == dwarf::DW_TAG_subroutine_type) + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + addType(Arg, DIType(Args.getElement(i).getNode())); + addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ?? + SPDie->addChild(Arg); + } + DIE *SPDeclDie = SPDie; + SPDie = new DIE(dwarf::DW_TAG_subprogram); + addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, + SPDeclDie); + + ModuleCU->addDie(SPDie); + } + addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, DWLabel("func_begin", SubprogramCount)); addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=91278&r1=91277&r2=91278&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Mon Dec 14 10:18:45 2009 @@ -350,17 +350,7 @@ DIE *createMemberDIE(const DIDerivedType &DT); /// createSubprogramDIE - Create new DIE using SP. - DIE *createSubprogramDIE(const DISubprogram &SP); - - /// createMemberSubprogramDIE - Create new member DIE using SP. This - /// routine always returns a die with DW_AT_declaration attribute. - - DIE *createMemberSubprogramDIE(const DISubprogram &SP); - - /// createRawSubprogramDIE - Create new partially incomplete DIE. This is - /// a helper routine used by createMemberSubprogramDIE and - /// createSubprogramDIE. - DIE *createRawSubprogramDIE(const DISubprogram &SP); + DIE *createSubprogramDIE(const DISubprogram &SP, bool MakeDecl = false); /// findCompileUnit - Get the compile unit for the given descriptor. /// From gohman at apple.com Mon Dec 14 10:37:30 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 16:37:30 -0000 Subject: [llvm-commits] [llvm] r91280 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200912141637.nBEGbU2I004678@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 10:37:29 2009 New Revision: 91280 URL: http://llvm.org/viewvc/llvm-project?rev=91280&view=rev Log: Minor code cleanups. Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=91280&r1=91279&r2=91280&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Dec 14 10:37:29 2009 @@ -228,19 +228,17 @@ if (DeadInsts.empty()) return; while (!DeadInsts.empty()) { - Instruction *I = dyn_cast_or_null(DeadInsts.back()); - DeadInsts.pop_back(); + Instruction *I = dyn_cast_or_null(DeadInsts.pop_back_val()); if (I == 0 || !isInstructionTriviallyDead(I)) continue; - for (User::op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) { + for (User::op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) if (Instruction *U = dyn_cast(*OI)) { *OI = 0; if (U->use_empty()) DeadInsts.push_back(U); } - } I->eraseFromParent(); Changed = true; From gohman at apple.com Mon Dec 14 10:52:55 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 16:52:55 -0000 Subject: [llvm-commits] [llvm] r91281 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200912141652.nBEGqtEZ005267@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 10:52:55 2009 New Revision: 91281 URL: http://llvm.org/viewvc/llvm-project?rev=91281&view=rev Log: Remove the code in LSR that manually hoists expansions out of loops; SCEVExpander does this automatically. Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=91281&r1=91280&r2=91281&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Dec 14 10:52:55 2009 @@ -109,8 +109,7 @@ public: static char ID; // Pass ID, replacement for typeid explicit LoopStrengthReduce(const TargetLowering *tli = NULL) : - LoopPass(&ID), TLI(tli) { - } + LoopPass(&ID), TLI(tli) {} bool runOnLoop(Loop *L, LPPassManager &LPM); @@ -381,14 +380,12 @@ void RewriteInstructionToUseNewBase(const SCEV *const &NewBase, Instruction *InsertPt, SCEVExpander &Rewriter, Loop *L, Pass *P, - LoopInfo &LI, SmallVectorImpl &DeadInsts); Value *InsertCodeForBaseAtPosition(const SCEV *const &NewBase, const Type *Ty, SCEVExpander &Rewriter, - Instruction *IP, Loop *L, - LoopInfo &LI); + Instruction *IP); void dump() const; }; } @@ -402,27 +399,11 @@ Value *BasedUser::InsertCodeForBaseAtPosition(const SCEV *const &NewBase, const Type *Ty, SCEVExpander &Rewriter, - Instruction *IP, Loop *L, - LoopInfo &LI) { - // Figure out where we *really* want to insert this code. In particular, if - // the user is inside of a loop that is nested inside of L, we really don't - // want to insert this expression before the user, we'd rather pull it out as - // many loops as possible. - Instruction *BaseInsertPt = IP; - - // Figure out the most-nested loop that IP is in. - Loop *InsertLoop = LI.getLoopFor(IP->getParent()); - - // If InsertLoop is not L, and InsertLoop is nested inside of L, figure out - // the preheader of the outer-most loop where NewBase is not loop invariant. - if (L->contains(IP->getParent())) - while (InsertLoop && NewBase->isLoopInvariant(InsertLoop)) { - BaseInsertPt = InsertLoop->getLoopPreheader()->getTerminator(); - InsertLoop = InsertLoop->getParentLoop(); - } - - Value *Base = Rewriter.expandCodeFor(NewBase, 0, BaseInsertPt); + Instruction *IP) { + Value *Base = Rewriter.expandCodeFor(NewBase, 0, IP); + // Wrap the base in a SCEVUnknown so that ScalarEvolution doesn't try to + // re-analyze it. const SCEV *NewValSCEV = SE->getUnknown(Base); // Always emit the immediate into the same block as the user. @@ -441,7 +422,6 @@ void BasedUser::RewriteInstructionToUseNewBase(const SCEV *const &NewBase, Instruction *NewBasePt, SCEVExpander &Rewriter, Loop *L, Pass *P, - LoopInfo &LI, SmallVectorImpl &DeadInsts) { if (!isa(Inst)) { // By default, insert code at the user instruction. @@ -471,7 +451,7 @@ } Value *NewVal = InsertCodeForBaseAtPosition(NewBase, OperandValToReplace->getType(), - Rewriter, InsertPt, L, LI); + Rewriter, InsertPt); // Replace the use of the operand Value with the new Phi we just created. Inst->replaceUsesOfWith(OperandValToReplace, NewVal); @@ -533,7 +513,7 @@ PHIPred->getTerminator() : OldLoc->getParent()->getTerminator(); Code = InsertCodeForBaseAtPosition(NewBase, PN->getType(), - Rewriter, InsertPt, L, LI); + Rewriter, InsertPt); DEBUG(errs() << " Changing PHI use to "); DEBUG(WriteAsOperand(errs(), Code, /*PrintType=*/false)); @@ -1778,7 +1758,7 @@ RewriteExpr = SE->getAddExpr(RewriteExpr, SE->getUnknown(BaseV)); User.RewriteInstructionToUseNewBase(RewriteExpr, NewBasePt, - Rewriter, L, this, *LI, + Rewriter, L, this, DeadInsts); // Mark old value we replaced as possibly dead, so that it is eliminated From gohman at apple.com Mon Dec 14 10:57:08 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 16:57:08 -0000 Subject: [llvm-commits] [llvm] r91282 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200912141657.nBEGv8lj005396@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 10:57:08 2009 New Revision: 91282 URL: http://llvm.org/viewvc/llvm-project?rev=91282&view=rev Log: LSR itself doesn't need DominatorTree. Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=91282&r1=91281&r2=91282&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Dec 14 10:57:08 2009 @@ -26,7 +26,6 @@ #include "llvm/IntrinsicInst.h" #include "llvm/Type.h" #include "llvm/DerivedTypes.h" -#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/IVUsers.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" @@ -86,7 +85,6 @@ class LoopStrengthReduce : public LoopPass { IVUsers *IU; LoopInfo *LI; - DominatorTree *DT; ScalarEvolution *SE; bool Changed; @@ -118,12 +116,11 @@ // many analyses if they are around. AU.addPreservedID(LoopSimplifyID); AU.addPreserved(); - AU.addPreserved(); - AU.addPreserved(); + AU.addPreserved("domfrontier"); + AU.addPreserved("domtree"); AU.addRequiredID(LoopSimplifyID); AU.addRequired(); - AU.addRequired(); AU.addRequired(); AU.addPreserved(); AU.addRequired(); @@ -2724,7 +2721,6 @@ bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager &LPM) { IU = &getAnalysis(); LI = &getAnalysis(); - DT = &getAnalysis(); SE = &getAnalysis(); Changed = false; From gohman at apple.com Mon Dec 14 11:02:34 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 17:02:34 -0000 Subject: [llvm-commits] [llvm] r91283 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200912141702.nBEH2YDB005622@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 11:02:34 2009 New Revision: 91283 URL: http://llvm.org/viewvc/llvm-project?rev=91283&view=rev Log: LSR itself doesn't need LoopInfo. Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=91283&r1=91282&r2=91283&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Dec 14 11:02:34 2009 @@ -27,7 +27,6 @@ #include "llvm/Type.h" #include "llvm/DerivedTypes.h" #include "llvm/Analysis/IVUsers.h" -#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/ScalarEvolutionExpander.h" #include "llvm/Transforms/Utils/AddrModeMatcher.h" @@ -84,7 +83,6 @@ class LoopStrengthReduce : public LoopPass { IVUsers *IU; - LoopInfo *LI; ScalarEvolution *SE; bool Changed; @@ -115,12 +113,11 @@ // We split critical edges, so we change the CFG. However, we do update // many analyses if they are around. AU.addPreservedID(LoopSimplifyID); - AU.addPreserved(); + AU.addPreserved("loops"); AU.addPreserved("domfrontier"); AU.addPreserved("domtree"); AU.addRequiredID(LoopSimplifyID); - AU.addRequired(); AU.addRequired(); AU.addPreserved(); AU.addRequired(); @@ -259,7 +256,7 @@ if (newLoop == L) return false; // if newLoop is an outer loop of L, this is OK. - if (!LoopInfo::isNotAlreadyContainedIn(L, newLoop)) + if (!newLoop->contains(L->getHeader())) return false; } return true; @@ -2720,7 +2717,6 @@ bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager &LPM) { IU = &getAnalysis(); - LI = &getAnalysis(); SE = &getAnalysis(); Changed = false; From grosbach at apple.com Mon Dec 14 11:02:56 2009 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 14 Dec 2009 17:02:56 -0000 Subject: [llvm-commits] [llvm] r91284 - /llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Message-ID: <200912141702.nBEH2uSv005645@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 11:02:55 2009 New Revision: 91284 URL: http://llvm.org/viewvc/llvm-project?rev=91284&view=rev Log: add ldrexd/strexd instructions Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=91284&r1=91283&r2=91284&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Dec 14 11:02:55 2009 @@ -1710,11 +1710,15 @@ def LDREX : AIldrex<0b00, (outs GPR:$dest), (ins GPR:$ptr), NoItinerary, "ldrex", "\t$dest, [$ptr]", []>; +def LDREXD : AIldrex<0b00, (outs GPR:$dest, GPR:$dest2), (ins GPR:$ptr), + NoItinerary, + "ldrexd", "\t$dest, $dest2, [$ptr]", + []>; } let mayStore = 1 in { def STREXB : AIstrex<0b10, (outs GPR:$success), (ins GPR:$src, GPR:$ptr), - NoItinerary, + NoItinerary, "strexb", "\t$success, $src, [$ptr]", []>; def STREXH : AIstrex<0b11, (outs GPR:$success), (ins GPR:$src, GPR:$ptr), @@ -1722,9 +1726,14 @@ "strexh", "\t$success, $src, [$ptr]", []>; def STREX : AIstrex<0b00, (outs GPR:$success), (ins GPR:$src, GPR:$ptr), - NoItinerary, + NoItinerary, "strex", "\t$success, $src, [$ptr]", []>; +def STREXD : AIstrex<0b00, (outs GPR:$success), + (ins GPR:$src, GPR:$src2, GPR:$ptr), + NoItinerary, + "strexd", "\t$success, $src, $src2, [$ptr]", + []>; } //===----------------------------------------------------------------------===// From gohman at apple.com Mon Dec 14 11:06:50 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 17:06:50 -0000 Subject: [llvm-commits] [llvm] r91286 - in /llvm/trunk: include/llvm/Analysis/LoopInfo.h lib/Analysis/IVUsers.cpp Message-ID: <200912141706.nBEH6oLg005799@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 11:06:50 2009 New Revision: 91286 URL: http://llvm.org/viewvc/llvm-project?rev=91286&view=rev Log: Drop Loop::isNotAlreadyContainedIn in favor of Loop::contains. The former was just exposing a LoopInfoBase implementation detail. Modified: llvm/trunk/include/llvm/Analysis/LoopInfo.h llvm/trunk/lib/Analysis/IVUsers.cpp Modified: llvm/trunk/include/llvm/Analysis/LoopInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopInfo.h?rev=91286&r1=91285&r2=91286&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/LoopInfo.h (original) +++ llvm/trunk/include/llvm/Analysis/LoopInfo.h Mon Dec 14 11:06:50 2009 @@ -976,13 +976,6 @@ void removeBlock(BasicBlock *BB) { LI.removeBlock(BB); } - - static bool isNotAlreadyContainedIn(const Loop *SubLoop, - const Loop *ParentLoop) { - return - LoopInfoBase::isNotAlreadyContainedIn(SubLoop, - ParentLoop); - } }; Modified: llvm/trunk/lib/Analysis/IVUsers.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/IVUsers.cpp?rev=91286&r1=91285&r2=91286&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/IVUsers.cpp (original) +++ llvm/trunk/lib/Analysis/IVUsers.cpp Mon Dec 14 11:06:50 2009 @@ -53,7 +53,7 @@ if (newLoop == L) return false; // if newLoop is an outer loop of L, this is OK. - if (!LoopInfo::isNotAlreadyContainedIn(L, newLoop)) + if (!newLoop->contains(L->getHeader())) return false; } return true; From gohman at apple.com Mon Dec 14 11:08:09 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 17:08:09 -0000 Subject: [llvm-commits] [llvm] r91287 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200912141708.nBEH89Yh005869@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 11:08:09 2009 New Revision: 91287 URL: http://llvm.org/viewvc/llvm-project?rev=91287&view=rev Log: Delete an unused variable. Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=91287&r1=91286&r2=91287&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Dec 14 11:08:09 2009 @@ -90,10 +90,6 @@ /// particular stride. std::map IVsByStride; - /// StrideNoReuse - Keep track of all the strides whose ivs cannot be - /// reused (nor should they be rewritten to reuse other strides). - SmallSet StrideNoReuse; - /// DeadInsts - Keep track of instructions we may have made dead, so that /// we can remove them after we are done working. SmallVector DeadInsts; @@ -983,17 +979,13 @@ const SCEV *const &Stride, IVExpr &IV, const Type *Ty, const std::vector& UsersToProcess) { - if (StrideNoReuse.count(Stride)) - return SE->getIntegerSCEV(0, Stride->getType()); - if (const SCEVConstant *SC = dyn_cast(Stride)) { int64_t SInt = SC->getValue()->getSExtValue(); for (unsigned NewStride = 0, e = IU->StrideOrder.size(); NewStride != e; ++NewStride) { std::map::iterator SI = IVsByStride.find(IU->StrideOrder[NewStride]); - if (SI == IVsByStride.end() || !isa(SI->first) || - StrideNoReuse.count(SI->first)) + if (SI == IVsByStride.end() || !isa(SI->first)) continue; // The other stride has no uses, don't reuse it. std::map::iterator UI = @@ -2766,7 +2758,6 @@ // We're done analyzing this loop; release all the state we built up for it. IVsByStride.clear(); - StrideNoReuse.clear(); // Clean up after ourselves if (!DeadInsts.empty()) From gohman at apple.com Mon Dec 14 11:10:45 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 17:10:45 -0000 Subject: [llvm-commits] [llvm] r91288 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200912141710.nBEHAjtL006068@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 11:10:44 2009 New Revision: 91288 URL: http://llvm.org/viewvc/llvm-project?rev=91288&view=rev Log: Don't bother cleaning up if there's nothing to clean up. Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=91288&r1=91287&r2=91288&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Dec 14 11:10:44 2009 @@ -2754,14 +2754,14 @@ // After all sharing is done, see if we can adjust the loop to test against // zero instead of counting up to a maximum. This is usually faster. OptimizeLoopCountIV(L); - } - // We're done analyzing this loop; release all the state we built up for it. - IVsByStride.clear(); + // We're done analyzing this loop; release all the state we built up for it. + IVsByStride.clear(); - // Clean up after ourselves - if (!DeadInsts.empty()) - DeleteTriviallyDeadInstructions(); + // Clean up after ourselves + if (!DeadInsts.empty()) + DeleteTriviallyDeadInstructions(); + } // At this point, it is worth checking to see if any recurrence PHIs are also // dead, so that we can remove them as well. From gohman at apple.com Mon Dec 14 11:12:51 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 17:12:51 -0000 Subject: [llvm-commits] [llvm] r91289 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200912141712.nBEHCpDj006196@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 11:12:51 2009 New Revision: 91289 URL: http://llvm.org/viewvc/llvm-project?rev=91289&view=rev Log: Instead of having a ScalarEvolution pointer member in BasedUser, just pass the ScalarEvolution pointer into the functions which need it. Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=91289&r1=91288&r2=91289&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Dec 14 11:12:51 2009 @@ -325,9 +325,6 @@ /// BasedUser - For a particular base value, keep information about how we've /// partitioned the expression so far. struct BasedUser { - /// SE - The current ScalarEvolution object. - ScalarEvolution *SE; - /// Base - The Base value for the PHI node that needs to be inserted for /// this use. As the use is processed, information gets moved from this /// field to the Imm field (below). BasedUser values are sorted by this @@ -359,9 +356,9 @@ bool isUseOfPostIncrementedValue; BasedUser(IVStrideUse &IVSU, ScalarEvolution *se) - : SE(se), Base(IVSU.getOffset()), Inst(IVSU.getUser()), + : Base(IVSU.getOffset()), Inst(IVSU.getUser()), OperandValToReplace(IVSU.getOperandValToReplace()), - Imm(SE->getIntegerSCEV(0, Base->getType())), + Imm(se->getIntegerSCEV(0, Base->getType())), isUseOfPostIncrementedValue(IVSU.isUseOfPostIncrementedValue()) {} // Once we rewrite the code to insert the new IVs we want, update the @@ -370,12 +367,14 @@ void RewriteInstructionToUseNewBase(const SCEV *const &NewBase, Instruction *InsertPt, SCEVExpander &Rewriter, Loop *L, Pass *P, - SmallVectorImpl &DeadInsts); + SmallVectorImpl &DeadInsts, + ScalarEvolution *SE); Value *InsertCodeForBaseAtPosition(const SCEV *const &NewBase, const Type *Ty, SCEVExpander &Rewriter, - Instruction *IP); + Instruction *IP, + ScalarEvolution *SE); void dump() const; }; } @@ -389,7 +388,8 @@ Value *BasedUser::InsertCodeForBaseAtPosition(const SCEV *const &NewBase, const Type *Ty, SCEVExpander &Rewriter, - Instruction *IP) { + Instruction *IP, + ScalarEvolution *SE) { Value *Base = Rewriter.expandCodeFor(NewBase, 0, IP); // Wrap the base in a SCEVUnknown so that ScalarEvolution doesn't try to @@ -412,7 +412,8 @@ void BasedUser::RewriteInstructionToUseNewBase(const SCEV *const &NewBase, Instruction *NewBasePt, SCEVExpander &Rewriter, Loop *L, Pass *P, - SmallVectorImpl &DeadInsts) { + SmallVectorImpl &DeadInsts, + ScalarEvolution *SE) { if (!isa(Inst)) { // By default, insert code at the user instruction. BasicBlock::iterator InsertPt = Inst; @@ -441,7 +442,7 @@ } Value *NewVal = InsertCodeForBaseAtPosition(NewBase, OperandValToReplace->getType(), - Rewriter, InsertPt); + Rewriter, InsertPt, SE); // Replace the use of the operand Value with the new Phi we just created. Inst->replaceUsesOfWith(OperandValToReplace, NewVal); @@ -503,7 +504,7 @@ PHIPred->getTerminator() : OldLoc->getParent()->getTerminator(); Code = InsertCodeForBaseAtPosition(NewBase, PN->getType(), - Rewriter, InsertPt); + Rewriter, InsertPt, SE); DEBUG(errs() << " Changing PHI use to "); DEBUG(WriteAsOperand(errs(), Code, /*PrintType=*/false)); @@ -1745,7 +1746,7 @@ User.RewriteInstructionToUseNewBase(RewriteExpr, NewBasePt, Rewriter, L, this, - DeadInsts); + DeadInsts, SE); // Mark old value we replaced as possibly dead, so that it is eliminated // if we just replaced the last use of that value. From gohman at apple.com Mon Dec 14 11:14:32 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 17:14:32 -0000 Subject: [llvm-commits] [llvm] r91291 - /llvm/trunk/include/llvm/Analysis/IVUsers.h Message-ID: <200912141714.nBEHEWEZ006374@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 11:14:32 2009 New Revision: 91291 URL: http://llvm.org/viewvc/llvm-project?rev=91291&view=rev Log: Make the IVUses member private. Modified: llvm/trunk/include/llvm/Analysis/IVUsers.h Modified: llvm/trunk/include/llvm/Analysis/IVUsers.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/IVUsers.h?rev=91291&r1=91290&r2=91291&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/IVUsers.h (original) +++ llvm/trunk/include/llvm/Analysis/IVUsers.h Mon Dec 14 11:14:32 2009 @@ -175,11 +175,11 @@ ScalarEvolution *SE; SmallPtrSet Processed; -public: /// IVUses - A list of all tracked IV uses of induction variable expressions /// we are interested in. ilist IVUses; +public: /// IVUsesByStride - A mapping from the strides in StrideOrder to the /// uses in IVUses. std::map IVUsesByStride; From gohman at apple.com Mon Dec 14 11:19:06 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 17:19:06 -0000 Subject: [llvm-commits] [llvm] r91293 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200912141719.nBEHJ690006551@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 11:19:06 2009 New Revision: 91293 URL: http://llvm.org/viewvc/llvm-project?rev=91293&view=rev Log: Remove unnecessary #includes. Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=91293&r1=91292&r2=91293&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Dec 14 11:19:06 2009 @@ -24,7 +24,6 @@ #include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" -#include "llvm/Type.h" #include "llvm/DerivedTypes.h" #include "llvm/Analysis/IVUsers.h" #include "llvm/Analysis/LoopPass.h" @@ -33,7 +32,6 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Support/CFG.h" #include "llvm/Support/Debug.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ValueHandle.h" From gohman at apple.com Mon Dec 14 11:31:01 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 17:31:01 -0000 Subject: [llvm-commits] [llvm] r91295 - in /llvm/trunk/lib: Analysis/IVUsers.cpp Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200912141731.nBEHV2Z7006982@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 11:31:01 2009 New Revision: 91295 URL: http://llvm.org/viewvc/llvm-project?rev=91295&view=rev Log: Fix a thinko; isNotAlreadyContainedIn had a built-in negative, so the condition was inverted when the code was converted to contains(). Modified: llvm/trunk/lib/Analysis/IVUsers.cpp llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Analysis/IVUsers.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/IVUsers.cpp?rev=91295&r1=91294&r2=91295&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/IVUsers.cpp (original) +++ llvm/trunk/lib/Analysis/IVUsers.cpp Mon Dec 14 11:31:01 2009 @@ -53,7 +53,7 @@ if (newLoop == L) return false; // if newLoop is an outer loop of L, this is OK. - if (!newLoop->contains(L->getHeader())) + if (newLoop->contains(L->getHeader())) return false; } return true; Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=91295&r1=91294&r2=91295&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon Dec 14 11:31:01 2009 @@ -250,7 +250,7 @@ if (newLoop == L) return false; // if newLoop is an outer loop of L, this is OK. - if (!newLoop->contains(L->getHeader())) + if (newLoop->contains(L->getHeader())) return false; } return true; From gohman at apple.com Mon Dec 14 11:35:17 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 17:35:17 -0000 Subject: [llvm-commits] [llvm] r91296 - /llvm/trunk/lib/Analysis/IVUsers.cpp Message-ID: <200912141735.nBEHZHW2007105@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 11:35:17 2009 New Revision: 91296 URL: http://llvm.org/viewvc/llvm-project?rev=91296&view=rev Log: Clear the Processed set when it is no longer used, and clear the IVUses list in releaseMemory(). Modified: llvm/trunk/lib/Analysis/IVUsers.cpp Modified: llvm/trunk/lib/Analysis/IVUsers.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/IVUsers.cpp?rev=91296&r1=91295&r2=91296&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/IVUsers.cpp (original) +++ llvm/trunk/lib/Analysis/IVUsers.cpp Mon Dec 14 11:35:17 2009 @@ -307,6 +307,7 @@ for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) AddUsersIfInteresting(I); + Processed.clear(); return false; } @@ -369,7 +370,7 @@ void IVUsers::releaseMemory() { IVUsesByStride.clear(); StrideOrder.clear(); - Processed.clear(); + IVUses.clear(); } void IVStrideUse::deleted() { From clattner at apple.com Mon Dec 14 11:47:37 2009 From: clattner at apple.com (Chris Lattner) Date: Mon, 14 Dec 2009 09:47:37 -0800 Subject: [llvm-commits] [llvm] r91277 - /llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll In-Reply-To: <200912141415.nBEEFFpr031877@zion.cs.uiuc.edu> References: <200912141415.nBEEFFpr031877@zion.cs.uiuc.edu> Message-ID: Doh, thanks Shantonu! -Chris On Dec 14, 2009, at 6:15 AM, Shantonu Sen wrote: > Author: ssen > Date: Mon Dec 14 08:15:15 2009 > New Revision: 91277 > > URL: http://llvm.org/viewvc/llvm-project?rev=91277&view=rev > Log: > Remove empty file completely > > Removed: > llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll > > Removed: llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll?rev=91276&view=auto > > = > = > = > = > = > = > = > = > ====================================================================== > (empty) > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From daniel at zuster.org Mon Dec 14 11:58:27 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Mon, 14 Dec 2009 17:58:27 -0000 Subject: [llvm-commits] [llvm] r91301 - /llvm/trunk/utils/NewNightlyTest.pl Message-ID: <200912141758.nBEHwSG2008318@zion.cs.uiuc.edu> Author: ddunbar Date: Mon Dec 14 11:58:27 2009 New Revision: 91301 URL: http://llvm.org/viewvc/llvm-project?rev=91301&view=rev Log: NNT: Always create the -sentdata.txt file. Modified: llvm/trunk/utils/NewNightlyTest.pl Modified: llvm/trunk/utils/NewNightlyTest.pl URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/NewNightlyTest.pl?rev=91301&r1=91300&r2=91301&view=diff ============================================================================== --- llvm/trunk/utils/NewNightlyTest.pl (original) +++ llvm/trunk/utils/NewNightlyTest.pl Mon Dec 14 11:58:27 2009 @@ -393,10 +393,8 @@ # to our central server via the post method # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -sub SendData { - $host = $_[0]; - $file = $_[1]; - $variables = $_[2]; +sub WriteSentData { + $variables = $_[0]; # Write out the "...-sentdata.txt" file. @@ -406,6 +404,12 @@ $sentdata.= "$x => $value\n"; } WriteFile "$Prefix-sentdata.txt", $sentdata; +} + +sub SendData { + $host = $_[0]; + $file = $_[1]; + $variables = $_[2]; if (!($SUBMITAUX eq "")) { system "$SUBMITAUX \"$Prefix-sentdata.txt\""; @@ -797,6 +801,9 @@ 'a_file_sizes' => "" ); +# Write out the "...-sentdata.txt" file. +WriteSentData \%hash_of_data; + if ($SUBMIT || !($SUBMITAUX eq "")) { my $response = SendData $SUBMITSERVER,$SUBMITSCRIPT,\%hash_of_data; if( $VERBOSE) { print "============================\n$response"; } From daniel at zuster.org Mon Dec 14 11:58:33 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Mon, 14 Dec 2009 17:58:33 -0000 Subject: [llvm-commits] [llvm] r91302 - /llvm/trunk/utils/NewNightlyTest.pl Message-ID: <200912141758.nBEHwXvQ008332@zion.cs.uiuc.edu> Author: ddunbar Date: Mon Dec 14 11:58:33 2009 New Revision: 91302 URL: http://llvm.org/viewvc/llvm-project?rev=91302&view=rev Log: NNT: Use [e]grep -a when scanning logs, its possibly they will have non-text characters in them, in which case the grep will just return 'Binary file matches' and the whole thing falls over. Modified: llvm/trunk/utils/NewNightlyTest.pl Modified: llvm/trunk/utils/NewNightlyTest.pl URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/NewNightlyTest.pl?rev=91302&r1=91301&r2=91302&view=diff ============================================================================== --- llvm/trunk/utils/NewNightlyTest.pl (original) +++ llvm/trunk/utils/NewNightlyTest.pl Mon Dec 14 11:58:33 2009 @@ -507,8 +507,8 @@ } RunAppendingLoggedCommand("(time -p $NICE $MAKECMD $MAKEOPTS)", $BuildLog, "BUILD"); - if (`grep '^$MAKECMD\[^:]*: .*Error' $BuildLog | wc -l` + 0 || - `grep '^$MAKECMD: \*\*\*.*Stop.' $BuildLog | wc -l` + 0) { + if (`grep -a '^$MAKECMD\[^:]*: .*Error' $BuildLog | wc -l` + 0 || + `grep -a '^$MAKECMD: \*\*\*.*Stop.' $BuildLog | wc -l` + 0) { return 0; } @@ -535,15 +535,15 @@ $LLCBetaOpts = `$MAKECMD print-llcbeta-option`; my $ProgramsTable; - if (`grep '^$MAKECMD\[^:]: .*Error' $ProgramTestLog | wc -l` + 0) { + if (`grep -a '^$MAKECMD\[^:]: .*Error' $ProgramTestLog | wc -l` + 0) { $ProgramsTable="Error running test $SubDir\n"; print "ERROR TESTING\n"; - } elsif (`grep '^$MAKECMD\[^:]: .*No rule to make target' $ProgramTestLog | wc -l` + 0) { + } elsif (`grep -a '^$MAKECMD\[^:]: .*No rule to make target' $ProgramTestLog | wc -l` + 0) { $ProgramsTable="Makefile error running tests $SubDir!\n"; print "ERROR TESTING\n"; } else { # Create a list of the tests which were run... - system "egrep 'TEST-(PASS|FAIL)' < $ProgramTestLog ". + system "egrep -a 'TEST-(PASS|FAIL)' < $ProgramTestLog ". "| sort > $Prefix-$SubDir-Tests.txt"; } $ProgramsTable = ReadFile "report.nightly.csv"; From grosbach at apple.com Mon Dec 14 12:31:20 2009 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 14 Dec 2009 18:31:20 -0000 Subject: [llvm-commits] [llvm] r91305 - in /llvm/trunk/lib/Target/ARM: ARMInstrFormats.td ARMInstrInfo.td Message-ID: <200912141831.nBEIVKq2009591@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 12:31:20 2009 New Revision: 91305 URL: http://llvm.org/viewvc/llvm-project?rev=91305&view=rev Log: ARM memory barrier instructions are not predicable Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=91305&r1=91304&r2=91305&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Mon Dec 14 12:31:20 2009 @@ -201,6 +201,19 @@ let Pattern = pattern; list Predicates = [IsARM]; } +// A few are not predicable +class InoP pattern> + : InstARM { + let OutOperandList = oops; + let InOperandList = iops; + let AsmString = !strconcat(opc, asm); + let Pattern = pattern; + let isPredicable = 0; + list Predicates = [IsARM]; +} // Same as I except it can optionally modify CPSR. Note it's modeled as // an input operand since by default it's a zero register. It will @@ -241,6 +254,10 @@ string asm, list pattern> : XI; +class AInoP pattern> + : InoP; // Ctrl flow instructions class ABI opcod, dag oops, dag iops, InstrItinClass itin, Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=91305&r1=91304&r2=91305&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Dec 14 12:31:20 2009 @@ -1574,8 +1574,8 @@ // // memory barriers protect the atomic sequences -let isPredicable = 0, hasSideEffects = 1 in { -def Int_MemBarrierV7 : AI<(outs), (ins), +let hasSideEffects = 1 in { +def Int_MemBarrierV7 : AInoP<(outs), (ins), Pseudo, NoItinerary, "dmb", "", [(ARMMemBarrier)]>, @@ -1585,7 +1585,7 @@ let Inst{3-0} = 0b1111; } -def Int_SyncBarrierV7 : AI<(outs), (ins), +def Int_SyncBarrierV7 : AInoP<(outs), (ins), Pseudo, NoItinerary, "dsb", "", [(ARMSyncBarrier)]>, From grosbach at apple.com Mon Dec 14 12:36:32 2009 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 14 Dec 2009 18:36:32 -0000 Subject: [llvm-commits] [llvm] r91307 - /llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Message-ID: <200912141836.nBEIaX8E009855@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 12:36:32 2009 New Revision: 91307 URL: http://llvm.org/viewvc/llvm-project?rev=91307&view=rev Log: whitespace Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=91307&r1=91306&r2=91307&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Dec 14 12:36:32 2009 @@ -1684,7 +1684,6 @@ "${:comment} ATOMIC_SWAP_I32 PSEUDO!", [(set GPR:$dst, (atomic_swap_32 GPR:$ptr, GPR:$new))]>; - def ATOMIC_CMP_SWAP_I8 : PseudoInst< (outs GPR:$dst), (ins GPR:$ptr, GPR:$old, GPR:$new), NoItinerary, "${:comment} ATOMIC_CMP_SWAP_I8 PSEUDO!", From grosbach at apple.com Mon Dec 14 12:56:48 2009 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 14 Dec 2009 18:56:48 -0000 Subject: [llvm-commits] [llvm] r91310 - /llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Message-ID: <200912141856.nBEIumWl010790@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 12:56:47 2009 New Revision: 91310 URL: http://llvm.org/viewvc/llvm-project?rev=91310&view=rev Log: add Thumb2 atomic and memory barrier instruction definitions Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=91310&r1=91309&r2=91310&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Mon Dec 14 12:56:47 2009 @@ -1065,6 +1065,66 @@ RegConstraint<"$false = $dst">; //===----------------------------------------------------------------------===// +// Atomic operations intrinsics +// + +// memory barriers protect the atomic sequences +let hasSideEffects = 1 in { +def t2Int_MemBarrierV7 : AInoP<(outs), (ins), + Pseudo, NoItinerary, + "dmb", "", + [(ARMMemBarrier)]> { + // FIXME: add support for options other than a full system DMB +} + +def t2Int_SyncBarrierV7 : AInoP<(outs), (ins), + Pseudo, NoItinerary, + "dsb", "", + [(ARMSyncBarrier)]> { + // FIXME: add support for options other than a full system DSB +} +} + +let mayLoad = 1 in { +def t2LDREXB : Thumb2I<(outs GPR:$dest), (ins GPR:$ptr), AddrModeNone, + Size4Bytes, NoItinerary, + "ldrexb", "\t$dest, [$ptr]", "", + []>; +def t2LDREXH : Thumb2I<(outs GPR:$dest), (ins GPR:$ptr), AddrModeNone, + Size4Bytes, NoItinerary, + "ldrexh", "\t$dest, [$ptr]", "", + []>; +def t2LDREX : Thumb2I<(outs GPR:$dest), (ins GPR:$ptr), AddrModeNone, + Size4Bytes, NoItinerary, + "ldrex", "\t$dest, [$ptr]", "", + []>; +def t2LDREXD : Thumb2I<(outs GPR:$dest, GPR:$dest2), (ins GPR:$ptr), + AddrModeNone, Size4Bytes, NoItinerary, + "ldrexd", "\t$dest, $dest2, [$ptr]", "", + []>; +} + +let mayStore = 1 in { +def t2STREXB : Thumb2I<(outs GPR:$success), (ins GPR:$src, GPR:$ptr), + AddrModeNone, Size4Bytes, NoItinerary, + "strexb", "\t$success, $src, [$ptr]", "", + []>; +def t2STREXH : Thumb2I<(outs GPR:$success), (ins GPR:$src, GPR:$ptr), + AddrModeNone, Size4Bytes, NoItinerary, + "strexh", "\t$success, $src, [$ptr]", "", + []>; +def t2STREX : Thumb2I<(outs GPR:$success), (ins GPR:$src, GPR:$ptr), + AddrModeNone, Size4Bytes, NoItinerary, + "strex", "\t$success, $src, [$ptr]", "", + []>; +def t2STREXD : Thumb2I<(outs GPR:$success), + (ins GPR:$src, GPR:$src2, GPR:$ptr), + AddrModeNone, Size4Bytes, NoItinerary, + "strexd", "\t$success, $src, $src2, [$ptr]", "", + []>; +} + +//===----------------------------------------------------------------------===// // TLS Instructions // From echristo at apple.com Mon Dec 14 13:07:26 2009 From: echristo at apple.com (Eric Christopher) Date: Mon, 14 Dec 2009 19:07:26 -0000 Subject: [llvm-commits] [llvm] r91312 - /llvm/trunk/test/Transforms/LICM/2009-12-10-LICM-Indbr-Crash.ll Message-ID: <200912141907.nBEJ7QpA011270@zion.cs.uiuc.edu> Author: echristo Date: Mon Dec 14 13:07:25 2009 New Revision: 91312 URL: http://llvm.org/viewvc/llvm-project?rev=91312&view=rev Log: Add radar fixed in comment. Modified: llvm/trunk/test/Transforms/LICM/2009-12-10-LICM-Indbr-Crash.ll Modified: llvm/trunk/test/Transforms/LICM/2009-12-10-LICM-Indbr-Crash.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/2009-12-10-LICM-Indbr-Crash.ll?rev=91312&r1=91311&r2=91312&view=diff ============================================================================== --- llvm/trunk/test/Transforms/LICM/2009-12-10-LICM-Indbr-Crash.ll (original) +++ llvm/trunk/test/Transforms/LICM/2009-12-10-LICM-Indbr-Crash.ll Mon Dec 14 13:07:25 2009 @@ -1,20 +1,21 @@ +; Test for rdar://7452967 ; RUN: opt < %s -licm -disable-output define void @foo (i8* %v) { entry: br i1 undef, label %preheader, label %return - + preheader: br i1 undef, label %loop, label %return - + loop: indirectbr i8* undef, [label %preheader, label %stuff] - + stuff: %0 = load i8* undef, align 1 br label %loop - + return: ret void -} \ No newline at end of file +} From grosbach at apple.com Mon Dec 14 13:24:11 2009 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 14 Dec 2009 19:24:11 -0000 Subject: [llvm-commits] [llvm] r91313 - in /llvm/trunk/lib/Target/ARM: ARMInstrInfo.td ARMInstrThumb2.td Message-ID: <200912141924.nBEJOBNQ012144@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 13:24:11 2009 New Revision: 91313 URL: http://llvm.org/viewvc/llvm-project?rev=91313&view=rev Log: correct selection requirements for thumb2 vs. arm versions of the barrier intrinsics Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=91313&r1=91312&r2=91313&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Dec 14 13:24:11 2009 @@ -1579,7 +1579,7 @@ Pseudo, NoItinerary, "dmb", "", [(ARMMemBarrier)]>, - Requires<[HasV7]> { + Requires<[IsARM, HasV7]> { let Inst{31-4} = 0xf57ff05; // FIXME: add support for options other than a full system DMB let Inst{3-0} = 0b1111; @@ -1589,7 +1589,7 @@ Pseudo, NoItinerary, "dsb", "", [(ARMSyncBarrier)]>, - Requires<[HasV7]> { + Requires<[IsARM, HasV7]> { let Inst{31-4} = 0xf57ff04; // FIXME: add support for options other than a full system DSB let Inst{3-0} = 0b1111; Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=91313&r1=91312&r2=91313&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Mon Dec 14 13:24:11 2009 @@ -1073,14 +1073,16 @@ def t2Int_MemBarrierV7 : AInoP<(outs), (ins), Pseudo, NoItinerary, "dmb", "", - [(ARMMemBarrier)]> { + [(ARMMemBarrier)]>, + Requires<[IsThumb2]> { // FIXME: add support for options other than a full system DMB } def t2Int_SyncBarrierV7 : AInoP<(outs), (ins), Pseudo, NoItinerary, "dsb", "", - [(ARMSyncBarrier)]> { + [(ARMSyncBarrier)]>, + Requires<[IsThumb2]> { // FIXME: add support for options other than a full system DSB } } From gohman at apple.com Mon Dec 14 13:32:32 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 19:32:32 -0000 Subject: [llvm-commits] [llvm] r91316 - in /llvm/trunk: include/llvm/Support/raw_ostream.h lib/Support/raw_ostream.cpp Message-ID: <200912141932.nBEJWW2u012521@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 13:32:31 2009 New Revision: 91316 URL: http://llvm.org/viewvc/llvm-project?rev=91316&view=rev Log: Micro-optimize these functions in the case where they are not inlined. Modified: llvm/trunk/include/llvm/Support/raw_ostream.h llvm/trunk/lib/Support/raw_ostream.cpp Modified: llvm/trunk/include/llvm/Support/raw_ostream.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/raw_ostream.h?rev=91316&r1=91315&r2=91316&view=diff ============================================================================== --- llvm/trunk/include/llvm/Support/raw_ostream.h (original) +++ llvm/trunk/include/llvm/Support/raw_ostream.h Mon Dec 14 13:32:31 2009 @@ -186,14 +186,12 @@ // Inline fast path, particulary for constant strings where a sufficiently // smart compiler will simplify strlen. - this->operator<<(StringRef(Str)); - return *this; + return this->operator<<(StringRef(Str)); } raw_ostream &operator<<(const std::string &Str) { // Avoid the fast path, it would only increase code size for a marginal win. - write(Str.data(), Str.length()); - return *this; + return write(Str.data(), Str.length()); } raw_ostream &operator<<(unsigned long N); @@ -202,13 +200,11 @@ raw_ostream &operator<<(long long N); raw_ostream &operator<<(const void *P); raw_ostream &operator<<(unsigned int N) { - this->operator<<(static_cast(N)); - return *this; + return this->operator<<(static_cast(N)); } raw_ostream &operator<<(int N) { - this->operator<<(static_cast(N)); - return *this; + return this->operator<<(static_cast(N)); } raw_ostream &operator<<(double N); Modified: llvm/trunk/lib/Support/raw_ostream.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/raw_ostream.cpp?rev=91316&r1=91315&r2=91316&view=diff ============================================================================== --- llvm/trunk/lib/Support/raw_ostream.cpp (original) +++ llvm/trunk/lib/Support/raw_ostream.cpp Mon Dec 14 13:32:31 2009 @@ -209,8 +209,7 @@ } raw_ostream &raw_ostream::operator<<(double N) { - this->operator<<(ftostr(N)); - return *this; + return this->operator<<(ftostr(N)); } From sabre at nondot.org Mon Dec 14 13:34:33 2009 From: sabre at nondot.org (Chris Lattner) Date: Mon, 14 Dec 2009 19:34:33 -0000 Subject: [llvm-commits] [llvm] r91318 - /llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp Message-ID: <200912141934.nBEJYX2L012628@zion.cs.uiuc.edu> Author: lattner Date: Mon Dec 14 13:34:32 2009 New Revision: 91318 URL: http://llvm.org/viewvc/llvm-project?rev=91318&view=rev Log: fix an obvious bug found by clang++ and collapse a redundant if. Here's the diagnostic from clang: /Volumes/Data/dgregor/Projects/llvm/lib/Target/CppBackend/CPPBackend.cpp:989:23: warning: 'gv' is always NULL in this context ????????printConstant(gv); ??????????????????????^ 1 diagnostic generated. Modified: llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp Modified: llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp?rev=91318&r1=91317&r2=91318&view=diff ============================================================================== --- llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp (original) +++ llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp Mon Dec 14 13:34:32 2009 @@ -976,21 +976,20 @@ nl(Out); printType(GV->getType()); if (GV->hasInitializer()) { - Constant* Init = GV->getInitializer(); + Constant *Init = GV->getInitializer(); printType(Init->getType()); - if (Function* F = dyn_cast(Init)) { + if (Function *F = dyn_cast(Init)) { nl(Out)<< "/ Function Declarations"; nl(Out); printFunctionHead(F); } else if (GlobalVariable* gv = dyn_cast(Init)) { nl(Out) << "// Global Variable Declarations"; nl(Out); printVariableHead(gv); - } else { - nl(Out) << "// Constant Definitions"; nl(Out); - printConstant(gv); - } - if (GlobalVariable* gv = dyn_cast(Init)) { + nl(Out) << "// Global Variable Definitions"; nl(Out); printVariableBody(gv); + } else { + nl(Out) << "// Constant Definitions"; nl(Out); + printConstant(Init); } } } From gohman at apple.com Mon Dec 14 13:43:17 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 19:43:17 -0000 Subject: [llvm-commits] [llvm] r91319 - in /llvm/trunk: include/llvm/Pass.h lib/VMCore/Pass.cpp Message-ID: <200912141943.nBEJhHhM012971@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 13:43:09 2009 New Revision: 91319 URL: http://llvm.org/viewvc/llvm-project?rev=91319&view=rev Log: Move several function bodies which are rarely inlined out of line. Modified: llvm/trunk/include/llvm/Pass.h llvm/trunk/lib/VMCore/Pass.cpp Modified: llvm/trunk/include/llvm/Pass.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Pass.h?rev=91319&r1=91318&r2=91319&view=diff ============================================================================== --- llvm/trunk/include/llvm/Pass.h (original) +++ llvm/trunk/include/llvm/Pass.h Mon Dec 14 13:43:09 2009 @@ -111,12 +111,10 @@ virtual void assignPassManager(PMStack &, PassManagerType = PMT_Unknown) {} /// Check if available pass managers are suitable for this pass or not. - virtual void preparePassManager(PMStack &) {} + virtual void preparePassManager(PMStack &); /// Return what kind of Pass Manager can manage this pass. - virtual PassManagerType getPotentialPassManagerType() const { - return PMT_Unknown; - } + virtual PassManagerType getPotentialPassManagerType() const; // Access AnalysisResolver inline void setResolver(AnalysisResolver *AR) { @@ -132,9 +130,7 @@ /// particular analysis result to this function, it can then use the /// getAnalysis() function, below. /// - virtual void getAnalysisUsage(AnalysisUsage &) const { - // By default, no analysis results are used, all are invalidated. - } + virtual void getAnalysisUsage(AnalysisUsage &) const; /// releaseMemory() - This member can be implemented by a pass if it wants to /// be able to release its memory when it is no longer needed. The default @@ -147,11 +143,11 @@ /// Optionally implement this function to release pass memory when it is no /// longer used. /// - virtual void releaseMemory() {} + virtual void releaseMemory(); /// verifyAnalysis() - This member can be implemented by a analysis pass to /// check state of analysis information. - virtual void verifyAnalysis() const {} + virtual void verifyAnalysis() const; // dumpPassStructure - Implement the -debug-passes=PassStructure option virtual void dumpPassStructure(unsigned Offset = 0); @@ -221,9 +217,7 @@ PassManagerType T = PMT_ModulePassManager); /// Return what kind of Pass Manager can manage this pass. - virtual PassManagerType getPotentialPassManagerType() const { - return PMT_ModulePassManager; - } + virtual PassManagerType getPotentialPassManagerType() const; explicit ModulePass(intptr_t pid) : Pass(pid) {} explicit ModulePass(const void *pid) : Pass(pid) {} @@ -245,7 +239,7 @@ /// and if it does, the overloaded version of initializePass may get access to /// these passes with getAnalysis<>. /// - virtual void initializePass() {} + virtual void initializePass(); /// ImmutablePasses are never run. /// @@ -276,7 +270,7 @@ /// doInitialization - Virtual method overridden by subclasses to do /// any necessary per-module initialization. /// - virtual bool doInitialization(Module &) { return false; } + virtual bool doInitialization(Module &); /// runOnFunction - Virtual method overriden by subclasses to do the /// per-function processing of the pass. @@ -286,7 +280,7 @@ /// doFinalization - Virtual method overriden by subclasses to do any post /// processing needed after all passes have run. /// - virtual bool doFinalization(Module &) { return false; } + virtual bool doFinalization(Module &); /// runOnModule - On a module, we run this pass by initializing, /// ronOnFunction'ing once for every function in the module, then by @@ -303,9 +297,7 @@ PassManagerType T = PMT_FunctionPassManager); /// Return what kind of Pass Manager can manage this pass. - virtual PassManagerType getPotentialPassManagerType() const { - return PMT_FunctionPassManager; - } + virtual PassManagerType getPotentialPassManagerType() const; }; @@ -328,12 +320,12 @@ /// doInitialization - Virtual method overridden by subclasses to do /// any necessary per-module initialization. /// - virtual bool doInitialization(Module &) { return false; } + virtual bool doInitialization(Module &); /// doInitialization - Virtual method overridden by BasicBlockPass subclasses /// to do any necessary per-function initialization. /// - virtual bool doInitialization(Function &) { return false; } + virtual bool doInitialization(Function &); /// runOnBasicBlock - Virtual method overriden by subclasses to do the /// per-basicblock processing of the pass. @@ -343,12 +335,12 @@ /// doFinalization - Virtual method overriden by BasicBlockPass subclasses to /// do any post processing needed after all passes have run. /// - virtual bool doFinalization(Function &) { return false; } + virtual bool doFinalization(Function &); /// doFinalization - Virtual method overriden by subclasses to do any post /// processing needed after all passes have run. /// - virtual bool doFinalization(Module &) { return false; } + virtual bool doFinalization(Module &); // To run this pass on a function, we simply call runOnBasicBlock once for @@ -360,9 +352,7 @@ PassManagerType T = PMT_BasicBlockPassManager); /// Return what kind of Pass Manager can manage this pass. - virtual PassManagerType getPotentialPassManagerType() const { - return PMT_BasicBlockPassManager; - } + virtual PassManagerType getPotentialPassManagerType() const; }; /// If the user specifies the -time-passes argument on an LLVM tool command line Modified: llvm/trunk/lib/VMCore/Pass.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Pass.cpp?rev=91319&r1=91318&r2=91319&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Pass.cpp (original) +++ llvm/trunk/lib/VMCore/Pass.cpp Mon Dec 14 13:43:09 2009 @@ -41,6 +41,10 @@ // Force out-of-line virtual method. ModulePass::~ModulePass() { } +PassManagerType ModulePass::getPotentialPassManagerType() const { + return PMT_ModulePassManager; +} + bool Pass::mustPreserveAnalysisID(const PassInfo *AnalysisID) const { return Resolver->getAnalysisIfAvailable(AnalysisID, true) != 0; } @@ -60,6 +64,27 @@ return "Unnamed pass: implement Pass::getPassName()"; } +void Pass::preparePassManager(PMStack &) { + // By default, don't do anything. +} + +PassManagerType Pass::getPotentialPassManagerType() const { + // Default implementation. + return PMT_Unknown; +} + +void Pass::getAnalysisUsage(AnalysisUsage &) const { + // By default, no analysis results are used, all are invalidated. +} + +void Pass::releaseMemory() { + // By default, don't do anything. +} + +void Pass::verifyAnalysis() const { + // By default, don't do anything. +} + // print - Print out the internal state of the pass. This is called by Analyze // to print out the contents of an analysis. Otherwise it is not necessary to // implement this method. @@ -79,6 +104,10 @@ // Force out-of-line virtual method. ImmutablePass::~ImmutablePass() { } +void ImmutablePass::initializePass() { + // By default, don't do anything. +} + //===----------------------------------------------------------------------===// // FunctionPass Implementation // @@ -107,6 +136,20 @@ return Changed | doFinalization(*F.getParent()); } +bool FunctionPass::doInitialization(Module &) { + // By default, don't do anything. + return false; +} + +bool FunctionPass::doFinalization(Module &) { + // By default, don't do anything. + return false; +} + +PassManagerType FunctionPass::getPotentialPassManagerType() const { + return PMT_FunctionPassManager; +} + //===----------------------------------------------------------------------===// // BasicBlockPass Implementation // @@ -121,6 +164,30 @@ return Changed | doFinalization(F); } +bool BasicBlockPass::doInitialization(Module &) { + // By default, don't do anything. + return false; +} + +bool BasicBlockPass::doInitialization(Function &) { + // By default, don't do anything. + return false; +} + +bool BasicBlockPass::doFinalization(Function &) { + // By default, don't do anything. + return false; +} + +bool BasicBlockPass::doFinalization(Module &) { + // By default, don't do anything. + return false; +} + +PassManagerType BasicBlockPass::getPotentialPassManagerType() const { + return PMT_BasicBlockPassManager; +} + //===----------------------------------------------------------------------===// // Pass Registration mechanism // From gohman at apple.com Mon Dec 14 13:55:23 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 19:55:23 -0000 Subject: [llvm-commits] [llvm] r91320 - in /llvm/trunk: include/llvm/Config/ lib/Target/X86/Disassembler/ Message-ID: <200912141955.nBEJtNj4013407@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 13:55:22 2009 New Revision: 91320 URL: http://llvm.org/viewvc/llvm-project?rev=91320&view=rev Log: Add svn:ignore entries for the Disassembler files. Modified: llvm/trunk/include/llvm/Config/ (props changed) llvm/trunk/lib/Target/X86/Disassembler/ (props changed) Propchange: llvm/trunk/include/llvm/Config/ ------------------------------------------------------------------------------ --- svn:ignore (original) +++ svn:ignore Mon Dec 14 13:55:22 2009 @@ -3,3 +3,4 @@ AsmPrinters.def Targets.def AsmParsers.def +Disassemblers.def Propchange: llvm/trunk/lib/Target/X86/Disassembler/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Mon Dec 14 13:55:22 2009 @@ -0,0 +1,8 @@ +Debug +Release +Release-Asserts +*.inc +Debug+Coverage-Asserts +Debug+Coverage +Release+Coverage +Debug+Checks From grosbach at apple.com Mon Dec 14 14:14:59 2009 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 14 Dec 2009 20:14:59 -0000 Subject: [llvm-commits] [llvm] r91321 - /llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Message-ID: <200912142014.nBEKEx6p014220@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 14:14:59 2009 New Revision: 91321 URL: http://llvm.org/viewvc/llvm-project?rev=91321&view=rev Log: Thumb2 atomic operations Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=91321&r1=91320&r2=91321&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Mon Dec 14 14:14:59 2009 @@ -3055,13 +3055,23 @@ .createVirtualRegister(ARM::GPRRegisterClass); const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); DebugLoc dl = MI->getDebugLoc(); + bool isThumb2 = Subtarget->isThumb2(); unsigned ldrOpc, strOpc; switch (Size) { default: llvm_unreachable("unsupported size for AtomicCmpSwap!"); - case 1: ldrOpc = ARM::LDREXB; strOpc = ARM::STREXB; break; - case 2: ldrOpc = ARM::LDREXH; strOpc = ARM::STREXH; break; - case 4: ldrOpc = ARM::LDREX; strOpc = ARM::STREX; break; + case 1: + ldrOpc = isThumb2 ? ARM::t2LDREXB : ARM::LDREXB; + strOpc = isThumb2 ? ARM::t2LDREXB : ARM::STREXB; + break; + case 2: + ldrOpc = isThumb2 ? ARM::t2LDREXH : ARM::LDREXH; + strOpc = isThumb2 ? ARM::t2STREXH : ARM::STREXH; + break; + case 4: + ldrOpc = isThumb2 ? ARM::t2LDREX : ARM::LDREX; + strOpc = isThumb2 ? ARM::t2STREX : ARM::STREX; + break; } MachineFunction *MF = BB->getParent(); @@ -3088,10 +3098,10 @@ // bne exitMBB BB = loop1MBB; AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr)); - AddDefaultPred(BuildMI(BB, dl, TII->get(ARM::CMPrr)) + AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr)) .addReg(dest).addReg(oldval)); - BuildMI(BB, dl, TII->get(ARM::Bcc)).addMBB(exitMBB).addImm(ARMCC::NE) - .addReg(ARM::CPSR); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) + .addMBB(exitMBB).addImm(ARMCC::NE).addReg(ARM::CPSR); BB->addSuccessor(loop2MBB); BB->addSuccessor(exitMBB); @@ -3102,10 +3112,10 @@ BB = loop2MBB; AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(newval) .addReg(ptr)); - AddDefaultPred(BuildMI(BB, dl, TII->get(ARM::CMPri)) + AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri)) .addReg(scratch).addImm(0)); - BuildMI(BB, dl, TII->get(ARM::Bcc)).addMBB(loop1MBB).addImm(ARMCC::NE) - .addReg(ARM::CPSR); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) + .addMBB(loop1MBB).addImm(ARMCC::NE).addReg(ARM::CPSR); BB->addSuccessor(loop1MBB); BB->addSuccessor(exitMBB); @@ -3130,12 +3140,22 @@ unsigned ptr = MI->getOperand(1).getReg(); unsigned incr = MI->getOperand(2).getReg(); DebugLoc dl = MI->getDebugLoc(); + bool isThumb2 = Subtarget->isThumb2(); unsigned ldrOpc, strOpc; switch (Size) { default: llvm_unreachable("unsupported size for AtomicCmpSwap!"); - case 1: ldrOpc = ARM::LDREXB; strOpc = ARM::STREXB; break; - case 2: ldrOpc = ARM::LDREXH; strOpc = ARM::STREXH; break; - case 4: ldrOpc = ARM::LDREX; strOpc = ARM::STREX; break; + case 1: + ldrOpc = isThumb2 ? ARM::t2LDREXB : ARM::LDREXB; + strOpc = isThumb2 ? ARM::t2LDREXB : ARM::STREXB; + break; + case 2: + ldrOpc = isThumb2 ? ARM::t2LDREXH : ARM::LDREXH; + strOpc = isThumb2 ? ARM::t2STREXH : ARM::STREXH; + break; + case 4: + ldrOpc = isThumb2 ? ARM::t2LDREX : ARM::LDREX; + strOpc = isThumb2 ? ARM::t2STREX : ARM::STREX; + break; } MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB); @@ -3156,8 +3176,8 @@ // loopMBB: // ldrex dest, ptr - // add tmp, dest, incr - // strex scratch, tmp, ptr + // scratch2, dest, incr + // strex scratch, scratch2, ptr // cmp scratch, #0 // bne- loopMBB // fallthrough --> exitMBB @@ -3169,10 +3189,10 @@ AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2) .addReg(ptr)); - AddDefaultPred(BuildMI(BB, dl, TII->get(ARM::CMPri)) + AddDefaultPred(BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri)) .addReg(scratch).addImm(0)); - BuildMI(BB, dl, TII->get(ARM::Bcc)).addMBB(loopMBB).addImm(ARMCC::NE) - .addReg(ARM::CPSR); + BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc)) + .addMBB(loopMBB).addImm(ARMCC::NE).addReg(ARM::CPSR); BB->addSuccessor(loopMBB); BB->addSuccessor(exitMBB); @@ -3189,38 +3209,57 @@ DenseMap *EM) const { const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); DebugLoc dl = MI->getDebugLoc(); + bool isThumb2 = Subtarget->isThumb2(); switch (MI->getOpcode()) { default: MI->dump(); llvm_unreachable("Unexpected instr type to insert"); - case ARM::ATOMIC_LOAD_ADD_I8: return EmitAtomicBinary(MI, BB, 1, ARM::ADDrr); - case ARM::ATOMIC_LOAD_ADD_I16: return EmitAtomicBinary(MI, BB, 2, ARM::ADDrr); - case ARM::ATOMIC_LOAD_ADD_I32: return EmitAtomicBinary(MI, BB, 4, ARM::ADDrr); - - case ARM::ATOMIC_LOAD_AND_I8: return EmitAtomicBinary(MI, BB, 1, ARM::ANDrr); - case ARM::ATOMIC_LOAD_AND_I16: return EmitAtomicBinary(MI, BB, 2, ARM::ANDrr); - case ARM::ATOMIC_LOAD_AND_I32: return EmitAtomicBinary(MI, BB, 4, ARM::ANDrr); - - case ARM::ATOMIC_LOAD_OR_I8: return EmitAtomicBinary(MI, BB, 1, ARM::ORRrr); - case ARM::ATOMIC_LOAD_OR_I16: return EmitAtomicBinary(MI, BB, 2, ARM::ORRrr); - case ARM::ATOMIC_LOAD_OR_I32: return EmitAtomicBinary(MI, BB, 4, ARM::ORRrr); - - case ARM::ATOMIC_LOAD_XOR_I8: return EmitAtomicBinary(MI, BB, 1, ARM::EORrr); - case ARM::ATOMIC_LOAD_XOR_I16: return EmitAtomicBinary(MI, BB, 2, ARM::EORrr); - case ARM::ATOMIC_LOAD_XOR_I32: return EmitAtomicBinary(MI, BB, 4, ARM::EORrr); - - case ARM::ATOMIC_LOAD_NAND_I8: return EmitAtomicBinary(MI, BB, 1, ARM::BICrr); - case ARM::ATOMIC_LOAD_NAND_I16:return EmitAtomicBinary(MI, BB, 2, ARM::BICrr); - case ARM::ATOMIC_LOAD_NAND_I32:return EmitAtomicBinary(MI, BB, 4, ARM::BICrr); - - case ARM::ATOMIC_LOAD_SUB_I8: return EmitAtomicBinary(MI, BB, 1, ARM::SUBrr); - case ARM::ATOMIC_LOAD_SUB_I16: return EmitAtomicBinary(MI, BB, 2, ARM::SUBrr); - case ARM::ATOMIC_LOAD_SUB_I32: return EmitAtomicBinary(MI, BB, 4, ARM::SUBrr); - - case ARM::ATOMIC_SWAP_I8: return EmitAtomicBinary(MI, BB, 1, 0); - case ARM::ATOMIC_SWAP_I16: return EmitAtomicBinary(MI, BB, 2, 0); - case ARM::ATOMIC_SWAP_I32: return EmitAtomicBinary(MI, BB, 4, 0); + case ARM::ATOMIC_LOAD_ADD_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr); + case ARM::ATOMIC_LOAD_ADD_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr); + case ARM::ATOMIC_LOAD_ADD_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2ADDrr : ARM::ADDrr); + + case ARM::ATOMIC_LOAD_AND_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2ANDrr : ARM::ANDrr); + case ARM::ATOMIC_LOAD_AND_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2ANDrr : ARM::ANDrr); + case ARM::ATOMIC_LOAD_AND_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2ANDrr : ARM::ANDrr); + + case ARM::ATOMIC_LOAD_OR_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2ORRrr : ARM::ORRrr); + case ARM::ATOMIC_LOAD_OR_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2ORRrr : ARM::ORRrr); + case ARM::ATOMIC_LOAD_OR_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2ORRrr : ARM::ORRrr); + + case ARM::ATOMIC_LOAD_XOR_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2EORrr : ARM::EORrr); + case ARM::ATOMIC_LOAD_XOR_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2EORrr : ARM::EORrr); + case ARM::ATOMIC_LOAD_XOR_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2EORrr : ARM::EORrr); + + case ARM::ATOMIC_LOAD_NAND_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2BICrr : ARM::BICrr); + case ARM::ATOMIC_LOAD_NAND_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2BICrr : ARM::BICrr); + case ARM::ATOMIC_LOAD_NAND_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2BICrr : ARM::BICrr); + + case ARM::ATOMIC_LOAD_SUB_I8: + return EmitAtomicBinary(MI, BB, 1, isThumb2 ? ARM::t2SUBrr : ARM::SUBrr); + case ARM::ATOMIC_LOAD_SUB_I16: + return EmitAtomicBinary(MI, BB, 2, isThumb2 ? ARM::t2SUBrr : ARM::SUBrr); + case ARM::ATOMIC_LOAD_SUB_I32: + return EmitAtomicBinary(MI, BB, 4, isThumb2 ? ARM::t2SUBrr : ARM::SUBrr); + + case ARM::ATOMIC_SWAP_I8: return EmitAtomicBinary(MI, BB, 1, 0); + case ARM::ATOMIC_SWAP_I16: return EmitAtomicBinary(MI, BB, 2, 0); + case ARM::ATOMIC_SWAP_I32: return EmitAtomicBinary(MI, BB, 4, 0); case ARM::ATOMIC_CMP_SWAP_I8: return EmitAtomicCmpSwap(MI, BB, 1); case ARM::ATOMIC_CMP_SWAP_I16: return EmitAtomicCmpSwap(MI, BB, 2); From johnny.chen at apple.com Mon Dec 14 15:01:46 2009 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 14 Dec 2009 21:01:46 -0000 Subject: [llvm-commits] [llvm] r91327 - /llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Message-ID: <200912142101.nBEL1kL7016122@zion.cs.uiuc.edu> Author: johnny Date: Mon Dec 14 15:01:46 2009 New Revision: 91327 URL: http://llvm.org/viewvc/llvm-project?rev=91327&view=rev Log: Fixed encoding bits typo of ldrexd/strexd. Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=91327&r1=91326&r2=91327&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Dec 14 15:01:46 2009 @@ -1709,7 +1709,7 @@ def LDREX : AIldrex<0b00, (outs GPR:$dest), (ins GPR:$ptr), NoItinerary, "ldrex", "\t$dest, [$ptr]", []>; -def LDREXD : AIldrex<0b00, (outs GPR:$dest, GPR:$dest2), (ins GPR:$ptr), +def LDREXD : AIldrex<0b01, (outs GPR:$dest, GPR:$dest2), (ins GPR:$ptr), NoItinerary, "ldrexd", "\t$dest, $dest2, [$ptr]", []>; @@ -1728,7 +1728,7 @@ NoItinerary, "strex", "\t$success, $src, [$ptr]", []>; -def STREXD : AIstrex<0b00, (outs GPR:$success), +def STREXD : AIstrex<0b01, (outs GPR:$success), (ins GPR:$src, GPR:$src2, GPR:$ptr), NoItinerary, "strexd", "\t$success, $src, $src2, [$ptr]", From Micah.Villmow at amd.com Mon Dec 14 15:10:43 2009 From: Micah.Villmow at amd.com (Villmow, Micah) Date: Mon, 14 Dec 2009 13:10:43 -0800 Subject: [llvm-commits] [llvm] r91158 - in /llvm/trunk: include/llvm/CodeGen/ValueTypes.h lib/CodeGen/SelectionDAG/DAGCombiner.cpp lib/CodeGen/SelectionDAG/LegalizeDAG.cpp lib/CodeGen/SelectionDAG/LegalizeTypes.h lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp In-Reply-To: <200912112131.nBBLVSbn029491@zion.cs.uiuc.edu> References: <200912112131.nBBLVSbn029491@zion.cs.uiuc.edu> Message-ID: <493720826E33B1459E7F5C253E6D4BB5BA49FE@ssanexmb2.amd.com> Dan, I've applied this patch set and it still does not work correctly. The problem seems to be an assert in TargetLowering.cpp. assert(Op.getValueType().getScalarType().getSizeInBits() == BitWidth > && > "Mask size mismatches value type size!"); This occurs on a truncating store of a vector type. I've attached the test case that I am using to get past this. The problem seems to be that the BitWidth of the mask is the vector bitwidth and not the scalar bitwidth. This test case asserts on both my backend and x86. > -----Original Message----- > From: llvm-commits-bounces at cs.uiuc.edu [mailto:llvm-commits- > bounces at cs.uiuc.edu] On Behalf Of Dan Gohman > Sent: Friday, December 11, 2009 1:31 PM > To: llvm-commits at cs.uiuc.edu > Subject: [llvm-commits] [llvm] r91158 - in /llvm/trunk: > include/llvm/CodeGen/ValueTypes.h > lib/CodeGen/SelectionDAG/DAGCombiner.cpp > lib/CodeGen/SelectionDAG/LegalizeDAG.cpp > lib/CodeGen/SelectionDAG/LegalizeTypes.h > lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp lib/ > > Author: djg > Date: Fri Dec 11 15:31:27 2009 > New Revision: 91158 > > URL: http://llvm.org/viewvc/llvm-project?rev=91158&view=rev > Log: > Implement vector widening, splitting, and scalarizing for > SIGN_EXTEND_INREG. > > Added: > llvm/trunk/test/CodeGen/X86/vec_ext_inreg.ll > Modified: > llvm/trunk/include/llvm/CodeGen/ValueTypes.h > llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp > llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp > llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h > llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp > llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp > llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp > llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp > llvm/trunk/lib/Target/X86/X86ISelLowering.cpp > > Modified: llvm/trunk/include/llvm/CodeGen/ValueTypes.h > URL: http://llvm.org/viewvc/llvm- > project/llvm/trunk/include/llvm/CodeGen/ValueTypes.h?rev=91158&r1=91157 > &r2=91158&view=diff > > ======================================================================= > ======= > --- llvm/trunk/include/llvm/CodeGen/ValueTypes.h (original) > +++ llvm/trunk/include/llvm/CodeGen/ValueTypes.h Fri Dec 11 15:31:27 > 2009 > @@ -166,6 +166,12 @@ > return *this; > } > } > + > + /// getScalarType - If this is a vector type, return the element > type, > + /// otherwise return this. > + MVT getScalarType() const { > + return isVector() ? getVectorElementType() : *this; > + } > > MVT getVectorElementType() const { > switch (SimpleTy) { > @@ -524,6 +530,12 @@ > return V; > } > > + /// getScalarType - If this is a vector type, return the element > type, > + /// otherwise return this. > + EVT getScalarType() const { > + return isVector() ? getVectorElementType() : *this; > + } > + > /// getVectorElementType - Given a vector type, return the type of > /// each element. > EVT getVectorElementType() const { > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp > URL: http://llvm.org/viewvc/llvm- > project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91158&r > 1=91157&r2=91158&view=diff > > ======================================================================= > ======= > --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Fri Dec 11 > 15:31:27 2009 > @@ -119,7 +119,8 @@ > /// it can be simplified or if things it uses can be simplified by > bit > /// propagation. If so, return true. > bool SimplifyDemandedBits(SDValue Op) { > - APInt Demanded = > APInt::getAllOnesValue(Op.getValueSizeInBits()); > + unsigned BitWidth = > Op.getValueType().getScalarType().getSizeInBits(); > + APInt Demanded = APInt::getAllOnesValue(BitWidth); > return SimplifyDemandedBits(Op, Demanded); > } > > @@ -2441,7 +2442,7 @@ > ConstantSDNode *N0C = dyn_cast(N0); > ConstantSDNode *N1C = dyn_cast(N1); > EVT VT = N0.getValueType(); > - unsigned OpSizeInBits = VT.getSizeInBits(); > + unsigned OpSizeInBits = VT.getScalarType().getSizeInBits(); > > // fold (shl c1, c2) -> c1< if (N0C && N1C) > @@ -2457,7 +2458,7 @@ > return N0; > // if (shl x, c) is known to be zero, return 0 > if (DAG.MaskedValueIsZero(SDValue(N, 0), > - > APInt::getAllOnesValue(VT.getSizeInBits()))) > + APInt::getAllOnesValue(OpSizeInBits))) > return DAG.getConstant(0, VT); > // fold (shl x, (trunc (and y, c))) -> (shl x, (and (trunc y), > (trunc c))). > if (N1.getOpcode() == ISD::TRUNCATE && > @@ -2533,6 +2534,7 @@ > ConstantSDNode *N0C = dyn_cast(N0); > ConstantSDNode *N1C = dyn_cast(N1); > EVT VT = N0.getValueType(); > + unsigned OpSizeInBits = VT.getScalarType().getSizeInBits(); > > // fold (sra c1, c2) -> (sra c1, c2) > if (N0C && N1C) > @@ -2544,7 +2546,7 @@ > if (N0C && N0C->isAllOnesValue()) > return N0; > // fold (sra x, (setge c, size(x))) -> undef > - if (N1C && N1C->getZExtValue() >= VT.getSizeInBits()) > + if (N1C && N1C->getZExtValue() >= OpSizeInBits) > return DAG.getUNDEF(VT); > // fold (sra x, 0) -> x > if (N1C && N1C->isNullValue()) > @@ -2552,7 +2554,7 @@ > // fold (sra (shl x, c1), c1) -> sext_inreg for some c1 and target > supports > // sext_inreg. > if (N1C && N0.getOpcode() == ISD::SHL && N1 == N0.getOperand(1)) { > - unsigned LowBits = VT.getSizeInBits() - (unsigned)N1C- > >getZExtValue(); > + unsigned LowBits = OpSizeInBits - (unsigned)N1C->getZExtValue(); > EVT EVT = EVT::getIntegerVT(*DAG.getContext(), LowBits); > if ((!LegalOperations || > TLI.isOperationLegal(ISD::SIGN_EXTEND_INREG, EVT))) > return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, > @@ -2563,7 +2565,7 @@ > if (N1C && N0.getOpcode() == ISD::SRA) { > if (ConstantSDNode *C1 = > dyn_cast(N0.getOperand(1))) { > unsigned Sum = N1C->getZExtValue() + C1->getZExtValue(); > - if (Sum >= VT.getSizeInBits()) Sum = VT.getSizeInBits()-1; > + if (Sum >= OpSizeInBits) Sum = OpSizeInBits-1; > return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, > N0.getOperand(0), > DAG.getConstant(Sum, N1C->getValueType(0))); > } > @@ -2579,9 +2581,8 @@ > const ConstantSDNode *N01C = > dyn_cast(N0.getOperand(1)); > if (N01C && N1C) { > // Determine what the truncate's result bitsize and type would > be. > - unsigned VTValSize = VT.getSizeInBits(); > EVT TruncVT = > - EVT::getIntegerVT(*DAG.getContext(), VTValSize - N1C- > >getZExtValue()); > + EVT::getIntegerVT(*DAG.getContext(), OpSizeInBits - N1C- > >getZExtValue()); > // Determine the residual right-shift amount. > signed ShiftAmt = N1C->getZExtValue() - N01C->getZExtValue(); > > @@ -2614,7 +2615,7 @@ > EVT TruncVT = N1.getValueType(); > SDValue N100 = N1.getOperand(0).getOperand(0); > APInt TruncC = N101C->getAPIntValue(); > - TruncC.trunc(TruncVT.getSizeInBits()); > + TruncC.trunc(TruncVT.getScalarType().getSizeInBits()); > return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0, > DAG.getNode(ISD::AND, N->getDebugLoc(), > TruncVT, > @@ -2643,7 +2644,7 @@ > ConstantSDNode *N0C = dyn_cast(N0); > ConstantSDNode *N1C = dyn_cast(N1); > EVT VT = N0.getValueType(); > - unsigned OpSizeInBits = VT.getSizeInBits(); > + unsigned OpSizeInBits = VT.getScalarType().getSizeInBits(); > > // fold (srl c1, c2) -> c1 >>u c2 > if (N0C && N1C) > @@ -3036,7 +3037,7 @@ > else if (Op.getValueType().bitsGT(VT)) > Op = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), VT, Op); > return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, > Op, > - DAG.getValueType(N0.getValueType())); > + > DAG.getValueType(N0.getValueType().getScalarType())); > } > } > > @@ -3177,7 +3178,8 @@ > } else if (Op.getValueType().bitsGT(VT)) { > Op = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Op); > } > - return DAG.getZeroExtendInReg(Op, N->getDebugLoc(), > N0.getValueType()); > + return DAG.getZeroExtendInReg(Op, N->getDebugLoc(), > + N0.getValueType().getScalarType()); > } > > // Fold (zext (and (trunc x), cst)) -> (and x, cst), > @@ -3536,7 +3538,7 @@ > SDValue N1 = N->getOperand(1); > EVT VT = N->getValueType(0); > EVT EVT = cast(N1)->getVT(); > - unsigned VTBits = VT.getSizeInBits(); > + unsigned VTBits = VT.getScalarType().getSizeInBits(); > unsigned EVTBits = EVT.getSizeInBits(); > > // fold (sext_in_reg c1) -> c1 > @@ -3544,7 +3546,7 @@ > return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), VT, > N0, N1); > > // If the input is already sign extended, just drop the extension. > - if (DAG.ComputeNumSignBits(N0) >= VT.getSizeInBits()-EVTBits+1) > + if (DAG.ComputeNumSignBits(N0) >= VTBits-EVTBits+1) > return N0; > > // fold (sext_in_reg (sext_in_reg x, VT2), VT1) -> (sext_in_reg x, > minVT) pt2 > @@ -3559,7 +3561,7 @@ > // if x is small enough. > if (N0.getOpcode() == ISD::SIGN_EXTEND || N0.getOpcode() == > ISD::ANY_EXTEND) { > SDValue N00 = N0.getOperand(0); > - if (N00.getValueType().getSizeInBits() < EVTBits) > + if (N00.getValueType().getScalarType().getSizeInBits() < EVTBits) > return DAG.getNode(ISD::SIGN_EXTEND, N->getDebugLoc(), VT, N00, > N1); > } > > @@ -3583,11 +3585,11 @@ > // We already fold "(sext_in_reg (srl X, 25), i8) -> srl X, 25" > above. > if (N0.getOpcode() == ISD::SRL) { > if (ConstantSDNode *ShAmt = > dyn_cast(N0.getOperand(1))) > - if (ShAmt->getZExtValue()+EVTBits <= VT.getSizeInBits()) { > + if (ShAmt->getZExtValue()+EVTBits <= VTBits) { > // We can turn this into an SRA iff the input to the SRL is > already sign > // extended enough. > unsigned InSignBits = > DAG.ComputeNumSignBits(N0.getOperand(0)); > - if (VT.getSizeInBits()-(ShAmt->getZExtValue()+EVTBits) < > InSignBits) > + if (VTBits-(ShAmt->getZExtValue()+EVTBits) < InSignBits) > return DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, > N0.getOperand(0), N0.getOperand(1)); > } > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp > URL: http://llvm.org/viewvc/llvm- > project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=91158&r > 1=91157&r2=91158&view=diff > > ======================================================================= > ======= > --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Fri Dec 11 > 15:31:27 2009 > @@ -2294,9 +2294,16 @@ > // NOTE: we could fall back on load/store here too for targets > without > // SAR. However, it is doubtful that any exist. > EVT ExtraVT = cast(Node->getOperand(1))->getVT(); > - unsigned BitsDiff = Node->getValueType(0).getSizeInBits() - > + EVT VT = Node->getValueType(0); > + EVT ShiftAmountTy = TLI.getShiftAmountTy(); > + if (ExtraVT.isVector()) ExtraVT = ExtraVT.getVectorElementType(); > + if (VT.isVector()) { > + ShiftAmountTy = VT; > + VT = VT.getVectorElementType(); > + } > + unsigned BitsDiff = VT.getSizeInBits() - > ExtraVT.getSizeInBits(); > - SDValue ShiftCst = DAG.getConstant(BitsDiff, > TLI.getShiftAmountTy()); > + SDValue ShiftCst = DAG.getConstant(BitsDiff, ShiftAmountTy); > Tmp1 = DAG.getNode(ISD::SHL, dl, Node->getValueType(0), > Node->getOperand(0), ShiftCst); > Tmp1 = DAG.getNode(ISD::SRA, dl, Node->getValueType(0), Tmp1, > ShiftCst); > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h > URL: http://llvm.org/viewvc/llvm- > project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h?rev=91158&r > 1=91157&r2=91158&view=diff > > ======================================================================= > ======= > --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Fri Dec 11 > 15:31:27 2009 > @@ -517,6 +517,7 @@ > SDValue ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N); > SDValue ScalarizeVecRes_LOAD(LoadSDNode *N); > SDValue ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N); > + SDValue ScalarizeVecRes_SIGN_EXTEND_INREG(SDNode *N); > SDValue ScalarizeVecRes_SELECT(SDNode *N); > SDValue ScalarizeVecRes_SELECT_CC(SDNode *N); > SDValue ScalarizeVecRes_SETCC(SDNode *N); > @@ -560,6 +561,7 @@ > void SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, SDValue > &Hi); > void SplitVecRes_LOAD(LoadSDNode *N, SDValue &Lo, SDValue &Hi); > void SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo, SDValue > &Hi); > + void SplitVecRes_SIGN_EXTEND_INREG(SDNode *N, SDValue &Lo, SDValue > &Hi); > void SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi); > void SplitVecRes_UNDEF(SDNode *N, SDValue &Lo, SDValue &Hi); > void SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N, SDValue &Lo, > @@ -602,6 +604,7 @@ > SDValue WidenVecRes_INSERT_VECTOR_ELT(SDNode* N); > SDValue WidenVecRes_LOAD(SDNode* N); > SDValue WidenVecRes_SCALAR_TO_VECTOR(SDNode* N); > + SDValue WidenVecRes_SIGN_EXTEND_INREG(SDNode* N); > SDValue WidenVecRes_SELECT(SDNode* N); > SDValue WidenVecRes_SELECT_CC(SDNode* N); > SDValue WidenVecRes_UNDEF(SDNode *N); > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp > URL: http://llvm.org/viewvc/llvm- > project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp?rev=9 > 1158&r1=91157&r2=91158&view=diff > > ======================================================================= > ======= > --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp > (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp Fri Dec > 11 15:31:27 2009 > @@ -179,6 +179,7 @@ > case ISD::FRINT: > case ISD::FNEARBYINT: > case ISD::FFLOOR: > + case ISD::SIGN_EXTEND_INREG: > QueryType = Node->getValueType(0); > break; > case ISD::SINT_TO_FP: > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp > URL: http://llvm.org/viewvc/llvm- > project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp?rev > =91158&r1=91157&r2=91158&view=diff > > ======================================================================= > ======= > --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp > (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Fri Dec > 11 15:31:27 2009 > @@ -54,6 +54,7 @@ > case ISD::INSERT_VECTOR_ELT: R = > ScalarizeVecRes_INSERT_VECTOR_ELT(N); break; > case ISD::LOAD: R = > ScalarizeVecRes_LOAD(cast(N));break; > case ISD::SCALAR_TO_VECTOR: R = > ScalarizeVecRes_SCALAR_TO_VECTOR(N); break; > + case ISD::SIGN_EXTEND_INREG: R = > ScalarizeVecRes_SIGN_EXTEND_INREG(N); break; > case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break; > case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); > break; > case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break; > @@ -195,6 +196,13 @@ > return InOp; > } > > +SDValue DAGTypeLegalizer::ScalarizeVecRes_SIGN_EXTEND_INREG(SDNode *N) > { > + EVT EltVT = N->getValueType(0).getVectorElementType(); > + SDValue LHS = GetScalarizedVector(N->getOperand(0)); > + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), EltVT, > + LHS, N->getOperand(1)); > +} > + > SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) { > SDValue LHS = GetScalarizedVector(N->getOperand(1)); > return DAG.getNode(ISD::SELECT, N->getDebugLoc(), > @@ -401,6 +409,7 @@ > case ISD::FPOWI: SplitVecRes_FPOWI(N, Lo, Hi); break; > case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, > Hi); break; > case ISD::SCALAR_TO_VECTOR: SplitVecRes_SCALAR_TO_VECTOR(N, Lo, > Hi); break; > + case ISD::SIGN_EXTEND_INREG: SplitVecRes_SIGN_EXTEND_INREG(N, Lo, > Hi); break; > case ISD::LOAD: > SplitVecRes_LOAD(cast(N), Lo, Hi); > break; > @@ -700,6 +709,18 @@ > Hi = DAG.getUNDEF(HiVT); > } > > +void DAGTypeLegalizer::SplitVecRes_SIGN_EXTEND_INREG(SDNode *N, > SDValue &Lo, > + SDValue &Hi) { > + SDValue LHSLo, LHSHi; > + GetSplitVector(N->getOperand(0), LHSLo, LHSHi); > + DebugLoc dl = N->getDebugLoc(); > + > + Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo, > + N->getOperand(1)); > + Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi, > + N->getOperand(1)); > +} > + > void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo, > SDValue &Hi) { > assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type > legalization!"); > @@ -1141,6 +1162,7 @@ > case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); > break; > case ISD::LOAD: Res = WidenVecRes_LOAD(N); break; > case ISD::SCALAR_TO_VECTOR: Res = WidenVecRes_SCALAR_TO_VECTOR(N); > break; > + case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_SIGN_EXTEND_INREG(N); > break; > case ISD::SELECT: Res = WidenVecRes_SELECT(N); break; > case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break; > case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break; > @@ -1691,6 +1713,13 @@ > WidenVT, N->getOperand(0)); > } > > +SDValue DAGTypeLegalizer::WidenVecRes_SIGN_EXTEND_INREG(SDNode *N) { > + EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N- > >getValueType(0)); > + SDValue WidenLHS = GetWidenedVector(N->getOperand(0)); > + return DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), > + WidenVT, WidenLHS, N->getOperand(1)); > +} > + > SDValue DAGTypeLegalizer::WidenVecRes_SELECT(SDNode *N) { > EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N- > >getValueType(0)); > unsigned WidenNumElts = WidenVT.getVectorNumElements(); > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp > URL: http://llvm.org/viewvc/llvm- > project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=91158& > r1=91157&r2=91158&view=diff > > ======================================================================= > ======= > --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Fri Dec 11 > 15:31:27 2009 > @@ -832,8 +832,12 @@ > } > > SDValue SelectionDAG::getZeroExtendInReg(SDValue Op, DebugLoc DL, EVT > VT) { > + assert(!VT.isVector() && > + "getZeroExtendInReg should use the vector element type > instead of " > + "the vector type!"); > if (Op.getValueType() == VT) return Op; > - APInt Imm = APInt::getLowBitsSet(Op.getValueSizeInBits(), > + unsigned BitWidth = > Op.getValueType().getScalarType().getSizeInBits(); > + APInt Imm = APInt::getLowBitsSet(BitWidth, > VT.getSizeInBits()); > return getNode(ISD::AND, DL, Op.getValueType(), Op, > getConstant(Imm, Op.getValueType())); > @@ -1481,7 +1485,7 @@ > if (Op.getValueType().isVector()) > return false; > > - unsigned BitWidth = Op.getValueSizeInBits(); > + unsigned BitWidth = > Op.getValueType().getScalarType().getSizeInBits(); > return MaskedValueIsZero(Op, APInt::getSignBit(BitWidth), Depth); > } > > @@ -1504,7 +1508,7 @@ > APInt &KnownZero, APInt > &KnownOne, > unsigned Depth) const { > unsigned BitWidth = Mask.getBitWidth(); > - assert(BitWidth == Op.getValueType().getSizeInBits() && > + assert(BitWidth == Op.getValueType().getScalarType().getSizeInBits() > && > "Mask size mismatches value type size!"); > > KnownZero = KnownOne = APInt(BitWidth, 0); // Don't know anything. > @@ -1761,7 +1765,7 @@ > } > case ISD::ZERO_EXTEND: { > EVT InVT = Op.getOperand(0).getValueType(); > - unsigned InBits = InVT.getSizeInBits(); > + unsigned InBits = InVT.getScalarType().getSizeInBits(); > APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - > InBits) & Mask; > APInt InMask = Mask; > InMask.trunc(InBits); > @@ -1775,7 +1779,7 @@ > } > case ISD::SIGN_EXTEND: { > EVT InVT = Op.getOperand(0).getValueType(); > - unsigned InBits = InVT.getSizeInBits(); > + unsigned InBits = InVT.getScalarType().getSizeInBits(); > APInt InSignBit = APInt::getSignBit(InBits); > APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - > InBits) & Mask; > APInt InMask = Mask; > @@ -1816,7 +1820,7 @@ > } > case ISD::ANY_EXTEND: { > EVT InVT = Op.getOperand(0).getValueType(); > - unsigned InBits = InVT.getSizeInBits(); > + unsigned InBits = InVT.getScalarType().getSizeInBits(); > APInt InMask = Mask; > InMask.trunc(InBits); > KnownZero.trunc(InBits); > @@ -1828,7 +1832,7 @@ > } > case ISD::TRUNCATE: { > EVT InVT = Op.getOperand(0).getValueType(); > - unsigned InBits = InVT.getSizeInBits(); > + unsigned InBits = InVT.getScalarType().getSizeInBits(); > APInt InMask = Mask; > InMask.zext(InBits); > KnownZero.zext(InBits); > @@ -1961,7 +1965,7 @@ > unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) > const{ > EVT VT = Op.getValueType(); > assert(VT.isInteger() && "Invalid VT!"); > - unsigned VTBits = VT.getSizeInBits(); > + unsigned VTBits = VT.getScalarType().getSizeInBits(); > unsigned Tmp, Tmp2; > unsigned FirstAnswer = 1; > > @@ -1988,7 +1992,7 @@ > } > > case ISD::SIGN_EXTEND: > - Tmp = VTBits-Op.getOperand(0).getValueType().getSizeInBits(); > + Tmp = VTBits- > Op.getOperand(0).getValueType().getScalarType().getSizeInBits(); > return ComputeNumSignBits(Op.getOperand(0), Depth+1) + Tmp; > > case ISD::SIGN_EXTEND_INREG: > @@ -2624,6 +2628,9 @@ > assert(VT == N1.getValueType() && "Not an inreg extend!"); > assert(VT.isInteger() && EVT.isInteger() && > "Cannot *_EXTEND_INREG FP types"); > + assert(!EVT.isVector() && > + "AssertSExt/AssertZExt type should be the vector element > type " > + "rather than the vector type!"); > assert(EVT.bitsLE(VT) && "Not extending!"); > if (VT == EVT) return N1; // noop assertion. > break; > @@ -2633,12 +2640,15 @@ > assert(VT == N1.getValueType() && "Not an inreg extend!"); > assert(VT.isInteger() && EVT.isInteger() && > "Cannot *_EXTEND_INREG FP types"); > - assert(EVT.bitsLE(VT) && "Not extending!"); > + assert(!EVT.isVector() && > + "SIGN_EXTEND_INREG type should be the vector element type > rather " > + "than the vector type!"); > + assert(EVT.bitsLE(VT.getScalarType()) && "Not extending!"); > if (EVT == VT) return N1; // Not actually extending > > if (N1C) { > APInt Val = N1C->getAPIntValue(); > - unsigned FromBits = cast(N2)->getVT().getSizeInBits(); > + unsigned FromBits = EVT.getSizeInBits(); > Val <<= Val.getBitWidth()-FromBits; > Val = Val.ashr(Val.getBitWidth()-FromBits); > return getConstant(Val, VT); > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp > URL: http://llvm.org/viewvc/llvm- > project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=9115 > 8&r1=91157&r2=91158&view=diff > > ======================================================================= > ======= > --- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Fri Dec 11 > 15:31:27 2009 > @@ -911,7 +911,7 @@ > TargetLoweringOpt &TLO, > unsigned Depth) const { > unsigned BitWidth = DemandedMask.getBitWidth(); > - assert(Op.getValueSizeInBits() == BitWidth && > + assert(Op.getValueType().getScalarType().getSizeInBits() == BitWidth > && > "Mask size mismatches value type size!"); > APInt NewMask = DemandedMask; > DebugLoc dl = Op.getDebugLoc(); > @@ -1240,7 +1240,7 @@ > // demand the input sign bit. > APInt HighBits = APInt::getHighBitsSet(BitWidth, ShAmt); > if (HighBits.intersects(NewMask)) > - InDemandedMask |= APInt::getSignBit(VT.getSizeInBits()); > + InDemandedMask |= > APInt::getSignBit(VT.getScalarType().getSizeInBits()); > > if (SimplifyDemandedBits(Op.getOperand(0), InDemandedMask, > KnownZero, KnownOne, TLO, Depth+1)) > > Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp > URL: http://llvm.org/viewvc/llvm- > project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=91158&r1=9115 > 7&r2=91158&view=diff > > ======================================================================= > ======= > --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) > +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Fri Dec 11 15:31:27 > 2009 > @@ -595,6 +595,7 @@ > setOperationAction(ISD::FP_TO_SINT, (MVT::SimpleValueType)VT, > Expand); > setOperationAction(ISD::UINT_TO_FP, (MVT::SimpleValueType)VT, > Expand); > setOperationAction(ISD::SINT_TO_FP, (MVT::SimpleValueType)VT, > Expand); > + setOperationAction(ISD::SIGN_EXTEND_INREG, > (MVT::SimpleValueType)VT,Expand); > } > > // FIXME: In order to prevent SSE instructions being expanded to MMX > ones > > Added: llvm/trunk/test/CodeGen/X86/vec_ext_inreg.ll > URL: http://llvm.org/viewvc/llvm- > project/llvm/trunk/test/CodeGen/X86/vec_ext_inreg.ll?rev=91158&view=aut > o > > ======================================================================= > ======= > --- llvm/trunk/test/CodeGen/X86/vec_ext_inreg.ll (added) > +++ llvm/trunk/test/CodeGen/X86/vec_ext_inreg.ll Fri Dec 11 15:31:27 > 2009 > @@ -0,0 +1,37 @@ > +; RUN: llc < %s -march=x86-64 > + > +define <8 x i32> @a(<8 x i32> %a) nounwind { > + %b = trunc <8 x i32> %a to <8 x i16> > + %c = sext <8 x i16> %b to <8 x i32> > + ret <8 x i32> %c > +} > + > +define <3 x i32> @b(<3 x i32> %a) nounwind { > + %b = trunc <3 x i32> %a to <3 x i16> > + %c = sext <3 x i16> %b to <3 x i32> > + ret <3 x i32> %c > +} > + > +define <1 x i32> @c(<1 x i32> %a) nounwind { > + %b = trunc <1 x i32> %a to <1 x i16> > + %c = sext <1 x i16> %b to <1 x i32> > + ret <1 x i32> %c > +} > + > +define <8 x i32> @d(<8 x i32> %a) nounwind { > + %b = trunc <8 x i32> %a to <8 x i16> > + %c = zext <8 x i16> %b to <8 x i32> > + ret <8 x i32> %c > +} > + > +define <3 x i32> @e(<3 x i32> %a) nounwind { > + %b = trunc <3 x i32> %a to <3 x i16> > + %c = zext <3 x i16> %b to <3 x i32> > + ret <3 x i32> %c > +} > + > +define <1 x i32> @f(<1 x i32> %a) nounwind { > + %b = trunc <1 x i32> %a to <1 x i16> > + %c = zext <1 x i16> %b to <1 x i32> > + ret <1 x i32> %c > +} > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits -------------- next part -------------- A non-text attachment was scrubbed... Name: loads-custom.bc Type: application/octet-stream Size: 2268 bytes Desc: loads-custom.bc Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20091214/fedf58cf/attachment.obj -------------- next part -------------- A non-text attachment was scrubbed... Name: loads-custom.ll Type: application/octet-stream Size: 12799 bytes Desc: loads-custom.ll Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20091214/fedf58cf/attachment-0001.obj From grosbach at apple.com Mon Dec 14 15:24:17 2009 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 14 Dec 2009 21:24:17 -0000 Subject: [llvm-commits] [llvm] r91329 - in /llvm/trunk/lib/Target/ARM: ARMISelLowering.cpp ARMInstrInfo.td ARMInstrThumb2.td Message-ID: <200912142124.nBELOHgF017049@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 15:24:16 2009 New Revision: 91329 URL: http://llvm.org/viewvc/llvm-project?rev=91329&view=rev Log: Add ARMv6 memory and sync barrier instructions Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp llvm/trunk/lib/Target/ARM/ARMInstrInfo.td llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=91329&r1=91328&r2=91329&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Mon Dec 14 15:24:16 2009 @@ -1474,17 +1474,24 @@ } } -static SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) { +static SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG, + const ARMSubtarget *Subtarget) { DebugLoc dl = Op.getDebugLoc(); SDValue Op5 = Op.getOperand(5); SDValue Res; unsigned isDeviceBarrier = cast(Op5)->getZExtValue(); if (isDeviceBarrier) { - Res = DAG.getNode(ARMISD::SYNCBARRIER, dl, MVT::Other, - Op.getOperand(0)); + if (Subtarget->hasV7Ops()) + Res = DAG.getNode(ARMISD::SYNCBARRIER, dl, MVT::Other, Op.getOperand(0)); + else + Res = DAG.getNode(ARMISD::SYNCBARRIER, dl, MVT::Other, Op.getOperand(0), + DAG.getConstant(0, MVT::i32)); } else { - Res = DAG.getNode(ARMISD::MEMBARRIER, dl, MVT::Other, - Op.getOperand(0)); + if (Subtarget->hasV7Ops()) + Res = DAG.getNode(ARMISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0)); + else + Res = DAG.getNode(ARMISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0), + DAG.getConstant(0, MVT::i32)); } return Res; } @@ -2991,7 +2998,7 @@ case ISD::BR_JT: return LowerBR_JT(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG, VarArgsFrameIndex); - case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG); + case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG, Subtarget); case ISD::SINT_TO_FP: case ISD::UINT_TO_FP: return LowerINT_TO_FP(Op, DAG); case ISD::FP_TO_SINT: Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=91329&r1=91328&r2=91329&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Dec 14 15:24:16 2009 @@ -46,8 +46,10 @@ def SDT_ARMThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; def SDT_ARMEH_SJLJ_Setjmp : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisPtrTy<1>]>; -def SDT_ARMMEMBARRIER : SDTypeProfile<0, 0, []>; -def SDT_ARMSYNCBARRIER : SDTypeProfile<0, 0, []>; +def SDT_ARMMEMBARRIERV7 : SDTypeProfile<0, 0, []>; +def SDT_ARMSYNCBARRIERV7 : SDTypeProfile<0, 0, []>; +def SDT_ARMMEMBARRIERV6 : SDTypeProfile<0, 1, [SDTCisInt<0>]>; +def SDT_ARMSYNCBARRIERV6 : SDTypeProfile<0, 1, [SDTCisInt<0>]>; // Node definitions. def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>; @@ -96,9 +98,13 @@ def ARMthread_pointer: SDNode<"ARMISD::THREAD_POINTER", SDT_ARMThreadPointer>; def ARMeh_sjlj_setjmp: SDNode<"ARMISD::EH_SJLJ_SETJMP", SDT_ARMEH_SJLJ_Setjmp>; -def ARMMemBarrier : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIER, +def ARMMemBarrierV7 : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIERV7, [SDNPHasChain]>; -def ARMSyncBarrier : SDNode<"ARMISD::SYNCBARRIER", SDT_ARMMEMBARRIER, +def ARMSyncBarrierV7 : SDNode<"ARMISD::SYNCBARRIER", SDT_ARMMEMBARRIERV7, + [SDNPHasChain]>; +def ARMMemBarrierV6 : SDNode<"ARMISD::MEMBARRIER", SDT_ARMMEMBARRIERV6, + [SDNPHasChain]>; +def ARMSyncBarrierV6 : SDNode<"ARMISD::SYNCBARRIER", SDT_ARMMEMBARRIERV6, [SDNPHasChain]>; //===----------------------------------------------------------------------===// @@ -1578,7 +1584,7 @@ def Int_MemBarrierV7 : AInoP<(outs), (ins), Pseudo, NoItinerary, "dmb", "", - [(ARMMemBarrier)]>, + [(ARMMemBarrierV7)]>, Requires<[IsARM, HasV7]> { let Inst{31-4} = 0xf57ff05; // FIXME: add support for options other than a full system DMB @@ -1588,12 +1594,30 @@ def Int_SyncBarrierV7 : AInoP<(outs), (ins), Pseudo, NoItinerary, "dsb", "", - [(ARMSyncBarrier)]>, + [(ARMSyncBarrierV7)]>, Requires<[IsARM, HasV7]> { let Inst{31-4} = 0xf57ff04; // FIXME: add support for options other than a full system DSB let Inst{3-0} = 0b1111; } + +def Int_MemBarrierV6 : AInoP<(outs), (ins GPR:$zero), + Pseudo, NoItinerary, + "mcr", "\tp15, 0, $zero, c7, c10, 5", + [(ARMMemBarrierV6 GPR:$zero)]>, + Requires<[IsARM, HasV6]> { + // FIXME: add support for options other than a full system DMB + // FIXME: add encoding +} + +def Int_SyncBarrierV6 : AInoP<(outs), (ins GPR:$zero), + Pseudo, NoItinerary, + "mcr", "\tp15, 0, $zero, c7, c10, 5", + [(ARMSyncBarrierV6 GPR:$zero)]>, + Requires<[IsARM, HasV6]> { + // FIXME: add support for options other than a full system DSB + // FIXME: add encoding +} } let usesCustomInserter = 1 in { Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=91329&r1=91328&r2=91329&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Mon Dec 14 15:24:16 2009 @@ -1073,7 +1073,7 @@ def t2Int_MemBarrierV7 : AInoP<(outs), (ins), Pseudo, NoItinerary, "dmb", "", - [(ARMMemBarrier)]>, + [(ARMMemBarrierV7)]>, Requires<[IsThumb2]> { // FIXME: add support for options other than a full system DMB } @@ -1081,7 +1081,7 @@ def t2Int_SyncBarrierV7 : AInoP<(outs), (ins), Pseudo, NoItinerary, "dsb", "", - [(ARMSyncBarrier)]>, + [(ARMSyncBarrierV7)]>, Requires<[IsThumb2]> { // FIXME: add support for options other than a full system DSB } From grosbach at apple.com Mon Dec 14 15:33:33 2009 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 14 Dec 2009 21:33:33 -0000 Subject: [llvm-commits] [llvm] r91333 - /llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Message-ID: <200912142133.nBELXXXG017503@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 15:33:32 2009 New Revision: 91333 URL: http://llvm.org/viewvc/llvm-project?rev=91333&view=rev Log: v6 sync insn copy/paste error Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=91333&r1=91332&r2=91333&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Dec 14 15:33:32 2009 @@ -1612,7 +1612,7 @@ def Int_SyncBarrierV6 : AInoP<(outs), (ins GPR:$zero), Pseudo, NoItinerary, - "mcr", "\tp15, 0, $zero, c7, c10, 5", + "mcr", "\tp15, 0, $zero, c7, c10, 4", [(ARMSyncBarrierV6 GPR:$zero)]>, Requires<[IsARM, HasV6]> { // FIXME: add support for options other than a full system DSB From grosbach at apple.com Mon Dec 14 15:48:46 2009 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 14 Dec 2009 21:48:46 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r91336 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Message-ID: <200912142148.nBELmkho018138@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 15:48:45 2009 New Revision: 91336 URL: http://llvm.org/viewvc/llvm-project?rev=91336&view=rev Log: Enable atomic builtins for ARM Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=91336&r1=91335&r2=91336&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Mon Dec 14 15:48:45 2009 @@ -5178,7 +5178,8 @@ C, C + 5); return true; } -#if defined(TARGET_ALPHA) || defined(TARGET_386) || defined(TARGET_POWERPC) +#if defined(TARGET_ALPHA) || defined(TARGET_386) || defined(TARGET_POWERPC) \ + || defined(TARGET_ARM) // gcc uses many names for the sync intrinsics // The type of the first argument is not reliable for choosing the // right llvm function; if the original type is not volatile, gcc has @@ -5189,18 +5190,33 @@ // Note that Intrinsic::getDeclaration expects the type list in reversed // order, while CreateCall expects the parameter list in normal order. case BUILT_IN_BOOL_COMPARE_AND_SWAP_1: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif Result = BuildCmpAndSwapAtomicBuiltin(exp, unsigned_char_type_node, true); return true; } case BUILT_IN_BOOL_COMPARE_AND_SWAP_2: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif Result = BuildCmpAndSwapAtomicBuiltin(exp, short_unsigned_type_node, true); return true; } case BUILT_IN_BOOL_COMPARE_AND_SWAP_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif Result = BuildCmpAndSwapAtomicBuiltin(exp, unsigned_type_node, true); return true; } case BUILT_IN_BOOL_COMPARE_AND_SWAP_8: { +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5211,6 +5227,9 @@ } case BUILT_IN_VAL_COMPARE_AND_SWAP_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5218,11 +5237,19 @@ case BUILT_IN_VAL_COMPARE_AND_SWAP_1: case BUILT_IN_VAL_COMPARE_AND_SWAP_2: case BUILT_IN_VAL_COMPARE_AND_SWAP_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif tree type = TREE_TYPE(exp); Result = BuildCmpAndSwapAtomicBuiltin(exp, type, false); return true; } case BUILT_IN_FETCH_AND_ADD_8: +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5234,6 +5261,9 @@ return true; } case BUILT_IN_FETCH_AND_SUB_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5241,10 +5271,17 @@ case BUILT_IN_FETCH_AND_SUB_1: case BUILT_IN_FETCH_AND_SUB_2: case BUILT_IN_FETCH_AND_SUB_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif Result = BuildBinaryAtomicBuiltin(exp, Intrinsic::atomic_load_sub); return true; } case BUILT_IN_FETCH_AND_OR_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5252,10 +5289,17 @@ case BUILT_IN_FETCH_AND_OR_1: case BUILT_IN_FETCH_AND_OR_2: case BUILT_IN_FETCH_AND_OR_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif Result = BuildBinaryAtomicBuiltin(exp, Intrinsic::atomic_load_or); return true; } case BUILT_IN_FETCH_AND_AND_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5263,10 +5307,17 @@ case BUILT_IN_FETCH_AND_AND_1: case BUILT_IN_FETCH_AND_AND_2: case BUILT_IN_FETCH_AND_AND_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif Result = BuildBinaryAtomicBuiltin(exp, Intrinsic::atomic_load_and); return true; } case BUILT_IN_FETCH_AND_XOR_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5274,10 +5325,17 @@ case BUILT_IN_FETCH_AND_XOR_1: case BUILT_IN_FETCH_AND_XOR_2: case BUILT_IN_FETCH_AND_XOR_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif Result = BuildBinaryAtomicBuiltin(exp, Intrinsic::atomic_load_xor); return true; } case BUILT_IN_FETCH_AND_NAND_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5285,10 +5343,17 @@ case BUILT_IN_FETCH_AND_NAND_1: case BUILT_IN_FETCH_AND_NAND_2: case BUILT_IN_FETCH_AND_NAND_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif Result = BuildBinaryAtomicBuiltin(exp, Intrinsic::atomic_load_nand); return true; } case BUILT_IN_LOCK_TEST_AND_SET_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5296,11 +5361,18 @@ case BUILT_IN_LOCK_TEST_AND_SET_1: case BUILT_IN_LOCK_TEST_AND_SET_2: case BUILT_IN_LOCK_TEST_AND_SET_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif Result = BuildBinaryAtomicBuiltin(exp, Intrinsic::atomic_swap); return true; } case BUILT_IN_ADD_AND_FETCH_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5308,6 +5380,10 @@ case BUILT_IN_ADD_AND_FETCH_1: case BUILT_IN_ADD_AND_FETCH_2: case BUILT_IN_ADD_AND_FETCH_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif const Type *ResultTy = ConvertType(TREE_TYPE(exp)); tree arglist = TREE_OPERAND(exp, 1); Value* C[2] = { @@ -5340,6 +5416,9 @@ return true; } case BUILT_IN_SUB_AND_FETCH_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5347,6 +5426,10 @@ case BUILT_IN_SUB_AND_FETCH_1: case BUILT_IN_SUB_AND_FETCH_2: case BUILT_IN_SUB_AND_FETCH_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif const Type *ResultTy = ConvertType(TREE_TYPE(exp)); tree arglist = TREE_OPERAND(exp, 1); Value* C[2] = { @@ -5379,6 +5462,9 @@ return true; } case BUILT_IN_OR_AND_FETCH_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5386,6 +5472,10 @@ case BUILT_IN_OR_AND_FETCH_1: case BUILT_IN_OR_AND_FETCH_2: case BUILT_IN_OR_AND_FETCH_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif const Type *ResultTy = ConvertType(TREE_TYPE(exp)); tree arglist = TREE_OPERAND(exp, 1); Value* C[2] = { @@ -5425,6 +5515,10 @@ case BUILT_IN_AND_AND_FETCH_1: case BUILT_IN_AND_AND_FETCH_2: case BUILT_IN_AND_AND_FETCH_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif const Type *ResultTy = ConvertType(TREE_TYPE(exp)); tree arglist = TREE_OPERAND(exp, 1); Value* C[2] = { @@ -5457,6 +5551,9 @@ return true; } case BUILT_IN_XOR_AND_FETCH_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5464,6 +5561,10 @@ case BUILT_IN_XOR_AND_FETCH_1: case BUILT_IN_XOR_AND_FETCH_2: case BUILT_IN_XOR_AND_FETCH_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif const Type *ResultTy = ConvertType(TREE_TYPE(exp)); tree arglist = TREE_OPERAND(exp, 1); Value* C[2] = { @@ -5496,6 +5597,9 @@ return true; } case BUILT_IN_NAND_AND_FETCH_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; @@ -5503,6 +5607,10 @@ case BUILT_IN_NAND_AND_FETCH_1: case BUILT_IN_NAND_AND_FETCH_2: case BUILT_IN_NAND_AND_FETCH_4: { +#if defined(TARGET_ARM) + if (TARGET_THUMB1 || !arm_arch6) + return false; +#endif const Type *ResultTy = ConvertType(TREE_TYPE(exp)); tree arglist = TREE_OPERAND(exp, 1); Value* C[2] = { From isanbard at gmail.com Mon Dec 14 15:49:44 2009 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 14 Dec 2009 21:49:44 -0000 Subject: [llvm-commits] [llvm] r91337 - /llvm/trunk/lib/CodeGen/AsmPrinter/DwarfException.cpp Message-ID: <200912142149.nBELnijF018208@zion.cs.uiuc.edu> Author: void Date: Mon Dec 14 15:49:44 2009 New Revision: 91337 URL: http://llvm.org/viewvc/llvm-project?rev=91337&view=rev Log: The CIE says that the LSDA point in the FDE section is an "sdata4". That's fine, but we need it to actually be 4-bytes in the FDE. Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfException.cpp Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfException.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfException.cpp?rev=91337&r1=91336&r2=91337&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfException.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfException.cpp Mon Dec 14 15:49:44 2009 @@ -292,14 +292,13 @@ Asm->EmitULEB128Bytes(is4Byte ? 4 : 8); Asm->EOL("Augmentation size"); + // We force 32-bits here because we've encoded our LSDA in the CIE with + // `dwarf::DW_EH_PE_sdata4'. And the CIE and FDE should agree. if (EHFrameInfo.hasLandingPads) - EmitReference("exception", EHFrameInfo.Number, true, false); - else { - if (is4Byte) - Asm->EmitInt32((int)0); - else - Asm->EmitInt64((int)0); - } + EmitReference("exception", EHFrameInfo.Number, true, true); + else + Asm->EmitInt32((int)0); + Asm->EOL("Language Specific Data Area"); } else { Asm->EmitULEB128Bytes(0); From johnny.chen at apple.com Mon Dec 14 15:51:34 2009 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 14 Dec 2009 21:51:34 -0000 Subject: [llvm-commits] [llvm] r91339 - /llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Message-ID: <200912142151.nBELpYkm018291@zion.cs.uiuc.edu> Author: johnny Date: Mon Dec 14 15:51:34 2009 New Revision: 91339 URL: http://llvm.org/viewvc/llvm-project?rev=91339&view=rev Log: Add encoding bits "let Inst{11-4} = 0b00000000;" to BR_JTr to disambiguate between BR_JTr and STREXD. Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=91339&r1=91338&r2=91339&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Dec 14 15:51:34 2009 @@ -786,6 +786,7 @@ def BR_JTr : JTI<(outs), (ins GPR:$target, jtblock_operand:$jt, i32imm:$id), IIC_Br, "mov\tpc, $target \n$jt", [(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]> { + let Inst{11-4} = 0b00000000; let Inst{15-12} = 0b1111; let Inst{20} = 0; // S Bit let Inst{24-21} = 0b1101; From grosbach at apple.com Mon Dec 14 16:40:51 2009 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 14 Dec 2009 22:40:51 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r91350 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-internal.h Message-ID: <200912142240.nBEMeppR020572@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 16:40:51 2009 New Revision: 91350 URL: http://llvm.org/viewvc/llvm-project?rev=91350&view=rev Log: ARM Darwin doesn't require as strict a memory barrier Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp llvm-gcc-4.2/trunk/gcc/llvm-internal.h Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=91350&r1=91349&r2=91350&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Mon Dec 14 16:40:51 2009 @@ -4762,14 +4762,14 @@ TargetBuiltinCache.clear(); } -void TreeToLLVM::EmitMemoryBarrier(bool ll, bool ls, bool sl, bool ss) { +void TreeToLLVM::EmitMemoryBarrier(bool ll, bool ls, bool sl, bool ss, + bool device) { Value* C[5]; C[0] = ConstantInt::get(Type::getInt1Ty(Context), ll); C[1] = ConstantInt::get(Type::getInt1Ty(Context), ls); C[2] = ConstantInt::get(Type::getInt1Ty(Context), sl); C[3] = ConstantInt::get(Type::getInt1Ty(Context), ss); - // Be conservatively safe. - C[4] = ConstantInt::get(Type::getInt1Ty(Context), true); + C[4] = ConstantInt::get(Type::getInt1Ty(Context), device); Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::memory_barrier), @@ -4792,7 +4792,11 @@ "cast"); // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Value *Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, id, Ty, 2), @@ -4821,7 +4825,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Value *Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, @@ -4831,7 +4839,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif if (isBool) Result = CastToUIntType(Builder.CreateICmpEQ(Result, C[1]), @@ -5399,7 +5411,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, @@ -5409,7 +5425,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateAdd(Result, C[1]); Result = Builder.CreateIntToPtr(Result, ResultTy); @@ -5445,7 +5465,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, @@ -5455,7 +5479,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateSub(Result, C[1]); Result = Builder.CreateIntToPtr(Result, ResultTy); @@ -5491,7 +5519,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, @@ -5501,7 +5533,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateOr(Result, C[1]); Result = Builder.CreateIntToPtr(Result, ResultTy); @@ -5534,7 +5570,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, @@ -5544,7 +5584,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateAnd(Result, C[1]); Result = Builder.CreateIntToPtr(Result, ResultTy); @@ -5580,7 +5624,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, @@ -5590,7 +5638,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateXor(Result, C[1]); Result = Builder.CreateIntToPtr(Result, ResultTy); @@ -5626,7 +5678,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, @@ -5636,7 +5692,11 @@ // The gcc builtins are also full memory barriers. // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. - EmitMemoryBarrier(true, true, true, true); +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) + EmitMemoryBarrier(true, true, true, true, false); +#else + EmitMemoryBarrier(true, true, true, true, true); +#endif Result = Builder.CreateAnd(Builder.CreateNot(Result), C[1]); Result = Builder.CreateIntToPtr(Result, ResultTy); Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=91350&r1=91349&r2=91350&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Mon Dec 14 16:40:51 2009 @@ -500,7 +500,7 @@ void EmitModifyOfRegisterVariable(tree_node *vardecl, Value *RHS); // Helpers for Builtin Function Expansion. - void EmitMemoryBarrier(bool ll, bool ls, bool sl, bool ss); + void EmitMemoryBarrier(bool ll, bool ls, bool sl, bool ss, bool device); Value *BuildVector(const std::vector &Elts); Value *BuildVector(Value *Elt, ...); Value *BuildVectorShuffle(Value *InVec1, Value *InVec2, ...); From bob.wilson at apple.com Mon Dec 14 16:44:23 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Mon, 14 Dec 2009 22:44:23 -0000 Subject: [llvm-commits] [llvm] r91352 - /llvm/trunk/docs/Makefile Message-ID: <200912142244.nBEMiN6L020736@zion.cs.uiuc.edu> Author: bwilson Date: Mon Dec 14 16:44:22 2009 New Revision: 91352 URL: http://llvm.org/viewvc/llvm-project?rev=91352&view=rev Log: Rearrange rules to add missing dependency and allow parallel makes. Modified: llvm/trunk/docs/Makefile Modified: llvm/trunk/docs/Makefile URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/Makefile?rev=91352&r1=91351&r2=91352&view=diff ============================================================================== --- llvm/trunk/docs/Makefile (original) +++ llvm/trunk/docs/Makefile Mon Dec 14 16:44:22 2009 @@ -100,7 +100,12 @@ $(FIND) . -type f -exec \ $(DataInstall) {} $(PROJ_docsdir)/ocamldoc/html \; -ocamldoc: regen-ocamldoc $(PROJ_OBJ_DIR)/ocamldoc.tar.gz +ocamldoc: regen-ocamldoc + $(Echo) Packaging ocamldoc documentation + $(Verb) $(RM) -rf $(PROJ_OBJ_DIR)/ocamldoc.tar* + $(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/ocamldoc.tar ocamldoc + $(Verb) $(GZIP) $(PROJ_OBJ_DIR)/ocamldoc.tar + $(Verb) $(CP) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(PROJ_OBJ_DIR)/ocamldoc/html/ regen-ocamldoc: $(Echo) Building ocamldoc documentation @@ -113,13 +118,6 @@ $(OCAMLDOC) -d $(PROJ_OBJ_DIR)/ocamldoc/html -sort -colorize-code -html \ `$(FIND) $(LEVEL)/bindings/ocaml -name "*.odoc" -exec echo -load '{}' ';'` -$(PROJ_OBJ_DIR)/ocamldoc.tar.gz: - $(Echo) Packaging ocamldoc documentation - $(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/ocamldoc.tar - $(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/ocamldoc.tar ocamldoc - $(Verb) $(GZIP) $(PROJ_OBJ_DIR)/ocamldoc.tar - $(Verb) $(CP) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(PROJ_OBJ_DIR)/ocamldoc/html/ - uninstall-local:: $(Echo) Uninstalling Documentation $(Verb) $(RM) -rf $(PROJ_docsdir) From dpatel at apple.com Mon Dec 14 16:47:09 2009 From: dpatel at apple.com (Devang Patel) Date: Mon, 14 Dec 2009 22:47:09 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r91353 - /llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Message-ID: <200912142247.nBEMl9uw020846@zion.cs.uiuc.edu> Author: dpatel Date: Mon Dec 14 16:47:09 2009 New Revision: 91353 URL: http://llvm.org/viewvc/llvm-project?rev=91353&view=rev Log: Check for existing type descriptor in type cache. Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp?rev=91353&r1=91352&r2=91353&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Mon Dec 14 16:47:09 2009 @@ -694,9 +694,18 @@ SFlags |= llvm::DIType::FlagAppleBlock; if (type_is_block_byref_struct(type)) SFlags |= llvm::DIType::FlagBlockByrefStruct; + DIDescriptor TyContext = findRegion(TYPE_CONTEXT(type)); + + // Check if this type is created while creating context information + // descriptor. + std::map::iterator I = TypeCache.find(type); + if (I != TypeCache.end()) + if (MDNode *TN = dyn_cast_or_null(I->second)) + return DIType(TN); + llvm::DICompositeType FwdDecl = DebugFactory.CreateCompositeType(Tag, - findRegion(TYPE_CONTEXT(type)), + TyContext, FwdName.c_str(), getOrCreateCompileUnit(Loc.file), Loc.line, From gohman at apple.com Mon Dec 14 17:08:09 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 23:08:09 -0000 Subject: [llvm-commits] [llvm] r91355 - /llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Message-ID: <200912142308.nBEN89sq021688@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 17:08:09 2009 New Revision: 91355 URL: http://llvm.org/viewvc/llvm-project?rev=91355&view=rev Log: Fix this to properly clear the FastISel debug location. Thanks to Bill for spotting this! Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=91355&r1=91354&r2=91355&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Mon Dec 14 17:08:09 2009 @@ -390,7 +390,7 @@ FastISel *FastIS) { SDB->setCurDebugLoc(DebugLoc::getUnknownLoc()); if (FastIS) - SDB->setCurDebugLoc(DebugLoc::getUnknownLoc()); + FastIS->setCurDebugLoc(DebugLoc::getUnknownLoc()); } void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB, From gohman at apple.com Mon Dec 14 17:13:31 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 23:13:31 -0000 Subject: [llvm-commits] [llvm] r91356 - /llvm/trunk/include/llvm/CodeGen/ValueTypes.h Message-ID: <200912142313.nBENDVHd021865@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 17:13:31 2009 New Revision: 91356 URL: http://llvm.org/viewvc/llvm-project?rev=91356&view=rev Log: Update this comment. Modified: llvm/trunk/include/llvm/CodeGen/ValueTypes.h Modified: llvm/trunk/include/llvm/CodeGen/ValueTypes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ValueTypes.h?rev=91356&r1=91355&r2=91356&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/ValueTypes.h (original) +++ llvm/trunk/include/llvm/CodeGen/ValueTypes.h Mon Dec 14 17:13:31 2009 @@ -47,7 +47,7 @@ f80 = 9, // This is a 80 bit floating point value f128 = 10, // This is a 128 bit floating point value ppcf128 = 11, // This is a PPC 128-bit floating point value - Flag = 12, // This is a condition code or machine flag. + Flag = 12, // This glues nodes together during pre-RA sched isVoid = 13, // This has no value From gohman at apple.com Mon Dec 14 17:34:37 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 23:34:37 -0000 Subject: [llvm-commits] [llvm] r91360 - /llvm/trunk/include/llvm/Target/TargetLowering.h Message-ID: <200912142334.nBENYbkp022799@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 17:34:36 2009 New Revision: 91360 URL: http://llvm.org/viewvc/llvm-project?rev=91360&view=rev Log: Fix these asserts to check the invariant that the code actually depends on. Modified: llvm/trunk/include/llvm/Target/TargetLowering.h Modified: llvm/trunk/include/llvm/Target/TargetLowering.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=91360&r1=91359&r2=91360&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/TargetLowering.h (original) +++ llvm/trunk/include/llvm/Target/TargetLowering.h Mon Dec 14 17:34:36 2009 @@ -972,7 +972,7 @@ /// not work with the with specified type and indicate what to do about it. void setLoadExtAction(unsigned ExtType, MVT VT, LegalizeAction Action) { - assert((unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && + assert((unsigned)VT.SimpleTy*2 < 63 && ExtType < array_lengthof(LoadExtActions) && "Table isn't big enough!"); LoadExtActions[ExtType] &= ~(uint64_t(3UL) << VT.SimpleTy*2); @@ -984,7 +984,7 @@ void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action) { assert((unsigned)ValVT.SimpleTy < array_lengthof(TruncStoreActions) && - (unsigned)MemVT.SimpleTy < MVT::LAST_VALUETYPE && + (unsigned)MemVT.SimpleTy*2 < 63 && "Table isn't big enough!"); TruncStoreActions[ValVT.SimpleTy] &= ~(uint64_t(3UL) << MemVT.SimpleTy*2); TruncStoreActions[ValVT.SimpleTy] |= (uint64_t)Action << MemVT.SimpleTy*2; From gohman at apple.com Mon Dec 14 17:36:04 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 23:36:04 -0000 Subject: [llvm-commits] [llvm] r91361 - in /llvm/trunk/include/llvm/CodeGen: ValueTypes.h ValueTypes.td Message-ID: <200912142336.nBENa4Kp022852@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 17:36:03 2009 New Revision: 91361 URL: http://llvm.org/viewvc/llvm-project?rev=91361&view=rev Log: Move Flag and isVoid after the vector types, since bit arithmetic with those enum values is less common. Modified: llvm/trunk/include/llvm/CodeGen/ValueTypes.h llvm/trunk/include/llvm/CodeGen/ValueTypes.td Modified: llvm/trunk/include/llvm/CodeGen/ValueTypes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ValueTypes.h?rev=91361&r1=91360&r2=91361&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/ValueTypes.h (original) +++ llvm/trunk/include/llvm/CodeGen/ValueTypes.h Mon Dec 14 17:36:03 2009 @@ -47,35 +47,36 @@ f80 = 9, // This is a 80 bit floating point value f128 = 10, // This is a 128 bit floating point value ppcf128 = 11, // This is a PPC 128-bit floating point value - Flag = 12, // This glues nodes together during pre-RA sched - isVoid = 13, // This has no value - - v2i8 = 14, // 2 x i8 - v4i8 = 15, // 4 x i8 - v8i8 = 16, // 8 x i8 - v16i8 = 17, // 16 x i8 - v32i8 = 18, // 32 x i8 - v2i16 = 19, // 2 x i16 - v4i16 = 20, // 4 x i16 - v8i16 = 21, // 8 x i16 - v16i16 = 22, // 16 x i16 - v2i32 = 23, // 2 x i32 - v4i32 = 24, // 4 x i32 - v8i32 = 25, // 8 x i32 - v1i64 = 26, // 1 x i64 - v2i64 = 27, // 2 x i64 - v4i64 = 28, // 4 x i64 - - v2f32 = 29, // 2 x f32 - v4f32 = 30, // 4 x f32 - v8f32 = 31, // 8 x f32 - v2f64 = 32, // 2 x f64 - v4f64 = 33, // 4 x f64 + v2i8 = 12, // 2 x i8 + v4i8 = 13, // 4 x i8 + v8i8 = 14, // 8 x i8 + v16i8 = 15, // 16 x i8 + v32i8 = 16, // 32 x i8 + v2i16 = 17, // 2 x i16 + v4i16 = 18, // 4 x i16 + v8i16 = 19, // 8 x i16 + v16i16 = 20, // 16 x i16 + v2i32 = 21, // 2 x i32 + v4i32 = 22, // 4 x i32 + v8i32 = 23, // 8 x i32 + v1i64 = 24, // 1 x i64 + v2i64 = 25, // 2 x i64 + v4i64 = 26, // 4 x i64 + + v2f32 = 27, // 2 x f32 + v4f32 = 28, // 4 x f32 + v8f32 = 29, // 8 x f32 + v2f64 = 30, // 2 x f64 + v4f64 = 31, // 4 x f64 FIRST_VECTOR_VALUETYPE = v2i8, LAST_VECTOR_VALUETYPE = v4f64, + Flag = 32, // This glues nodes together during pre-RA sched + + isVoid = 33, // This has no value + LAST_VALUETYPE = 34, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. Modified: llvm/trunk/include/llvm/CodeGen/ValueTypes.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ValueTypes.td?rev=91361&r1=91360&r2=91361&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/ValueTypes.td (original) +++ llvm/trunk/include/llvm/CodeGen/ValueTypes.td Mon Dec 14 17:36:03 2009 @@ -31,30 +31,31 @@ def f80 : ValueType<80 , 9>; // 80-bit floating point value def f128 : ValueType<128, 10>; // 128-bit floating point value def ppcf128: ValueType<128, 11>; // PPC 128-bit floating point value -def FlagVT : ValueType<0 , 12>; // Condition code or machine flag -def isVoid : ValueType<0 , 13>; // Produces no value -def v2i8 : ValueType<16 , 14>; // 2 x i8 vector value -def v4i8 : ValueType<32 , 15>; // 4 x i8 vector value -def v8i8 : ValueType<64 , 16>; // 8 x i8 vector value -def v16i8 : ValueType<128, 17>; // 16 x i8 vector value -def v32i8 : ValueType<256, 18>; // 32 x i8 vector value -def v2i16 : ValueType<32 , 19>; // 2 x i16 vector value -def v4i16 : ValueType<64 , 20>; // 4 x i16 vector value -def v8i16 : ValueType<128, 21>; // 8 x i16 vector value -def v16i16 : ValueType<256, 22>; // 16 x i16 vector value -def v2i32 : ValueType<64 , 23>; // 2 x i32 vector value -def v4i32 : ValueType<128, 24>; // 4 x i32 vector value -def v8i32 : ValueType<256, 25>; // 8 x i32 vector value -def v1i64 : ValueType<64 , 26>; // 1 x i64 vector value -def v2i64 : ValueType<128, 27>; // 2 x i64 vector value -def v4i64 : ValueType<256, 28>; // 4 x f64 vector value - -def v2f32 : ValueType<64, 29>; // 2 x f32 vector value -def v4f32 : ValueType<128, 30>; // 4 x f32 vector value -def v8f32 : ValueType<256, 31>; // 8 x f32 vector value -def v2f64 : ValueType<128, 32>; // 2 x f64 vector value -def v4f64 : ValueType<256, 33>; // 4 x f64 vector value +def v2i8 : ValueType<16 , 12>; // 2 x i8 vector value +def v4i8 : ValueType<32 , 13>; // 4 x i8 vector value +def v8i8 : ValueType<64 , 14>; // 8 x i8 vector value +def v16i8 : ValueType<128, 15>; // 16 x i8 vector value +def v32i8 : ValueType<256, 16>; // 32 x i8 vector value +def v2i16 : ValueType<32 , 17>; // 2 x i16 vector value +def v4i16 : ValueType<64 , 18>; // 4 x i16 vector value +def v8i16 : ValueType<128, 19>; // 8 x i16 vector value +def v16i16 : ValueType<256, 20>; // 16 x i16 vector value +def v2i32 : ValueType<64 , 21>; // 2 x i32 vector value +def v4i32 : ValueType<128, 22>; // 4 x i32 vector value +def v8i32 : ValueType<256, 23>; // 8 x i32 vector value +def v1i64 : ValueType<64 , 24>; // 1 x i64 vector value +def v2i64 : ValueType<128, 25>; // 2 x i64 vector value +def v4i64 : ValueType<256, 26>; // 4 x f64 vector value + +def v2f32 : ValueType<64, 27>; // 2 x f32 vector value +def v4f32 : ValueType<128, 28>; // 4 x f32 vector value +def v8f32 : ValueType<256, 29>; // 8 x f32 vector value +def v2f64 : ValueType<128, 30>; // 2 x f64 vector value +def v4f64 : ValueType<256, 31>; // 4 x f64 vector value + +def FlagVT : ValueType<0 , 32>; // Pre-RA sched glue +def isVoid : ValueType<0 , 33>; // Produces no value def MetadataVT: ValueType<0, 250>; // Metadata From gohman at apple.com Mon Dec 14 17:40:38 2009 From: gohman at apple.com (Dan Gohman) Date: Mon, 14 Dec 2009 23:40:38 -0000 Subject: [llvm-commits] [llvm] r91362 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp lib/CodeGen/SelectionDAG/SelectionDAG.cpp lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/vec-trunc-store.ll Message-ID: <200912142340.nBENecaK023015@zion.cs.uiuc.edu> Author: djg Date: Mon Dec 14 17:40:38 2009 New Revision: 91362 URL: http://llvm.org/viewvc/llvm-project?rev=91362&view=rev Log: Fix integer cast code to handle vector types. Added: llvm/trunk/test/CodeGen/X86/vec-trunc-store.ll Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91362&r1=91361&r2=91362&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 17:40:38 2009 @@ -5196,7 +5196,7 @@ // SimplifyDemandedBits, which only works if the value has a single use. if (SimplifyDemandedBits(Value, APInt::getLowBitsSet( - Value.getValueSizeInBits(), + Value.getValueType().getScalarType().getSizeInBits(), ST->getMemoryVT().getSizeInBits()))) return SDValue(N, 0); } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=91362&r1=91361&r2=91362&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Dec 14 17:40:38 2009 @@ -2354,6 +2354,10 @@ assert(VT.isFloatingPoint() && Operand.getValueType().isFloatingPoint() && "Invalid FP cast!"); if (Operand.getValueType() == VT) return Operand; // noop conversion. + assert((!VT.isVector() || + VT.getVectorNumElements() == + Operand.getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); if (Operand.getOpcode() == ISD::UNDEF) return getUNDEF(VT); break; @@ -2361,8 +2365,12 @@ assert(VT.isInteger() && Operand.getValueType().isInteger() && "Invalid SIGN_EXTEND!"); if (Operand.getValueType() == VT) return Operand; // noop extension - assert(Operand.getValueType().bitsLT(VT) - && "Invalid sext node, dst < src!"); + assert(Operand.getValueType().getScalarType().bitsLT(VT.getScalarType()) && + "Invalid sext node, dst < src!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == + Operand.getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); if (OpOpcode == ISD::SIGN_EXTEND || OpOpcode == ISD::ZERO_EXTEND) return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); break; @@ -2370,8 +2378,12 @@ assert(VT.isInteger() && Operand.getValueType().isInteger() && "Invalid ZERO_EXTEND!"); if (Operand.getValueType() == VT) return Operand; // noop extension - assert(Operand.getValueType().bitsLT(VT) - && "Invalid zext node, dst < src!"); + assert(Operand.getValueType().getScalarType().bitsLT(VT.getScalarType()) && + "Invalid zext node, dst < src!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == + Operand.getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); if (OpOpcode == ISD::ZERO_EXTEND) // (zext (zext x)) -> (zext x) return getNode(ISD::ZERO_EXTEND, DL, VT, Operand.getNode()->getOperand(0)); @@ -2380,8 +2392,12 @@ assert(VT.isInteger() && Operand.getValueType().isInteger() && "Invalid ANY_EXTEND!"); if (Operand.getValueType() == VT) return Operand; // noop extension - assert(Operand.getValueType().bitsLT(VT) - && "Invalid anyext node, dst < src!"); + assert(Operand.getValueType().getScalarType().bitsLT(VT.getScalarType()) && + "Invalid anyext node, dst < src!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == + Operand.getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); if (OpOpcode == ISD::ZERO_EXTEND || OpOpcode == ISD::SIGN_EXTEND) // (ext (zext x)) -> (zext x) and (ext (sext x)) -> (sext x) return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); @@ -2390,14 +2406,19 @@ assert(VT.isInteger() && Operand.getValueType().isInteger() && "Invalid TRUNCATE!"); if (Operand.getValueType() == VT) return Operand; // noop truncate - assert(Operand.getValueType().bitsGT(VT) - && "Invalid truncate node, src < dst!"); + assert(Operand.getValueType().getScalarType().bitsGT(VT.getScalarType()) && + "Invalid truncate node, src < dst!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == + Operand.getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); if (OpOpcode == ISD::TRUNCATE) return getNode(ISD::TRUNCATE, DL, VT, Operand.getNode()->getOperand(0)); else if (OpOpcode == ISD::ZERO_EXTEND || OpOpcode == ISD::SIGN_EXTEND || OpOpcode == ISD::ANY_EXTEND) { // If the source is smaller than the dest, we still need an extend. - if (Operand.getNode()->getOperand(0).getValueType().bitsLT(VT)) + if (Operand.getNode()->getOperand(0).getValueType().getScalarType() + .bitsLT(VT.getScalarType())) return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); else if (Operand.getNode()->getOperand(0).getValueType().bitsGT(VT)) return getNode(ISD::TRUNCATE, DL, VT, Operand.getNode()->getOperand(0)); @@ -3743,16 +3764,15 @@ assert(VT == MemVT && "Non-extending load from different memory type!"); } else { // Extending load. - if (VT.isVector()) - assert(MemVT.getVectorNumElements() == VT.getVectorNumElements() && - "Invalid vector extload!"); - else - assert(MemVT.bitsLT(VT) && - "Should only be an extending load, not truncating!"); - assert((ExtType == ISD::EXTLOAD || VT.isInteger()) && - "Cannot sign/zero extend a FP/Vector load!"); + assert(MemVT.getScalarType().bitsLT(VT.getScalarType()) && + "Should only be an extending load, not truncating!"); assert(VT.isInteger() == MemVT.isInteger() && "Cannot convert from FP to Int or Int -> FP!"); + assert(VT.isVector() == MemVT.isVector() && + "Cannot use trunc store to convert to or from a vector!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == MemVT.getVectorNumElements()) && + "Cannot use trunc store to change the number of vector elements!"); } bool Indexed = AM != ISD::UNINDEXED; @@ -3885,10 +3905,15 @@ if (VT == SVT) return getStore(Chain, dl, Val, Ptr, MMO); - assert(VT.bitsGT(SVT) && "Not a truncation?"); + assert(SVT.getScalarType().bitsLT(VT.getScalarType()) && + "Should only be a truncating store, not extending!"); assert(VT.isInteger() == SVT.isInteger() && "Can't do FP-INT conversion!"); - + assert(VT.isVector() == SVT.isVector() && + "Cannot use trunc store to convert to or from a vector!"); + assert((!VT.isVector() || + VT.getVectorNumElements() == SVT.getVectorNumElements()) && + "Cannot use trunc store to change the number of vector elements!"); SDVTList VTs = getVTList(MVT::Other); SDValue Undef = getUNDEF(Ptr.getValueType()); Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=91362&r1=91361&r2=91362&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Dec 14 17:40:38 2009 @@ -596,6 +596,17 @@ setOperationAction(ISD::UINT_TO_FP, (MVT::SimpleValueType)VT, Expand); setOperationAction(ISD::SINT_TO_FP, (MVT::SimpleValueType)VT, Expand); setOperationAction(ISD::SIGN_EXTEND_INREG, (MVT::SimpleValueType)VT,Expand); + setOperationAction(ISD::TRUNCATE, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::SIGN_EXTEND, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::ZERO_EXTEND, (MVT::SimpleValueType)VT, Expand); + setOperationAction(ISD::ANY_EXTEND, (MVT::SimpleValueType)VT, Expand); + for (unsigned InnerVT = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; + InnerVT <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++InnerVT) + setTruncStoreAction((MVT::SimpleValueType)VT, + (MVT::SimpleValueType)InnerVT, Expand); + setLoadExtAction(ISD::SEXTLOAD, (MVT::SimpleValueType)VT, Expand); + setLoadExtAction(ISD::ZEXTLOAD, (MVT::SimpleValueType)VT, Expand); + setLoadExtAction(ISD::EXTLOAD, (MVT::SimpleValueType)VT, Expand); } // FIXME: In order to prevent SSE instructions being expanded to MMX ones @@ -672,8 +683,6 @@ setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4i16, Custom); - setTruncStoreAction(MVT::v8i16, MVT::v8i8, Expand); - setOperationAction(ISD::TRUNCATE, MVT::v8i8, Expand); setOperationAction(ISD::SELECT, MVT::v8i8, Promote); setOperationAction(ISD::SELECT, MVT::v4i16, Promote); setOperationAction(ISD::SELECT, MVT::v2i32, Promote); Added: llvm/trunk/test/CodeGen/X86/vec-trunc-store.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec-trunc-store.ll?rev=91362&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec-trunc-store.ll (added) +++ llvm/trunk/test/CodeGen/X86/vec-trunc-store.ll Mon Dec 14 17:40:38 2009 @@ -0,0 +1,13 @@ +; RUN: llc < %s -march=x86-64 -disable-mmx | grep punpcklwd | count 2 + +define void @foo() nounwind { + %cti69 = trunc <8 x i32> undef to <8 x i16> ; <<8 x i16>> [#uses=1] + store <8 x i16> %cti69, <8 x i16>* undef + ret void +} + +define void @bar() nounwind { + %cti44 = trunc <4 x i32> undef to <4 x i16> ; <<4 x i16>> [#uses=1] + store <4 x i16> %cti44, <4 x i16>* undef + ret void +} From anton at korobeynikov.info Mon Dec 14 18:01:01 2009 From: anton at korobeynikov.info (Anton Korobeynikov) Date: Tue, 15 Dec 2009 03:01:01 +0300 Subject: [llvm-commits] [llvm-gcc-4.2] r91350 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-internal.h In-Reply-To: <200912142240.nBEMeppR020572@zion.cs.uiuc.edu> References: <200912142240.nBEMeppR020572@zion.cs.uiuc.edu> Message-ID: Hell, Jim > - ?EmitMemoryBarrier(true, true, true, true); > +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) > + ?EmitMemoryBarrier(true, true, true, true, false); > +#else > + ?EmitMemoryBarrier(true, true, true, true, true); > +#endif Could this be moved to some target hook? I don't think we'd want a chain of target ifdef's here. Thanks! -- With best regards, Anton Korobeynikov Faculty of Mathematics and Mechanics, Saint Petersburg State University From daniel at zuster.org Mon Dec 14 18:02:42 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Tue, 15 Dec 2009 00:02:42 -0000 Subject: [llvm-commits] [test-suite] r91369 - in /test-suite/trunk/External: Makefile SPEC/CFP2006/Makefile SPEC/CINT2000/Makefile SPEC/CINT2006/Makefile Message-ID: <200912150002.nBF02gac023921@zion.cs.uiuc.edu> Author: ddunbar Date: Mon Dec 14 18:02:42 2009 New Revision: 91369 URL: http://llvm.org/viewvc/llvm-project?rev=91369&view=rev Log: NightlyTest: Implement DISABLE_CXX for externals. Modified: test-suite/trunk/External/Makefile (contents, props changed) test-suite/trunk/External/SPEC/CFP2006/Makefile (contents, props changed) test-suite/trunk/External/SPEC/CINT2000/Makefile (contents, props changed) test-suite/trunk/External/SPEC/CINT2006/Makefile (contents, props changed) Modified: test-suite/trunk/External/Makefile URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/External/Makefile?rev=91369&r1=91368&r2=91369&view=diff ============================================================================== --- test-suite/trunk/External/Makefile (original) +++ test-suite/trunk/External/Makefile Mon Dec 14 18:02:42 2009 @@ -39,4 +39,8 @@ PARALLEL_DIRS := $(filter-out Namd, $(PARALLEL_DIRS)) endif +ifdef DISABLE_CXX +PARALLEL_DIRS := $(filter-out Nurbs, $(PARALLEL_DIRS)) +endif + include Makefile.external Propchange: test-suite/trunk/External/Makefile ------------------------------------------------------------------------------ svn:executable = * Modified: test-suite/trunk/External/SPEC/CFP2006/Makefile URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/External/SPEC/CFP2006/Makefile?rev=91369&r1=91368&r2=91369&view=diff ============================================================================== --- test-suite/trunk/External/SPEC/CFP2006/Makefile (original) +++ test-suite/trunk/External/SPEC/CFP2006/Makefile Mon Dec 14 18:02:42 2009 @@ -50,6 +50,12 @@ # 465.tonto - infinite loop, works at -O0, not at -O2 # 482.sphinx3 - generates control file at run time +ifdef DISABLE_CXX +PARALLEL_DIRS := $(filter-out 444.namd, $(PARALLEL_DIRS)) +PARALLEL_DIRS := $(filter-out 447.dealII, $(PARALLEL_DIRS)) +PARALLEL_DIRS := $(filter-out 450.soplex, $(PARALLEL_DIRS)) +endif + # Get the $(ARCH) setting include $(LEVEL)/Makefile.config Propchange: test-suite/trunk/External/SPEC/CFP2006/Makefile ------------------------------------------------------------------------------ svn:executable = * Modified: test-suite/trunk/External/SPEC/CINT2000/Makefile URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/External/SPEC/CINT2000/Makefile?rev=91369&r1=91368&r2=91369&view=diff ============================================================================== --- test-suite/trunk/External/SPEC/CINT2000/Makefile (original) +++ test-suite/trunk/External/SPEC/CINT2000/Makefile Mon Dec 14 18:02:42 2009 @@ -26,4 +26,8 @@ endif +ifdef DISABLE_CXX +PARALLEL_DIRS := $(filter-out 252.eon, $(PARALLEL_DIRS)) +endif + include $(LEVEL)/Makefile.programs Propchange: test-suite/trunk/External/SPEC/CINT2000/Makefile ------------------------------------------------------------------------------ svn:executable = * Modified: test-suite/trunk/External/SPEC/CINT2006/Makefile URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/External/SPEC/CINT2006/Makefile?rev=91369&r1=91368&r2=91369&view=diff ============================================================================== --- test-suite/trunk/External/SPEC/CINT2006/Makefile (original) +++ test-suite/trunk/External/SPEC/CINT2006/Makefile Mon Dec 14 18:02:42 2009 @@ -24,6 +24,11 @@ 473.astar endif +ifdef DISABLE_CXX +PARALLEL_DIRS := $(filter-out 471.omnetpp, $(PARALLEL_DIRS)) +PARALLEL_DIRS := $(filter-out 483.xalancbmk, $(PARALLEL_DIRS)) +endif + # Get the $(ARCH) setting include $(LEVEL)/Makefile.config Propchange: test-suite/trunk/External/SPEC/CINT2006/Makefile ------------------------------------------------------------------------------ svn:executable = * From grosbach at apple.com Mon Dec 14 18:12:36 2009 From: grosbach at apple.com (Jim Grosbach) Date: Tue, 15 Dec 2009 00:12:36 -0000 Subject: [llvm-commits] [llvm] r91371 - /llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Message-ID: <200912150012.nBF0Ca4W024302@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 18:12:35 2009 New Revision: 91371 URL: http://llvm.org/viewvc/llvm-project?rev=91371&view=rev Log: nand atomic requires opposite operand ordering Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=91371&r1=91370&r2=91371&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Mon Dec 14 18:12:35 2009 @@ -3190,9 +3190,15 @@ // fallthrough --> exitMBB BB = loopMBB; AddDefaultPred(BuildMI(BB, dl, TII->get(ldrOpc), dest).addReg(ptr)); - if (BinOpcode) - AddDefaultPred(BuildMI(BB, dl, TII->get(BinOpcode), scratch2). - addReg(dest).addReg(incr)).addReg(0); + if (BinOpcode) { + // operand order needs to go the other way for NAND + if (BinOpcode == ARM::BICrr || BinOpcode == ARM::t2BICrr) + AddDefaultPred(BuildMI(BB, dl, TII->get(BinOpcode), scratch2). + addReg(incr).addReg(dest)).addReg(0); + else + AddDefaultPred(BuildMI(BB, dl, TII->get(BinOpcode), scratch2). + addReg(dest).addReg(incr)).addReg(0); + } AddDefaultPred(BuildMI(BB, dl, TII->get(strOpc), scratch).addReg(scratch2) .addReg(ptr)); From daniel at zuster.org Mon Dec 14 18:35:46 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Tue, 15 Dec 2009 00:35:46 -0000 Subject: [llvm-commits] [test-suite] r91375 - in /test-suite/trunk/MultiSource/Benchmarks: Prolangs-C/TimberWolfMC/main.c Prolangs-C/TimberWolfMC/mt.c Prolangs-C/archie-client/archie.c Prolangs-C/bison/main.c Prolangs-C/fixoutput/fixoutput.c Prolangs-C/unix-tbl/t1.c Ptrdist/ft/ft.c Ptrdist/ks/KS-2.c Ptrdist/ks/KS.h Message-ID: <200912150035.nBF0ZkE7025270@zion.cs.uiuc.edu> Author: ddunbar Date: Mon Dec 14 18:35:45 2009 New Revision: 91375 URL: http://llvm.org/viewvc/llvm-project?rev=91375&view=rev Log: Fix uses of 'void main ...', clang doesn't like this. Modified: test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/TimberWolfMC/main.c test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/TimberWolfMC/mt.c test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/archie-client/archie.c test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/bison/main.c test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/fixoutput/fixoutput.c test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/unix-tbl/t1.c test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ft/ft.c test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ks/KS-2.c test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ks/KS.h Modified: test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/TimberWolfMC/main.c URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/TimberWolfMC/main.c?rev=91375&r1=91374&r2=91375&view=diff ============================================================================== --- test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/TimberWolfMC/main.c (original) +++ test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/TimberWolfMC/main.c Mon Dec 14 18:35:45 2009 @@ -51,7 +51,7 @@ void TW_oldinput( FILE *fp ); void prepSpots(void); -void main( int argc , char *argv[]) +int main( int argc , char *argv[]) { FILE *fp , *fopen() ; @@ -330,6 +330,7 @@ fprintf(fpo,"\n\n************************************ \n\n"); fclose(fpo); exit(0); +return 0; } Modified: test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/TimberWolfMC/mt.c URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/TimberWolfMC/mt.c?rev=91375&r1=91374&r2=91375&view=diff ============================================================================== --- test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/TimberWolfMC/mt.c (original) +++ test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/TimberWolfMC/mt.c Mon Dec 14 18:35:45 2009 @@ -406,7 +406,7 @@ } #ifdef TEST1 -void main(void) +int main(void) { int selection; MT *t; @@ -475,5 +475,6 @@ default: printf("What?\n"); break; } } + return 0; } #endif Modified: test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/archie-client/archie.c URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/archie-client/archie.c?rev=91375&r1=91374&r2=91375&view=diff ============================================================================== --- test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/archie-client/archie.c (original) +++ test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/archie-client/archie.c Mon Dec 14 18:35:45 2009 @@ -63,7 +63,7 @@ #define ARCHIE_HOST "archie.rutgers.edu" -void main(int argc,char *argv[]) +int main(int argc,char *argv[]) { char *cur_arg; char qtype = '='; /* Default to exact string match */ @@ -287,4 +287,5 @@ netshut(); #endif exit(0); + return 0; } Modified: test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/bison/main.c URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/bison/main.c?rev=91375&r1=91374&r2=91375&view=diff ============================================================================== --- test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/bison/main.c (original) +++ test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/bison/main.c Mon Dec 14 18:35:45 2009 @@ -40,7 +40,7 @@ extern void output(void); extern void done(int k); -void main(int argc,char *argv[]) +int main(int argc,char *argv[]) { failure = 0; lineno = 0; @@ -78,6 +78,7 @@ /* output the tables and the parser to ftable. In file output. */ output(); done(failure); + return 0; } /* functions to report errors which prevent a parser from being generated */ Modified: test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/fixoutput/fixoutput.c URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/fixoutput/fixoutput.c?rev=91375&r1=91374&r2=91375&view=diff ============================================================================== --- test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/fixoutput/fixoutput.c (original) +++ test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/fixoutput/fixoutput.c Mon Dec 14 18:35:45 2009 @@ -1,4 +1,5 @@ + #include "scanner.h" /* Useful Macro Definitions */ #include @@ -39,7 +40,7 @@ EOF_FLAG = 0; } -void main(void) +int main(void) { int CODE; /* TOKEN CODE */ int I1,I2; /* temp storage */ @@ -318,4 +319,5 @@ printf("****** %d format errors found in output of your scanner.\n", ERROR_CNT); exit(0); + return 0; } Modified: test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/unix-tbl/t1.c URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/unix-tbl/t1.c?rev=91375&r1=91374&r2=91375&view=diff ============================================================================== --- test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/unix-tbl/t1.c (original) +++ test-suite/trunk/MultiSource/Benchmarks/Prolangs-C/unix-tbl/t1.c Mon Dec 14 18:35:45 2009 @@ -33,7 +33,7 @@ int swapin(void); -void main(int argc,char *argv[]) +int main(int argc,char *argv[]) { extern init_options(); # ifdef unix @@ -45,6 +45,7 @@ # endif init_options(); exit(tbl(argc,argv)); +return 0; } Modified: test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ft/ft.c URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ft/ft.c?rev=91375&r1=91374&r2=91375&view=diff ============================================================================== --- test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ft/ft.c (original) +++ test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ft/ft.c Mon Dec 14 18:35:45 2009 @@ -65,7 +65,7 @@ */ int debug = 1; -void +int main(int argc, char *argv[]) { int nVertex; @@ -119,6 +119,7 @@ PrintHeapSize(stderr); #endif /* PLUS_STATS */ exit(0); + return 0; } Vertices * Modified: test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ks/KS-2.c URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ks/KS-2.c?rev=91375&r1=91374&r2=91375&view=diff ============================================================================== --- test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ks/KS-2.c (original) +++ test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ks/KS-2.c Mon Dec 14 18:35:45 2009 @@ -323,7 +323,7 @@ netStats[i].edgesCut, netStats[i].netsCut); } -void +int main(int argc, char **argv) { unsigned long p, iMax; @@ -405,4 +405,5 @@ PrintHeapSize(stderr); #endif /* PLUS_STATS */ exit(0); + return 0; } Modified: test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ks/KS.h URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ks/KS.h?rev=91375&r1=91374&r2=91375&view=diff ============================================================================== --- test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ks/KS.h (original) +++ test-suite/trunk/MultiSource/Benchmarks/Ptrdist/ks/KS.h Mon Dec 14 18:35:45 2009 @@ -95,4 +95,4 @@ float FindMaxGpAndSwap(); void SwapSubsetAndReset(unsigned long iMax); void PrintResults(int verbose); -void main(int argc, char **argv); +int main(int argc, char **argv); From grosbach at apple.com Mon Dec 14 18:36:25 2009 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 14 Dec 2009 16:36:25 -0800 Subject: [llvm-commits] [llvm-gcc-4.2] r91350 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-internal.h In-Reply-To: References: <200912142240.nBEMeppR020572@zion.cs.uiuc.edu> Message-ID: On Dec 14, 2009, at 4:01 PM, Anton Korobeynikov wrote: >> - EmitMemoryBarrier(true, true, true, true); >> +#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) >> + EmitMemoryBarrier(true, true, true, true, false); >> +#else >> + EmitMemoryBarrier(true, true, true, true, true); >> +#endif > Could this be moved to some target hook? I don't think we'd want a > chain of target ifdef's here. > Maybe? I agree having a bunch of ifdef stuff there is pretty ugly. I'm not sure how best to do target-specific bits in the front end, though, so I added these bits in the same manner the current PowerPC-specific portions are done. Likewise, the whole sequence for the atomics is conditionalized on whether the target is known to support the intrinsics, which is suboptimal. Much better would be to always create the intrinsics, then the legalizer (probably) could check if the back end explicitly supports them, and insert the library support calls if it doesn't. That sort of refactoring is beyond the scope of what I was looking to do here, though, so I just stayed with the current scheme. I'd wholeheartedly support it if someone with more frontend expertise than I wanted to make something like that happen, though. -Jim From isanbard at gmail.com Mon Dec 14 18:39:25 2009 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 15 Dec 2009 00:39:25 -0000 Subject: [llvm-commits] [llvm] r91376 - in /llvm/trunk: include/llvm/CodeGen/MachineBasicBlock.h lib/CodeGen/BranchFolding.cpp lib/CodeGen/MachineBasicBlock.cpp Message-ID: <200912150039.nBF0dPpY025409@zion.cs.uiuc.edu> Author: void Date: Mon Dec 14 18:39:24 2009 New Revision: 91376 URL: http://llvm.org/viewvc/llvm-project?rev=91376&view=rev Log: Revert these. They may have been causing 483_xalancbmk to fail: $ svn merge -c -91161 https://llvm.org/svn/llvm-project/llvm/trunk --- Reverse-merging r91161 into '.': U lib/CodeGen/BranchFolding.cpp U lib/CodeGen/MachineBasicBlock.cpp $ svn merge -c -91113 https://llvm.org/svn/llvm-project/llvm/trunk --- Reverse-merging r91113 into '.': G lib/CodeGen/MachineBasicBlock.cpp $ svn merge -c -91101 https://llvm.org/svn/llvm-project/llvm/trunk --- Reverse-merging r91101 into '.': U include/llvm/CodeGen/MachineBasicBlock.h G lib/CodeGen/MachineBasicBlock.cpp $ svn merge -c -91092 https://llvm.org/svn/llvm-project/llvm/trunk --- Reverse-merging r91092 into '.': G include/llvm/CodeGen/MachineBasicBlock.h G lib/CodeGen/MachineBasicBlock.cpp Modified: llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h llvm/trunk/lib/CodeGen/BranchFolding.cpp llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp Modified: llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h?rev=91376&r1=91375&r2=91376&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h (original) +++ llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h Mon Dec 14 18:39:24 2009 @@ -327,11 +327,6 @@ /// 'Old', change the code and CFG so that it branches to 'New' instead. void ReplaceUsesOfBlockWith(MachineBasicBlock *Old, MachineBasicBlock *New); - /// BranchesToLandingPad - The basic block is a landing pad or branches only - /// to a landing pad. No other instructions are present other than the - /// unconditional branch. - bool BranchesToLandingPad(const MachineBasicBlock *MBB) const; - /// CorrectExtraCFGEdges - Various pieces of code can cause excess edges in /// the CFG to be inserted. If we have proven that MBB can only branch to /// DestA and DestB, remove any other MBB successors from the CFG. DestA and Modified: llvm/trunk/lib/CodeGen/BranchFolding.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/BranchFolding.cpp?rev=91376&r1=91375&r2=91376&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/BranchFolding.cpp (original) +++ llvm/trunk/lib/CodeGen/BranchFolding.cpp Mon Dec 14 18:39:24 2009 @@ -1205,11 +1205,11 @@ } } - // If the prior block doesn't fall through into this block and if this block - // doesn't fall through into some other block and it's not branching only to a - // landing pad, then see if we can find a place to move this block where a - // fall-through will happen. - if (!PrevBB.canFallThrough() && !MBB->BranchesToLandingPad(MBB)) { + // If the prior block doesn't fall through into this block, and if this + // block doesn't fall through into some other block, see if we can find a + // place to move this block where a fall-through will happen. + if (!PrevBB.canFallThrough()) { + // Now we know that there was no fall-through into this block, check to // see if it has a fall-through into its successor. bool CurFallsThru = MBB->canFallThrough(); @@ -1221,32 +1221,28 @@ E = MBB->pred_end(); PI != E; ++PI) { // Analyze the branch at the end of the pred. MachineBasicBlock *PredBB = *PI; - MachineFunction::iterator PredNextBB = PredBB; ++PredNextBB; + MachineFunction::iterator PredFallthrough = PredBB; ++PredFallthrough; MachineBasicBlock *PredTBB, *PredFBB; SmallVector PredCond; - if (PredBB != MBB && !PredBB->canFallThrough() - && !TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true) + if (PredBB != MBB && !PredBB->canFallThrough() && + !TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true) && (!CurFallsThru || !CurTBB || !CurFBB) && (!CurFallsThru || MBB->getNumber() >= PredBB->getNumber())) { - // If the current block doesn't fall through, just move it. If the - // current block can fall through and does not end with a conditional - // branch, we need to append an unconditional jump to the (current) - // next block. To avoid a possible compile-time infinite loop, move - // blocks only backward in this case. - // - // Also, if there are already 2 branches here, we cannot add a third. - // I.e. we have the case: - // - // Bcc next - // B elsewhere - // next: + // If the current block doesn't fall through, just move it. + // If the current block can fall through and does not end with a + // conditional branch, we need to append an unconditional jump to + // the (current) next block. To avoid a possible compile-time + // infinite loop, move blocks only backward in this case. + // Also, if there are already 2 branches here, we cannot add a third; + // this means we have the case + // Bcc next + // B elsewhere + // next: if (CurFallsThru) { - MachineBasicBlock *NextBB = - llvm::next(MachineFunction::iterator(MBB)); + MachineBasicBlock *NextBB = llvm::next(MachineFunction::iterator(MBB)); CurCond.clear(); TII->InsertBranch(*MBB, NextBB, 0, CurCond); } - MBB->moveAfter(PredBB); MadeChange = true; goto ReoptimizeBlock; Modified: llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp?rev=91376&r1=91375&r2=91376&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp (original) +++ llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp Mon Dec 14 18:39:24 2009 @@ -13,16 +13,15 @@ #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/BasicBlock.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrDesc.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/LeakDetector.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Assembly/Writer.h" #include using namespace llvm; @@ -449,28 +448,10 @@ addSuccessor(New); } -/// BranchesToLandingPad - The basic block is a landing pad or branches only to -/// a landing pad. No other instructions are present other than the -/// unconditional branch. -bool -MachineBasicBlock::BranchesToLandingPad(const MachineBasicBlock *MBB) const { - SmallSet Visited; - const MachineBasicBlock *CurMBB = MBB; - - while (!CurMBB->isLandingPad()) { - if (CurMBB->succ_size() != 1) break; - if (!Visited.insert(CurMBB)) break; - CurMBB = *CurMBB->succ_begin(); - } - - return CurMBB->isLandingPad(); -} - /// CorrectExtraCFGEdges - Various pieces of code can cause excess edges in the /// CFG to be inserted. If we have proven that MBB can only branch to DestA and /// DestB, remove any other MBB successors from the CFG. DestA and DestB can /// be null. -/// /// Besides DestA and DestB, retain other edges leading to LandingPads /// (currently there can be only one; we don't check or require that here). /// Note it is possible that DestA and/or DestB are LandingPads. @@ -500,17 +481,16 @@ } MachineBasicBlock::succ_iterator SI = succ_begin(); - const MachineBasicBlock *OrigDestA = DestA, *OrigDestB = DestB; + MachineBasicBlock *OrigDestA = DestA, *OrigDestB = DestB; while (SI != succ_end()) { - const MachineBasicBlock *MBB = *SI; - if (MBB == DestA) { + if (*SI == DestA) { DestA = 0; ++SI; - } else if (MBB == DestB) { + } else if (*SI == DestB) { DestB = 0; ++SI; - } else if (MBB != OrigDestA && MBB != OrigDestB && - BranchesToLandingPad(MBB)) { + } else if ((*SI)->isLandingPad() && + *SI!=OrigDestA && *SI!=OrigDestB) { ++SI; } else { // Otherwise, this is a superfluous edge, remove it. @@ -518,14 +498,12 @@ MadeChange = true; } } - if (!AddedFallThrough) { assert(DestA == 0 && DestB == 0 && "MachineCFG is missing edges!"); } else if (isCond) { assert(DestA == 0 && "MachineCFG is missing edges!"); } - return MadeChange; } From echristo at apple.com Mon Dec 14 18:40:55 2009 From: echristo at apple.com (Eric Christopher) Date: Tue, 15 Dec 2009 00:40:55 -0000 Subject: [llvm-commits] [llvm] r91377 - /llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp Message-ID: <200912150040.nBF0et2w025465@zion.cs.uiuc.edu> Author: echristo Date: Mon Dec 14 18:40:55 2009 New Revision: 91377 URL: http://llvm.org/viewvc/llvm-project?rev=91377&view=rev Log: Formatting. Modified: llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp Modified: llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp?rev=91377&r1=91376&r2=91377&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp Mon Dec 14 18:40:55 2009 @@ -208,7 +208,7 @@ JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode, - CodeModel::Model CMM) { + CodeModel::Model CMM) { // Make sure we can resolve symbols in the program as well. The zero arg // to the function tells DynamicLibrary to load the program, not a library. if (sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr)) From evan.cheng at apple.com Mon Dec 14 18:41:36 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 15 Dec 2009 00:41:36 -0000 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll Message-ID: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> Author: evancheng Date: Mon Dec 14 18:41:36 2009 New Revision: 91378 URL: http://llvm.org/viewvc/llvm-project?rev=91378&view=rev Log: Propagate zest through logical shift. Added: llvm/trunk/test/CodeGen/X86/setcc.ll llvm/trunk/test/CodeGen/X86/zext-shl.ll Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91378&r1=91377&r2=91378&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:41:36 2009 @@ -3278,6 +3278,16 @@ if (SCC.getNode()) return SCC; } + // (zext (shl (zext x), y)) -> (shl (zext x), (zext y)) + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL) && + N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND && + N0.hasOneUse()) { + DebugLoc dl = N->getDebugLoc(); + return DAG.getNode(N0.getOpcode(), dl, VT, + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(0)), + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(1))); + } + return SDValue(); } Added: llvm/trunk/test/CodeGen/X86/setcc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=91378&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/setcc.ll (added) +++ llvm/trunk/test/CodeGen/X86/setcc.ll Mon Dec 14 18:41:36 2009 @@ -0,0 +1,13 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s + +define zeroext i16 @t1(i16 zeroext %x) nounwind readnone ssp { +entry: +; CHECK: t1: +; CHECK: seta %al +; CHECK: movzbl %al, %eax +; CHECK: shll $5, %eax + %0 = icmp ugt i16 %x, 26 ; [#uses=1] + %iftmp.1.0 = select i1 %0, i16 32, i16 0 ; [#uses=1] + ret i16 %iftmp.1.0 +} + Added: llvm/trunk/test/CodeGen/X86/zext-shl.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/zext-shl.ll?rev=91378&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/zext-shl.ll (added) +++ llvm/trunk/test/CodeGen/X86/zext-shl.ll Mon Dec 14 18:41:36 2009 @@ -0,0 +1,38 @@ +; RUN: llc < %s -march=x86 | FileCheck %s + +define i32 @t1(i8 zeroext %x) nounwind readnone ssp { +entry: +; CHECK: t1: +; CHECK: shll +; CHECK-NOT: movzwl +; CHECK: ret + %0 = zext i8 %x to i16 + %1 = shl i16 %0, 5 + %2 = zext i16 %1 to i32 + ret i32 %2 +} + +define i32 @t2(i8 zeroext %x) nounwind readnone ssp { +entry: +; CHECK: t2: +; CHECK: shrl +; CHECK-NOT: movzwl +; CHECK: ret + %0 = zext i8 %x to i16 + %1 = lshr i16 %0, 3 + %2 = zext i16 %1 to i32 + ret i32 %2 +} + +define i32 @t3(i8 zeroext %x, i8 zeroext %y) nounwind readnone ssp { +entry: +; CHECK: t3: +; CHECK: shll +; CHECK-NOT: movzwl +; CHECK: ret + %0 = zext i8 %x to i16 + %1 = zext i8 %y to i16 + %2 = shl i16 %0, %1 + %3 = zext i16 %2 to i32 + ret i32 %3 +} From daniel at zuster.org Mon Dec 14 18:41:47 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Tue, 15 Dec 2009 00:41:47 -0000 Subject: [llvm-commits] [llvm] r91379 - /llvm/trunk/utils/NewNightlyTest.pl Message-ID: <200912150041.nBF0flOX025512@zion.cs.uiuc.edu> Author: ddunbar Date: Mon Dec 14 18:41:47 2009 New Revision: 91379 URL: http://llvm.org/viewvc/llvm-project?rev=91379&view=rev Log: NNT: Make sure stderr for build commands goes to log file, as intended but misdirected. Modified: llvm/trunk/utils/NewNightlyTest.pl Modified: llvm/trunk/utils/NewNightlyTest.pl URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/NewNightlyTest.pl?rev=91379&r1=91378&r2=91379&view=diff ============================================================================== --- llvm/trunk/utils/NewNightlyTest.pl (original) +++ llvm/trunk/utils/NewNightlyTest.pl Mon Dec 14 18:41:47 2009 @@ -317,9 +317,9 @@ } else { if ($VERBOSE) { print "$Title\n"; - print "$Command 2>&1 > $Log\n"; + print "$Command > $Log 2>&1\n"; } - system "$Command 2>&1 > $Log"; + system "$Command > $Log 2>&1"; } } @@ -336,9 +336,9 @@ } else { if ($VERBOSE) { print "$Title\n"; - print "$Command 2>&1 > $Log\n"; + print "$Command >> $Log 2>&1\n"; } - system "$Command 2>&1 >> $Log"; + system "$Command >> $Log 2>&1"; } } From evan.cheng at apple.com Mon Dec 14 18:52:11 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 15 Dec 2009 00:52:11 -0000 Subject: [llvm-commits] [llvm] r91380 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/CellSPU/and_ops.ll Message-ID: <200912150052.nBF0qBhN025917@zion.cs.uiuc.edu> Author: evancheng Date: Mon Dec 14 18:52:11 2009 New Revision: 91380 URL: http://llvm.org/viewvc/llvm-project?rev=91380&view=rev Log: Fold (zext (and x, cst)) -> (and (zext x), cst). Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp llvm/trunk/test/CodeGen/CellSPU/and_ops.ll Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91380&r1=91379&r2=91380&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:52:11 2009 @@ -3202,6 +3202,19 @@ X, DAG.getConstant(Mask, VT)); } + // Fold (zext (and x, cst)) -> (and (zext x), cst) + if (N0.getOpcode() == ISD::AND && + N0.getOperand(1).getOpcode() == ISD::Constant && + N0.getOperand(0).getOpcode() != ISD::TRUNCATE && + N0.getOperand(0).hasOneUse()) { + APInt Mask = cast(N0.getOperand(1))->getAPIntValue(); + Mask.zext(VT.getSizeInBits()); + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, + N0.getOperand(0)), + DAG.getConstant(Mask, VT)); + } + // fold (zext (load x)) -> (zext (truncate (zextload x))) if (ISD::isNON_EXTLoad(N0.getNode()) && ((!LegalOperations && !cast(N0)->isVolatile()) || Modified: llvm/trunk/test/CodeGen/CellSPU/and_ops.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CellSPU/and_ops.ll?rev=91380&r1=91379&r2=91380&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/CellSPU/and_ops.ll (original) +++ llvm/trunk/test/CodeGen/CellSPU/and_ops.ll Mon Dec 14 18:52:11 2009 @@ -1,9 +1,9 @@ ; RUN: llc < %s -march=cellspu > %t1.s -; RUN: grep and %t1.s | count 234 +; RUN: grep and %t1.s | count 230 ; RUN: grep andc %t1.s | count 85 -; RUN: grep andi %t1.s | count 37 -; RUN: grep andhi %t1.s | count 30 -; RUN: grep andbi %t1.s | count 4 +; RUN: grep andi %t1.s | count 39 +; RUN: grep andhi %t1.s | count 28 +; RUN: grep andbi %t1.s | count 2 target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128" target triple = "spu" From evan.cheng at apple.com Mon Dec 14 18:53:42 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 15 Dec 2009 00:53:42 -0000 Subject: [llvm-commits] [llvm] r91381 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86ISelLowering.h lib/Target/X86/X86Instr64bit.td lib/Target/X86/X86InstrInfo.td test/CodeGen/X86/setcc.ll Message-ID: <200912150053.nBF0rhfK025969@zion.cs.uiuc.edu> Author: evancheng Date: Mon Dec 14 18:53:42 2009 New Revision: 91381 URL: http://llvm.org/viewvc/llvm-project?rev=91381&view=rev Log: Use sbb x, x to materialize carry bit in a GPR. The result is all one's or all zero's. Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/lib/Target/X86/X86ISelLowering.h llvm/trunk/lib/Target/X86/X86Instr64bit.td llvm/trunk/lib/Target/X86/X86InstrInfo.td llvm/trunk/test/CodeGen/X86/setcc.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=91381&r1=91380&r2=91381&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Dec 14 18:53:42 2009 @@ -5750,6 +5750,15 @@ return SDValue(); SDValue Cond = EmitCmp(Op0, Op1, X86CC, DAG); + + // Use sbb x, x to materialize carry bit into a GPR. + if (X86CC == X86::COND_B) { + return DAG.getNode(ISD::AND, dl, MVT::i8, + DAG.getNode(X86ISD::SETCC_CARRY, dl, MVT::i8, + DAG.getConstant(X86CC, MVT::i8), Cond), + DAG.getConstant(1, MVT::i8)); + } + return DAG.getNode(X86ISD::SETCC, dl, MVT::i8, DAG.getConstant(X86CC, MVT::i8), Cond); } @@ -5902,9 +5911,18 @@ Cond = NewCond; } + // Look pass (and (setcc_carry (cmp ...)), 1). + if (Cond.getOpcode() == ISD::AND && + Cond.getOperand(0).getOpcode() == X86ISD::SETCC_CARRY) { + ConstantSDNode *C = dyn_cast(Cond.getOperand(1)); + if (C && C->getAPIntValue() == 1) + Cond = Cond.getOperand(0); + } + // If condition flag is set by a X86ISD::CMP, then use it as the condition // setting operand in place of the X86ISD::SETCC. - if (Cond.getOpcode() == X86ISD::SETCC) { + if (Cond.getOpcode() == X86ISD::SETCC || + Cond.getOpcode() == X86ISD::SETCC_CARRY) { CC = Cond.getOperand(0); SDValue Cmp = Cond.getOperand(1); @@ -5987,9 +6005,18 @@ Cond = LowerXALUO(Cond, DAG); #endif + // Look pass (and (setcc_carry (cmp ...)), 1). + if (Cond.getOpcode() == ISD::AND && + Cond.getOperand(0).getOpcode() == X86ISD::SETCC_CARRY) { + ConstantSDNode *C = dyn_cast(Cond.getOperand(1)); + if (C && C->getAPIntValue() == 1) + Cond = Cond.getOperand(0); + } + // If condition flag is set by a X86ISD::CMP, then use it as the condition // setting operand in place of the X86ISD::SETCC. - if (Cond.getOpcode() == X86ISD::SETCC) { + if (Cond.getOpcode() == X86ISD::SETCC || + Cond.getOpcode() == X86ISD::SETCC_CARRY) { CC = Cond.getOperand(0); SDValue Cmp = Cond.getOperand(1); @@ -7376,6 +7403,7 @@ case X86ISD::COMI: return "X86ISD::COMI"; case X86ISD::UCOMI: return "X86ISD::UCOMI"; case X86ISD::SETCC: return "X86ISD::SETCC"; + case X86ISD::SETCC_CARRY: return "X86ISD::SETCC_CARRY"; case X86ISD::CMOV: return "X86ISD::CMOV"; case X86ISD::BRCOND: return "X86ISD::BRCOND"; case X86ISD::RET_FLAG: return "X86ISD::RET_FLAG"; @@ -8950,11 +8978,42 @@ return SDValue(); } +static SDValue PerformSHLCombine(SDNode *N, SelectionDAG &DAG) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + ConstantSDNode *N1C = dyn_cast(N1); + EVT VT = N0.getValueType(); + + // fold (shl (and (setcc_c), c1), c2) -> (and setcc_c, (c1 << c2)) + // since the result of setcc_c is all zero's or all ones. + if (N1C && N0.getOpcode() == ISD::AND && + N0.getOperand(1).getOpcode() == ISD::Constant) { + SDValue N00 = N0.getOperand(0); + if (N00.getOpcode() == X86ISD::SETCC_CARRY || + ((N00.getOpcode() == ISD::ANY_EXTEND || + N00.getOpcode() == ISD::ZERO_EXTEND) && + N00.getOperand(0).getOpcode() == X86ISD::SETCC_CARRY)) { + APInt Mask = cast(N0.getOperand(1))->getAPIntValue(); + APInt ShAmt = N1C->getAPIntValue(); + Mask = Mask.shl(ShAmt); + if (Mask != 0) + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + N00, DAG.getConstant(Mask, VT)); + } + } + + return SDValue(); +} /// PerformShiftCombine - Transforms vector shift nodes to use vector shifts /// when possible. static SDValue PerformShiftCombine(SDNode* N, SelectionDAG &DAG, const X86Subtarget *Subtarget) { + EVT VT = N->getValueType(0); + if (!VT.isVector() && VT.isInteger() && + N->getOpcode() == ISD::SHL) + return PerformSHLCombine(N, DAG); + // On X86 with SSE2 support, we can transform this to a vector shift if // all elements are shifted by the same amount. We can't do this in legalize // because the a constant vector is typically transformed to a constant pool @@ -8962,7 +9021,6 @@ if (!Subtarget->hasSSE2()) return SDValue(); - EVT VT = N->getValueType(0); if (VT != MVT::v2i64 && VT != MVT::v4i32 && VT != MVT::v8i16) return SDValue(); Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.h?rev=91381&r1=91380&r2=91381&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Mon Dec 14 18:53:42 2009 @@ -118,6 +118,10 @@ /// operand produced by a CMP instruction. SETCC, + // Same as SETCC except it's materialized with a sbb and the value is all + // one's or all zero's. + SETCC_CARRY, + /// X86 conditional moves. Operand 0 and operand 1 are the two values /// to select from. Operand 2 is the condition code, and operand 3 is the /// flag operand produced by a CMP or TEST instruction. It also writes a Modified: llvm/trunk/lib/Target/X86/X86Instr64bit.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Instr64bit.td?rev=91381&r1=91380&r2=91381&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original) +++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Mon Dec 14 18:53:42 2009 @@ -1333,6 +1333,15 @@ X86_COND_NO, EFLAGS))]>, TB; } // isTwoAddress +// Use sbb to materialize carry flag into a GPR. +let Defs = [EFLAGS], Uses = [EFLAGS], isCodeGenOnly = 1 in +def SETB_C64r : RI<0x19, MRMDestReg, (outs GR64:$dst), (ins), + "sbb{q}\t$dst, $dst", + [(set GR64:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>; + +def : Pat<(i64 (anyext (X86setcc_c X86_COND_B, EFLAGS))), + (SETB_C64r)>; + //===----------------------------------------------------------------------===// // Conversion Instructions... // Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=91381&r1=91380&r2=91381&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Mon Dec 14 18:53:42 2009 @@ -87,6 +87,7 @@ def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>; def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC>; +def X86setcc_c : SDNode<"X86ISD::SETCC_CARRY", SDTX86SetCC>; def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas, [SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore, @@ -3059,6 +3060,21 @@ def LAHF : I<0x9F, RawFrm, (outs), (ins), "lahf", []>; // AH = flags let Uses = [EFLAGS] in { +// Use sbb to materialize carry bit. + +let Defs = [EFLAGS], isCodeGenOnly = 1 in { +def SETB_C8r : I<0x18, MRMInitReg, (outs GR8:$dst), (ins), + "sbb{b}\t$dst, $dst", + [(set GR8:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; +def SETB_C16r : I<0x19, MRMInitReg, (outs GR16:$dst), (ins), + "sbb{w}\t$dst, $dst", + [(set GR16:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>, + OpSize; +def SETB_C32r : I<0x19, MRMInitReg, (outs GR32:$dst), (ins), + "sbb{l}\t$dst, $dst", + [(set GR32:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>; +} // isCodeGenOnly + def SETEr : I<0x94, MRM0r, (outs GR8 :$dst), (ins), "sete\t$dst", @@ -4169,6 +4185,12 @@ GR16:$src2, (i8 imm:$amt2)), addr:$dst), (SHLD16mri8 addr:$dst, GR16:$src2, (i8 imm:$amt1))>; +// (anyext (setcc_carry)) -> (zext (setcc_carry)) +def : Pat<(i16 (anyext (X86setcc_c X86_COND_B, EFLAGS))), + (SETB_C16r)>; +def : Pat<(i32 (anyext (X86setcc_c X86_COND_B, EFLAGS))), + (SETB_C32r)>; + //===----------------------------------------------------------------------===// // EFLAGS-defining Patterns //===----------------------------------------------------------------------===// Modified: llvm/trunk/test/CodeGen/X86/setcc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=91381&r1=91380&r2=91381&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/setcc.ll (original) +++ llvm/trunk/test/CodeGen/X86/setcc.ll Mon Dec 14 18:53:42 2009 @@ -1,4 +1,8 @@ ; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s +; rdar://7329206 + +; Use sbb x, x to materialize carry bit in a GPR. The value is either +; all 1's or all 0's. define zeroext i16 @t1(i16 zeroext %x) nounwind readnone ssp { entry: @@ -11,3 +15,22 @@ ret i16 %iftmp.1.0 } +define zeroext i16 @t2(i16 zeroext %x) nounwind readnone ssp { +entry: +; CHECK: t2: +; CHECK: sbbl %eax, %eax +; CHECK: andl $32, %eax + %0 = icmp ult i16 %x, 26 ; [#uses=1] + %iftmp.0.0 = select i1 %0, i16 32, i16 0 ; [#uses=1] + ret i16 %iftmp.0.0 +} + +define i64 @t3(i64 %x) nounwind readnone ssp { +entry: +; CHECK: t3: +; CHECK: sbbq %rax, %rax +; CHECK: andq $64, %rax + %0 = icmp ult i64 %x, 18 ; [#uses=1] + %iftmp.2.0 = select i1 %0, i64 64, i64 0 ; [#uses=1] + ret i64 %iftmp.2.0 +} From clattner at apple.com Mon Dec 14 19:00:01 2009 From: clattner at apple.com (Chris Lattner) Date: Mon, 14 Dec 2009 17:00:01 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> Message-ID: On Dec 14, 2009, at 4:41 PM, Evan Cheng wrote: > Author: evancheng > Date: Mon Dec 14 18:41:36 2009 > New Revision: 91378 > > URL: http://llvm.org/viewvc/llvm-project?rev=91378&view=rev > Log: > Propagate zest through logical shift. Is this really profitable in the general case? It seems that this should only be done if at least one of the inputs to the shift will fold away. Adding a nice "WouldFoldAZExt" predicate that would return true for zext/trunc would make sense, no? -Chris > > Added: > llvm/trunk/test/CodeGen/X86/setcc.ll > llvm/trunk/test/CodeGen/X86/zext-shl.ll > Modified: > llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91378&r1=91377&r2=91378&view=diff > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 > 18:41:36 2009 > @@ -3278,6 +3278,16 @@ > if (SCC.getNode()) return SCC; > } > > + // (zext (shl (zext x), y)) -> (shl (zext x), (zext y)) > + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL) && > + N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND && > + N0.hasOneUse()) { > + DebugLoc dl = N->getDebugLoc(); > + return DAG.getNode(N0.getOpcode(), dl, VT, > + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, > N0.getOperand(0)), > + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, > N0.getOperand(1))); > + } > + > return SDValue(); > } > > > Added: llvm/trunk/test/CodeGen/X86/setcc.ll > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=91378&view=auto > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/test/CodeGen/X86/setcc.ll (added) > +++ llvm/trunk/test/CodeGen/X86/setcc.ll Mon Dec 14 18:41:36 2009 > @@ -0,0 +1,13 @@ > +; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s > + > +define zeroext i16 @t1(i16 zeroext %x) nounwind readnone ssp { > +entry: > +; CHECK: t1: > +; CHECK: seta %al > +; CHECK: movzbl %al, %eax > +; CHECK: shll $5, %eax > + %0 = icmp ugt i16 %x, 26 ; [#uses=1] > + %iftmp.1.0 = select i1 %0, i16 32, i16 0 ; [#uses=1] > + ret i16 %iftmp.1.0 > +} > + > > Added: llvm/trunk/test/CodeGen/X86/zext-shl.ll > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/zext-shl.ll?rev=91378&view=auto > > = > = > = > = > = > = > = > = > ====================================================================== > --- llvm/trunk/test/CodeGen/X86/zext-shl.ll (added) > +++ llvm/trunk/test/CodeGen/X86/zext-shl.ll Mon Dec 14 18:41:36 2009 > @@ -0,0 +1,38 @@ > +; RUN: llc < %s -march=x86 | FileCheck %s > + > +define i32 @t1(i8 zeroext %x) nounwind readnone ssp { > +entry: > +; CHECK: t1: > +; CHECK: shll > +; CHECK-NOT: movzwl > +; CHECK: ret > + %0 = zext i8 %x to i16 > + %1 = shl i16 %0, 5 > + %2 = zext i16 %1 to i32 > + ret i32 %2 > +} > + > +define i32 @t2(i8 zeroext %x) nounwind readnone ssp { > +entry: > +; CHECK: t2: > +; CHECK: shrl > +; CHECK-NOT: movzwl > +; CHECK: ret > + %0 = zext i8 %x to i16 > + %1 = lshr i16 %0, 3 > + %2 = zext i16 %1 to i32 > + ret i32 %2 > +} > + > +define i32 @t3(i8 zeroext %x, i8 zeroext %y) nounwind readnone ssp { > +entry: > +; CHECK: t3: > +; CHECK: shll > +; CHECK-NOT: movzwl > +; CHECK: ret > + %0 = zext i8 %x to i16 > + %1 = zext i8 %y to i16 > + %2 = shl i16 %0, %1 > + %3 = zext i16 %2 to i32 > + ret i32 %3 > +} > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From wendling at apple.com Mon Dec 14 19:05:04 2009 From: wendling at apple.com (Bill Wendling) Date: Mon, 14 Dec 2009 17:05:04 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> Message-ID: <4C43CF46-A38E-4B9E-9AEB-5A0D20BED56C@apple.com> On Dec 14, 2009, at 4:41 PM, Evan Cheng wrote: > Author: evancheng > Date: Mon Dec 14 18:41:36 2009 > New Revision: 91378 > > URL: http://llvm.org/viewvc/llvm-project?rev=91378&view=rev > Log: > Propagate zest through logical shift. > > Added: > llvm/trunk/test/CodeGen/X86/setcc.ll > llvm/trunk/test/CodeGen/X86/zext-shl.ll > Modified: > llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91378&r1=91377&r2=91378&view=diff > > ============================================================================== > --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:41:36 2009 > @@ -3278,6 +3278,16 @@ > if (SCC.getNode()) return SCC; > } > > + // (zext (shl (zext x), y)) -> (shl (zext x), (zext y)) > + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL) && > + N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND && Is it necessary that op 0 be zext? -bw From evan.cheng at apple.com Mon Dec 14 19:07:46 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 15 Dec 2009 01:07:46 -0000 Subject: [llvm-commits] [test-suite] r91385 - /test-suite/trunk/Makefile.programs Message-ID: <200912150107.nBF17kkY026443@zion.cs.uiuc.edu> Author: evancheng Date: Mon Dec 14 19:07:46 2009 New Revision: 91385 URL: http://llvm.org/viewvc/llvm-project?rev=91385&view=rev Log: Test -disable-16bit. Modified: test-suite/trunk/Makefile.programs Modified: test-suite/trunk/Makefile.programs URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/Makefile.programs?rev=91385&r1=91384&r2=91385&view=diff ============================================================================== --- test-suite/trunk/Makefile.programs (original) +++ test-suite/trunk/Makefile.programs Mon Dec 14 19:07:46 2009 @@ -225,13 +225,15 @@ LLCBETAOPTION := -sched=simple endif ifeq ($(ARCH),x86_64) -LLCBETAOPTION := -split-gep-gvn +LLCBETAOPTION := -disable-16bit +#-split-gep-gvn #-combiner-alias-analysis #-pre-alloc-split #-remat-pic-stub-load endif ifeq ($(ARCH),x86) -LLCBETAOPTION := -split-gep-gvn +LLCBETAOPTION := -disable-16bit +#-split-gep-gvn #-combiner-alias-analysis #-pre-alloc-split #-remat-pic-stub-load From jyasskin at google.com Mon Dec 14 19:25:52 2009 From: jyasskin at google.com (Jeffrey Yasskin) Date: Mon, 14 Dec 2009 17:25:52 -0800 Subject: [llvm-commits] [PATCH] Fix http://llvm.org/PR5735: available_externally codegen Message-ID: Patch at http://llvm.org/bugs/attachment.cgi?id=3948 or http://codereview.appspot.com/179048. Jeffrey From grosbach at apple.com Mon Dec 14 19:35:31 2009 From: grosbach at apple.com (Jim Grosbach) Date: Tue, 15 Dec 2009 01:35:31 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r91387 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Message-ID: <200912150135.nBF1ZVBu027404@zion.cs.uiuc.edu> Author: grosbach Date: Mon Dec 14 19:35:31 2009 New Revision: 91387 URL: http://llvm.org/viewvc/llvm-project?rev=91387&view=rev Log: ARM doesn't support double-word atomics yet. Fix copy-paste error and a missed case. Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=91387&r1=91386&r2=91387&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Mon Dec 14 19:35:31 2009 @@ -5259,8 +5259,7 @@ } case BUILT_IN_FETCH_AND_ADD_8: #if defined(TARGET_ARM) - if (TARGET_THUMB1 || !arm_arch6) - return false; + return false; #endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) @@ -5544,6 +5543,9 @@ return true; } case BUILT_IN_AND_AND_FETCH_8: +#if defined(TARGET_ARM) + return false; +#endif #if defined(TARGET_POWERPC) if (!TARGET_64BIT) return false; From evan.cheng at apple.com Mon Dec 14 19:44:10 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 15 Dec 2009 01:44:10 -0000 Subject: [llvm-commits] [llvm] r91390 - /llvm/trunk/lib/CodeGen/TailDuplication.cpp Message-ID: <200912150144.nBF1iAmH027740@zion.cs.uiuc.edu> Author: evancheng Date: Mon Dec 14 19:44:10 2009 New Revision: 91390 URL: http://llvm.org/viewvc/llvm-project?rev=91390&view=rev Log: Tail duplication should zap a copy it inserted for SSA update if the copy is the only use of its source. Modified: llvm/trunk/lib/CodeGen/TailDuplication.cpp Modified: llvm/trunk/lib/CodeGen/TailDuplication.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TailDuplication.cpp?rev=91390&r1=91389&r2=91390&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/TailDuplication.cpp (original) +++ llvm/trunk/lib/CodeGen/TailDuplication.cpp Mon Dec 14 19:44:10 2009 @@ -90,7 +90,8 @@ SmallSetVector &Succs); bool TailDuplicateBlocks(MachineFunction &MF); bool TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF, - SmallVector &TDBBs); + SmallVector &TDBBs, + SmallVector &Copies); void RemoveDeadBlock(MachineBasicBlock *MBB); }; @@ -194,7 +195,8 @@ MBB->succ_end()); SmallVector TDBBs; - if (TailDuplicate(MBB, MF, TDBBs)) { + SmallVector Copies; + if (TailDuplicate(MBB, MF, TDBBs, Copies)) { ++NumTails; // TailBB's immediate successors are now successors of those predecessors @@ -251,6 +253,21 @@ SSAUpdateVals.clear(); } + // Eliminate some of the copies inserted tail duplication to maintain + // SSA form. + for (unsigned i = 0, e = Copies.size(); i != e; ++i) { + MachineInstr *Copy = Copies[i]; + unsigned Src, Dst, SrcSR, DstSR; + if (TII->isMoveInstr(*Copy, Src, Dst, SrcSR, DstSR)) { + MachineRegisterInfo::use_iterator UI = MRI->use_begin(Src); + if (++UI == MRI->use_end()) { + // Copy is the only use. Do trivial copy propagation here. + MRI->replaceRegWith(Dst, Src); + Copy->eraseFromParent(); + } + } + } + if (PreRegAlloc && TailDupVerify) VerifyPHIs(MF, false); MadeChange = true; @@ -418,7 +435,8 @@ /// of its predecessors. bool TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF, - SmallVector &TDBBs) { + SmallVector &TDBBs, + SmallVector &Copies) { // Don't try to tail-duplicate single-block loops. if (TailBB->isSuccessor(TailBB)) return false; @@ -502,7 +520,7 @@ // Clone the contents of TailBB into PredBB. DenseMap LocalVRMap; - SmallVector, 4> Copies; + SmallVector, 4> CopyInfos; MachineBasicBlock::iterator I = TailBB->begin(); while (I != TailBB->end()) { MachineInstr *MI = &*I; @@ -510,7 +528,7 @@ if (MI->getOpcode() == TargetInstrInfo::PHI) { // Replace the uses of the def of the PHI with the register coming // from PredBB. - ProcessPHI(MI, TailBB, PredBB, LocalVRMap, Copies); + ProcessPHI(MI, TailBB, PredBB, LocalVRMap, CopyInfos); } else { // Replace def of virtual registers with new registers, and update // uses with PHI source register or the new registers. @@ -518,9 +536,12 @@ } } MachineBasicBlock::iterator Loc = PredBB->getFirstTerminator(); - for (unsigned i = 0, e = Copies.size(); i != e; ++i) { - const TargetRegisterClass *RC = MRI->getRegClass(Copies[i].first); - TII->copyRegToReg(*PredBB, Loc, Copies[i].first, Copies[i].second, RC, RC); + for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) { + const TargetRegisterClass *RC = MRI->getRegClass(CopyInfos[i].first); + TII->copyRegToReg(*PredBB, Loc, CopyInfos[i].first, + CopyInfos[i].second, RC,RC); + MachineInstr *CopyMI = prior(Loc); + Copies.push_back(CopyMI); } NumInstrDups += TailBB->size() - 1; // subtract one for removed branch @@ -553,14 +574,14 @@ << "From MBB: " << *TailBB); if (PreRegAlloc) { DenseMap LocalVRMap; - SmallVector, 4> Copies; + SmallVector, 4> CopyInfos; MachineBasicBlock::iterator I = TailBB->begin(); // Process PHI instructions first. while (I != TailBB->end() && I->getOpcode() == TargetInstrInfo::PHI) { // Replace the uses of the def of the PHI with the register coming // from PredBB. MachineInstr *MI = &*I++; - ProcessPHI(MI, TailBB, PrevBB, LocalVRMap, Copies); + ProcessPHI(MI, TailBB, PrevBB, LocalVRMap, CopyInfos); if (MI->getParent()) MI->eraseFromParent(); } @@ -574,9 +595,12 @@ MI->eraseFromParent(); } MachineBasicBlock::iterator Loc = PrevBB->getFirstTerminator(); - for (unsigned i = 0, e = Copies.size(); i != e; ++i) { - const TargetRegisterClass *RC = MRI->getRegClass(Copies[i].first); - TII->copyRegToReg(*PrevBB, Loc, Copies[i].first, Copies[i].second, RC, RC); + for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) { + const TargetRegisterClass *RC = MRI->getRegClass(CopyInfos[i].first); + TII->copyRegToReg(*PrevBB, Loc, CopyInfos[i].first, + CopyInfos[i].second, RC, RC); + MachineInstr *CopyMI = prior(Loc); + Copies.push_back(CopyMI); } } else { // No PHIs to worry about, just splice the instructions over. From evan.cheng at apple.com Mon Dec 14 19:45:29 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 14 Dec 2009 17:45:29 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> Message-ID: <6ED59F80-2FD1-4C09-8325-BD4ED7C90EBE@apple.com> On Dec 14, 2009, at 5:00 PM, Chris Lattner wrote: > > On Dec 14, 2009, at 4:41 PM, Evan Cheng wrote: > >> Author: evancheng >> Date: Mon Dec 14 18:41:36 2009 >> New Revision: 91378 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=91378&view=rev >> Log: >> Propagate zest through logical shift. > > Is this really profitable in the general case? It seems that this should only be done if at least one of the inputs to the shift will fold away. Adding a nice "WouldFoldAZExt" predicate that would return true for zext/trunc would make sense, no? Are there cases where (zext (zext)) would not fold into a single zext? Evan > > -Chris > >> >> Added: >> llvm/trunk/test/CodeGen/X86/setcc.ll >> llvm/trunk/test/CodeGen/X86/zext-shl.ll >> Modified: >> llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >> >> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91378&r1=91377&r2=91378&view=diff >> >> ============================================================================== >> --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) >> +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:41:36 2009 >> @@ -3278,6 +3278,16 @@ >> if (SCC.getNode()) return SCC; >> } >> >> + // (zext (shl (zext x), y)) -> (shl (zext x), (zext y)) >> + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL) && >> + N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND && >> + N0.hasOneUse()) { >> + DebugLoc dl = N->getDebugLoc(); >> + return DAG.getNode(N0.getOpcode(), dl, VT, >> + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(0)), >> + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(1))); >> + } >> + >> return SDValue(); >> } >> >> >> Added: llvm/trunk/test/CodeGen/X86/setcc.ll >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=91378&view=auto >> >> ============================================================================== >> --- llvm/trunk/test/CodeGen/X86/setcc.ll (added) >> +++ llvm/trunk/test/CodeGen/X86/setcc.ll Mon Dec 14 18:41:36 2009 >> @@ -0,0 +1,13 @@ >> +; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s >> + >> +define zeroext i16 @t1(i16 zeroext %x) nounwind readnone ssp { >> +entry: >> +; CHECK: t1: >> +; CHECK: seta %al >> +; CHECK: movzbl %al, %eax >> +; CHECK: shll $5, %eax >> + %0 = icmp ugt i16 %x, 26 ; [#uses=1] >> + %iftmp.1.0 = select i1 %0, i16 32, i16 0 ; [#uses=1] >> + ret i16 %iftmp.1.0 >> +} >> + >> >> Added: llvm/trunk/test/CodeGen/X86/zext-shl.ll >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/zext-shl.ll?rev=91378&view=auto >> >> ============================================================================== >> --- llvm/trunk/test/CodeGen/X86/zext-shl.ll (added) >> +++ llvm/trunk/test/CodeGen/X86/zext-shl.ll Mon Dec 14 18:41:36 2009 >> @@ -0,0 +1,38 @@ >> +; RUN: llc < %s -march=x86 | FileCheck %s >> + >> +define i32 @t1(i8 zeroext %x) nounwind readnone ssp { >> +entry: >> +; CHECK: t1: >> +; CHECK: shll >> +; CHECK-NOT: movzwl >> +; CHECK: ret >> + %0 = zext i8 %x to i16 >> + %1 = shl i16 %0, 5 >> + %2 = zext i16 %1 to i32 >> + ret i32 %2 >> +} >> + >> +define i32 @t2(i8 zeroext %x) nounwind readnone ssp { >> +entry: >> +; CHECK: t2: >> +; CHECK: shrl >> +; CHECK-NOT: movzwl >> +; CHECK: ret >> + %0 = zext i8 %x to i16 >> + %1 = lshr i16 %0, 3 >> + %2 = zext i16 %1 to i32 >> + ret i32 %2 >> +} >> + >> +define i32 @t3(i8 zeroext %x, i8 zeroext %y) nounwind readnone ssp { >> +entry: >> +; CHECK: t3: >> +; CHECK: shll >> +; CHECK-NOT: movzwl >> +; CHECK: ret >> + %0 = zext i8 %x to i16 >> + %1 = zext i8 %y to i16 >> + %2 = shl i16 %0, %1 >> + %3 = zext i16 %2 to i32 >> + ret i32 %3 >> +} >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From clattner at apple.com Mon Dec 14 19:47:00 2009 From: clattner at apple.com (Chris Lattner) Date: Mon, 14 Dec 2009 17:47:00 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: <6ED59F80-2FD1-4C09-8325-BD4ED7C90EBE@apple.com> References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> <6ED59F80-2FD1-4C09-8325-BD4ED7C90EBE@apple.com> Message-ID: On Dec 14, 2009, at 5:45 PM, Evan Cheng wrote: > > On Dec 14, 2009, at 5:00 PM, Chris Lattner wrote: > >> >> On Dec 14, 2009, at 4:41 PM, Evan Cheng wrote: >> >>> Author: evancheng >>> Date: Mon Dec 14 18:41:36 2009 >>> New Revision: 91378 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=91378&view=rev >>> Log: >>> Propagate zest through logical shift. >> >> Is this really profitable in the general case? It seems that this >> should only be done if at least one of the inputs to the shift will >> fold away. Adding a nice "WouldFoldAZExt" predicate that would >> return true for zext/trunc would make sense, no? > > Are there cases where (zext (zext)) would not fold into a single zext? No, I'm worried that you're turning something like: zext(shr(call, call)) -> shr(zext(call), zext(call)) which introduces two zexts and deletes one. -Chris From evan.cheng at apple.com Mon Dec 14 19:49:43 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 14 Dec 2009 17:49:43 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> <6ED59F80-2FD1-4C09-8325-BD4ED7C90EBE@apple.com> Message-ID: On Dec 14, 2009, at 5:47 PM, Chris Lattner wrote: > > On Dec 14, 2009, at 5:45 PM, Evan Cheng wrote: > >> >> On Dec 14, 2009, at 5:00 PM, Chris Lattner wrote: >> >>> >>> On Dec 14, 2009, at 4:41 PM, Evan Cheng wrote: >>> >>>> Author: evancheng >>>> Date: Mon Dec 14 18:41:36 2009 >>>> New Revision: 91378 >>>> >>>> URL: http://llvm.org/viewvc/llvm-project?rev=91378&view=rev >>>> Log: >>>> Propagate zest through logical shift. >>> >>> Is this really profitable in the general case? It seems that this should only be done if at least one of the inputs to the shift will fold away. Adding a nice "WouldFoldAZExt" predicate that would return true for zext/trunc would make sense, no? >> >> Are there cases where (zext (zext)) would not fold into a single zext? > > No, I'm worried that you're turning something like: > > zext(shr(call, call)) -> shr(zext(call), zext(call)) > > which introduces two zexts and deletes one. No. The transformation only happens when one of the shift's operand is a zext. Evan > > -Chris From evan.cheng at apple.com Mon Dec 14 19:50:28 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 14 Dec 2009 17:50:28 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: <4C43CF46-A38E-4B9E-9AEB-5A0D20BED56C@apple.com> References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> <4C43CF46-A38E-4B9E-9AEB-5A0D20BED56C@apple.com> Message-ID: On Dec 14, 2009, at 5:05 PM, Bill Wendling wrote: > On Dec 14, 2009, at 4:41 PM, Evan Cheng wrote: > >> Author: evancheng >> Date: Mon Dec 14 18:41:36 2009 >> New Revision: 91378 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=91378&view=rev >> Log: >> Propagate zest through logical shift. >> >> Added: >> llvm/trunk/test/CodeGen/X86/setcc.ll >> llvm/trunk/test/CodeGen/X86/zext-shl.ll >> Modified: >> llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >> >> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91378&r1=91377&r2=91378&view=diff >> >> ============================================================================== >> --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) >> +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:41:36 2009 >> @@ -3278,6 +3278,16 @@ >> if (SCC.getNode()) return SCC; >> } >> >> + // (zext (shl (zext x), y)) -> (shl (zext x), (zext y)) >> + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL) && >> + N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND && > > Is it necessary that op 0 be zext? Not necessary, but more likely. I can change it. (After I figure out which of my patches broke self-host). Evan > > -bw > From eli.friedman at gmail.com Mon Dec 14 19:54:06 2009 From: eli.friedman at gmail.com (Eli Friedman) Date: Mon, 14 Dec 2009 17:54:06 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> Message-ID: On Mon, Dec 14, 2009 at 4:41 PM, Evan Cheng wrote: > --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:41:36 2009 > @@ -3278,6 +3278,16 @@ > ? ? if (SCC.getNode()) return SCC; > ? } > > + ?// (zext (shl (zext x), y)) -> (shl (zext x), (zext y)) > + ?if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL) && > + ? ? ?N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND && > + ? ? ?N0.hasOneUse()) { > + ? ?DebugLoc dl = N->getDebugLoc(); > + ? ?return DAG.getNode(N0.getOpcode(), dl, VT, > + ? ? ? ? ? ? ? ? ? ? ? DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(0)), > + ? ? ? ? ? ? ? ? ? ? ? DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(1))); > + ?} > + > ? return SDValue(); > ?} I think you need a check here to make sure the original shift never shifts out any set bits. (Only happens with unusual widths, but I think it's possible before legalization.) -Eli From isanbard at gmail.com Mon Dec 14 19:54:51 2009 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 15 Dec 2009 01:54:51 -0000 Subject: [llvm-commits] [llvm] r91392 - in /llvm/trunk: include/llvm/CodeGen/SelectionDAG.h lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp lib/CodeGen/SelectionDAG/SelectionDAG.cpp lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Message-ID: <200912150154.nBF1spun028126@zion.cs.uiuc.edu> Author: void Date: Mon Dec 14 19:54:51 2009 New Revision: 91392 URL: http://llvm.org/viewvc/llvm-project?rev=91392&view=rev Log: Initial work on disabling the scheduler. This is a work in progress, and this stuff isn't used just yet. We want to model the GCC `-fno-schedule-insns' and `-fno-schedule-insns2' flags. The hypothesis is that the people who use these flags know what they are doing, and have hand-optimized the C code to reduce latencies and other conflicts. The idea behind our scheme to turn off scheduling is to create a map "on the side" during DAG generation. It will order the nodes by how they appeared in the code. This map is then used during scheduling to get the ordering. Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=91392&r1=91391&r2=91392&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Mon Dec 14 19:54:51 2009 @@ -110,6 +110,46 @@ /// SelectionDAG. BumpPtrAllocator Allocator; + /// NodeOrdering - Assigns a "line number" value to each SDNode that + /// corresponds to the "line number" of the original LLVM instruction. This + /// used for turning off scheduling, because we'll forgo the normal scheduling + /// algorithm and output the instructions according to this ordering. + class NodeOrdering { + /// LineNo - The line of the instruction the node corresponds to. A value of + /// `0' means it's not assigned. + unsigned LineNo; + std::map Order; + + void operator=(const NodeOrdering&); // Do not implement. + NodeOrdering(const NodeOrdering&); // Do not implement. + public: + NodeOrdering() : LineNo(0) {} + + void add(const SDNode *Node) { + assert(LineNo && "Invalid line number!"); + Order[Node] = LineNo; + } + void remove(const SDNode *Node) { + std::map::iterator Itr = Order.find(Node); + if (Itr != Order.end()) + Order.erase(Itr); + } + void clear() { + Order.clear(); + LineNo = 1; + } + unsigned getLineNo(const SDNode *Node) { + unsigned LN = Order[Node]; + assert(LN && "Node isn't in ordering map!"); + return LN; + } + void newInst() { + ++LineNo; + } + + void dump() const; + } *Ordering; + /// VerifyNode - Sanity check the given node. Aborts if it is invalid. void VerifyNode(SDNode *N); @@ -120,6 +160,9 @@ DenseSet &visited, int level, bool &printed); + void operator=(const SelectionDAG&); // Do not implement. + SelectionDAG(const SelectionDAG&); // Do not implement. + public: SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli); ~SelectionDAG(); @@ -199,6 +242,13 @@ return Root = N; } + /// NewInst - Tell the ordering object that we're processing a new + /// instruction. + void NewInst() { + if (Ordering) + Ordering->newInst(); + } + /// Combine - This iterates over the nodes in the SelectionDAG, folding /// certain types of nodes together, or eliminating superfluous nodes. The /// Level argument controls whether Combine is allowed to produce nodes and Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp?rev=91392&r1=91391&r2=91392&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp Mon Dec 14 19:54:51 2009 @@ -20,10 +20,16 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtarget.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; +cl::opt +DisableInstScheduling("disable-inst-scheduling", + cl::init(false), + cl::desc("Disable instruction scheduling")); + ScheduleDAGSDNodes::ScheduleDAGSDNodes(MachineFunction &mf) : ScheduleDAG(mf) { } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=91392&r1=91391&r2=91392&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Dec 14 19:54:51 2009 @@ -48,6 +48,8 @@ #include using namespace llvm; +extern cl::opt DisableInstScheduling; + /// makeVTList - Return an instance of the SDVTList struct initialized with the /// specified members. static SDVTList makeVTList(const EVT *VTs, unsigned NumVTs) { @@ -552,6 +554,9 @@ } DeallocateNode(N); + + // Remove the ordering of this node. + if (Ordering) Ordering->remove(N); } } @@ -577,6 +582,9 @@ N->DropOperands(); DeallocateNode(N); + + // Remove the ordering of this node. + if (Ordering) Ordering->remove(N); } void SelectionDAG::DeallocateNode(SDNode *N) { @@ -588,6 +596,9 @@ N->NodeType = ISD::DELETED_NODE; NodeAllocator.Deallocate(AllNodes.remove(N)); + + // Remove the ordering of this node. + if (Ordering) Ordering->remove(N); } /// RemoveNodeFromCSEMaps - Take the specified node out of the CSE map that @@ -691,7 +702,9 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, 1); AddNodeIDCustom(ID, N); - return CSEMap.FindNodeOrInsertPos(ID, InsertPos); + SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); + if (Ordering) Ordering->remove(Node); + return Node; } /// FindModifiedNodeSlot - Find a slot for the specified node if its operands @@ -708,7 +721,9 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, 2); AddNodeIDCustom(ID, N); - return CSEMap.FindNodeOrInsertPos(ID, InsertPos); + SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); + if (Ordering) Ordering->remove(Node); + return Node; } @@ -725,7 +740,9 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, NumOps); AddNodeIDCustom(ID, N); - return CSEMap.FindNodeOrInsertPos(ID, InsertPos); + SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); + if (Ordering) Ordering->remove(Node); + return Node; } /// VerifyNode - Sanity check the given node. Aborts if it is invalid. @@ -778,8 +795,13 @@ SelectionDAG::SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli) : TLI(tli), FLI(fli), DW(0), EntryNode(ISD::EntryToken, DebugLoc::getUnknownLoc(), - getVTList(MVT::Other)), Root(getEntryNode()) { + getVTList(MVT::Other)), + Root(getEntryNode()), Ordering(0) { AllNodes.push_back(&EntryNode); + if (DisableInstScheduling) { + Ordering = new NodeOrdering(); + Ordering->add(&EntryNode); + } } void SelectionDAG::init(MachineFunction &mf, MachineModuleInfo *mmi, @@ -792,6 +814,7 @@ SelectionDAG::~SelectionDAG() { allnodes_clear(); + delete Ordering; } void SelectionDAG::allnodes_clear() { @@ -817,6 +840,10 @@ EntryNode.UseList = 0; AllNodes.push_back(&EntryNode); Root = getEntryNode(); + if (DisableInstScheduling) { + Ordering = new NodeOrdering(); + Ordering->add(&EntryNode); + } } SDValue SelectionDAG::getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) { @@ -877,14 +904,17 @@ ID.AddPointer(&Val); void *IP = 0; SDNode *N = NULL; - if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) + if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) { + if (Ordering) Ordering->add(N); if (!VT.isVector()) return SDValue(N, 0); + } if (!N) { N = NodeAllocator.Allocate(); new (N) ConstantSDNode(isT, &Val, EltVT); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); } SDValue Result(N, 0); @@ -921,14 +951,17 @@ ID.AddPointer(&V); void *IP = 0; SDNode *N = NULL; - if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) + if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) { + if (Ordering) Ordering->add(N); if (!VT.isVector()) return SDValue(N, 0); + } if (!N) { N = NodeAllocator.Allocate(); new (N) ConstantFPSDNode(isTarget, &V, EltVT); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); } SDValue Result(N, 0); @@ -983,12 +1016,15 @@ ID.AddInteger(Offset); ID.AddInteger(TargetFlags); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) GlobalAddressSDNode(Opc, GV, VT, Offset, TargetFlags); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -998,12 +1034,15 @@ AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); ID.AddInteger(FI); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) FrameIndexSDNode(FI, VT, isTarget); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1017,12 +1056,15 @@ ID.AddInteger(JTI); ID.AddInteger(TargetFlags); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) JumpTableSDNode(JTI, VT, isTarget, TargetFlags); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1042,12 +1084,15 @@ ID.AddPointer(C); ID.AddInteger(TargetFlags); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) ConstantPoolSDNode(isTarget, C, VT, Offset, Alignment, TargetFlags); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1068,12 +1113,15 @@ C->AddSelectionDAGCSEId(ID); ID.AddInteger(TargetFlags); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) ConstantPoolSDNode(isTarget, C, VT, Offset, Alignment, TargetFlags); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1082,12 +1130,15 @@ AddNodeIDNode(ID, ISD::BasicBlock, getVTList(MVT::Other), 0, 0); ID.AddPointer(MBB); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) BasicBlockSDNode(MBB); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1103,6 +1154,7 @@ N = NodeAllocator.Allocate(); new (N) VTSDNode(VT); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1112,6 +1164,7 @@ N = NodeAllocator.Allocate(); new (N) ExternalSymbolSDNode(false, Sym, 0, VT); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1124,6 +1177,7 @@ N = NodeAllocator.Allocate(); new (N) ExternalSymbolSDNode(true, Sym, TargetFlags, VT); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1136,6 +1190,7 @@ new (N) CondCodeSDNode(Cond); CondCodeNodes[Cond] = N; AllNodes.push_back(N); + if (Ordering) Ordering->add(N); } return SDValue(CondCodeNodes[Cond], 0); } @@ -1228,8 +1283,10 @@ ID.AddInteger(MaskVec[i]); void* IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } // Allocate the mask array for the node out of the BumpPtrAllocator, since // SDNode doesn't have access to it. This memory will be "leaked" when @@ -1241,6 +1298,7 @@ new (N) ShuffleVectorSDNode(VT, dl, N1, N2, MaskAlloc); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1258,12 +1316,15 @@ SDValue Ops[] = { Val, DTy, STy, Rnd, Sat }; AddNodeIDNode(ID, ISD::CONVERT_RNDSAT, getVTList(VT), &Ops[0], 5); void* IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } CvtRndSatSDNode *N = NodeAllocator.Allocate(); new (N) CvtRndSatSDNode(VT, dl, Ops, 5, Code); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1272,12 +1333,15 @@ AddNodeIDNode(ID, ISD::Register, getVTList(VT), 0, 0); ID.AddInteger(RegNo); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) RegisterSDNode(RegNo, VT); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1289,12 +1353,15 @@ AddNodeIDNode(ID, Opcode, getVTList(MVT::Other), &Ops[0], 1); ID.AddInteger(LabelID); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) LabelSDNode(Opcode, dl, Root, LabelID); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1308,12 +1375,15 @@ ID.AddPointer(BA); ID.AddInteger(TargetFlags); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) BlockAddressSDNode(Opc, VT, BA, TargetFlags); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1326,13 +1396,16 @@ ID.AddPointer(V); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) SrcValueSDNode(V); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -2243,13 +2316,16 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, getVTList(VT), 0, 0); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) SDNode(Opcode, DL, getVTList(VT)); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -2473,8 +2549,10 @@ SDValue Ops[1] = { Operand }; AddNodeIDNode(ID, Opcode, VTs, Ops, 1); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } N = NodeAllocator.Allocate(); new (N) UnarySDNode(Opcode, DL, VTs, Operand); CSEMap.InsertNode(N, IP); @@ -2484,6 +2562,7 @@ } AllNodes.push_back(N); + if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -2891,8 +2970,10 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTs, Ops, 2); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } N = NodeAllocator.Allocate(); new (N) BinarySDNode(Opcode, DL, VTs, N1, N2); CSEMap.InsertNode(N, IP); @@ -2902,6 +2983,7 @@ } AllNodes.push_back(N); + if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -2968,8 +3050,10 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTs, Ops, 3); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } N = NodeAllocator.Allocate(); new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); CSEMap.InsertNode(N, IP); @@ -2977,7 +3061,9 @@ N = NodeAllocator.Allocate(); new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); } + AllNodes.push_back(N); + if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -3573,12 +3659,14 @@ void* IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); + if (Ordering) Ordering->add(E); return SDValue(E, 0); } SDNode* N = NodeAllocator.Allocate(); new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Cmp, Swp, MMO); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -3636,12 +3724,14 @@ void* IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); + if (Ordering) Ordering->add(E); return SDValue(E, 0); } SDNode* N = NodeAllocator.Allocate(); new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Val, MMO); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -3714,6 +3804,7 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); + if (Ordering) Ordering->add(E); return SDValue(E, 0); } @@ -3725,6 +3816,7 @@ new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO); } AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -3789,12 +3881,14 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); + if (Ordering) Ordering->add(E); return SDValue(E, 0); } SDNode *N = NodeAllocator.Allocate(); new (N) LoadSDNode(Ops, dl, VTs, AM, ExtType, MemVT, MMO); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -3865,12 +3959,14 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); + if (Ordering) Ordering->add(E); return SDValue(E, 0); } SDNode *N = NodeAllocator.Allocate(); new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, false, VT, MMO); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -3925,12 +4021,14 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); + if (Ordering) Ordering->add(E); return SDValue(E, 0); } SDNode *N = NodeAllocator.Allocate(); new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, true, SVT, MMO); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -3947,14 +4045,17 @@ ID.AddInteger(ST->getMemoryVT().getRawBits()); ID.AddInteger(ST->getRawSubclassData()); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } SDNode *N = NodeAllocator.Allocate(); new (N) StoreSDNode(Ops, dl, VTs, AM, ST->isTruncatingStore(), ST->getMemoryVT(), ST->getMemOperand()); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -4020,8 +4121,10 @@ AddNodeIDNode(ID, Opcode, VTs, Ops, NumOps); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } N = NodeAllocator.Allocate(); new (N) SDNode(Opcode, DL, VTs, Ops, NumOps); @@ -4032,6 +4135,7 @@ } AllNodes.push_back(N); + if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -4087,8 +4191,10 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return SDValue(E, 0); + } if (NumOps == 1) { N = NodeAllocator.Allocate(); new (N) UnarySDNode(Opcode, DL, VTList, Ops[0]); @@ -4119,6 +4225,7 @@ } } AllNodes.push_back(N); + if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -4581,8 +4688,10 @@ if (VTs.VTs[VTs.NumVTs-1] != MVT::Flag) { FoldingSetNodeID ID; AddNodeIDNode(ID, Opc, VTs, Ops, NumOps); - if (SDNode *ON = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *ON = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(ON); return ON; + } } if (!RemoveNodeFromCSEMaps(N)) @@ -4646,6 +4755,7 @@ if (IP) CSEMap.InsertNode(N, IP); // Memoize the new node. + if (Ordering) Ordering->add(N); return N; } @@ -4784,8 +4894,10 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, ~Opcode, VTs, Ops, NumOps); IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return cast(E); + } } // Allocate a new MachineSDNode. @@ -4807,6 +4919,7 @@ CSEMap.InsertNode(N, IP); AllNodes.push_back(N); + if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -4843,8 +4956,10 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + if (Ordering) Ordering->add(E); return E; + } } return NULL; } @@ -6011,6 +6126,9 @@ errs() << "\n\n"; } +void SelectionDAG::NodeOrdering::dump() const { +} + void SDNode::printr(raw_ostream &OS, const SelectionDAG *G) const { print_types(OS, G); print_details(OS, G); @@ -6151,4 +6269,3 @@ return false; return true; } - Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=91392&r1=91391&r2=91392&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Mon Dec 14 19:54:51 2009 @@ -583,6 +583,9 @@ } void SelectionDAGBuilder::visit(unsigned Opcode, User &I) { + // Tell the DAG that we're processing a new instruction. + DAG.NewInst(); + // Note: this doesn't use InstVisitor, because it has to work with // ConstantExpr's in addition to instructions. switch (Opcode) { From rjmccall at apple.com Mon Dec 14 20:35:25 2009 From: rjmccall at apple.com (John McCall) Date: Tue, 15 Dec 2009 02:35:25 -0000 Subject: [llvm-commits] [llvm] r91397 - /llvm/trunk/lib/Analysis/ProfileInfo.cpp Message-ID: <200912150235.nBF2ZPTE029607@zion.cs.uiuc.edu> Author: rjmccall Date: Mon Dec 14 20:35:24 2009 New Revision: 91397 URL: http://llvm.org/viewvc/llvm-project?rev=91397&view=rev Log: You can't use typedefs to declare template member specializations, and clang enforces it. Modified: llvm/trunk/lib/Analysis/ProfileInfo.cpp Modified: llvm/trunk/lib/Analysis/ProfileInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ProfileInfo.cpp?rev=91397&r1=91396&r2=91397&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ProfileInfo.cpp (original) +++ llvm/trunk/lib/Analysis/ProfileInfo.cpp Mon Dec 14 20:35:24 2009 @@ -44,19 +44,19 @@ } template<> -char ProfileInfo::ID = 0; +char ProfileInfoT::ID = 0; template<> -char MachineProfileInfo::ID = 0; +char ProfileInfoT::ID = 0; template<> -const double ProfileInfo::MissingValue = -1; +const double ProfileInfoT::MissingValue = -1; -template<> -const double MachineProfileInfo::MissingValue = -1; +template<> const +double ProfileInfoT::MissingValue = -1; -template<> -double ProfileInfo::getExecutionCount(const BasicBlock *BB) { +template<> double +ProfileInfoT::getExecutionCount(const BasicBlock *BB) { std::map::iterator J = BlockInformation.find(BB->getParent()); if (J != BlockInformation.end()) { @@ -118,7 +118,8 @@ } template<> -double MachineProfileInfo::getExecutionCount(const MachineBasicBlock *MBB) { +double ProfileInfoT:: + getExecutionCount(const MachineBasicBlock *MBB) { std::map::iterator J = BlockInformation.find(MBB->getParent()); if (J != BlockInformation.end()) { @@ -131,7 +132,7 @@ } template<> -double ProfileInfo::getExecutionCount(const Function *F) { +double ProfileInfoT::getExecutionCount(const Function *F) { std::map::iterator J = FunctionInformation.find(F); if (J != FunctionInformation.end()) @@ -147,7 +148,8 @@ } template<> -double MachineProfileInfo::getExecutionCount(const MachineFunction *MF) { +double ProfileInfoT:: + getExecutionCount(const MachineFunction *MF) { std::map::iterator J = FunctionInformation.find(MF); if (J != FunctionInformation.end()) @@ -159,21 +161,23 @@ } template<> -void ProfileInfo::setExecutionCount(const BasicBlock *BB, double w) { +void ProfileInfoT:: + setExecutionCount(const BasicBlock *BB, double w) { DEBUG(errs() << "Creating Block " << BB->getName() << " (weight: " << format("%.20g",w) << ")\n"); BlockInformation[BB->getParent()][BB] = w; } template<> -void MachineProfileInfo::setExecutionCount(const MachineBasicBlock *MBB, double w) { +void ProfileInfoT:: + setExecutionCount(const MachineBasicBlock *MBB, double w) { DEBUG(errs() << "Creating Block " << MBB->getBasicBlock()->getName() << " (weight: " << format("%.20g",w) << ")\n"); BlockInformation[MBB->getParent()][MBB] = w; } template<> -void ProfileInfo::addEdgeWeight(Edge e, double w) { +void ProfileInfoT::addEdgeWeight(Edge e, double w) { double oldw = getEdgeWeight(e); assert (oldw != MissingValue && "Adding weight to Edge with no previous weight"); DEBUG(errs() << "Adding to Edge " << e @@ -182,7 +186,8 @@ } template<> -void ProfileInfo::addExecutionCount(const BasicBlock *BB, double w) { +void ProfileInfoT:: + addExecutionCount(const BasicBlock *BB, double w) { double oldw = getExecutionCount(BB); assert (oldw != MissingValue && "Adding weight to Block with no previous weight"); DEBUG(errs() << "Adding to Block " << BB->getName() @@ -191,7 +196,7 @@ } template<> -void ProfileInfo::removeBlock(const BasicBlock *BB) { +void ProfileInfoT::removeBlock(const BasicBlock *BB) { std::map::iterator J = BlockInformation.find(BB->getParent()); if (J == BlockInformation.end()) return; @@ -201,7 +206,7 @@ } template<> -void ProfileInfo::removeEdge(Edge e) { +void ProfileInfoT::removeEdge(Edge e) { std::map::iterator J = EdgeInformation.find(getFunction(e)); if (J == EdgeInformation.end()) return; @@ -211,7 +216,8 @@ } template<> -void ProfileInfo::replaceEdge(const Edge &oldedge, const Edge &newedge) { +void ProfileInfoT:: + replaceEdge(const Edge &oldedge, const Edge &newedge) { double w; if ((w = getEdgeWeight(newedge)) == MissingValue) { w = getEdgeWeight(oldedge); @@ -225,8 +231,9 @@ } template<> -const BasicBlock *ProfileInfo::GetPath(const BasicBlock *Src, const BasicBlock *Dest, - Path &P, unsigned Mode) { +const BasicBlock *ProfileInfoT:: + GetPath(const BasicBlock *Src, const BasicBlock *Dest, + Path &P, unsigned Mode) { const BasicBlock *BB = 0; bool hasFoundPath = false; @@ -268,7 +275,8 @@ } template<> -void ProfileInfo::divertFlow(const Edge &oldedge, const Edge &newedge) { +void ProfileInfoT:: + divertFlow(const Edge &oldedge, const Edge &newedge) { DEBUG(errs() << "Diverting " << oldedge << " via " << newedge ); // First check if the old edge was taken, if not, just delete it... @@ -302,8 +310,8 @@ /// This checks all edges of the function the blocks reside in and replaces the /// occurences of RmBB with DestBB. template<> -void ProfileInfo::replaceAllUses(const BasicBlock *RmBB, - const BasicBlock *DestBB) { +void ProfileInfoT:: + replaceAllUses(const BasicBlock *RmBB, const BasicBlock *DestBB) { DEBUG(errs() << "Replacing " << RmBB->getName() << " with " << DestBB->getName() << "\n"); const Function *F = DestBB->getParent(); @@ -352,10 +360,10 @@ /// Since its possible that there is more than one edge in the CFG from FristBB /// to SecondBB its necessary to redirect the flow proporionally. template<> -void ProfileInfo::splitEdge(const BasicBlock *FirstBB, - const BasicBlock *SecondBB, - const BasicBlock *NewBB, - bool MergeIdenticalEdges) { +void ProfileInfoT::splitEdge(const BasicBlock *FirstBB, + const BasicBlock *SecondBB, + const BasicBlock *NewBB, + bool MergeIdenticalEdges) { const Function *F = FirstBB->getParent(); std::map::iterator J = EdgeInformation.find(F); @@ -398,7 +406,8 @@ } template<> -void ProfileInfo::splitBlock(const BasicBlock *Old, const BasicBlock* New) { +void ProfileInfoT::splitBlock(const BasicBlock *Old, + const BasicBlock* New) { const Function *F = Old->getParent(); std::map::iterator J = EdgeInformation.find(F); @@ -426,8 +435,10 @@ } template<> -void ProfileInfo::splitBlock(const BasicBlock *BB, const BasicBlock* NewBB, - BasicBlock *const *Preds, unsigned NumPreds) { +void ProfileInfoT::splitBlock(const BasicBlock *BB, + const BasicBlock* NewBB, + BasicBlock *const *Preds, + unsigned NumPreds) { const Function *F = BB->getParent(); std::map::iterator J = EdgeInformation.find(F); @@ -461,7 +472,8 @@ } template<> -void ProfileInfo::transfer(const Function *Old, const Function *New) { +void ProfileInfoT::transfer(const Function *Old, + const Function *New) { DEBUG(errs() << "Replacing Function " << Old->getName() << " with " << New->getName() << "\n"); std::map::iterator J = @@ -474,8 +486,8 @@ FunctionInformation.erase(Old); } -static double readEdgeOrRemember(ProfileInfo::Edge edge, double w, ProfileInfo::Edge &tocalc, - unsigned &uncalc) { +static double readEdgeOrRemember(ProfileInfo::Edge edge, double w, + ProfileInfo::Edge &tocalc, unsigned &uncalc) { if (w == ProfileInfo::MissingValue) { tocalc = edge; uncalc++; @@ -486,7 +498,9 @@ } template<> -bool ProfileInfo::CalculateMissingEdge(const BasicBlock *BB, Edge &removed, bool assumeEmptySelf) { +bool ProfileInfoT:: + CalculateMissingEdge(const BasicBlock *BB, Edge &removed, + bool assumeEmptySelf) { Edge edgetocalc; unsigned uncalculated = 0; @@ -562,7 +576,7 @@ } template<> -bool ProfileInfo::EstimateMissingEdges(const BasicBlock *BB) { +bool ProfileInfoT::EstimateMissingEdges(const BasicBlock *BB) { bool hasNoSuccessors = false; double inWeight = 0; @@ -619,7 +633,7 @@ } template<> -void ProfileInfo::repair(const Function *F) { +void ProfileInfoT::repair(const Function *F) { // if (getExecutionCount(&(F->getEntryBlock())) == 0) { // for (Function::const_iterator FI = F->begin(), FE = F->end(); // FI != FE; ++FI) { From lhames at gmail.com Mon Dec 14 20:36:17 2009 From: lhames at gmail.com (Lang Hames) Date: Tue, 15 Dec 2009 13:36:17 +1100 Subject: [llvm-commits] [llvm] r91273 - in /llvm/trunk: include/llvm/CodeGen/CalcSpillWeights.h lib/CodeGen/CalcSpillWeights.cpp lib/CodeGen/PreAllocSplitting.cpp lib/CodeGen/RegAllocLinearScan.cpp lib/CodeGen/RegAllocPBQP.cpp lib/CodeGen/SimpleRegisterCo Message-ID: <728927c70912141836h5af5f1ey1aeb6359216ea85c@mail.gmail.com> > I think you can do without the header file. Just put a > CalculateSpillWeightsID in Passes.h instead. > I'm planning to add functionality to the pass to compute the spill weight of individual intervals. Passes using this (such as the new spiller) will need access to the interface. > > +/// Returns true if the given live interval is zero length. > > +bool CalculateSpillWeights::isZeroLengthInterval(LiveInterval *li) const > { > > Should this be a method on LiveInterval instead? > Probably. I'll move it over. :) - Lang. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20091215/a0696aec/attachment.html From evan.cheng at apple.com Mon Dec 14 21:00:32 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 15 Dec 2009 03:00:32 -0000 Subject: [llvm-commits] [llvm] r91399 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/zext-shl.ll Message-ID: <200912150300.nBF30Wsv030497@zion.cs.uiuc.edu> Author: evancheng Date: Mon Dec 14 21:00:32 2009 New Revision: 91399 URL: http://llvm.org/viewvc/llvm-project?rev=91399&view=rev Log: Make 91378 more conservative. 1. Only perform (zext (shl (zext x), y)) -> (shl (zext x), y) when y is a constant. This makes sure it remove at least one zest. 2. If the shift is a left shift, make sure the original shift cannot shift out bits. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp llvm/trunk/test/CodeGen/X86/zext-shl.ll Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91399&r1=91398&r2=91399&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 21:00:32 2009 @@ -3291,10 +3291,20 @@ if (SCC.getNode()) return SCC; } - // (zext (shl (zext x), y)) -> (shl (zext x), (zext y)) + // (zext (shl (zext x), cst)) -> (shl (zext x), cst) if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL) && + isa(N0.getOperand(1)) && N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND && N0.hasOneUse()) { + if (N0.getOpcode() == ISD::SHL) { + // If the original shl may be shifting out bits, do not perform this + // transformation. + unsigned ShAmt = cast(N0.getOperand(1))->getZExtValue(); + unsigned KnownZeroBits = N0.getOperand(0).getValueType().getSizeInBits() - + N0.getOperand(0).getOperand(0).getValueType().getSizeInBits(); + if (ShAmt > KnownZeroBits) + return SDValue(); + } DebugLoc dl = N->getDebugLoc(); return DAG.getNode(N0.getOpcode(), dl, VT, DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(0)), Modified: llvm/trunk/test/CodeGen/X86/zext-shl.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/zext-shl.ll?rev=91399&r1=91398&r2=91399&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/zext-shl.ll (original) +++ llvm/trunk/test/CodeGen/X86/zext-shl.ll Mon Dec 14 21:00:32 2009 @@ -23,16 +23,3 @@ %2 = zext i16 %1 to i32 ret i32 %2 } - -define i32 @t3(i8 zeroext %x, i8 zeroext %y) nounwind readnone ssp { -entry: -; CHECK: t3: -; CHECK: shll -; CHECK-NOT: movzwl -; CHECK: ret - %0 = zext i8 %x to i16 - %1 = zext i8 %y to i16 - %2 = shl i16 %0, %1 - %3 = zext i16 %2 to i32 - ret i32 %3 -} From evan.cheng at apple.com Mon Dec 14 21:00:51 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 14 Dec 2009 19:00:51 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> Message-ID: Good idea. See 91399. Thanks. Evan On Dec 14, 2009, at 5:54 PM, Eli Friedman wrote: > On Mon, Dec 14, 2009 at 4:41 PM, Evan Cheng wrote: >> --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) >> +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:41:36 2009 >> @@ -3278,6 +3278,16 @@ >> if (SCC.getNode()) return SCC; >> } >> >> + // (zext (shl (zext x), y)) -> (shl (zext x), (zext y)) >> + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL) && >> + N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND && >> + N0.hasOneUse()) { >> + DebugLoc dl = N->getDebugLoc(); >> + return DAG.getNode(N0.getOpcode(), dl, VT, >> + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(0)), >> + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(1))); >> + } >> + >> return SDValue(); >> } > > I think you need a check here to make sure the original shift never > shifts out any set bits. (Only happens with unusual widths, but I > think it's possible before legalization.) > > -Eli From foldr at codedgers.com Mon Dec 14 21:03:37 2009 From: foldr at codedgers.com (Mikhail Glushenkov) Date: Tue, 15 Dec 2009 03:03:37 -0000 Subject: [llvm-commits] [llvm] r91401 - /llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst Message-ID: <200912150303.nBF33bCv030653@zion.cs.uiuc.edu> Author: foldr Date: Mon Dec 14 21:03:37 2009 New Revision: 91401 URL: http://llvm.org/viewvc/llvm-project?rev=91401&view=rev Log: Small documentation update. Modified: llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst Modified: llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst?rev=91401&r1=91400&r2=91401&view=diff ============================================================================== --- llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst (original) +++ llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst Mon Dec 14 21:03:37 2009 @@ -360,10 +360,11 @@ and ``required`` properties. - ``init`` - this option has a default value, either a string (if it is a - parameter), or a boolean (if it is a switch; boolean constants are called - ``true`` and ``false``). List options can't have this attribute. Usage - examples: ``(switch_option "foo", (init true))``; ``(prefix_option "bar", - (init "baz"))``. + parameter), or a boolean (if it is a switch; as in C++, boolean constants + are called ``true`` and ``false``). List options can't have ``init`` + attribute. + Usage examples: ``(switch_option "foo", (init true))``; ``(prefix_option + "bar", (init "baz"))``. - ``extern`` - this option is defined in some other plugin, see `below`__. From foldr at codedgers.com Mon Dec 14 21:04:02 2009 From: foldr at codedgers.com (Mikhail Glushenkov) Date: Tue, 15 Dec 2009 03:04:02 -0000 Subject: [llvm-commits] [llvm] r91402 - in /llvm/trunk: test/LLVMC/HookWithInFile.td utils/TableGen/LLVMCConfigurationEmitter.cpp Message-ID: <200912150304.nBF343NP030677@zion.cs.uiuc.edu> Author: foldr Date: Mon Dec 14 21:04:02 2009 New Revision: 91402 URL: http://llvm.org/viewvc/llvm-project?rev=91402&view=rev Log: Allow $CALL(Hook, '$INFILE') for non-join tools. Added: llvm/trunk/test/LLVMC/HookWithInFile.td Modified: llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp Added: llvm/trunk/test/LLVMC/HookWithInFile.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/HookWithInFile.td?rev=91402&view=auto ============================================================================== --- llvm/trunk/test/LLVMC/HookWithInFile.td (added) +++ llvm/trunk/test/LLVMC/HookWithInFile.td Mon Dec 14 21:04:02 2009 @@ -0,0 +1,13 @@ +// Check that a hook can be given $INFILE as an argument. +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: grep Hook\\(inFile.c_str\\(\\)\\) %t | count 1 + +include "llvm/CompilerDriver/Common.td" + +def dummy_tool : Tool<[ +(cmd_line "$CALL(Hook, '$INFILE')/path $INFILE"), +(in_language "dummy"), +(out_language "dummy") +]>; + +def DummyGraph : CompilationGraph<[SimpleEdge<"root", "dummy_tool">]>; Modified: llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp?rev=91402&r1=91401&r2=91402&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp (original) +++ llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp Mon Dec 14 21:04:02 2009 @@ -1537,62 +1537,99 @@ } } -/// SubstituteSpecialCommands - Perform string substitution for $CALL -/// and $ENV. Helper function used by EmitCmdLineVecFill(). -StrVector::const_iterator SubstituteSpecialCommands -(StrVector::const_iterator Pos, StrVector::const_iterator End, raw_ostream& O) +/// SubstituteCall - Given "$CALL(HookName, [Arg1 [, Arg2 [...]]])", output +/// "hooks::HookName([Arg1 [, Arg2 [, ...]]])". Helper function used by +/// SubstituteSpecialCommands(). +StrVector::const_iterator +SubstituteCall (StrVector::const_iterator Pos, + StrVector::const_iterator End, + bool IsJoin, raw_ostream& O) { + const char* errorMessage = "Syntax error in $CALL invocation!"; + checkedIncrement(Pos, End, errorMessage); + const std::string& CmdName = *Pos; - const std::string& cmd = *Pos; - - if (cmd == "$CALL") { - checkedIncrement(Pos, End, "Syntax error in $CALL invocation!"); - const std::string& CmdName = *Pos; + if (CmdName == ")") + throw "$CALL invocation: empty argument list!"; - if (CmdName == ")") - throw "$CALL invocation: empty argument list!"; + O << "hooks::"; + O << CmdName << "("; - O << "hooks::"; - O << CmdName << "("; + bool firstIteration = true; + while (true) { + checkedIncrement(Pos, End, errorMessage); + const std::string& Arg = *Pos; + assert(Arg.size() != 0); - bool firstIteration = true; - while (true) { - checkedIncrement(Pos, End, "Syntax error in $CALL invocation!"); - const std::string& Arg = *Pos; - assert(Arg.size() != 0); + if (Arg[0] == ')') + break; - if (Arg[0] == ')') - break; + if (firstIteration) + firstIteration = false; + else + O << ", "; - if (firstIteration) - firstIteration = false; + if (Arg == "$INFILE") { + if (IsJoin) + throw "$CALL(Hook, $INFILE) can't be used with a Join tool!"; else - O << ", "; - + O << "inFile.c_str()"; + } + else { O << '"' << Arg << '"'; } + } - O << ')'; + O << ')'; - } - else if (cmd == "$ENV") { - checkedIncrement(Pos, End, "Syntax error in $ENV invocation!"); - const std::string& EnvName = *Pos; + return Pos; +} - if (EnvName == ")") - throw "$ENV invocation: empty argument list!"; +/// SubstituteEnv - Given '$ENV(VAR_NAME)', output 'getenv("VAR_NAME")'. Helper +/// function used by SubstituteSpecialCommands(). +StrVector::const_iterator +SubstituteEnv (StrVector::const_iterator Pos, + StrVector::const_iterator End, raw_ostream& O) +{ + const char* errorMessage = "Syntax error in $ENV invocation!"; + checkedIncrement(Pos, End, errorMessage); + const std::string& EnvName = *Pos; + + if (EnvName == ")") + throw "$ENV invocation: empty argument list!"; + + O << "checkCString(std::getenv(\""; + O << EnvName; + O << "\"))"; + + checkedIncrement(Pos, End, errorMessage); + + return Pos; +} - O << "checkCString(std::getenv(\""; - O << EnvName; - O << "\"))"; +/// SubstituteSpecialCommands - Given an invocation of $CALL or $ENV, output +/// handler code. Helper function used by EmitCmdLineVecFill(). +StrVector::const_iterator +SubstituteSpecialCommands (StrVector::const_iterator Pos, + StrVector::const_iterator End, + bool IsJoin, raw_ostream& O) +{ - checkedIncrement(Pos, End, "Syntax error in $ENV invocation!"); + const std::string& cmd = *Pos; + + // Perform substitution. + if (cmd == "$CALL") { + Pos = SubstituteCall(Pos, End, IsJoin, O); + } + else if (cmd == "$ENV") { + Pos = SubstituteEnv(Pos, End, O); } else { throw "Unknown special command: " + cmd; } + // Handle '$CMD(ARG)/additional/text'. const std::string& Leftover = *Pos; assert(Leftover.at(0) == ')'); if (Leftover.size() != 1) @@ -1652,7 +1689,7 @@ } else { O << "vec.push_back("; - I = SubstituteSpecialCommands(I, E, O); + I = SubstituteSpecialCommands(I, E, IsJoin, O); O << ");\n"; } } @@ -1665,7 +1702,7 @@ O.indent(IndentLevel) << "cmd = "; if (StrVec[0][0] == '$') - SubstituteSpecialCommands(StrVec.begin(), StrVec.end(), O); + SubstituteSpecialCommands(StrVec.begin(), StrVec.end(), IsJoin, O); else O << '"' << StrVec[0] << '"'; O << ";\n"; From foldr at codedgers.com Mon Dec 14 21:04:14 2009 From: foldr at codedgers.com (Mikhail Glushenkov) Date: Tue, 15 Dec 2009 03:04:14 -0000 Subject: [llvm-commits] [llvm] r91403 - /llvm/trunk/test/LLVMC/Init.td Message-ID: <200912150304.nBF34EB2030697@zion.cs.uiuc.edu> Author: foldr Date: Mon Dec 14 21:04:14 2009 New Revision: 91403 URL: http://llvm.org/viewvc/llvm-project?rev=91403&view=rev Log: Pipe 'grep' output to 'count'. Modified: llvm/trunk/test/LLVMC/Init.td Modified: llvm/trunk/test/LLVMC/Init.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/Init.td?rev=91403&r1=91402&r2=91403&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/Init.td (original) +++ llvm/trunk/test/LLVMC/Init.td Mon Dec 14 21:04:14 2009 @@ -1,7 +1,7 @@ // Check that (init true/false) and (init "str") work. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep cl::init("some-string") %t -// RUN: grep cl::init(true) %t +// RUN: grep cl::init(\\"some-string\\") %t | count 1 +// RUN: grep cl::init(true) %t | count 1 include "llvm/CompilerDriver/Common.td" From foldr at codedgers.com Mon Dec 14 21:04:52 2009 From: foldr at codedgers.com (Mikhail Glushenkov) Date: Tue, 15 Dec 2009 03:04:52 -0000 Subject: [llvm-commits] [llvm] r91404 - in /llvm/trunk: include/llvm/CompilerDriver/ test/LLVMC/ tools/llvmc/doc/ utils/TableGen/ Message-ID: <200912150304.nBF34rPa030741@zion.cs.uiuc.edu> Author: foldr Date: Mon Dec 14 21:04:52 2009 New Revision: 91404 URL: http://llvm.org/viewvc/llvm-project?rev=91404&view=rev Log: Validate the generated C++ code in llvmc tests. Checks that the code generated by 'tblgen --emit-llvmc' can be actually compiled. Also fixes two bugs found in this way: - forward_transformed_value didn't work with non-list arguments - cl::ZeroOrOne is now called cl::Optional Modified: llvm/trunk/include/llvm/CompilerDriver/Common.td llvm/trunk/test/LLVMC/EmptyCompilationGraph.td llvm/trunk/test/LLVMC/EnvParentheses.td llvm/trunk/test/LLVMC/ExternOptions.td llvm/trunk/test/LLVMC/ForwardAs.td llvm/trunk/test/LLVMC/ForwardTransformedValue.td llvm/trunk/test/LLVMC/ForwardValue.td llvm/trunk/test/LLVMC/HookWithArguments.td llvm/trunk/test/LLVMC/HookWithInFile.td llvm/trunk/test/LLVMC/Init.td llvm/trunk/test/LLVMC/MultiValuedOption.td llvm/trunk/test/LLVMC/MultipleCompilationGraphs.td llvm/trunk/test/LLVMC/NoActions.td llvm/trunk/test/LLVMC/NoCompilationGraph.td llvm/trunk/test/LLVMC/OneOrMore.td llvm/trunk/test/LLVMC/OptionPreprocessor.td llvm/trunk/test/LLVMC/TestWarnings.td llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp Modified: llvm/trunk/include/llvm/CompilerDriver/Common.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CompilerDriver/Common.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/include/llvm/CompilerDriver/Common.td (original) +++ llvm/trunk/include/llvm/CompilerDriver/Common.td Mon Dec 14 21:04:52 2009 @@ -42,9 +42,9 @@ def init; def multi_val; def one_or_more; +def optional; def really_hidden; def required; -def zero_or_one; def comma_separated; // The 'case' construct. Modified: llvm/trunk/test/LLVMC/EmptyCompilationGraph.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/EmptyCompilationGraph.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/EmptyCompilationGraph.td (original) +++ llvm/trunk/test/LLVMC/EmptyCompilationGraph.td Mon Dec 14 21:04:52 2009 @@ -1,5 +1,6 @@ // Check that the compilation graph can be empty. -// RUN: tblgen -I %p/../../include --gen-llvmc %s +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/EnvParentheses.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/EnvParentheses.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/EnvParentheses.td (original) +++ llvm/trunk/test/LLVMC/EnvParentheses.td Mon Dec 14 21:04:52 2009 @@ -2,6 +2,7 @@ // http://llvm.org/bugs/show_bug.cgi?id=4157 // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t // RUN: not grep {)));} %t +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/ExternOptions.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/ExternOptions.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/ExternOptions.td (original) +++ llvm/trunk/test/LLVMC/ExternOptions.td Mon Dec 14 21:04:52 2009 @@ -2,6 +2,7 @@ // The dummy tool and graph are required to silence warnings. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t // RUN: grep {extern .* AutoGeneratedSwitch_Wall} %t +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/ForwardAs.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/ForwardAs.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/ForwardAs.td (original) +++ llvm/trunk/test/LLVMC/ForwardAs.td Mon Dec 14 21:04:52 2009 @@ -2,6 +2,7 @@ // http://llvm.org/bugs/show_bug.cgi?id=4159 // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t // RUN: grep unique_name %t +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/ForwardTransformedValue.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/ForwardTransformedValue.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/ForwardTransformedValue.td (original) +++ llvm/trunk/test/LLVMC/ForwardTransformedValue.td Mon Dec 14 21:04:52 2009 @@ -1,8 +1,9 @@ // Check that forward_transformed_value works. // The dummy tool and graph are required to silence warnings. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep HookA %t -// RUN: grep HookB %t +// RUN: grep HookA %t | count 2 +// RUN: grep HookB %t | count 2 +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/ForwardValue.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/ForwardValue.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/ForwardValue.td (original) +++ llvm/trunk/test/LLVMC/ForwardValue.td Mon Dec 14 21:04:52 2009 @@ -3,6 +3,7 @@ // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t // RUN: grep {vec.push_back\(AutoGeneratedParameter_a\)} %t // RUN: grep {std::copy\(AutoGeneratedList_b.begin\(\)} %t +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/HookWithArguments.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/HookWithArguments.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/HookWithArguments.td (original) +++ llvm/trunk/test/LLVMC/HookWithArguments.td Mon Dec 14 21:04:52 2009 @@ -4,6 +4,7 @@ // RUN: grep "/path" %t | count 1 // RUN: grep "VARIABLE" %t | count 1 // RUN: grep "/2path" %t | count 1 +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/HookWithInFile.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/HookWithInFile.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/HookWithInFile.td (original) +++ llvm/trunk/test/LLVMC/HookWithInFile.td Mon Dec 14 21:04:52 2009 @@ -1,6 +1,7 @@ // Check that a hook can be given $INFILE as an argument. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t // RUN: grep Hook\\(inFile.c_str\\(\\)\\) %t | count 1 +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/Init.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/Init.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/Init.td (original) +++ llvm/trunk/test/LLVMC/Init.td Mon Dec 14 21:04:52 2009 @@ -2,6 +2,7 @@ // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t // RUN: grep cl::init(\\"some-string\\") %t | count 1 // RUN: grep cl::init(true) %t | count 1 +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/MultiValuedOption.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/MultiValuedOption.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/MultiValuedOption.td (original) +++ llvm/trunk/test/LLVMC/MultiValuedOption.td Mon Dec 14 21:04:52 2009 @@ -2,6 +2,7 @@ // The dummy tool and graph are required to silence warnings. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t // RUN: grep cl::multi_val(2) %t | count 1 +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/MultipleCompilationGraphs.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/MultipleCompilationGraphs.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/MultipleCompilationGraphs.td (original) +++ llvm/trunk/test/LLVMC/MultipleCompilationGraphs.td Mon Dec 14 21:04:52 2009 @@ -1,5 +1,6 @@ // Check that multiple compilation graphs are allowed. -// RUN: tblgen -I %p/../../include --gen-llvmc %s +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/NoActions.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/NoActions.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/NoActions.td (original) +++ llvm/trunk/test/LLVMC/NoActions.td Mon Dec 14 21:04:52 2009 @@ -1,5 +1,7 @@ // Check that tools without associated actions are accepted. -// RUN: tblgen -I %p/../../include --gen-llvmc %s | grep dummy_tool +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: grep dummy_tool %t +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/NoCompilationGraph.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/NoCompilationGraph.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/NoCompilationGraph.td (original) +++ llvm/trunk/test/LLVMC/NoCompilationGraph.td Mon Dec 14 21:04:52 2009 @@ -1,4 +1,5 @@ // Check that the compilation graph is not required. -// RUN: tblgen -I %p/../../include --gen-llvmc %s +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/OneOrMore.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/OneOrMore.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/OneOrMore.td (original) +++ llvm/trunk/test/LLVMC/OneOrMore.td Mon Dec 14 21:04:52 2009 @@ -1,14 +1,15 @@ // Check that (one_or_more) and (zero_or_one) properties work. // The dummy tool and graph are required to silence warnings. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep cl::ZeroOrOne %t | count 1 +// RUN: grep cl::Optional %t | count 1 // RUN: grep cl::OneOrMore %t | count 1 +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" def OptList : OptionList<[ (prefix_list_option "foo", (one_or_more)), - (parameter_list_option "baz", (zero_or_one))]>; + (parameter_list_option "baz", (optional))]>; def dummy_tool : Tool<[ (cmd_line "dummy_cmd $INFILE"), Modified: llvm/trunk/test/LLVMC/OptionPreprocessor.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/OptionPreprocessor.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/OptionPreprocessor.td (original) +++ llvm/trunk/test/LLVMC/OptionPreprocessor.td Mon Dec 14 21:04:52 2009 @@ -3,6 +3,7 @@ // RUN: grep W1 %t // RUN: grep W2 %t // RUN: grep W3 %t +// RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/TestWarnings.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/TestWarnings.td?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/TestWarnings.td (original) +++ llvm/trunk/test/LLVMC/TestWarnings.td Mon Dec 14 21:04:52 2009 @@ -1,4 +1,4 @@ -// Check that the compiler warns about unused options. +// Check that warnings about unused options are really emitted. // This should fail because the output is printed on stderr. // RUN: ignore tblgen -I %p/../../include --gen-llvmc %s |& grep "option '-Wall' has no effect!" Modified: llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst (original) +++ llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst Mon Dec 14 21:04:52 2009 @@ -336,8 +336,8 @@ it is synonymous with ``required``. Incompatible with ``required`` and ``zero_or_one``. - - ``zero_or_one`` - the option can be specified zero or one times. Useful - only for list options in conjunction with ``multi_val``. Incompatible with + - ``optional`` - the option can be specified zero or one times. Useful only + for list options in conjunction with ``multi_val``. Incompatible with ``required`` and ``one_or_more``. - ``hidden`` - the description of this option will not appear in @@ -356,7 +356,7 @@ - ``multi_val n`` - this option takes *n* arguments (can be useful in some special cases). Usage example: ``(parameter_list_option "foo", (multi_val 3))``; the command-line syntax is '-foo a b c'. Only list options can have - this attribute; you can, however, use the ``one_or_more``, ``zero_or_one`` + this attribute; you can, however, use the ``one_or_more``, ``optional`` and ``required`` properties. - ``init`` - this option has a default value, either a string (if it is a Modified: llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp?rev=91404&r1=91403&r2=91404&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp (original) +++ llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp Mon Dec 14 21:04:52 2009 @@ -211,7 +211,7 @@ namespace OptionDescriptionFlags { enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2, ReallyHidden = 0x4, Extern = 0x8, - OneOrMore = 0x10, ZeroOrOne = 0x20, + OneOrMore = 0x10, Optional = 0x20, CommaSeparated = 0x40 }; } @@ -260,8 +260,8 @@ bool isOneOrMore() const; void setOneOrMore(); - bool isZeroOrOne() const; - void setZeroOrOne(); + bool isOptional() const; + void setOptional(); bool isHidden() const; void setHidden(); @@ -331,11 +331,11 @@ Flags |= OptionDescriptionFlags::OneOrMore; } -bool OptionDescription::isZeroOrOne() const { - return Flags & OptionDescriptionFlags::ZeroOrOne; +bool OptionDescription::isOptional() const { + return Flags & OptionDescriptionFlags::Optional; } -void OptionDescription::setZeroOrOne() { - Flags |= OptionDescriptionFlags::ZeroOrOne; +void OptionDescription::setOptional() { + Flags |= OptionDescriptionFlags::Optional; } bool OptionDescription::isHidden() const { @@ -548,7 +548,7 @@ AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore); AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden); AddHandler("required", &CollectOptionProperties::onRequired); - AddHandler("zero_or_one", &CollectOptionProperties::onZeroOrOne); + AddHandler("optional", &CollectOptionProperties::onOptional); AddHandler("comma_separated", &CollectOptionProperties::onCommaSeparated); staticMembersInitialized_ = true; @@ -595,8 +595,8 @@ void onRequired (const DagInit* d) { checkNumberOfArguments(d, 0); - if (optDesc_.isOneOrMore() || optDesc_.isZeroOrOne()) - throw "Only one of (required), (zero_or_one) or " + if (optDesc_.isOneOrMore() || optDesc_.isOptional()) + throw "Only one of (required), (optional) or " "(one_or_more) properties is allowed!"; optDesc_.setRequired(); } @@ -617,8 +617,8 @@ void onOneOrMore (const DagInit* d) { checkNumberOfArguments(d, 0); - if (optDesc_.isRequired() || optDesc_.isZeroOrOne()) - throw "Only one of (required), (zero_or_one) or " + if (optDesc_.isRequired() || optDesc_.isOptional()) + throw "Only one of (required), (optional) or " "(one_or_more) properties is allowed!"; if (!OptionType::IsList(optDesc_.Type)) llvm::errs() << "Warning: specifying the 'one_or_more' property " @@ -626,15 +626,15 @@ optDesc_.setOneOrMore(); } - void onZeroOrOne (const DagInit* d) { + void onOptional (const DagInit* d) { checkNumberOfArguments(d, 0); if (optDesc_.isRequired() || optDesc_.isOneOrMore()) - throw "Only one of (required), (zero_or_one) or " + throw "Only one of (required), (optional) or " "(one_or_more) properties is allowed!"; if (!OptionType::IsList(optDesc_.Type)) - llvm::errs() << "Warning: specifying the 'zero_or_one' property" + llvm::errs() << "Warning: specifying the 'optional' property" "on a non-list option will have no effect.\n"; - optDesc_.setZeroOrOne(); + optDesc_.setOptional(); } void onMultiVal (const DagInit* d) { @@ -1882,7 +1882,8 @@ const OptionDescription& D = OptDescs.FindListOrParameter(Name); O.indent(IndentLevel) << "vec.push_back(" << "hooks::" - << Hook << "(" << D.GenVariableName() << "));\n"; + << Hook << "(" << D.GenVariableName() + << (D.isParameter() ? ".c_str()" : "") << "));\n"; } @@ -2211,8 +2212,8 @@ else if (val.isOneOrMore() && val.isList()) { O << ", cl::OneOrMore"; } - else if (val.isZeroOrOne() && val.isList()) { - O << ", cl::ZeroOrOne"; + else if (val.isOptional() && val.isList()) { + O << ", cl::Optional"; } if (val.isReallyHidden()) From evan.cheng at apple.com Mon Dec 14 21:07:11 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 15 Dec 2009 03:07:11 -0000 Subject: [llvm-commits] [llvm] r91405 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/setcc.ll Message-ID: <200912150307.nBF37Btj030812@zion.cs.uiuc.edu> Author: evancheng Date: Mon Dec 14 21:07:11 2009 New Revision: 91405 URL: http://llvm.org/viewvc/llvm-project?rev=91405&view=rev Log: Disable 91381 for now. It's miscompiling ARMISelDAG2DAG.cpp. Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/test/CodeGen/X86/setcc.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=91405&r1=91404&r2=91405&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Dec 14 21:07:11 2009 @@ -5752,7 +5752,9 @@ SDValue Cond = EmitCmp(Op0, Op1, X86CC, DAG); // Use sbb x, x to materialize carry bit into a GPR. - if (X86CC == X86::COND_B) { + // FIXME: Temporarily disabled since it breaks self-hosting. It's apparently + // miscompiling ARMISelDAGToDAG.cpp. + if (0 && !isFP && X86CC == X86::COND_B) { return DAG.getNode(ISD::AND, dl, MVT::i8, DAG.getNode(X86ISD::SETCC_CARRY, dl, MVT::i8, DAG.getConstant(X86CC, MVT::i8), Cond), Modified: llvm/trunk/test/CodeGen/X86/setcc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=91405&r1=91404&r2=91405&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/setcc.ll (original) +++ llvm/trunk/test/CodeGen/X86/setcc.ll Mon Dec 14 21:07:11 2009 @@ -1,4 +1,5 @@ ; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s +; XFAIL: * ; rdar://7329206 ; Use sbb x, x to materialize carry bit in a GPR. The value is either From rjmccall at apple.com Mon Dec 14 21:10:26 2009 From: rjmccall at apple.com (John McCall) Date: Tue, 15 Dec 2009 03:10:26 -0000 Subject: [llvm-commits] [llvm] r91407 - /llvm/trunk/include/llvm/ADT/ilist.h Message-ID: <200912150310.nBF3AR5P030923@zion.cs.uiuc.edu> Author: rjmccall Date: Mon Dec 14 21:10:26 2009 New Revision: 91407 URL: http://llvm.org/viewvc/llvm-project?rev=91407&view=rev Log: Names from dependent base classes are not found by unqualified lookup. Modified: llvm/trunk/include/llvm/ADT/ilist.h Modified: llvm/trunk/include/llvm/ADT/ilist.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ilist.h?rev=91407&r1=91406&r2=91407&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/ilist.h (original) +++ llvm/trunk/include/llvm/ADT/ilist.h Mon Dec 14 21:10:26 2009 @@ -643,7 +643,7 @@ // Main implementation here - Insert for a node passed by value... iterator insert(iterator where, const NodeTy &val) { - return insert(where, createNode(val)); + return insert(where, this->createNode(val)); } From kennethuil at gmail.com Mon Dec 14 21:27:52 2009 From: kennethuil at gmail.com (Kenneth Uildriks) Date: Tue, 15 Dec 2009 03:27:52 -0000 Subject: [llvm-commits] [llvm] r91410 - in /llvm/trunk: lib/Target/X86/X86CallingConv.td test/CodeGen/X86/fastcc3struct.ll Message-ID: <200912150327.nBF3RqRc031581@zion.cs.uiuc.edu> Author: kennethuil Date: Mon Dec 14 21:27:52 2009 New Revision: 91410 URL: http://llvm.org/viewvc/llvm-project?rev=91410&view=rev Log: For fastcc on x86, let ECX be used as a return register after EAX and EDX Added: llvm/trunk/test/CodeGen/X86/fastcc3struct.ll Modified: llvm/trunk/lib/Target/X86/X86CallingConv.td Modified: llvm/trunk/lib/Target/X86/X86CallingConv.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CallingConv.td?rev=91410&r1=91409&r2=91410&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86CallingConv.td (original) +++ llvm/trunk/lib/Target/X86/X86CallingConv.td Mon Dec 14 21:27:52 2009 @@ -64,11 +64,18 @@ // X86-32 FastCC return-value convention. def RetCC_X86_32_Fast : CallingConv<[ // The X86-32 fastcc returns 1, 2, or 3 FP values in XMM0-2 if the target has - // SSE2, otherwise it is the the C calling conventions. + // SSE2. // This can happen when a float, 2 x float, or 3 x float vector is split by // target lowering, and is returned in 1-3 sse regs. CCIfType<[f32], CCIfSubtarget<"hasSSE2()", CCAssignToReg<[XMM0,XMM1,XMM2]>>>, CCIfType<[f64], CCIfSubtarget<"hasSSE2()", CCAssignToReg<[XMM0,XMM1,XMM2]>>>, + + // For integers, ECX can be used as an extra return register + CCIfType<[i8], CCAssignToReg<[AL, DL, CL]>>, + CCIfType<[i16], CCAssignToReg<[AX, DX, CX]>>, + CCIfType<[i32], CCAssignToReg<[EAX, EDX, ECX]>>, + + // Otherwise, it is the same as the common X86 calling convention. CCDelegateTo ]>; Added: llvm/trunk/test/CodeGen/X86/fastcc3struct.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fastcc3struct.ll?rev=91410&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/fastcc3struct.ll (added) +++ llvm/trunk/test/CodeGen/X86/fastcc3struct.ll Mon Dec 14 21:27:52 2009 @@ -0,0 +1,15 @@ +; RUN: llc < %s -march=x86 -o %t +; RUN: grep "movl .48, %ecx" %t +; RUN: grep "movl .24, %edx" %t +; RUN: grep "movl .12, %eax" %t + +%0 = type { i32, i32, i32 } + +define internal fastcc %0 @ReturnBigStruct() nounwind readnone { +entry: + %0 = insertvalue %0 zeroinitializer, i32 12, 0 + %1 = insertvalue %0 %0, i32 24, 1 + %2 = insertvalue %0 %1, i32 48, 2 + ret %0 %2 +} + From clattner at apple.com Mon Dec 14 23:45:35 2009 From: clattner at apple.com (Chris Lattner) Date: Mon, 14 Dec 2009 21:45:35 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> <6ED59F80-2FD1-4C09-8325-BD4ED7C90EBE@apple.com> Message-ID: <36B43602-B224-444F-AF93-AFA3CF30E539@apple.com> On Dec 14, 2009, at 5:49 PM, Evan Cheng wrote: >>>> >>>> Is this really profitable in the general case? It seems that this should only be done if at least one of the inputs to the shift will fold away. Adding a nice "WouldFoldAZExt" predicate that would return true for zext/trunc would make sense, no? >>> >>> Are there cases where (zext (zext)) would not fold into a single zext? >> >> No, I'm worried that you're turning something like: >> >> zext(shr(call, call)) -> shr(zext(call), zext(call)) >> >> which introduces two zexts and deletes one. > > No. The transformation only happens when one of the shift's operand is a zext. Oh ok! -Chris From clattner at apple.com Mon Dec 14 23:46:11 2009 From: clattner at apple.com (Chris Lattner) Date: Mon, 14 Dec 2009 21:46:11 -0800 Subject: [llvm-commits] [llvm] r91397 - /llvm/trunk/lib/Analysis/ProfileInfo.cpp In-Reply-To: <200912150235.nBF2ZPTE029607@zion.cs.uiuc.edu> References: <200912150235.nBF2ZPTE029607@zion.cs.uiuc.edu> Message-ID: <9367CAC4-5D67-4A50-A4F2-C4BE12F88A4C@apple.com> On Dec 14, 2009, at 6:35 PM, John McCall wrote: > Author: rjmccall > Date: Mon Dec 14 20:35:24 2009 > New Revision: 91397 > > URL: http://llvm.org/viewvc/llvm-project?rev=91397&view=rev > Log: > You can't use typedefs to declare template member specializations, and > clang enforces it. Does clang produce a good diagnostic (with a fixit hint) for this error? -Chris > > > Modified: > llvm/trunk/lib/Analysis/ProfileInfo.cpp > > Modified: llvm/trunk/lib/Analysis/ProfileInfo.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ProfileInfo.cpp?rev=91397&r1=91396&r2=91397&view=diff > > ============================================================================== > --- llvm/trunk/lib/Analysis/ProfileInfo.cpp (original) > +++ llvm/trunk/lib/Analysis/ProfileInfo.cpp Mon Dec 14 20:35:24 2009 > @@ -44,19 +44,19 @@ > } > > template<> > -char ProfileInfo::ID = 0; > +char ProfileInfoT::ID = 0; > > template<> > -char MachineProfileInfo::ID = 0; > +char ProfileInfoT::ID = 0; > > template<> > -const double ProfileInfo::MissingValue = -1; > +const double ProfileInfoT::MissingValue = -1; > > -template<> > -const double MachineProfileInfo::MissingValue = -1; > +template<> const > +double ProfileInfoT::MissingValue = -1; > > -template<> > -double ProfileInfo::getExecutionCount(const BasicBlock *BB) { > +template<> double > +ProfileInfoT::getExecutionCount(const BasicBlock *BB) { > std::map::iterator J = > BlockInformation.find(BB->getParent()); > if (J != BlockInformation.end()) { > @@ -118,7 +118,8 @@ > } > > template<> > -double MachineProfileInfo::getExecutionCount(const MachineBasicBlock *MBB) { > +double ProfileInfoT:: > + getExecutionCount(const MachineBasicBlock *MBB) { > std::map::iterator J = > BlockInformation.find(MBB->getParent()); > if (J != BlockInformation.end()) { > @@ -131,7 +132,7 @@ > } > > template<> > -double ProfileInfo::getExecutionCount(const Function *F) { > +double ProfileInfoT::getExecutionCount(const Function *F) { > std::map::iterator J = > FunctionInformation.find(F); > if (J != FunctionInformation.end()) > @@ -147,7 +148,8 @@ > } > > template<> > -double MachineProfileInfo::getExecutionCount(const MachineFunction *MF) { > +double ProfileInfoT:: > + getExecutionCount(const MachineFunction *MF) { > std::map::iterator J = > FunctionInformation.find(MF); > if (J != FunctionInformation.end()) > @@ -159,21 +161,23 @@ > } > > template<> > -void ProfileInfo::setExecutionCount(const BasicBlock *BB, double w) { > +void ProfileInfoT:: > + setExecutionCount(const BasicBlock *BB, double w) { > DEBUG(errs() << "Creating Block " << BB->getName() > << " (weight: " << format("%.20g",w) << ")\n"); > BlockInformation[BB->getParent()][BB] = w; > } > > template<> > -void MachineProfileInfo::setExecutionCount(const MachineBasicBlock *MBB, double w) { > +void ProfileInfoT:: > + setExecutionCount(const MachineBasicBlock *MBB, double w) { > DEBUG(errs() << "Creating Block " << MBB->getBasicBlock()->getName() > << " (weight: " << format("%.20g",w) << ")\n"); > BlockInformation[MBB->getParent()][MBB] = w; > } > > template<> > -void ProfileInfo::addEdgeWeight(Edge e, double w) { > +void ProfileInfoT::addEdgeWeight(Edge e, double w) { > double oldw = getEdgeWeight(e); > assert (oldw != MissingValue && "Adding weight to Edge with no previous weight"); > DEBUG(errs() << "Adding to Edge " << e > @@ -182,7 +186,8 @@ > } > > template<> > -void ProfileInfo::addExecutionCount(const BasicBlock *BB, double w) { > +void ProfileInfoT:: > + addExecutionCount(const BasicBlock *BB, double w) { > double oldw = getExecutionCount(BB); > assert (oldw != MissingValue && "Adding weight to Block with no previous weight"); > DEBUG(errs() << "Adding to Block " << BB->getName() > @@ -191,7 +196,7 @@ > } > > template<> > -void ProfileInfo::removeBlock(const BasicBlock *BB) { > +void ProfileInfoT::removeBlock(const BasicBlock *BB) { > std::map::iterator J = > BlockInformation.find(BB->getParent()); > if (J == BlockInformation.end()) return; > @@ -201,7 +206,7 @@ > } > > template<> > -void ProfileInfo::removeEdge(Edge e) { > +void ProfileInfoT::removeEdge(Edge e) { > std::map::iterator J = > EdgeInformation.find(getFunction(e)); > if (J == EdgeInformation.end()) return; > @@ -211,7 +216,8 @@ > } > > template<> > -void ProfileInfo::replaceEdge(const Edge &oldedge, const Edge &newedge) { > +void ProfileInfoT:: > + replaceEdge(const Edge &oldedge, const Edge &newedge) { > double w; > if ((w = getEdgeWeight(newedge)) == MissingValue) { > w = getEdgeWeight(oldedge); > @@ -225,8 +231,9 @@ > } > > template<> > -const BasicBlock *ProfileInfo::GetPath(const BasicBlock *Src, const BasicBlock *Dest, > - Path &P, unsigned Mode) { > +const BasicBlock *ProfileInfoT:: > + GetPath(const BasicBlock *Src, const BasicBlock *Dest, > + Path &P, unsigned Mode) { > const BasicBlock *BB = 0; > bool hasFoundPath = false; > > @@ -268,7 +275,8 @@ > } > > template<> > -void ProfileInfo::divertFlow(const Edge &oldedge, const Edge &newedge) { > +void ProfileInfoT:: > + divertFlow(const Edge &oldedge, const Edge &newedge) { > DEBUG(errs() << "Diverting " << oldedge << " via " << newedge ); > > // First check if the old edge was taken, if not, just delete it... > @@ -302,8 +310,8 @@ > /// This checks all edges of the function the blocks reside in and replaces the > /// occurences of RmBB with DestBB. > template<> > -void ProfileInfo::replaceAllUses(const BasicBlock *RmBB, > - const BasicBlock *DestBB) { > +void ProfileInfoT:: > + replaceAllUses(const BasicBlock *RmBB, const BasicBlock *DestBB) { > DEBUG(errs() << "Replacing " << RmBB->getName() > << " with " << DestBB->getName() << "\n"); > const Function *F = DestBB->getParent(); > @@ -352,10 +360,10 @@ > /// Since its possible that there is more than one edge in the CFG from FristBB > /// to SecondBB its necessary to redirect the flow proporionally. > template<> > -void ProfileInfo::splitEdge(const BasicBlock *FirstBB, > - const BasicBlock *SecondBB, > - const BasicBlock *NewBB, > - bool MergeIdenticalEdges) { > +void ProfileInfoT::splitEdge(const BasicBlock *FirstBB, > + const BasicBlock *SecondBB, > + const BasicBlock *NewBB, > + bool MergeIdenticalEdges) { > const Function *F = FirstBB->getParent(); > std::map::iterator J = > EdgeInformation.find(F); > @@ -398,7 +406,8 @@ > } > > template<> > -void ProfileInfo::splitBlock(const BasicBlock *Old, const BasicBlock* New) { > +void ProfileInfoT::splitBlock(const BasicBlock *Old, > + const BasicBlock* New) { > const Function *F = Old->getParent(); > std::map::iterator J = > EdgeInformation.find(F); > @@ -426,8 +435,10 @@ > } > > template<> > -void ProfileInfo::splitBlock(const BasicBlock *BB, const BasicBlock* NewBB, > - BasicBlock *const *Preds, unsigned NumPreds) { > +void ProfileInfoT::splitBlock(const BasicBlock *BB, > + const BasicBlock* NewBB, > + BasicBlock *const *Preds, > + unsigned NumPreds) { > const Function *F = BB->getParent(); > std::map::iterator J = > EdgeInformation.find(F); > @@ -461,7 +472,8 @@ > } > > template<> > -void ProfileInfo::transfer(const Function *Old, const Function *New) { > +void ProfileInfoT::transfer(const Function *Old, > + const Function *New) { > DEBUG(errs() << "Replacing Function " << Old->getName() << " with " > << New->getName() << "\n"); > std::map::iterator J = > @@ -474,8 +486,8 @@ > FunctionInformation.erase(Old); > } > > -static double readEdgeOrRemember(ProfileInfo::Edge edge, double w, ProfileInfo::Edge &tocalc, > - unsigned &uncalc) { > +static double readEdgeOrRemember(ProfileInfo::Edge edge, double w, > + ProfileInfo::Edge &tocalc, unsigned &uncalc) { > if (w == ProfileInfo::MissingValue) { > tocalc = edge; > uncalc++; > @@ -486,7 +498,9 @@ > } > > template<> > -bool ProfileInfo::CalculateMissingEdge(const BasicBlock *BB, Edge &removed, bool assumeEmptySelf) { > +bool ProfileInfoT:: > + CalculateMissingEdge(const BasicBlock *BB, Edge &removed, > + bool assumeEmptySelf) { > Edge edgetocalc; > unsigned uncalculated = 0; > > @@ -562,7 +576,7 @@ > } > > template<> > -bool ProfileInfo::EstimateMissingEdges(const BasicBlock *BB) { > +bool ProfileInfoT::EstimateMissingEdges(const BasicBlock *BB) { > bool hasNoSuccessors = false; > > double inWeight = 0; > @@ -619,7 +633,7 @@ > } > > template<> > -void ProfileInfo::repair(const Function *F) { > +void ProfileInfoT::repair(const Function *F) { > // if (getExecutionCount(&(F->getEntryBlock())) == 0) { > // for (Function::const_iterator FI = F->begin(), FE = F->end(); > // FI != FE; ++FI) { > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From clattner at apple.com Mon Dec 14 23:47:38 2009 From: clattner at apple.com (Chris Lattner) Date: Mon, 14 Dec 2009 21:47:38 -0800 Subject: [llvm-commits] [llvm] r91403 - /llvm/trunk/test/LLVMC/Init.td In-Reply-To: <200912150304.nBF34EB2030697@zion.cs.uiuc.edu> References: <200912150304.nBF34EB2030697@zion.cs.uiuc.edu> Message-ID: On Dec 14, 2009, at 7:04 PM, Mikhail Glushenkov wrote: > Author: foldr > Date: Mon Dec 14 21:04:14 2009 > New Revision: 91403 > > URL: http://llvm.org/viewvc/llvm-project?rev=91403&view=rev > Log: > Pipe 'grep' output to 'count'. Hi Mikhail, Please convert this to use FileCheck. Not all systems have "nice" grep implementations that can handle all the escapes etc. FileCheck is documented here: http://llvm.org/docs/TestingGuide.html#FileCheck -Chris > > Modified: > llvm/trunk/test/LLVMC/Init.td > > Modified: llvm/trunk/test/LLVMC/Init.td > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/Init.td?rev=91403&r1=91402&r2=91403&view=diff > > ============================================================================== > --- llvm/trunk/test/LLVMC/Init.td (original) > +++ llvm/trunk/test/LLVMC/Init.td Mon Dec 14 21:04:14 2009 > @@ -1,7 +1,7 @@ > // Check that (init true/false) and (init "str") work. > // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t > -// RUN: grep cl::init("some-string") %t > -// RUN: grep cl::init(true) %t > +// RUN: grep cl::init(\\"some-string\\") %t | count 1 > +// RUN: grep cl::init(true) %t | count 1 > > include "llvm/CompilerDriver/Common.td" > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From nicholas at mxc.ca Tue Dec 15 00:05:14 2009 From: nicholas at mxc.ca (Nick Lewycky) Date: Mon, 14 Dec 2009 22:05:14 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> Message-ID: <4B27271A.7040105@mxc.ca> Evan Cheng wrote: > Author: evancheng > Date: Mon Dec 14 18:41:36 2009 > New Revision: 91378 > > URL: http://llvm.org/viewvc/llvm-project?rev=91378&view=rev > Log: > Propagate zest through logical shift. Evan, should instcombine be doing this? > > Added: > llvm/trunk/test/CodeGen/X86/setcc.ll > llvm/trunk/test/CodeGen/X86/zext-shl.ll > Modified: > llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91378&r1=91377&r2=91378&view=diff > > ============================================================================== > --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:41:36 2009 > @@ -3278,6 +3278,16 @@ > if (SCC.getNode()) return SCC; > } > > + // (zext (shl (zext x), y)) -> (shl (zext x), (zext y)) > + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL)&& > + N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND&& > + N0.hasOneUse()) { > + DebugLoc dl = N->getDebugLoc(); > + return DAG.getNode(N0.getOpcode(), dl, VT, > + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(0)), > + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(1))); > + } > + > return SDValue(); > } > > > Added: llvm/trunk/test/CodeGen/X86/setcc.ll > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=91378&view=auto > > ============================================================================== > --- llvm/trunk/test/CodeGen/X86/setcc.ll (added) > +++ llvm/trunk/test/CodeGen/X86/setcc.ll Mon Dec 14 18:41:36 2009 > @@ -0,0 +1,13 @@ > +; RUN: llc< %s -mtriple=x86_64-apple-darwin | FileCheck %s > + > +define zeroext i16 @t1(i16 zeroext %x) nounwind readnone ssp { > +entry: > +; CHECK: t1: > +; CHECK: seta %al > +; CHECK: movzbl %al, %eax > +; CHECK: shll $5, %eax > + %0 = icmp ugt i16 %x, 26 ; [#uses=1] > + %iftmp.1.0 = select i1 %0, i16 32, i16 0 ; [#uses=1] > + ret i16 %iftmp.1.0 > +} > + > > Added: llvm/trunk/test/CodeGen/X86/zext-shl.ll > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/zext-shl.ll?rev=91378&view=auto > > ============================================================================== > --- llvm/trunk/test/CodeGen/X86/zext-shl.ll (added) > +++ llvm/trunk/test/CodeGen/X86/zext-shl.ll Mon Dec 14 18:41:36 2009 > @@ -0,0 +1,38 @@ > +; RUN: llc< %s -march=x86 | FileCheck %s > + > +define i32 @t1(i8 zeroext %x) nounwind readnone ssp { > +entry: > +; CHECK: t1: > +; CHECK: shll > +; CHECK-NOT: movzwl > +; CHECK: ret > + %0 = zext i8 %x to i16 > + %1 = shl i16 %0, 5 > + %2 = zext i16 %1 to i32 > + ret i32 %2 > +} > + > +define i32 @t2(i8 zeroext %x) nounwind readnone ssp { > +entry: > +; CHECK: t2: > +; CHECK: shrl > +; CHECK-NOT: movzwl > +; CHECK: ret > + %0 = zext i8 %x to i16 > + %1 = lshr i16 %0, 3 > + %2 = zext i16 %1 to i32 > + ret i32 %2 > +} > + > +define i32 @t3(i8 zeroext %x, i8 zeroext %y) nounwind readnone ssp { > +entry: > +; CHECK: t3: > +; CHECK: shll > +; CHECK-NOT: movzwl > +; CHECK: ret > + %0 = zext i8 %x to i16 > + %1 = zext i8 %y to i16 > + %2 = shl i16 %0, %1 > + %3 = zext i16 %2 to i32 > + ret i32 %3 > +} > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From nicholas at mxc.ca Tue Dec 15 00:08:25 2009 From: nicholas at mxc.ca (Nick Lewycky) Date: Mon, 14 Dec 2009 22:08:25 -0800 Subject: [llvm-commits] [llvm] r91380 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/CellSPU/and_ops.ll In-Reply-To: <200912150052.nBF0qBhN025917@zion.cs.uiuc.edu> References: <200912150052.nBF0qBhN025917@zion.cs.uiuc.edu> Message-ID: <4B2727D9.5090203@mxc.ca> Evan Cheng wrote: > Author: evancheng > Date: Mon Dec 14 18:52:11 2009 > New Revision: 91380 > > URL: http://llvm.org/viewvc/llvm-project?rev=91380&view=rev > Log: > Fold (zext (and x, cst)) -> (and (zext x), cst). Again, this looks like something instcombine ought to be doing instead? Nick > > Modified: > llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp > llvm/trunk/test/CodeGen/CellSPU/and_ops.ll > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91380&r1=91379&r2=91380&view=diff > > ============================================================================== > --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:52:11 2009 > @@ -3202,6 +3202,19 @@ > X, DAG.getConstant(Mask, VT)); > } > > + // Fold (zext (and x, cst)) -> (and (zext x), cst) > + if (N0.getOpcode() == ISD::AND&& > + N0.getOperand(1).getOpcode() == ISD::Constant&& > + N0.getOperand(0).getOpcode() != ISD::TRUNCATE&& > + N0.getOperand(0).hasOneUse()) { > + APInt Mask = cast(N0.getOperand(1))->getAPIntValue(); > + Mask.zext(VT.getSizeInBits()); > + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, > + DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, > + N0.getOperand(0)), > + DAG.getConstant(Mask, VT)); > + } > + > // fold (zext (load x)) -> (zext (truncate (zextload x))) > if (ISD::isNON_EXTLoad(N0.getNode())&& > ((!LegalOperations&& !cast(N0)->isVolatile()) || > > Modified: llvm/trunk/test/CodeGen/CellSPU/and_ops.ll > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CellSPU/and_ops.ll?rev=91380&r1=91379&r2=91380&view=diff > > ============================================================================== > --- llvm/trunk/test/CodeGen/CellSPU/and_ops.ll (original) > +++ llvm/trunk/test/CodeGen/CellSPU/and_ops.ll Mon Dec 14 18:52:11 2009 > @@ -1,9 +1,9 @@ > ; RUN: llc< %s -march=cellspu> %t1.s > -; RUN: grep and %t1.s | count 234 > +; RUN: grep and %t1.s | count 230 > ; RUN: grep andc %t1.s | count 85 > -; RUN: grep andi %t1.s | count 37 > -; RUN: grep andhi %t1.s | count 30 > -; RUN: grep andbi %t1.s | count 4 > +; RUN: grep andi %t1.s | count 39 > +; RUN: grep andhi %t1.s | count 28 > +; RUN: grep andbi %t1.s | count 2 > > target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128" > target triple = "spu" > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From sabre at nondot.org Tue Dec 15 00:14:33 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 15 Dec 2009 06:14:33 -0000 Subject: [llvm-commits] [llvm] r91416 - /llvm/trunk/include/llvm/Support/Compiler.h Message-ID: <200912150614.nBF6EXLV005148@zion.cs.uiuc.edu> Author: lattner Date: Tue Dec 15 00:14:33 2009 New Revision: 91416 URL: http://llvm.org/viewvc/llvm-project?rev=91416&view=rev Log: add an ALWAYS_INLINE macro, which does the obvious thing. Modified: llvm/trunk/include/llvm/Support/Compiler.h Modified: llvm/trunk/include/llvm/Support/Compiler.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Compiler.h?rev=91416&r1=91415&r2=91416&view=diff ============================================================================== --- llvm/trunk/include/llvm/Support/Compiler.h (original) +++ llvm/trunk/include/llvm/Support/Compiler.h Tue Dec 15 00:14:33 2009 @@ -70,6 +70,16 @@ #define DISABLE_INLINE #endif +// ALWAYS_INLINE - On compilers where we have a directive to do so, mark a +// method "always inline" because it is performance sensitive. +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +#define ALWAYS_INLINE __attribute__((always_inline)) +#else +// TODO: No idea how to do this with MSVC. +#define ALWAYS_INLINE +#endif + + #ifdef __GNUC__ #define NORETURN __attribute__((noreturn)) #elif defined(_MSC_VER) From evan.cheng at apple.com Tue Dec 15 00:49:02 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 15 Dec 2009 06:49:02 -0000 Subject: [llvm-commits] [llvm] r91417 - /llvm/trunk/lib/Target/X86/X86Instr64bit.td Message-ID: <200912150649.nBF6n3V1006606@zion.cs.uiuc.edu> Author: evancheng Date: Tue Dec 15 00:49:02 2009 New Revision: 91417 URL: http://llvm.org/viewvc/llvm-project?rev=91417&view=rev Log: Fix an encoding bug. Modified: llvm/trunk/lib/Target/X86/X86Instr64bit.td Modified: llvm/trunk/lib/Target/X86/X86Instr64bit.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Instr64bit.td?rev=91417&r1=91416&r2=91417&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original) +++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Tue Dec 15 00:49:02 2009 @@ -1335,7 +1335,7 @@ // Use sbb to materialize carry flag into a GPR. let Defs = [EFLAGS], Uses = [EFLAGS], isCodeGenOnly = 1 in -def SETB_C64r : RI<0x19, MRMDestReg, (outs GR64:$dst), (ins), +def SETB_C64r : RI<0x19, MRMInitReg, (outs GR64:$dst), (ins), "sbb{q}\t$dst, $dst", [(set GR64:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>; From evan.cheng at apple.com Tue Dec 15 00:56:28 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 14 Dec 2009 22:56:28 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: <4B27271A.7040105@mxc.ca> References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> <4B27271A.7040105@mxc.ca> Message-ID: <0C6C95C0-C677-4131-9485-8FA8D5C10C33@apple.com> On Dec 14, 2009, at 10:05 PM, Nick Lewycky wrote: > Evan Cheng wrote: >> Author: evancheng >> Date: Mon Dec 14 18:41:36 2009 >> New Revision: 91378 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=91378&view=rev >> Log: >> Propagate zest through logical shift. > > Evan, should instcombine be doing this? I am not sure. This is one of those transforms that can go into either pass. Now that dag combine does it, I am not sure if there is benefit to adding it to instcombine. Evan > >> >> Added: >> llvm/trunk/test/CodeGen/X86/setcc.ll >> llvm/trunk/test/CodeGen/X86/zext-shl.ll >> Modified: >> llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >> >> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91378&r1=91377&r2=91378&view=diff >> >> ============================================================================== >> --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) >> +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:41:36 2009 >> @@ -3278,6 +3278,16 @@ >> if (SCC.getNode()) return SCC; >> } >> >> + // (zext (shl (zext x), y)) -> (shl (zext x), (zext y)) >> + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL)&& >> + N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND&& >> + N0.hasOneUse()) { >> + DebugLoc dl = N->getDebugLoc(); >> + return DAG.getNode(N0.getOpcode(), dl, VT, >> + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(0)), >> + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(1))); >> + } >> + >> return SDValue(); >> } >> >> >> Added: llvm/trunk/test/CodeGen/X86/setcc.ll >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=91378&view=auto >> >> ============================================================================== >> --- llvm/trunk/test/CodeGen/X86/setcc.ll (added) >> +++ llvm/trunk/test/CodeGen/X86/setcc.ll Mon Dec 14 18:41:36 2009 >> @@ -0,0 +1,13 @@ >> +; RUN: llc< %s -mtriple=x86_64-apple-darwin | FileCheck %s >> + >> +define zeroext i16 @t1(i16 zeroext %x) nounwind readnone ssp { >> +entry: >> +; CHECK: t1: >> +; CHECK: seta %al >> +; CHECK: movzbl %al, %eax >> +; CHECK: shll $5, %eax >> + %0 = icmp ugt i16 %x, 26 ; [#uses=1] >> + %iftmp.1.0 = select i1 %0, i16 32, i16 0 ; [#uses=1] >> + ret i16 %iftmp.1.0 >> +} >> + >> >> Added: llvm/trunk/test/CodeGen/X86/zext-shl.ll >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/zext-shl.ll?rev=91378&view=auto >> >> ============================================================================== >> --- llvm/trunk/test/CodeGen/X86/zext-shl.ll (added) >> +++ llvm/trunk/test/CodeGen/X86/zext-shl.ll Mon Dec 14 18:41:36 2009 >> @@ -0,0 +1,38 @@ >> +; RUN: llc< %s -march=x86 | FileCheck %s >> + >> +define i32 @t1(i8 zeroext %x) nounwind readnone ssp { >> +entry: >> +; CHECK: t1: >> +; CHECK: shll >> +; CHECK-NOT: movzwl >> +; CHECK: ret >> + %0 = zext i8 %x to i16 >> + %1 = shl i16 %0, 5 >> + %2 = zext i16 %1 to i32 >> + ret i32 %2 >> +} >> + >> +define i32 @t2(i8 zeroext %x) nounwind readnone ssp { >> +entry: >> +; CHECK: t2: >> +; CHECK: shrl >> +; CHECK-NOT: movzwl >> +; CHECK: ret >> + %0 = zext i8 %x to i16 >> + %1 = lshr i16 %0, 3 >> + %2 = zext i16 %1 to i32 >> + ret i32 %2 >> +} >> + >> +define i32 @t3(i8 zeroext %x, i8 zeroext %y) nounwind readnone ssp { >> +entry: >> +; CHECK: t3: >> +; CHECK: shll >> +; CHECK-NOT: movzwl >> +; CHECK: ret >> + %0 = zext i8 %x to i16 >> + %1 = zext i8 %y to i16 >> + %2 = shl i16 %0, %1 >> + %3 = zext i16 %2 to i32 >> + ret i32 %3 >> +} >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> > From evan.cheng at apple.com Tue Dec 15 00:58:30 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 14 Dec 2009 22:58:30 -0800 Subject: [llvm-commits] [llvm] r91380 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/CellSPU/and_ops.ll In-Reply-To: <4B2727D9.5090203@mxc.ca> References: <200912150052.nBF0qBhN025917@zion.cs.uiuc.edu> <4B2727D9.5090203@mxc.ca> Message-ID: <26DE8EB3-26F1-44B2-B019-B43B1C0BAE30@apple.com> On Dec 14, 2009, at 10:08 PM, Nick Lewycky wrote: > Evan Cheng wrote: >> Author: evancheng >> Date: Mon Dec 14 18:52:11 2009 >> New Revision: 91380 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=91380&view=rev >> Log: >> Fold (zext (and x, cst)) -> (and (zext x), cst). > > Again, this looks like something instcombine ought to be doing instead? Why? See my patch that use sbb to put carry bit into GPR. Target lowering can create opportunities for this transformation. Evan > > Nick > >> >> Modified: >> llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >> llvm/trunk/test/CodeGen/CellSPU/and_ops.ll >> >> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91380&r1=91379&r2=91380&view=diff >> >> ============================================================================== >> --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) >> +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:52:11 2009 >> @@ -3202,6 +3202,19 @@ >> X, DAG.getConstant(Mask, VT)); >> } >> >> + // Fold (zext (and x, cst)) -> (and (zext x), cst) >> + if (N0.getOpcode() == ISD::AND&& >> + N0.getOperand(1).getOpcode() == ISD::Constant&& >> + N0.getOperand(0).getOpcode() != ISD::TRUNCATE&& >> + N0.getOperand(0).hasOneUse()) { >> + APInt Mask = cast(N0.getOperand(1))->getAPIntValue(); >> + Mask.zext(VT.getSizeInBits()); >> + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, >> + DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, >> + N0.getOperand(0)), >> + DAG.getConstant(Mask, VT)); >> + } >> + >> // fold (zext (load x)) -> (zext (truncate (zextload x))) >> if (ISD::isNON_EXTLoad(N0.getNode())&& >> ((!LegalOperations&& !cast(N0)->isVolatile()) || >> >> Modified: llvm/trunk/test/CodeGen/CellSPU/and_ops.ll >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CellSPU/and_ops.ll?rev=91380&r1=91379&r2=91380&view=diff >> >> ============================================================================== >> --- llvm/trunk/test/CodeGen/CellSPU/and_ops.ll (original) >> +++ llvm/trunk/test/CodeGen/CellSPU/and_ops.ll Mon Dec 14 18:52:11 2009 >> @@ -1,9 +1,9 @@ >> ; RUN: llc< %s -march=cellspu> %t1.s >> -; RUN: grep and %t1.s | count 234 >> +; RUN: grep and %t1.s | count 230 >> ; RUN: grep andc %t1.s | count 85 >> -; RUN: grep andi %t1.s | count 37 >> -; RUN: grep andhi %t1.s | count 30 >> -; RUN: grep andbi %t1.s | count 4 >> +; RUN: grep andi %t1.s | count 39 >> +; RUN: grep andhi %t1.s | count 28 >> +; RUN: grep andbi %t1.s | count 2 >> >> target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128" >> target triple = "spu" >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> > From nicholas at mxc.ca Tue Dec 15 01:11:11 2009 From: nicholas at mxc.ca (Nick Lewycky) Date: Mon, 14 Dec 2009 23:11:11 -0800 Subject: [llvm-commits] [llvm] r91378 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/X86/setcc.ll test/CodeGen/X86/zext-shl.ll In-Reply-To: <0C6C95C0-C677-4131-9485-8FA8D5C10C33@apple.com> References: <200912150041.nBF0faC8025493@zion.cs.uiuc.edu> <4B27271A.7040105@mxc.ca> <0C6C95C0-C677-4131-9485-8FA8D5C10C33@apple.com> Message-ID: <4B27368F.1010504@mxc.ca> Evan Cheng wrote: > > On Dec 14, 2009, at 10:05 PM, Nick Lewycky wrote: > >> Evan Cheng wrote: >>> Author: evancheng >>> Date: Mon Dec 14 18:41:36 2009 >>> New Revision: 91378 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=91378&view=rev >>> Log: >>> Propagate zest through logical shift. >> >> Evan, should instcombine be doing this? > > I am not sure. This is one of those transforms that can go into either pass. Now that dag combine does it, I am not sure if there is benefit to adding it to instcombine. Something like this which can lead to further optz'ns probably belongs in instcombine. It might make the difference between being too large for inlining and not, for example. It would need to be in the DAG combiner if the backend internally produces this sort of code. It could be that it belongs in both places, which is why I'm asking. > Evan > >> >>> >>> Added: >>> llvm/trunk/test/CodeGen/X86/setcc.ll >>> llvm/trunk/test/CodeGen/X86/zext-shl.ll >>> Modified: >>> llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >>> >>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91378&r1=91377&r2=91378&view=diff >>> >>> ============================================================================== >>> --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) >>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:41:36 2009 >>> @@ -3278,6 +3278,16 @@ >>> if (SCC.getNode()) return SCC; >>> } >>> >>> + // (zext (shl (zext x), y)) -> (shl (zext x), (zext y)) >>> + if ((N0.getOpcode() == ISD::SHL || N0.getOpcode() == ISD::SRL)&& >>> + N0.getOperand(0).getOpcode() == ISD::ZERO_EXTEND&& >>> + N0.hasOneUse()) { >>> + DebugLoc dl = N->getDebugLoc(); >>> + return DAG.getNode(N0.getOpcode(), dl, VT, >>> + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(0)), >>> + DAG.getNode(ISD::ZERO_EXTEND, dl, VT, N0.getOperand(1))); >>> + } >>> + >>> return SDValue(); >>> } >>> >>> >>> Added: llvm/trunk/test/CodeGen/X86/setcc.ll >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=91378&view=auto >>> >>> ============================================================================== >>> --- llvm/trunk/test/CodeGen/X86/setcc.ll (added) >>> +++ llvm/trunk/test/CodeGen/X86/setcc.ll Mon Dec 14 18:41:36 2009 >>> @@ -0,0 +1,13 @@ >>> +; RUN: llc< %s -mtriple=x86_64-apple-darwin | FileCheck %s >>> + >>> +define zeroext i16 @t1(i16 zeroext %x) nounwind readnone ssp { >>> +entry: >>> +; CHECK: t1: >>> +; CHECK: seta %al >>> +; CHECK: movzbl %al, %eax >>> +; CHECK: shll $5, %eax >>> + %0 = icmp ugt i16 %x, 26 ; [#uses=1] >>> + %iftmp.1.0 = select i1 %0, i16 32, i16 0 ; [#uses=1] >>> + ret i16 %iftmp.1.0 >>> +} >>> + >>> >>> Added: llvm/trunk/test/CodeGen/X86/zext-shl.ll >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/zext-shl.ll?rev=91378&view=auto >>> >>> ============================================================================== >>> --- llvm/trunk/test/CodeGen/X86/zext-shl.ll (added) >>> +++ llvm/trunk/test/CodeGen/X86/zext-shl.ll Mon Dec 14 18:41:36 2009 >>> @@ -0,0 +1,38 @@ >>> +; RUN: llc< %s -march=x86 | FileCheck %s >>> + >>> +define i32 @t1(i8 zeroext %x) nounwind readnone ssp { >>> +entry: >>> +; CHECK: t1: >>> +; CHECK: shll >>> +; CHECK-NOT: movzwl >>> +; CHECK: ret >>> + %0 = zext i8 %x to i16 >>> + %1 = shl i16 %0, 5 >>> + %2 = zext i16 %1 to i32 >>> + ret i32 %2 >>> +} >>> + >>> +define i32 @t2(i8 zeroext %x) nounwind readnone ssp { >>> +entry: >>> +; CHECK: t2: >>> +; CHECK: shrl >>> +; CHECK-NOT: movzwl >>> +; CHECK: ret >>> + %0 = zext i8 %x to i16 >>> + %1 = lshr i16 %0, 3 >>> + %2 = zext i16 %1 to i32 >>> + ret i32 %2 >>> +} >>> + >>> +define i32 @t3(i8 zeroext %x, i8 zeroext %y) nounwind readnone ssp { >>> +entry: >>> +; CHECK: t3: >>> +; CHECK: shll >>> +; CHECK-NOT: movzwl >>> +; CHECK: ret >>> + %0 = zext i8 %x to i16 >>> + %1 = zext i8 %y to i16 >>> + %2 = shl i16 %0, %1 >>> + %3 = zext i16 %2 to i32 >>> + ret i32 %3 >>> +} >>> >>> >>> _______________________________________________ >>> llvm-commits mailing list >>> llvm-commits at cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >>> >> > > From nicholas at mxc.ca Tue Dec 15 01:15:20 2009 From: nicholas at mxc.ca (Nick Lewycky) Date: Mon, 14 Dec 2009 23:15:20 -0800 Subject: [llvm-commits] [llvm] r91380 - in /llvm/trunk: lib/CodeGen/SelectionDAG/DAGCombiner.cpp test/CodeGen/CellSPU/and_ops.ll In-Reply-To: <26DE8EB3-26F1-44B2-B019-B43B1C0BAE30@apple.com> References: <200912150052.nBF0qBhN025917@zion.cs.uiuc.edu> <4B2727D9.5090203@mxc.ca> <26DE8EB3-26F1-44B2-B019-B43B1C0BAE30@apple.com> Message-ID: <4B273788.7070609@mxc.ca> Evan Cheng wrote: > > On Dec 14, 2009, at 10:08 PM, Nick Lewycky wrote: > >> Evan Cheng wrote: >>> Author: evancheng >>> Date: Mon Dec 14 18:52:11 2009 >>> New Revision: 91380 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=91380&view=rev >>> Log: >>> Fold (zext (and x, cst)) -> (and (zext x), cst). >> >> Again, this looks like something instcombine ought to be doing instead? > > Why? See my patch that use sbb to put carry bit into GPR. Target lowering can create opportunities for this transformation. I was asking because instcombine doesn't pick one. That means that anyone who wants to optimize it further down the line has to check for both of these patterns. Instcombine should just canonicalize it down to one -- but it doesn't seem like either one is particularly better in this case, so I thought I'd see if you had an opinion from the backend point of view. No biggie. This doesn't strike me as a very important transformation to do in the middle-end. Nick > Evan > >> >> Nick >> >>> >>> Modified: >>> llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >>> llvm/trunk/test/CodeGen/CellSPU/and_ops.ll >>> >>> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=91380&r1=91379&r2=91380&view=diff >>> >>> ============================================================================== >>> --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) >>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Mon Dec 14 18:52:11 2009 >>> @@ -3202,6 +3202,19 @@ >>> X, DAG.getConstant(Mask, VT)); >>> } >>> >>> + // Fold (zext (and x, cst)) -> (and (zext x), cst) >>> + if (N0.getOpcode() == ISD::AND&& >>> + N0.getOperand(1).getOpcode() == ISD::Constant&& >>> + N0.getOperand(0).getOpcode() != ISD::TRUNCATE&& >>> + N0.getOperand(0).hasOneUse()) { >>> + APInt Mask = cast(N0.getOperand(1))->getAPIntValue(); >>> + Mask.zext(VT.getSizeInBits()); >>> + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, >>> + DAG.getNode(ISD::ZERO_EXTEND, N->getDebugLoc(), VT, >>> + N0.getOperand(0)), >>> + DAG.getConstant(Mask, VT)); >>> + } >>> + >>> // fold (zext (load x)) -> (zext (truncate (zextload x))) >>> if (ISD::isNON_EXTLoad(N0.getNode())&& >>> ((!LegalOperations&& !cast(N0)->isVolatile()) || >>> >>> Modified: llvm/trunk/test/CodeGen/CellSPU/and_ops.ll >>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CellSPU/and_ops.ll?rev=91380&r1=91379&r2=91380&view=diff >>> >>> ============================================================================== >>> --- llvm/trunk/test/CodeGen/CellSPU/and_ops.ll (original) >>> +++ llvm/trunk/test/CodeGen/CellSPU/and_ops.ll Mon Dec 14 18:52:11 2009 >>> @@ -1,9 +1,9 @@ >>> ; RUN: llc< %s -march=cellspu> %t1.s >>> -; RUN: grep and %t1.s | count 234 >>> +; RUN: grep and %t1.s | count 230 >>> ; RUN: grep andc %t1.s | count 85 >>> -; RUN: grep andi %t1.s | count 37 >>> -; RUN: grep andhi %t1.s | count 30 >>> -; RUN: grep andbi %t1.s | count 4 >>> +; RUN: grep andi %t1.s | count 39 >>> +; RUN: grep andhi %t1.s | count 28 >>> +; RUN: grep andbi %t1.s | count 2 >>> >>> target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128" >>> target triple = "spu" >>> >>> >>> _______________________________________________ >>> llvm-commits mailing list >>> llvm-commits at cs.uiuc.edu >>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >>> >> > > From foldr at codedgers.com Tue Dec 15 01:20:50 2009 From: foldr at codedgers.com (Mikhail Glushenkov) Date: Tue, 15 Dec 2009 07:20:50 -0000 Subject: [llvm-commits] [llvm] r91419 - in /llvm/trunk: test/LLVMC/AppendCmdHook.td test/LLVMC/OutputSuffixHook.td utils/TableGen/LLVMCConfigurationEmitter.cpp Message-ID: <200912150720.nBF7KoB8007577@zion.cs.uiuc.edu> Author: foldr Date: Tue Dec 15 01:20:50 2009 New Revision: 91419 URL: http://llvm.org/viewvc/llvm-project?rev=91419&view=rev Log: Support hook invocation from 'append_cmd'. Added: llvm/trunk/test/LLVMC/AppendCmdHook.td llvm/trunk/test/LLVMC/OutputSuffixHook.td Modified: llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp Added: llvm/trunk/test/LLVMC/AppendCmdHook.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/AppendCmdHook.td?rev=91419&view=auto ============================================================================== --- llvm/trunk/test/LLVMC/AppendCmdHook.td (added) +++ llvm/trunk/test/LLVMC/AppendCmdHook.td Tue Dec 15 01:20:50 2009 @@ -0,0 +1,28 @@ +// Check that hooks can be invoked from 'append_cmd'. +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: FileCheck -input-file=%t %s +// RUN: %compile_cxx -fexceptions -x c++ %t + +include "llvm/CompilerDriver/Common.td" + +// CHECK: std::string MyHook() + +def OptList : OptionList<[ +(switch_option "dummy1", (help "none")), +(switch_option "dummy2", (help "none")) +]>; + +def dummy_tool : Tool<[ +(cmd_line "dummy_cmd $INFILE"), +(in_language "dummy_lang"), +(out_language "dummy_lang"), +(actions (case + // CHECK: push_back("-arg1") + // CHECK: push_back("-arg2") + (switch_on "dummy1"), (append_cmd "-arg1 -arg2"), + // CHECK: push_back("-arg3") + // CHECK: hooks::MyHook() + (switch_on "dummy2"), (append_cmd "-arg3 $CALL(MyHook)"))) +]>; + +def DummyGraph : CompilationGraph<[SimpleEdge<"root", "dummy_tool">]>; Added: llvm/trunk/test/LLVMC/OutputSuffixHook.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/OutputSuffixHook.td?rev=91419&view=auto ============================================================================== --- llvm/trunk/test/LLVMC/OutputSuffixHook.td (added) +++ llvm/trunk/test/LLVMC/OutputSuffixHook.td Tue Dec 15 01:20:50 2009 @@ -0,0 +1,24 @@ +// Check that hooks can be invoked from 'output_suffix'. +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: FileCheck -input-file=%t %s +// RUN: %compile_cxx -fexceptions -x c++ %t +// XFAIL: * + +include "llvm/CompilerDriver/Common.td" + +// CHECK: std::string MyHook() + +def OptList : OptionList<[ +(switch_option "dummy1", (help "none")) +]>; + +def dummy_tool : Tool<[ +(cmd_line "dummy_cmd $INFILE"), +(in_language "dummy_lang"), +(out_language "dummy_lang"), +(actions (case + // CHECK: hooks::MyHook() + (switch_on "dummy1"), (output_suffix "$CALL(MyHook)"))) +]>; + +def DummyGraph : CompilationGraph<[SimpleEdge<"root", "dummy_tool">]>; Modified: llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp?rev=91419&r1=91418&r2=91419&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp (original) +++ llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp Tue Dec 15 01:20:50 2009 @@ -15,8 +15,6 @@ #include "Record.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include @@ -1454,9 +1452,9 @@ EmitCaseStatementCallback(Callback, O), IndentLevel); } -/// TokenizeCmdline - converts from "$CALL(HookName, 'Arg1', 'Arg2')/path" to -/// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path"] . -/// Helper function used by EmitCmdLineVecFill and. +/// TokenizeCmdline - converts from +/// "$CALL(HookName, 'Arg1', 'Arg2')/path -arg1 -arg2" to +/// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path", "-arg1", "-arg2"]. void TokenizeCmdline(const std::string& CmdLine, StrVector& Out) { const char* Delimiters = " \t\n\v\f\r"; enum TokenizerState @@ -1823,17 +1821,36 @@ const OptionDescriptions& OptDescs; typedef EmitActionHandlersCallbackHandler Handler; - void onAppendCmd (const DagInit& Dag, - unsigned IndentLevel, raw_ostream& O) const + /// EmitHookInvocation - Common code for hook invocation from actions. Used by + /// onAppendCmd and onOutputSuffix. + void EmitHookInvocation(const std::string& Str, + const char* BlockOpen, const char* BlockClose, + unsigned IndentLevel, raw_ostream& O) const { - checkNumberOfArguments(&Dag, 1); - const std::string& Cmd = InitPtrToString(Dag.getArg(0)); StrVector Out; - llvm::SplitString(Cmd, Out); + TokenizeCmdline(Str, Out); for (StrVector::const_iterator B = Out.begin(), E = Out.end(); - B != E; ++B) - O.indent(IndentLevel) << "vec.push_back(\"" << *B << "\");\n"; + B != E; ++B) { + const std::string& cmd = *B; + + O.indent(IndentLevel) << BlockOpen; + + if (cmd.at(0) == '$') + B = SubstituteSpecialCommands(B, E, /* IsJoin = */ true, O); + else + O << '"' << cmd << '"'; + + O << BlockClose; + } + } + + void onAppendCmd (const DagInit& Dag, + unsigned IndentLevel, raw_ostream& O) const + { + checkNumberOfArguments(&Dag, 1); + this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)), + "vec.push_back(", ");\n", IndentLevel, O); } void onForward (const DagInit& Dag, @@ -1886,13 +1903,12 @@ << (D.isParameter() ? ".c_str()" : "") << "));\n"; } - void onOutputSuffix (const DagInit& Dag, unsigned IndentLevel, raw_ostream& O) const { checkNumberOfArguments(&Dag, 1); - const std::string& OutSuf = InitPtrToString(Dag.getArg(0)); - O.indent(IndentLevel) << "output_suffix = \"" << OutSuf << "\";\n"; + this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)), + "output_suffix = ", ";\n", IndentLevel, O); } void onStopCompilation (const DagInit& Dag, @@ -2521,7 +2537,9 @@ {} void onAction (const DagInit& Dag) { - if (GetOperatorName(Dag) == "forward_transformed_value") { + const std::string& Name = GetOperatorName(Dag); + + if (Name == "forward_transformed_value") { checkNumberOfArguments(Dag, 2); const std::string& OptName = InitPtrToString(Dag.getArg(0)); const std::string& HookName = InitPtrToString(Dag.getArg(1)); @@ -2530,29 +2548,16 @@ HookNames_[HookName] = HookInfo(D.isList() ? HookInfo::ListHook : HookInfo::ArgHook); } - } - - void operator()(const Init* Arg) { - - // We're invoked on an action (either a dag or a dag list). - if (typeid(*Arg) == typeid(DagInit)) { - const DagInit& Dag = InitPtrToDag(Arg); - this->onAction(Dag); - return; - } - else if (typeid(*Arg) == typeid(ListInit)) { - const ListInit& List = InitPtrToList(Arg); - for (ListInit::const_iterator B = List.begin(), E = List.end(); B != E; - ++B) { - const DagInit& Dag = InitPtrToDag(*B); - this->onAction(Dag); - } - return; + else if (Name == "append_cmd" || Name == "output_suffix") { + checkNumberOfArguments(Dag, 1); + this->onCmdLine(InitPtrToString(Dag.getArg(0))); } + } - // We're invoked on a command line. + void onCmdLine(const std::string& Cmd) { StrVector cmds; - TokenizeCmdline(InitPtrToString(Arg), cmds); + TokenizeCmdline(Cmd, cmds); + for (StrVector::const_iterator B = cmds.begin(), E = cmds.end(); B != E; ++B) { const std::string& cmd = *B; @@ -2562,7 +2567,6 @@ checkedIncrement(B, E, "Syntax error in $CALL invocation!"); const std::string& HookName = *B; - if (HookName.at(0) == ')') throw "$CALL invoked with no arguments!"; @@ -2578,9 +2582,30 @@ + HookName; else HookNames_[HookName] = HookInfo(NumArgs); + } + } + } + + void operator()(const Init* Arg) { + // We're invoked on an action (either a dag or a dag list). + if (typeid(*Arg) == typeid(DagInit)) { + const DagInit& Dag = InitPtrToDag(Arg); + this->onAction(Dag); + return; + } + else if (typeid(*Arg) == typeid(ListInit)) { + const ListInit& List = InitPtrToList(Arg); + for (ListInit::const_iterator B = List.begin(), E = List.end(); B != E; + ++B) { + const DagInit& Dag = InitPtrToDag(*B); + this->onAction(Dag); } + return; } + + // We're invoked on a command line. + this->onCmdLine(InitPtrToString(Arg)); } void operator()(const DagInit* Test, unsigned, bool) { From foldr at codedgers.com Tue Dec 15 01:21:14 2009 From: foldr at codedgers.com (Mikhail Glushenkov) Date: Tue, 15 Dec 2009 07:21:14 -0000 Subject: [llvm-commits] [llvm] r91420 - in /llvm/trunk: test/LLVMC/AppendCmdHook.td test/LLVMC/ExternOptions.td test/LLVMC/ForwardAs.td test/LLVMC/ForwardTransformedValue.td test/LLVMC/ForwardValue.td test/LLVMC/HookWithArguments.td test/LLVMC/HookWithInFile.td test/LLVMC/Init.td test/LLVMC/MultiValuedOption.td test/LLVMC/NoActions.td test/LLVMC/OneOrMore.td test/LLVMC/OptionPreprocessor.td test/LLVMC/OutputSuffixHook.td utils/TableGen/LLVMCConfigurationEmitter.cpp Message-ID: <200912150721.nBF7LFsl007611@zion.cs.uiuc.edu> Author: foldr Date: Tue Dec 15 01:21:14 2009 New Revision: 91420 URL: http://llvm.org/viewvc/llvm-project?rev=91420&view=rev Log: Convert llvmc tests to FileCheck. Modified: llvm/trunk/test/LLVMC/AppendCmdHook.td llvm/trunk/test/LLVMC/ExternOptions.td llvm/trunk/test/LLVMC/ForwardAs.td llvm/trunk/test/LLVMC/ForwardTransformedValue.td llvm/trunk/test/LLVMC/ForwardValue.td llvm/trunk/test/LLVMC/HookWithArguments.td llvm/trunk/test/LLVMC/HookWithInFile.td llvm/trunk/test/LLVMC/Init.td llvm/trunk/test/LLVMC/MultiValuedOption.td llvm/trunk/test/LLVMC/NoActions.td llvm/trunk/test/LLVMC/OneOrMore.td llvm/trunk/test/LLVMC/OptionPreprocessor.td llvm/trunk/test/LLVMC/OutputSuffixHook.td llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp Modified: llvm/trunk/test/LLVMC/AppendCmdHook.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/AppendCmdHook.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/AppendCmdHook.td (original) +++ llvm/trunk/test/LLVMC/AppendCmdHook.td Tue Dec 15 01:21:14 2009 @@ -1,6 +1,6 @@ // Check that hooks can be invoked from 'append_cmd'. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: FileCheck -input-file=%t %s +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" Modified: llvm/trunk/test/LLVMC/ExternOptions.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/ExternOptions.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/ExternOptions.td (original) +++ llvm/trunk/test/LLVMC/ExternOptions.td Tue Dec 15 01:21:14 2009 @@ -1,11 +1,13 @@ // Check that extern options work. // The dummy tool and graph are required to silence warnings. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep {extern .* AutoGeneratedSwitch_Wall} %t +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" +// CHECK: extern cl::opt AutoGeneratedSwitch_Wall + def OptList : OptionList<[(switch_option "Wall", (extern)), (parameter_option "std", (extern)), (prefix_list_option "L", (extern))]>; Modified: llvm/trunk/test/LLVMC/ForwardAs.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/ForwardAs.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/ForwardAs.td (original) +++ llvm/trunk/test/LLVMC/ForwardAs.td Tue Dec 15 01:21:14 2009 @@ -1,7 +1,7 @@ // Check the fix for PR4159. // http://llvm.org/bugs/show_bug.cgi?id=4159 // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep unique_name %t +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" @@ -13,6 +13,7 @@ (in_language "dummy"), (out_language "dummy"), (actions (case + // CHECK: vec.push_back("unique_name") (not_empty "dummy"), (forward_as "dummy", "unique_name"))) ]>; Modified: llvm/trunk/test/LLVMC/ForwardTransformedValue.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/ForwardTransformedValue.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/ForwardTransformedValue.td (original) +++ llvm/trunk/test/LLVMC/ForwardTransformedValue.td Tue Dec 15 01:21:14 2009 @@ -1,8 +1,7 @@ // Check that forward_transformed_value works. // The dummy tool and graph are required to silence warnings. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep HookA %t | count 2 -// RUN: grep HookB %t | count 2 +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" @@ -10,12 +9,17 @@ def OptList : OptionList<[(parameter_option "a", (extern)), (prefix_list_option "b", (extern))]>; +// CHECK: std::string HookA +// CHECK: std::string HookB + def dummy_tool : Tool<[ (cmd_line "dummy_cmd $INFILE"), (in_language "dummy"), (out_language "dummy"), (actions (case + // CHECK: HookA(AutoGeneratedParameter_a (not_empty "a"), (forward_transformed_value "a", "HookA"), + // CHECK: HookB(AutoGeneratedList_b (not_empty "b"), (forward_transformed_value "b", "HookB"))) ]>; Modified: llvm/trunk/test/LLVMC/ForwardValue.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/ForwardValue.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/ForwardValue.td (original) +++ llvm/trunk/test/LLVMC/ForwardValue.td Tue Dec 15 01:21:14 2009 @@ -1,8 +1,7 @@ // Check that forward_value works. // The dummy tool and graph are required to silence warnings. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep {vec.push_back\(AutoGeneratedParameter_a\)} %t -// RUN: grep {std::copy\(AutoGeneratedList_b.begin\(\)} %t +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" @@ -15,7 +14,9 @@ (in_language "dummy"), (out_language "dummy"), (actions (case + // CHECK: vec.push_back(AutoGeneratedParameter_a) (not_empty "a"), (forward_value "a"), + // CHECK: std::copy(AutoGeneratedList_b.begin() (not_empty "b"), (forward_value "b"))) ]>; Modified: llvm/trunk/test/LLVMC/HookWithArguments.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/HookWithArguments.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/HookWithArguments.td (original) +++ llvm/trunk/test/LLVMC/HookWithArguments.td Tue Dec 15 01:21:14 2009 @@ -1,13 +1,15 @@ // Check that hooks with arguments work. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep {Hook(const char\\* Arg0, const char\\* Arg1, const char\\* Arg2);} %t | count 1 -// RUN: grep "/path" %t | count 1 -// RUN: grep "VARIABLE" %t | count 1 -// RUN: grep "/2path" %t | count 1 +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" +// CHECK: Hook(const char* Arg0, const char* Arg1, const char* Arg2); +// CHECK: std::getenv("VARIABLE") +// CHECK: "/2path" +// CHECK: "/path" + def dummy_tool : Tool<[ (cmd_line "$CALL(Hook, 'Arg1', 'Arg2', 'Arg3 Arg3Cont')/path arg1 $ENV(VARIABLE)/2path arg2 $INFILE"), (in_language "dummy"), Modified: llvm/trunk/test/LLVMC/HookWithInFile.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/HookWithInFile.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/HookWithInFile.td (original) +++ llvm/trunk/test/LLVMC/HookWithInFile.td Tue Dec 15 01:21:14 2009 @@ -1,11 +1,12 @@ // Check that a hook can be given $INFILE as an argument. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep Hook\\(inFile.c_str\\(\\)\\) %t | count 1 +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" def dummy_tool : Tool<[ +// CHECK: Hook(inFile.c_str()) (cmd_line "$CALL(Hook, '$INFILE')/path $INFILE"), (in_language "dummy"), (out_language "dummy") Modified: llvm/trunk/test/LLVMC/Init.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/Init.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/Init.td (original) +++ llvm/trunk/test/LLVMC/Init.td Tue Dec 15 01:21:14 2009 @@ -1,13 +1,14 @@ // Check that (init true/false) and (init "str") work. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep cl::init(\\"some-string\\") %t | count 1 -// RUN: grep cl::init(true) %t | count 1 +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" def OptList : OptionList<[ +// CHECK: cl::init(true) (switch_option "dummy1", (help "none"), (init true)), +// CHECK: cl::init("some-string") (parameter_option "dummy2", (help "none"), (init "some-string")) ]>; Modified: llvm/trunk/test/LLVMC/MultiValuedOption.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/MultiValuedOption.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/MultiValuedOption.td (original) +++ llvm/trunk/test/LLVMC/MultiValuedOption.td Tue Dec 15 01:21:14 2009 @@ -1,12 +1,13 @@ // Check that multivalued options work. // The dummy tool and graph are required to silence warnings. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep cl::multi_val(2) %t | count 1 +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" def OptList : OptionList<[ + // CHECK: cl::multi_val(2) (prefix_list_option "foo", (multi_val 2)), (parameter_list_option "baz", (multi_val 2), (extern))]>; Modified: llvm/trunk/test/LLVMC/NoActions.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/NoActions.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/NoActions.td (original) +++ llvm/trunk/test/LLVMC/NoActions.td Tue Dec 15 01:21:14 2009 @@ -1,10 +1,11 @@ // Check that tools without associated actions are accepted. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep dummy_tool %t +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" +// CHECK: class dummy_tool : public Tool { def dummy_tool : Tool<[ (cmd_line "dummy_cmd $INFILE"), (in_language "dummy"), Modified: llvm/trunk/test/LLVMC/OneOrMore.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/OneOrMore.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/OneOrMore.td (original) +++ llvm/trunk/test/LLVMC/OneOrMore.td Tue Dec 15 01:21:14 2009 @@ -1,14 +1,15 @@ // Check that (one_or_more) and (zero_or_one) properties work. // The dummy tool and graph are required to silence warnings. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep cl::Optional %t | count 1 -// RUN: grep cl::OneOrMore %t | count 1 +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" def OptList : OptionList<[ + // CHECK: cl::OneOrMore (prefix_list_option "foo", (one_or_more)), + // CHECK: cl::Optional (parameter_list_option "baz", (optional))]>; def dummy_tool : Tool<[ Modified: llvm/trunk/test/LLVMC/OptionPreprocessor.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/OptionPreprocessor.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/OptionPreprocessor.td (original) +++ llvm/trunk/test/LLVMC/OptionPreprocessor.td Tue Dec 15 01:21:14 2009 @@ -1,8 +1,6 @@ // Test for the OptionPreprocessor and any*. -// RUN: ignore tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: grep W1 %t -// RUN: grep W2 %t -// RUN: grep W3 %t +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" @@ -17,10 +15,14 @@ ]>; def Preprocess : OptionPreprocessor< -(case (and (switch_on "foo"), (any_switch_on ["bar", "baz"])), +(case + // CHECK: W1 + (and (switch_on "foo"), (any_switch_on ["bar", "baz"])), (warning "W1"), + // CHECK: W2 (and (switch_on ["foo", "bar"]), (any_empty ["foo_p", "bar_p"])), (warning "W2"), + // CHECK: W3 (and (empty ["foo_p", "bar_p"]), (any_not_empty ["baz_p"])), (warning "W3")) >; Modified: llvm/trunk/test/LLVMC/OutputSuffixHook.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LLVMC/OutputSuffixHook.td?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/test/LLVMC/OutputSuffixHook.td (original) +++ llvm/trunk/test/LLVMC/OutputSuffixHook.td Tue Dec 15 01:21:14 2009 @@ -1,6 +1,6 @@ // Check that hooks can be invoked from 'output_suffix'. // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: FileCheck -input-file=%t %s +// RUN: FileCheck -input-file %t %s // RUN: %compile_cxx -fexceptions -x c++ %t // XFAIL: * Modified: llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp?rev=91420&r1=91419&r2=91420&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp (original) +++ llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp Tue Dec 15 01:21:14 2009 @@ -2169,7 +2169,7 @@ else O << "Tool"; - O << "{\nprivate:\n"; + O << " {\nprivate:\n"; O.indent(Indent1) << "static const char* InputLanguages_[];\n\n"; O << "public:\n"; From sabre at nondot.org Tue Dec 15 01:26:43 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 15 Dec 2009 07:26:43 -0000 Subject: [llvm-commits] [llvm] r91421 - in /llvm/trunk: include/llvm/ADT/ include/llvm/Analysis/ include/llvm/Bitcode/ include/llvm/CodeGen/ include/llvm/Support/ lib/Analysis/IPA/ lib/Bitcode/Reader/ lib/CodeGen/AsmPrinter/ lib/ExecutionEngine/JIT/ lib/Transforms/Scalar/ lib/Transforms/Utils/ lib/VMCore/ Message-ID: <200912150726.nBF7Qipr007844@zion.cs.uiuc.edu> Author: lattner Date: Tue Dec 15 01:26:43 2009 New Revision: 91421 URL: http://llvm.org/viewvc/llvm-project?rev=91421&view=rev Log: Remove isPod() from DenseMapInfo, splitting it out to its own isPodLike type trait. This is a generally useful type trait for more than just DenseMap, and we really care about whether something acts like a pod, not whether it really is a pod. Modified: llvm/trunk/include/llvm/ADT/DenseMap.h llvm/trunk/include/llvm/ADT/DenseMapInfo.h llvm/trunk/include/llvm/ADT/ImmutableList.h llvm/trunk/include/llvm/ADT/PointerIntPair.h llvm/trunk/include/llvm/ADT/ValueMap.h llvm/trunk/include/llvm/Analysis/AliasSetTracker.h llvm/trunk/include/llvm/Bitcode/Deserialize.h llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h llvm/trunk/include/llvm/CodeGen/SlotIndexes.h llvm/trunk/include/llvm/Support/DebugLoc.h llvm/trunk/include/llvm/Support/ValueHandle.h llvm/trunk/include/llvm/Support/type_traits.h llvm/trunk/lib/Analysis/IPA/Andersens.cpp llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp llvm/trunk/lib/CodeGen/AsmPrinter/DwarfException.h llvm/trunk/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp llvm/trunk/lib/Transforms/Scalar/GVN.cpp llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp llvm/trunk/lib/Transforms/Scalar/SCCVN.cpp llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp llvm/trunk/lib/VMCore/LLVMContextImpl.h Modified: llvm/trunk/include/llvm/ADT/DenseMap.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/DenseMap.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/DenseMap.h (original) +++ llvm/trunk/include/llvm/ADT/DenseMap.h Tue Dec 15 01:26:43 2009 @@ -217,7 +217,8 @@ private: void CopyFrom(const DenseMap& other) { - if (NumBuckets != 0 && (!KeyInfoT::isPod() || !ValueInfoT::isPod())) { + if (NumBuckets != 0 && + (!isPodLike::value || !isPodLike::value)) { const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { if (!KeyInfoT::isEqual(P->first, EmptyKey) && @@ -239,7 +240,7 @@ Buckets = static_cast(operator new(sizeof(BucketT) * other.NumBuckets)); - if (KeyInfoT::isPod() && ValueInfoT::isPod()) + if (isPodLike::value && isPodLike::value) memcpy(Buckets, other.Buckets, other.NumBuckets * sizeof(BucketT)); else for (size_t i = 0; i < other.NumBuckets; ++i) { Modified: llvm/trunk/include/llvm/ADT/DenseMapInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/DenseMapInfo.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/DenseMapInfo.h (original) +++ llvm/trunk/include/llvm/ADT/DenseMapInfo.h Tue Dec 15 01:26:43 2009 @@ -15,7 +15,7 @@ #define LLVM_ADT_DENSEMAPINFO_H #include "llvm/Support/PointerLikeTypeTraits.h" -#include +#include "llvm/Support/type_traits.h" namespace llvm { @@ -25,7 +25,6 @@ //static inline T getTombstoneKey(); //static unsigned getHashValue(const T &Val); //static bool isEqual(const T &LHS, const T &RHS); - //static bool isPod() }; // Provide DenseMapInfo for all pointers. @@ -46,7 +45,6 @@ (unsigned((uintptr_t)PtrVal) >> 9); } static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; } - static bool isPod() { return true; } }; // Provide DenseMapInfo for chars. @@ -54,7 +52,6 @@ static inline char getEmptyKey() { return ~0; } static inline char getTombstoneKey() { return ~0 - 1; } static unsigned getHashValue(const char& Val) { return Val * 37; } - static bool isPod() { return true; } static bool isEqual(const char &LHS, const char &RHS) { return LHS == RHS; } @@ -65,7 +62,6 @@ static inline unsigned getEmptyKey() { return ~0; } static inline unsigned getTombstoneKey() { return ~0U - 1; } static unsigned getHashValue(const unsigned& Val) { return Val * 37; } - static bool isPod() { return true; } static bool isEqual(const unsigned& LHS, const unsigned& RHS) { return LHS == RHS; } @@ -78,7 +74,6 @@ static unsigned getHashValue(const unsigned long& Val) { return (unsigned)(Val * 37UL); } - static bool isPod() { return true; } static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) { return LHS == RHS; } @@ -91,7 +86,6 @@ static unsigned getHashValue(const unsigned long long& Val) { return (unsigned)(Val * 37ULL); } - static bool isPod() { return true; } static bool isEqual(const unsigned long long& LHS, const unsigned long long& RHS) { return LHS == RHS; @@ -127,7 +121,6 @@ return (unsigned)key; } static bool isEqual(const Pair& LHS, const Pair& RHS) { return LHS == RHS; } - static bool isPod() { return FirstInfo::isPod() && SecondInfo::isPod(); } }; } // end namespace llvm Modified: llvm/trunk/include/llvm/ADT/ImmutableList.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ImmutableList.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/ImmutableList.h (original) +++ llvm/trunk/include/llvm/ADT/ImmutableList.h Tue Dec 15 01:26:43 2009 @@ -211,9 +211,12 @@ static bool isEqual(ImmutableList X1, ImmutableList X2) { return X1 == X2; } - static bool isPod() { return true; } }; +template struct isPodLike; +template +struct isPodLike > { static const bool value = true; }; + } // end llvm namespace #endif Modified: llvm/trunk/include/llvm/ADT/PointerIntPair.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/PointerIntPair.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/PointerIntPair.h (original) +++ llvm/trunk/include/llvm/ADT/PointerIntPair.h Tue Dec 15 01:26:43 2009 @@ -106,6 +106,12 @@ bool operator>=(const PointerIntPair &RHS) const {return Value >= RHS.Value;} }; +template struct isPodLike; +template +struct isPodLike > { + static const bool value = true; +}; + // Provide specialization of DenseMapInfo for PointerIntPair. template struct DenseMapInfo > { @@ -125,7 +131,6 @@ return unsigned(IV) ^ unsigned(IV >> 9); } static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; } - static bool isPod() { return true; } }; // Teach SmallPtrSet that PointerIntPair is "basically a pointer". Modified: llvm/trunk/include/llvm/ADT/ValueMap.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ValueMap.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/ValueMap.h (original) +++ llvm/trunk/include/llvm/ADT/ValueMap.h Tue Dec 15 01:26:43 2009 @@ -250,6 +250,12 @@ } }; + +template +struct isPodLike > { + static const bool value = true; +}; + template struct DenseMapInfo > { typedef ValueMapCallbackVH VH; @@ -267,7 +273,6 @@ static bool isEqual(const VH &LHS, const VH &RHS) { return LHS == RHS; } - static bool isPod() { return false; } }; Modified: llvm/trunk/include/llvm/Analysis/AliasSetTracker.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AliasSetTracker.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/AliasSetTracker.h (original) +++ llvm/trunk/include/llvm/Analysis/AliasSetTracker.h Tue Dec 15 01:26:43 2009 @@ -259,11 +259,9 @@ ASTCallbackVH(Value *V, AliasSetTracker *AST = 0); ASTCallbackVH &operator=(Value *V); }; - /// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that ASTCallbackVH - /// is not a POD (it needs its destructor called). - struct ASTCallbackVHDenseMapInfo : public DenseMapInfo { - static bool isPod() { return false; } - }; + /// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that tell us how to + /// compare and hash the value handle. + struct ASTCallbackVHDenseMapInfo : public DenseMapInfo {}; AliasAnalysis &AA; ilist AliasSets; Modified: llvm/trunk/include/llvm/Bitcode/Deserialize.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/Deserialize.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/Bitcode/Deserialize.h (original) +++ llvm/trunk/include/llvm/Bitcode/Deserialize.h Tue Dec 15 01:26:43 2009 @@ -25,53 +25,52 @@ namespace llvm { +struct BPNode { + BPNode* Next; + uintptr_t& PtrRef; + + BPNode(BPNode* n, uintptr_t& pref) + : Next(n), PtrRef(pref) { + PtrRef = 0; + } +}; + +struct BPEntry { + union { BPNode* Head; void* Ptr; }; + BPEntry() : Head(NULL) {} + void SetPtr(BPNode*& FreeList, void* P); +}; + +class BPKey { + unsigned Raw; +public: + BPKey(SerializedPtrID PtrId) : Raw(PtrId << 1) { assert (PtrId > 0); } + BPKey(unsigned code, unsigned) : Raw(code) {} + + void MarkFinal() { Raw |= 0x1; } + bool hasFinalPtr() const { return Raw & 0x1 ? true : false; } + SerializedPtrID getID() const { return Raw >> 1; } + + static inline BPKey getEmptyKey() { return BPKey(0,0); } + static inline BPKey getTombstoneKey() { return BPKey(1,0); } + static inline unsigned getHashValue(const BPKey& K) { return K.Raw & ~0x1; } + + static bool isEqual(const BPKey& K1, const BPKey& K2) { + return (K1.Raw ^ K2.Raw) & ~0x1 ? false : true; + } +}; + +template <> +struct isPodLike { static const bool value = true; }; +template <> +struct isPodLike { static const bool value = true; }; + class Deserializer { //===----------------------------------------------------------===// // Internal type definitions. //===----------------------------------------------------------===// - struct BPNode { - BPNode* Next; - uintptr_t& PtrRef; - - BPNode(BPNode* n, uintptr_t& pref) - : Next(n), PtrRef(pref) { - PtrRef = 0; - } - }; - - struct BPEntry { - union { BPNode* Head; void* Ptr; }; - - BPEntry() : Head(NULL) {} - - static inline bool isPod() { return true; } - - void SetPtr(BPNode*& FreeList, void* P); - }; - - class BPKey { - unsigned Raw; - - public: - BPKey(SerializedPtrID PtrId) : Raw(PtrId << 1) { assert (PtrId > 0); } - BPKey(unsigned code, unsigned) : Raw(code) {} - - void MarkFinal() { Raw |= 0x1; } - bool hasFinalPtr() const { return Raw & 0x1 ? true : false; } - SerializedPtrID getID() const { return Raw >> 1; } - - static inline BPKey getEmptyKey() { return BPKey(0,0); } - static inline BPKey getTombstoneKey() { return BPKey(1,0); } - static inline unsigned getHashValue(const BPKey& K) { return K.Raw & ~0x1; } - - static bool isEqual(const BPKey& K1, const BPKey& K2) { - return (K1.Raw ^ K2.Raw) & ~0x1 ? false : true; - } - - static bool isPod() { return true; } - }; typedef llvm::DenseMap MapTy; Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Tue Dec 15 01:26:43 2009 @@ -891,8 +891,9 @@ static bool isEqual(const SDValue &LHS, const SDValue &RHS) { return LHS == RHS; } - static bool isPod() { return true; } }; +template <> struct isPodLike { static const bool value = true; }; + /// simplify_type specializations - Allow casting operators to work directly on /// SDValues as if they were SDNode*'s. Modified: llvm/trunk/include/llvm/CodeGen/SlotIndexes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SlotIndexes.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SlotIndexes.h (original) +++ llvm/trunk/include/llvm/CodeGen/SlotIndexes.h Tue Dec 15 01:26:43 2009 @@ -329,6 +329,7 @@ }; /// DenseMapInfo specialization for SlotIndex. + /// TODO: Not a POD? template <> struct DenseMapInfo { static inline SlotIndex getEmptyKey() { @@ -343,7 +344,6 @@ static inline bool isEqual(const SlotIndex &LHS, const SlotIndex &RHS) { return (LHS == RHS); } - static inline bool isPod() { return false; } }; inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) { Modified: llvm/trunk/include/llvm/Support/DebugLoc.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/DebugLoc.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/Support/DebugLoc.h (original) +++ llvm/trunk/include/llvm/Support/DebugLoc.h Tue Dec 15 01:26:43 2009 @@ -66,7 +66,7 @@ }; // Specialize DenseMapInfo for DebugLocTuple. - template<> struct DenseMapInfo { + template<> struct DenseMapInfo { static inline DebugLocTuple getEmptyKey() { return DebugLocTuple(0, 0, ~0U, ~0U); } @@ -85,9 +85,9 @@ LHS.Line == RHS.Line && LHS.Col == RHS.Col; } - - static bool isPod() { return true; } }; + template <> struct isPodLike {static const bool value = true;}; + /// DebugLocTracker - This class tracks debug location information. /// Modified: llvm/trunk/include/llvm/Support/ValueHandle.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ValueHandle.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/Support/ValueHandle.h (original) +++ llvm/trunk/include/llvm/Support/ValueHandle.h Tue Dec 15 01:26:43 2009 @@ -254,15 +254,18 @@ static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { return LHS == RHS; } - static bool isPod() { +}; + +template +struct isPodLike > { #ifdef NDEBUG - return true; + static const bool value = true; #else - return false; + static const bool value = false; #endif - } }; + /// TrackingVH - This is a value handle that tracks a Value (or Value subclass), /// even across RAUW operations. /// Modified: llvm/trunk/include/llvm/Support/type_traits.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/type_traits.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/include/llvm/Support/type_traits.h (original) +++ llvm/trunk/include/llvm/Support/type_traits.h Tue Dec 15 01:26:43 2009 @@ -17,6 +17,8 @@ #ifndef LLVM_SUPPORT_TYPE_TRAITS_H #define LLVM_SUPPORT_TYPE_TRAITS_H +#include + // This is actually the conforming implementation which works with abstract // classes. However, enough compilers have trouble with it that most will use // the one in boost/type_traits/object_traits.hpp. This implementation actually @@ -24,6 +26,33 @@ namespace llvm { +/// isPodLike - This is a type trait that is used to determine whether a given +/// type can be copied around with memcpy instead of running ctors etc. +template +struct isPodLike { + static const bool value = false; +}; + +// pointers are all pod-like. +template +struct isPodLike { static const bool value = true; }; + +// builtin types are pod-like as well. +// There is probably a much better way to do this. +template <> struct isPodLike { static const bool value = true; }; +template <> struct isPodLike { static const bool value = true; }; +template <> struct isPodLike { static const bool value = true; }; +template <> struct isPodLike { + static const bool value = true; +}; + + +// pairs are pod-like if their elements are. +template +struct isPodLike > { + static const bool value = isPodLike::value & isPodLike::value; +}; + namespace dont_use { // These two functions should never be used. They are helpers to Modified: llvm/trunk/lib/Analysis/IPA/Andersens.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/IPA/Andersens.cpp?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/IPA/Andersens.cpp (original) +++ llvm/trunk/lib/Analysis/IPA/Andersens.cpp Tue Dec 15 01:26:43 2009 @@ -121,8 +121,6 @@ return *LHS == *RHS; } - - static bool isPod() { return true; } }; class Andersens : public ModulePass, public AliasAnalysis, Modified: llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp (original) +++ llvm/trunk/lib/Bitcode/Reader/Deserialize.cpp Tue Dec 15 01:26:43 2009 @@ -413,7 +413,7 @@ return GetFinalPtr(E); } -void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) { +void BPEntry::SetPtr(BPNode*& FreeList, void* P) { BPNode* Last = NULL; for (BPNode* N = Head; N != NULL; N=N->Next) { Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfException.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfException.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfException.h (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfException.h Tue Dec 15 01:26:43 2009 @@ -119,7 +119,6 @@ static inline unsigned getTombstoneKey() { return -2U; } static unsigned getHashValue(const unsigned &Key) { return Key; } static bool isEqual(unsigned LHS, unsigned RHS) { return LHS == RHS; } - static bool isPod() { return true; } }; /// PadRange - Structure holding a try-range and the associated landing pad. Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp Tue Dec 15 01:26:43 2009 @@ -175,7 +175,6 @@ static inline unsigned getTombstoneKey() { return -2U; } static unsigned getHashValue(const unsigned &Key) { return Key; } static bool isEqual(unsigned LHS, unsigned RHS) { return LHS == RHS; } - static bool isPod() { return true; } }; /// ActionEntry - Structure describing an entry in the actions table. Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Tue Dec 15 01:26:43 2009 @@ -190,8 +190,11 @@ static bool isEqual(const Expression &LHS, const Expression &RHS) { return LHS == RHS; } - static bool isPod() { return true; } }; + +template <> +struct isPodLike { static const bool value = true; }; + } //===----------------------------------------------------------------------===// Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Tue Dec 15 01:26:43 2009 @@ -11200,8 +11200,9 @@ return LHS.PN == RHS.PN && LHS.Shift == RHS.Shift && LHS.Width == RHS.Width; } - static bool isPod() { return true; } }; + template <> + struct isPodLike { static const bool value = true; }; } Modified: llvm/trunk/lib/Transforms/Scalar/SCCVN.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCVN.cpp?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/SCCVN.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/SCCVN.cpp Tue Dec 15 01:26:43 2009 @@ -154,8 +154,10 @@ static bool isEqual(const Expression &LHS, const Expression &RHS) { return LHS == RHS; } - static bool isPod() { return true; } }; +template <> +struct isPodLike { static const bool value = true; }; + } //===----------------------------------------------------------------------===// Modified: llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp Tue Dec 15 01:26:43 2009 @@ -55,7 +55,6 @@ static bool isEqual(const EltTy &LHS, const EltTy &RHS) { return LHS == RHS; } - static bool isPod() { return true; } }; } Modified: llvm/trunk/lib/VMCore/LLVMContextImpl.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/LLVMContextImpl.h?rev=91421&r1=91420&r2=91421&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/LLVMContextImpl.h (original) +++ llvm/trunk/lib/VMCore/LLVMContextImpl.h Tue Dec 15 01:26:43 2009 @@ -62,7 +62,6 @@ static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) { return LHS == RHS; } - static bool isPod() { return false; } }; struct DenseMapAPFloatKeyInfo { @@ -89,7 +88,6 @@ static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) { return LHS == RHS; } - static bool isPod() { return false; } }; class LLVMContextImpl { From sabre at nondot.org Tue Dec 15 01:27:58 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 15 Dec 2009 07:27:58 -0000 Subject: [llvm-commits] [llvm] r91423 - /llvm/trunk/include/llvm/CodeGen/SlotIndexes.h Message-ID: <200912150727.nBF7Rwru007913@zion.cs.uiuc.edu> Author: lattner Date: Tue Dec 15 01:27:58 2009 New Revision: 91423 URL: http://llvm.org/viewvc/llvm-project?rev=91423&view=rev Log: Lang verified that SlotIndex is "pod like" even though it isn't a pod. Modified: llvm/trunk/include/llvm/CodeGen/SlotIndexes.h Modified: llvm/trunk/include/llvm/CodeGen/SlotIndexes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SlotIndexes.h?rev=91423&r1=91422&r2=91423&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SlotIndexes.h (original) +++ llvm/trunk/include/llvm/CodeGen/SlotIndexes.h Tue Dec 15 01:27:58 2009 @@ -329,7 +329,6 @@ }; /// DenseMapInfo specialization for SlotIndex. - /// TODO: Not a POD? template <> struct DenseMapInfo { static inline SlotIndex getEmptyKey() { @@ -345,6 +344,9 @@ return (LHS == RHS); } }; + + template <> struct isPodLike { static const bool value = true; }; + inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) { li.print(os); From sabre at nondot.org Tue Dec 15 01:40:44 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 15 Dec 2009 07:40:44 -0000 Subject: [llvm-commits] [llvm] r91425 - in /llvm/trunk/include/llvm: ADT/SmallVector.h Support/type_traits.h Message-ID: <200912150740.nBF7eipD008398@zion.cs.uiuc.edu> Author: lattner Date: Tue Dec 15 01:40:44 2009 New Revision: 91425 URL: http://llvm.org/viewvc/llvm-project?rev=91425&view=rev Log: improve isPodLike to know that all non-class types are pod. Modified: llvm/trunk/include/llvm/ADT/SmallVector.h llvm/trunk/include/llvm/Support/type_traits.h Modified: llvm/trunk/include/llvm/ADT/SmallVector.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=91425&r1=91424&r2=91425&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/SmallVector.h (original) +++ llvm/trunk/include/llvm/ADT/SmallVector.h Tue Dec 15 01:40:44 2009 @@ -46,6 +46,13 @@ namespace llvm { +/// SmallVectorBase - This is all the non-templated stuff common to all +/// SmallVectors. +class SmallVectorBase { + +}; + + /// SmallVectorImpl - This class consists of common code factored out of the /// SmallVector class to reduce code duplication based on the SmallVector 'N' /// template parameter. Modified: llvm/trunk/include/llvm/Support/type_traits.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/type_traits.h?rev=91425&r1=91424&r2=91425&view=diff ============================================================================== --- llvm/trunk/include/llvm/Support/type_traits.h (original) +++ llvm/trunk/include/llvm/Support/type_traits.h Tue Dec 15 01:40:44 2009 @@ -25,33 +25,6 @@ // works with VC7.0, but other interactions seem to fail when we use it. namespace llvm { - -/// isPodLike - This is a type trait that is used to determine whether a given -/// type can be copied around with memcpy instead of running ctors etc. -template -struct isPodLike { - static const bool value = false; -}; - -// pointers are all pod-like. -template -struct isPodLike { static const bool value = true; }; - -// builtin types are pod-like as well. -// There is probably a much better way to do this. -template <> struct isPodLike { static const bool value = true; }; -template <> struct isPodLike { static const bool value = true; }; -template <> struct isPodLike { static const bool value = true; }; -template <> struct isPodLike { - static const bool value = true; -}; - - -// pairs are pod-like if their elements are. -template -struct isPodLike > { - static const bool value = isPodLike::value & isPodLike::value; -}; namespace dont_use { @@ -77,6 +50,23 @@ public: enum { value = sizeof(char) == sizeof(dont_use::is_class_helper(0)) }; }; + + +/// isPodLike - This is a type trait that is used to determine whether a given +/// type can be copied around with memcpy instead of running ctors etc. +template +struct isPodLike { + // If we don't know anything else, we can (at least) assume that all non-class + // types are PODs. + static const bool value = !is_class::value; +}; + +// std::pair's are pod-like if their elements are. +template +struct isPodLike > { + static const bool value = isPodLike::value & isPodLike::value; +}; + /// \brief Metafunction that determines whether the two given types are /// equivalent. From anton at korobeynikov.info Tue Dec 15 02:03:34 2009 From: anton at korobeynikov.info (Anton Korobeynikov) Date: Tue, 15 Dec 2009 11:03:34 +0300 Subject: [llvm-commits] [llvm] r91416 - /llvm/trunk/include/llvm/Support/Compiler.h In-Reply-To: <200912150614.nBF6EXLV005148@zion.cs.uiuc.edu> References: <200912150614.nBF6EXLV005148@zion.cs.uiuc.edu> Message-ID: > +#else > +// TODO: No idea how to do this with MSVC. > +#define ALWAYS_INLINE __forceinline iirc -- With best regards, Anton Korobeynikov Faculty of Mathematics and Mechanics, Saint Petersburg State University From sabre at nondot.org Tue Dec 15 02:16:40 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 15 Dec 2009 00:16:40 -0800 Subject: [llvm-commits] [llvm] r91416 - /llvm/trunk/include/llvm/Support/Compiler.h In-Reply-To: References: <200912150614.nBF6EXLV005148@zion.cs.uiuc.edu> Message-ID: <800B636E-F0C5-4CD0-BAB3-27856352E386@nondot.org> On Dec 15, 2009, at 12:03 AM, Anton Korobeynikov wrote: >> +#else >> +// TODO: No idea how to do this with MSVC. >> +#define ALWAYS_INLINE > __forceinline iirc I'll let someone who can test it do it if they care. This is just an optimization hint, so it doesn't hurt not to. -Chris From sabre at nondot.org Tue Dec 15 02:29:22 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 15 Dec 2009 08:29:22 -0000 Subject: [llvm-commits] [llvm] r91426 - /llvm/trunk/include/llvm/ADT/SmallVector.h Message-ID: <200912150829.nBF8TMtU010096@zion.cs.uiuc.edu> Author: lattner Date: Tue Dec 15 02:29:22 2009 New Revision: 91426 URL: http://llvm.org/viewvc/llvm-project?rev=91426&view=rev Log: hoist the begin/end/capacity members and a few trivial methods up into the non-templated SmallVectorBase class. Modified: llvm/trunk/include/llvm/ADT/SmallVector.h Modified: llvm/trunk/include/llvm/ADT/SmallVector.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=91426&r1=91425&r2=91426&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/SmallVector.h (original) +++ llvm/trunk/include/llvm/ADT/SmallVector.h Tue Dec 15 02:29:22 2009 @@ -49,24 +49,14 @@ /// SmallVectorBase - This is all the non-templated stuff common to all /// SmallVectors. class SmallVectorBase { - -}; - - -/// SmallVectorImpl - This class consists of common code factored out of the -/// SmallVector class to reduce code duplication based on the SmallVector 'N' -/// template parameter. -template -class SmallVectorImpl { protected: - T *Begin, *End, *Capacity; + void *BeginX, *EndX, *CapacityX; // Allocate raw space for N elements of type T. If T has a ctor or dtor, we // don't want it to be automatically run, so we need to represent the space as // something else. An array of char would work great, but might not be // aligned sufficiently. Instead, we either use GCC extensions, or some // number of union instances for the space, which guarantee maximal alignment. -protected: #ifdef __GNUC__ typedef char U; U FirstEl __attribute__((aligned)); @@ -79,46 +69,65 @@ } FirstEl; #endif // Space after 'FirstEl' is clobbered, do not add any instance vars after it. + +protected: + SmallVectorBase(size_t Size) + : BeginX(&FirstEl), EndX(&FirstEl), CapacityX((char*)&FirstEl+Size) {} + + /// isSmall - Return true if this is a smallvector which has not had dynamic + /// memory allocated for it. + bool isSmall() const { + return BeginX == static_cast(&FirstEl); + } + + +public: + bool empty() const { return BeginX == EndX; } +}; + +/// SmallVectorImpl - This class consists of common code factored out of the +/// SmallVector class to reduce code duplication based on the SmallVector 'N' +/// template parameter. +template +class SmallVectorImpl : public SmallVectorBase { + void setEnd(T *P) { EndX = P; } public: // Default ctor - Initialize to empty. - explicit SmallVectorImpl(unsigned N) - : Begin(reinterpret_cast(&FirstEl)), - End(reinterpret_cast(&FirstEl)), - Capacity(reinterpret_cast(&FirstEl)+N) { + explicit SmallVectorImpl(unsigned N) : SmallVectorBase(N*sizeof(T)) { } ~SmallVectorImpl() { // Destroy the constructed elements in the vector. - destroy_range(Begin, End); + destroy_range(begin(), end()); // If this wasn't grown from the inline copy, deallocate the old space. if (!isSmall()) - operator delete(Begin); + operator delete(begin()); } typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T value_type; - typedef T* iterator; - typedef const T* const_iterator; - - typedef std::reverse_iterator const_reverse_iterator; - typedef std::reverse_iterator reverse_iterator; + typedef T *iterator; + typedef const T *const_iterator; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; - bool empty() const { return Begin == End; } - size_type size() const { return End-Begin; } - size_type max_size() const { return size_type(-1) / sizeof(T); } + typedef T &reference; + typedef const T &const_reference; + typedef T *pointer; + typedef const T *const_pointer; // forward iterator creation methods. - iterator begin() { return Begin; } - const_iterator begin() const { return Begin; } - iterator end() { return End; } - const_iterator end() const { return End; } + iterator begin() { return (iterator)BeginX; } + const_iterator begin() const { return (const_iterator)BeginX; } + iterator end() { return (iterator)EndX; } + const_iterator end() const { return (const_iterator)EndX; } +private: + iterator capacity_ptr() { return (iterator)CapacityX; } + const_iterator capacity_ptr() const { return (const_iterator)CapacityX; } +public: // reverse iterator creation methods. reverse_iterator rbegin() { return reverse_iterator(end()); } @@ -126,14 +135,25 @@ reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin());} - + size_type size() const { return end()-begin(); } + size_type max_size() const { return size_type(-1) / sizeof(T); } + + /// capacity - Return the total number of elements in the currently allocated + /// buffer. + size_t capacity() const { return capacity_ptr() - begin(); } + + /// data - Return a pointer to the vector's buffer, even if empty(). + pointer data() { return pointer(begin()); } + /// data - Return a pointer to the vector's buffer, even if empty(). + const_pointer data() const { return const_pointer(begin()); } + reference operator[](unsigned idx) { - assert(Begin + idx < End); - return Begin[idx]; + assert(begin() + idx < end()); + return begin()[idx]; } const_reference operator[](unsigned idx) const { - assert(Begin + idx < End); - return Begin[idx]; + assert(begin() + idx < end()); + return begin()[idx]; } reference front() { @@ -151,10 +171,10 @@ } void push_back(const_reference Elt) { - if (End < Capacity) { + if (EndX < CapacityX) { Retry: - new (End) T(Elt); - ++End; + new (end()) T(Elt); + setEnd(end()+1); return; } grow(); @@ -162,8 +182,8 @@ } void pop_back() { - --End; - End->~T(); + setEnd(end()-1); + end()->~T(); } T pop_back_val() { @@ -173,36 +193,36 @@ } void clear() { - destroy_range(Begin, End); - End = Begin; + destroy_range(begin(), end()); + EndX = BeginX; } void resize(unsigned N) { if (N < size()) { - destroy_range(Begin+N, End); - End = Begin+N; + destroy_range(begin()+N, end()); + setEnd(begin()+N); } else if (N > size()) { - if (unsigned(Capacity-Begin) < N) + if (capacity() < N) grow(N); - construct_range(End, Begin+N, T()); - End = Begin+N; + construct_range(end(), begin()+N, T()); + setEnd(begin()+N); } } void resize(unsigned N, const T &NV) { if (N < size()) { - destroy_range(Begin+N, End); - End = Begin+N; + destroy_range(begin()+N, end()); + setEnd(begin()+N); } else if (N > size()) { - if (unsigned(Capacity-Begin) < N) + if (capacity() < N) grow(N); - construct_range(End, Begin+N, NV); - End = Begin+N; + construct_range(end(), begin()+N, NV); + setEnd(begin()+N); } } void reserve(unsigned N) { - if (unsigned(Capacity-Begin) < N) + if (capacity() < N) grow(N); } @@ -214,38 +234,38 @@ void append(in_iter in_start, in_iter in_end) { size_type NumInputs = std::distance(in_start, in_end); // Grow allocated space if needed. - if (NumInputs > size_type(Capacity-End)) + if (NumInputs > size_type(capacity_ptr()-end())) grow(size()+NumInputs); // Copy the new elements over. - std::uninitialized_copy(in_start, in_end, End); - End += NumInputs; + std::uninitialized_copy(in_start, in_end, end()); + setEnd(end() + NumInputs); } /// append - Add the specified range to the end of the SmallVector. /// void append(size_type NumInputs, const T &Elt) { // Grow allocated space if needed. - if (NumInputs > size_type(Capacity-End)) + if (NumInputs > size_type(capacity_ptr()-end())) grow(size()+NumInputs); // Copy the new elements over. - std::uninitialized_fill_n(End, NumInputs, Elt); - End += NumInputs; + std::uninitialized_fill_n(end(), NumInputs, Elt); + setEnd(end() + NumInputs); } void assign(unsigned NumElts, const T &Elt) { clear(); - if (unsigned(Capacity-Begin) < NumElts) + if (capacity() < NumElts) grow(NumElts); - End = Begin+NumElts; - construct_range(Begin, End, Elt); + setEnd(begin()+NumElts); + construct_range(begin(), end(), Elt); } iterator erase(iterator I) { iterator N = I; // Shift all elts down one. - std::copy(I+1, End, I); + std::copy(I+1, end(), I); // Drop the last elt. pop_back(); return(N); @@ -254,36 +274,36 @@ iterator erase(iterator S, iterator E) { iterator N = S; // Shift all elts down. - iterator I = std::copy(E, End, S); + iterator I = std::copy(E, end(), S); // Drop the last elts. - destroy_range(I, End); - End = I; + destroy_range(I, end()); + setEnd(I); return(N); } iterator insert(iterator I, const T &Elt) { - if (I == End) { // Important special case for empty vector. + if (I == end()) { // Important special case for empty vector. push_back(Elt); return end()-1; } - if (End < Capacity) { + if (EndX < CapacityX) { Retry: - new (End) T(back()); - ++End; + new (end()) T(back()); + setEnd(end()+1); // Push everything else over. - std::copy_backward(I, End-1, End); + std::copy_backward(I, end()-1, end()); *I = Elt; return I; } - size_t EltNo = I-Begin; + size_t EltNo = I-begin(); grow(); - I = Begin+EltNo; + I = begin()+EltNo; goto Retry; } iterator insert(iterator I, size_type NumToInsert, const T &Elt) { - if (I == End) { // Important special case for empty vector. + if (I == end()) { // Important special case for empty vector. append(NumToInsert, Elt); return end()-1; } @@ -302,8 +322,8 @@ // insertion. Since we already reserved space, we know that this won't // reallocate the vector. if (size_t(end()-I) >= NumToInsert) { - T *OldEnd = End; - append(End-NumToInsert, End); + T *OldEnd = end(); + append(end()-NumToInsert, end()); // Copy the existing elements that get replaced. std::copy_backward(I, OldEnd-NumToInsert, OldEnd); @@ -316,10 +336,10 @@ // not inserting at the end. // Copy over the elements that we're about to overwrite. - T *OldEnd = End; - End += NumToInsert; + T *OldEnd = end(); + setEnd(end() + NumToInsert); size_t NumOverwritten = OldEnd-I; - std::uninitialized_copy(I, OldEnd, End-NumOverwritten); + std::uninitialized_copy(I, OldEnd, end()-NumOverwritten); // Replace the overwritten part. std::fill_n(I, NumOverwritten, Elt); @@ -331,7 +351,7 @@ template iterator insert(iterator I, ItTy From, ItTy To) { - if (I == End) { // Important special case for empty vector. + if (I == end()) { // Important special case for empty vector. append(From, To); return end()-1; } @@ -351,8 +371,8 @@ // insertion. Since we already reserved space, we know that this won't // reallocate the vector. if (size_t(end()-I) >= NumToInsert) { - T *OldEnd = End; - append(End-NumToInsert, End); + T *OldEnd = end(); + append(end()-NumToInsert, end()); // Copy the existing elements that get replaced. std::copy_backward(I, OldEnd-NumToInsert, OldEnd); @@ -365,10 +385,10 @@ // not inserting at the end. // Copy over the elements that we're about to overwrite. - T *OldEnd = End; - End += NumToInsert; + T *OldEnd = end(); + setEnd(end() + NumToInsert); size_t NumOverwritten = OldEnd-I; - std::uninitialized_copy(I, OldEnd, End-NumOverwritten); + std::uninitialized_copy(I, OldEnd, end()-NumOverwritten); // Replace the overwritten part. std::copy(From, From+NumOverwritten, I); @@ -378,21 +398,11 @@ return I; } - /// data - Return a pointer to the vector's buffer, even if empty(). - pointer data() { - return pointer(Begin); - } - - /// data - Return a pointer to the vector's buffer, even if empty(). - const_pointer data() const { - return const_pointer(Begin); - } - const SmallVectorImpl &operator=(const SmallVectorImpl &RHS); bool operator==(const SmallVectorImpl &RHS) const { if (size() != RHS.size()) return false; - for (T *This = Begin, *That = RHS.Begin, *E = Begin+size(); + for (const T *This = begin(), *That = RHS.begin(), *E = end(); This != E; ++This, ++That) if (*This != *That) return false; @@ -405,10 +415,6 @@ RHS.begin(), RHS.end()); } - /// capacity - Return the total number of elements in the currently allocated - /// buffer. - size_t capacity() const { return Capacity - Begin; } - /// set_size - Set the array size to \arg N, which the current array must have /// enough capacity for. /// @@ -420,17 +426,10 @@ /// which will only be overwritten. void set_size(unsigned N) { assert(N <= capacity()); - End = Begin + N; + setEnd(begin() + N); } private: - /// isSmall - Return true if this is a smallvector which has not had dynamic - /// memory allocated for it. - bool isSmall() const { - return static_cast(Begin) == - static_cast(&FirstEl); - } - /// grow - double the size of the allocated memory, guaranteeing space for at /// least one more element or MinSize if specified. void grow(size_type MinSize = 0); @@ -441,6 +440,7 @@ } void destroy_range(T *S, T *E) { + // TODO: POD while (S != E) { --E; E->~T(); @@ -451,7 +451,7 @@ // Define this out-of-line to dissuade the C++ compiler from inlining it. template void SmallVectorImpl::grow(size_t MinSize) { - size_t CurCapacity = Capacity-Begin; + size_t CurCapacity = capacity(); size_t CurSize = size(); size_t NewCapacity = 2*CurCapacity; if (NewCapacity < MinSize) @@ -460,21 +460,21 @@ // Copy the elements over. if (is_class::value) - std::uninitialized_copy(Begin, End, NewElts); + std::uninitialized_copy(begin(), end(), NewElts); else // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove). - memcpy(NewElts, Begin, CurSize * sizeof(T)); + memcpy(NewElts, begin(), CurSize * sizeof(T)); // Destroy the original elements. - destroy_range(Begin, End); + destroy_range(begin(), end()); // If this wasn't grown from the inline copy, deallocate the old space. if (!isSmall()) - operator delete(Begin); + operator delete(begin()); - Begin = NewElts; - End = NewElts+CurSize; - Capacity = Begin+NewCapacity; + setEnd(NewElts+CurSize); + BeginX = NewElts; + CapacityX = begin()+NewCapacity; } template @@ -483,35 +483,35 @@ // We can only avoid copying elements if neither vector is small. if (!isSmall() && !RHS.isSmall()) { - std::swap(Begin, RHS.Begin); - std::swap(End, RHS.End); - std::swap(Capacity, RHS.Capacity); + std::swap(BeginX, RHS.BeginX); + std::swap(EndX, RHS.EndX); + std::swap(CapacityX, RHS.CapacityX); return; } - if (RHS.size() > size_type(Capacity-Begin)) + if (RHS.size() > capacity()) grow(RHS.size()); - if (size() > size_type(RHS.Capacity-RHS.begin())) + if (size() > RHS.capacity()) RHS.grow(size()); // Swap the shared elements. size_t NumShared = size(); if (NumShared > RHS.size()) NumShared = RHS.size(); for (unsigned i = 0; i != static_cast(NumShared); ++i) - std::swap(Begin[i], RHS[i]); + std::swap((*this)[i], RHS[i]); // Copy over the extra elts. if (size() > RHS.size()) { size_t EltDiff = size() - RHS.size(); - std::uninitialized_copy(Begin+NumShared, End, RHS.End); - RHS.End += EltDiff; - destroy_range(Begin+NumShared, End); - End = Begin+NumShared; + std::uninitialized_copy(begin()+NumShared, end(), RHS.end()); + RHS.setEnd(RHS.end()+EltDiff); + destroy_range(begin()+NumShared, end()); + setEnd(begin()+NumShared); } else if (RHS.size() > size()) { size_t EltDiff = RHS.size() - size(); - std::uninitialized_copy(RHS.Begin+NumShared, RHS.End, End); - End += EltDiff; - destroy_range(RHS.Begin+NumShared, RHS.End); - RHS.End = RHS.Begin+NumShared; + std::uninitialized_copy(RHS.begin()+NumShared, RHS.end(), end()); + setEnd(end() + EltDiff); + destroy_range(RHS.begin()+NumShared, RHS.end()); + RHS.setEnd(RHS.begin()+NumShared); } } @@ -523,42 +523,42 @@ // If we already have sufficient space, assign the common elements, then // destroy any excess. - unsigned RHSSize = unsigned(RHS.size()); - unsigned CurSize = unsigned(size()); + size_t RHSSize = RHS.size(); + size_t CurSize = size(); if (CurSize >= RHSSize) { // Assign common elements. iterator NewEnd; if (RHSSize) - NewEnd = std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin); + NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, begin()); else - NewEnd = Begin; + NewEnd = begin(); // Destroy excess elements. - destroy_range(NewEnd, End); + destroy_range(NewEnd, end()); // Trim. - End = NewEnd; + setEnd(NewEnd); return *this; } // If we have to grow to have enough elements, destroy the current elements. // This allows us to avoid copying them during the grow. - if (unsigned(Capacity-Begin) < RHSSize) { + if (capacity() < RHSSize) { // Destroy current elements. - destroy_range(Begin, End); - End = Begin; + destroy_range(begin(), end()); + setEnd(begin()); CurSize = 0; grow(RHSSize); } else if (CurSize) { // Otherwise, use assignment for the already-constructed elements. - std::copy(RHS.Begin, RHS.Begin+CurSize, Begin); + std::copy(RHS.begin(), RHS.begin()+CurSize, begin()); } // Copy construct the new elements in place. - std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize); + std::uninitialized_copy(RHS.begin()+CurSize, RHS.end(), begin()+CurSize); // Set end. - End = Begin+RHSSize; + setEnd(begin()+RHSSize); return *this; } From sabre at nondot.org Tue Dec 15 02:34:01 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 15 Dec 2009 08:34:01 -0000 Subject: [llvm-commits] [llvm] r91427 - /llvm/trunk/include/llvm/ADT/SmallVector.h Message-ID: <200912150834.nBF8Y16A010437@zion.cs.uiuc.edu> Author: lattner Date: Tue Dec 15 02:34:01 2009 New Revision: 91427 URL: http://llvm.org/viewvc/llvm-project?rev=91427&view=rev Log: a few improvements: 1. Use std::equal instead of reinventing it. 2. don't run dtors in destroy_range if element is pod-like. 3. Use isPodLike to decide between memcpy/uninitialized_copy instead of is_class. isPodLike is more generous in some cases. Modified: llvm/trunk/include/llvm/ADT/SmallVector.h Modified: llvm/trunk/include/llvm/ADT/SmallVector.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=91427&r1=91426&r2=91427&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/SmallVector.h (original) +++ llvm/trunk/include/llvm/ADT/SmallVector.h Tue Dec 15 02:34:01 2009 @@ -402,11 +402,7 @@ bool operator==(const SmallVectorImpl &RHS) const { if (size() != RHS.size()) return false; - for (const T *This = begin(), *That = RHS.begin(), *E = end(); - This != E; ++This, ++That) - if (*This != *That) - return false; - return true; + return std::equal(begin(), end(), RHS.begin()); } bool operator!=(const SmallVectorImpl &RHS) const { return !(*this == RHS); } @@ -440,7 +436,9 @@ } void destroy_range(T *S, T *E) { - // TODO: POD + // No need to do a destroy loop for POD's. + if (isPodLike::value) return; + while (S != E) { --E; E->~T(); @@ -459,11 +457,11 @@ T *NewElts = static_cast(operator new(NewCapacity*sizeof(T))); // Copy the elements over. - if (is_class::value) - std::uninitialized_copy(begin(), end(), NewElts); - else - // Use memcpy for PODs (std::uninitialized_copy optimizes to memmove). + if (isPodLike::value) + // Use memcpy for PODs: std::uninitialized_copy optimizes to memmove. memcpy(NewElts, begin(), CurSize * sizeof(T)); + else + std::uninitialized_copy(begin(), end(), NewElts); // Destroy the original elements. destroy_range(begin(), end()); From sabre at nondot.org Tue Dec 15 03:05:16 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 15 Dec 2009 09:05:16 -0000 Subject: [llvm-commits] [llvm] r91428 - /llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp Message-ID: <200912150905.nBF95HBc025336@zion.cs.uiuc.edu> Author: lattner Date: Tue Dec 15 03:05:13 2009 New Revision: 91428 URL: http://llvm.org/viewvc/llvm-project?rev=91428&view=rev Log: add some other xforms that should be done as part of PR5783 Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp?rev=91428&r1=91427&r2=91428&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp Tue Dec 15 03:05:13 2009 @@ -2644,10 +2644,11 @@ // * strcspn("",a) -> 0 // * strcspn(s,"") -> strlen(a) // -// strstr: +// strstr: (PR5783) // * strstr(x,x) -> x -// * strstr(s1,s2) -> offset_of_s2_in(s1) -// (if s1 and s2 are constant strings) +// * strstr(x, "") -> x +// * strstr(x, "a") -> strchr(x, 'a') +// * strstr(s1,s2) -> result (if s1 and s2 are constant strings) // // tan, tanf, tanl: // * tan(atan(x)) -> x From gohman at apple.com Tue Dec 15 10:30:10 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 15 Dec 2009 16:30:10 -0000 Subject: [llvm-commits] [llvm] r91432 - /llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Message-ID: <200912151630.nBFGUAgT009603@zion.cs.uiuc.edu> Author: djg Date: Tue Dec 15 10:30:09 2009 New Revision: 91432 URL: http://llvm.org/viewvc/llvm-project?rev=91432&view=rev Log: Delete an unused function. Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=91432&r1=91431&r2=91432&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Tue Dec 15 10:30:09 2009 @@ -232,44 +232,6 @@ } } -/// containsAddRecFromDifferentLoop - Determine whether expression S involves a -/// subexpression that is an AddRec from a loop other than L. An outer loop -/// of L is OK, but not an inner loop nor a disjoint loop. -static bool containsAddRecFromDifferentLoop(const SCEV *S, Loop *L) { - // This is very common, put it first. - if (isa(S)) - return false; - if (const SCEVCommutativeExpr *AE = dyn_cast(S)) { - for (unsigned int i=0; i< AE->getNumOperands(); i++) - if (containsAddRecFromDifferentLoop(AE->getOperand(i), L)) - return true; - return false; - } - if (const SCEVAddRecExpr *AE = dyn_cast(S)) { - if (const Loop *newLoop = AE->getLoop()) { - if (newLoop == L) - return false; - // if newLoop is an outer loop of L, this is OK. - if (newLoop->contains(L->getHeader())) - return false; - } - return true; - } - if (const SCEVUDivExpr *DE = dyn_cast(S)) - return containsAddRecFromDifferentLoop(DE->getLHS(), L) || - containsAddRecFromDifferentLoop(DE->getRHS(), L); -#if 0 - // SCEVSDivExpr has been backed out temporarily, but will be back; we'll - // need this when it is. - if (const SCEVSDivExpr *DE = dyn_cast(S)) - return containsAddRecFromDifferentLoop(DE->getLHS(), L) || - containsAddRecFromDifferentLoop(DE->getRHS(), L); -#endif - if (const SCEVCastExpr *CE = dyn_cast(S)) - return containsAddRecFromDifferentLoop(CE->getOperand(), L); - return false; -} - /// isAddressUse - Returns true if the specified instruction is using the /// specified value as an address. static bool isAddressUse(Instruction *Inst, Value *OperandVal) { From ken at linux.vnet.ibm.com Tue Dec 15 05:54:54 2009 From: ken at linux.vnet.ibm.com (Ken Werner) Date: Tue, 15 Dec 2009 12:54:54 +0100 Subject: [llvm-commits] [patch] disable biarch for llvm-gcc on PPC64 Message-ID: <200912151254.54223.ken@linux.vnet.ibm.com> Hi, This patch disables biarch on powerpc64-*-linux* as LLVM doesn't seem to support it. -ken -------------- next part -------------- A non-text attachment was scrubbed... Name: ppc64-disable-biarch.patch Type: text/x-patch Size: 585 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20091215/32131787/attachment.bin From ken at linux.vnet.ibm.com Tue Dec 15 05:55:05 2009 From: ken at linux.vnet.ibm.com (Ken Werner) Date: Tue, 15 Dec 2009 12:55:05 +0100 Subject: [llvm-commits] [patch] frame pointer offset PPC64 Message-ID: <200912151255.05230.ken@linux.vnet.ibm.com> Hi, Small fix for the frame pointer offset on PPC64. -ken -------------- next part -------------- A non-text attachment was scrubbed... Name: ppc64-FPSaveOffset.patch Type: text/x-patch Size: 468 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20091215/13c9cea3/attachment.bin From ken at linux.vnet.ibm.com Tue Dec 15 05:55:29 2009 From: ken at linux.vnet.ibm.com (Ken Werner) Date: Tue, 15 Dec 2009 12:55:29 +0100 Subject: [llvm-commits] [patch] fptr support for PPC64 Message-ID: <200912151255.29701.ken@linux.vnet.ibm.com> Hi, The attached patch adds support for indirect calls (through function pointer) according to the ABI (http://refspecs.linuxfoundation.org/ELF/ppc64/PPC- elf64abi-1.9.html#FUNC-CALLS). The patch was made against revision 91275. -ken -------------- next part -------------- A non-text attachment was scrubbed... Name: ppc64-fptr.patch Type: text/x-patch Size: 8130 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20091215/e4c3f871/attachment.bin From johnny.chen at apple.com Tue Dec 15 11:24:15 2009 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 15 Dec 2009 17:24:15 -0000 Subject: [llvm-commits] [llvm] r91434 - in /llvm/trunk/lib/Target/ARM: ARMInstrFormats.td ARMInstrThumb.td ARMInstrThumb2.td Message-ID: <200912151724.nBFHOF6k011394@zion.cs.uiuc.edu> Author: johnny Date: Tue Dec 15 11:24:14 2009 New Revision: 91434 URL: http://llvm.org/viewvc/llvm-project?rev=91434&view=rev Log: Added encoding bits for the Thumb ISA. Initial checkin. Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td llvm/trunk/lib/Target/ARM/ARMInstrThumb.td llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=91434&r1=91433&r2=91434&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Tue Dec 15 11:24:14 2009 @@ -146,11 +146,9 @@ // ARM Instruction templates. // -class InstARM +class InstTemplate : Instruction { - field bits<32> Inst; - let Namespace = "ARM"; // TSFlagsFields @@ -179,6 +177,20 @@ let Itinerary = itin; } +class Encoding { + field bits<32> Inst; +} + +class InstARM + : InstTemplate, Encoding; + +// This Encoding-less class is used by Thumb1 to specify the encoding bits later +// on by adding flavors to specific instructions. +class InstThumb + : InstTemplate; + class PseudoInst pattern> : InstARM pattern> - : InstARM { + : InstThumb { let OutOperandList = oops; let InOperandList = iops; let AsmString = asm; @@ -876,9 +888,14 @@ class TIt pattern> : ThumbI; -// tBL, tBX instructions -class TIx2 pattern> - : ThumbI; +// tBL, tBX 32-bit instructions +class TIx2 opcod1, bits<2> opcod2, bit opcod3, + dag oops, dag iops, InstrItinClass itin, string asm, list pattern> + : ThumbI, Encoding { + let Inst{31-27} = opcod1; + let Inst{15-14} = opcod2; + let Inst{12} = opcod3; +} // BR_JT instructions class TJTI pattern> @@ -887,7 +904,7 @@ // Thumb1 only class Thumb1I pattern> - : InstARM { + : InstThumb { let OutOperandList = oops; let InOperandList = iops; let AsmString = asm; @@ -903,7 +920,8 @@ : Thumb1I; class T1JTI pattern> - : Thumb1I; + : Thumb1I, + Encoding; // Two-address instructions class T1It pattern> - : InstARM { + : InstThumb { let OutOperandList = !con(oops, (ops s_cc_out:$s)); let InOperandList = !con(iops, (ops pred:$p)); let AsmString = !strconcat(opc, !strconcat("${s}${p}", asm)); @@ -937,7 +955,7 @@ class Thumb1pI pattern> - : InstARM { + : InstThumb { let OutOperandList = oops; let InOperandList = !con(iops, (ops pred:$p)); let AsmString = !strconcat(opc, !strconcat("${p}", asm)); @@ -968,6 +986,46 @@ InstrItinClass itin, string opc, string asm, list pattern> : Thumb1pI; +// A6.2 16-bit Thumb instruction encoding +class T1Encoding opcode> : Encoding { + let Inst{15-10} = opcode; +} + +// A6.2.1 Shift (immediate), add, subtract, move, and compare encoding. +class T1General opcode> : Encoding { + let Inst{15-14} = 0b00; + let Inst{13-9} = opcode; +} + +// A6.2.2 Data-processing encoding. +class T1DataProcessing opcode> : Encoding { + let Inst{15-10} = 0b010000; + let Inst{9-6} = opcode; +} + +// A6.2.3 Special data instructions and branch and exchange encoding. +class T1Special opcode> : Encoding { + let Inst{15-10} = 0b010001; + let Inst{9-6} = opcode; +} + +// A6.2.4 Load/store single data item encoding. +class T1LoadStore opA, bits<3> opB> : Encoding { + let Inst{15-12} = opA; + let Inst{11-9} = opB; +} +class T1LdSt opB> : T1LoadStore<0b0101, opB>; +class T1LdSt4Imm opB> : T1LoadStore<0b0110, opB>; // Immediate, 4 bytes +class T1LdSt1Imm opB> : T1LoadStore<0b0111, opB>; // Immediate, 1 byte +class T1LdSt2Imm opB> : T1LoadStore<0b1000, opB>; // Immediate, 2 bytes +class T1LdStSP opB> : T1LoadStore<0b1001, opB>; // SP relative + +// A6.2.5 Miscellaneous 16-bit instructions encoding. +class T1Misc opcode> : Encoding { + let Inst{15-12} = 0b1011; + let Inst{11-5} = opcode; +} + // Thumb2I - Thumb2 instruction. Almost all Thumb2 instructions are predicable. class Thumb2I pattern> : Thumb2I; -class T2Ii8s4 pattern> - : Thumb2I; + : Thumb2I { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b00; + let Inst{24} = P; + let Inst{23} = ?; // The U bit. + let Inst{22} = 1; + let Inst{21} = W; + let Inst{20} = load; +} class T2sI pattern> @@ -1055,8 +1122,9 @@ // T2Iidxldst - Thumb2 indexed load / store instructions. -class T2Iidxldst opcod, bit load, bit pre, + dag oops, dag iops, + AddrMode am, IndexMode im, InstrItinClass itin, string opc, string asm, string cstr, list pattern> : InstARM { let OutOperandList = oops; @@ -1064,6 +1132,16 @@ let AsmString = !strconcat(opc, !strconcat("${p}", asm)); let Pattern = pattern; list Predicates = [IsThumb2]; + let Inst{31-27} = 0b11111; + let Inst{26-25} = 0b00; + let Inst{24} = signed; + let Inst{23} = 0; + let Inst{22-21} = opcod; + let Inst{20} = load; + let Inst{11} = 1; + // (P, W) = (1, 1) Pre-indexed or (0, 1) Post-indexed + let Inst{10} = pre; // The P bit. + let Inst{8} = 1; // The W bit. } // Tv5Pat - Same as Pat<>, but requires V5T Thumb mode. Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=91434&r1=91433&r2=91434&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Tue Dec 15 11:24:14 2009 @@ -136,31 +136,46 @@ let isNotDuplicable = 1 in def tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, "\n$cp:\n\tadd\t$dst, pc", - [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>; + [(set GPR:$dst, (ARMpic_add GPR:$lhs, imm:$cp))]>, + T1Special<{0,0,?,?}> { + let Inst{6-3} = 0b1111; // A8.6.6 Rm = pc +} // PC relative add. def tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi, - "add\t$dst, pc, $rhs", []>; + "add\t$dst, pc, $rhs", []>, + T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 // ADD rd, sp, #imm8 def tADDrSPi : T1I<(outs tGPR:$dst), (ins GPR:$sp, t_imm_s4:$rhs), IIC_iALUi, - "add\t$dst, $sp, $rhs", []>; + "add\t$dst, $sp, $rhs", []>, + T1Encoding<{1,0,1,0,1,?}>; // A6.2 & A8.6.8 // ADD sp, sp, #imm7 def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, - "add\t$dst, $rhs", []>; + "add\t$dst, $rhs", []>, + T1Misc<{0,0,0,0,0,?,?}>; // A6.2.5 & A8.6.8 // SUB sp, sp, #imm7 def tSUBspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, t_imm_s4:$rhs), IIC_iALUi, - "sub\t$dst, $rhs", []>; + "sub\t$dst, $rhs", []>, + T1Misc<{0,0,0,0,1,?,?}>; // A6.2.5 & A8.6.215 // ADD rm, sp def tADDrSP : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, - "add\t$dst, $rhs", []>; + "add\t$dst, $rhs", []>, + T1Special<{0,0,?,?}> { + let Inst{6-3} = 0b1101; // A8.6.9 Encoding T1 +} // ADD sp, rm def tADDspr : TIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, - "add\t$dst, $rhs", []>; + "add\t$dst, $rhs", []>, + T1Special<{0,0,?,?}> { + // A8.6.9 Encoding T2 + let Inst{7} = 1; + let Inst{2-0} = 0b101; +} // Pseudo instruction that will expand into a tSUBspi + a copy. let usesCustomInserter = 1 in { // Expanded after instruction selection. @@ -180,22 +195,32 @@ // let isReturn = 1, isTerminator = 1, isBarrier = 1 in { - def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr", [(ARMretflag)]>; + def tBX_RET : TI<(outs), (ins), IIC_Br, "bx\tlr", [(ARMretflag)]>, + T1Special<{1,1,0,?}> { // A6.2.3 & A8.6.25 + let Inst{6-3} = 0b1110; // Rm = lr + } // Alternative return instruction used by vararg functions. - def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target", []>; + def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target", []>, + T1Special<{1,1,0,?}>; // A6.2.3 & A8.6.25 } // Indirect branches let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { def tBRIND : TI<(outs), (ins GPR:$dst), IIC_Br, "mov\tpc, $dst", - [(brind GPR:$dst)]>; + [(brind GPR:$dst)]>, + T1Special<{1,0,?,?}> { + // = pc + let Inst{7} = 1; + let Inst{2-0} = 0b111; + } } // FIXME: remove when we have a way to marking a MI with these properties. let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, hasExtraDefRegAllocReq = 1 in def tPOP_RET : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, - "pop${p}\t$wb", []>; + "pop${p}\t$wb", []>, + T1Misc<{1,1,0,?,?,?,?}>; let isCall = 1, Defs = [R0, R1, R2, R3, R12, LR, @@ -203,25 +228,29 @@ D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { // Also used for Thumb2 - def tBL : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, - "bl\t${func:call}", - [(ARMtcall tglobaladdr:$func)]>, + def tBL : TIx2<0b11110, 0b11, 1, + (outs), (ins i32imm:$func, variable_ops), IIC_Br, + "bl\t${func:call}", + [(ARMtcall tglobaladdr:$func)]>, Requires<[IsThumb, IsNotDarwin]>; // ARMv5T and above, also used for Thumb2 - def tBLXi : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, - "blx\t${func:call}", - [(ARMcall tglobaladdr:$func)]>, + def tBLXi : TIx2<0b11110, 0b11, 0, + (outs), (ins i32imm:$func, variable_ops), IIC_Br, + "blx\t${func:call}", + [(ARMcall tglobaladdr:$func)]>, Requires<[IsThumb, HasV5T, IsNotDarwin]>; // Also used for Thumb2 def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, "blx\t$func", [(ARMtcall GPR:$func)]>, - Requires<[IsThumb, HasV5T, IsNotDarwin]>; + Requires<[IsThumb, HasV5T, IsNotDarwin]>, + T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24; // ARMv4T - def tBX : TIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, + def tBX : TIx2<{?,?,?,?,?}, {?,?}, ?, + (outs), (ins tGPR:$func, variable_ops), IIC_Br, "mov\tlr, pc\n\tbx\t$func", [(ARMcall_nolink tGPR:$func)]>, Requires<[IsThumb1Only, IsNotDarwin]>; @@ -234,27 +263,31 @@ D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { // Also used for Thumb2 - def tBLr9 : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, + def tBLr9 : TIx2<0b11110, 0b11, 1, + (outs), (ins i32imm:$func, variable_ops), IIC_Br, "bl\t${func:call}", [(ARMtcall tglobaladdr:$func)]>, Requires<[IsThumb, IsDarwin]>; // ARMv5T and above, also used for Thumb2 - def tBLXi_r9 : TIx2<(outs), (ins i32imm:$func, variable_ops), IIC_Br, + def tBLXi_r9 : TIx2<0b11110, 0b11, 0, + (outs), (ins i32imm:$func, variable_ops), IIC_Br, "blx\t${func:call}", [(ARMcall tglobaladdr:$func)]>, Requires<[IsThumb, HasV5T, IsDarwin]>; // Also used for Thumb2 def tBLXr_r9 : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, - "blx\t$func", - [(ARMtcall GPR:$func)]>, - Requires<[IsThumb, HasV5T, IsDarwin]>; + "blx\t$func", + [(ARMtcall GPR:$func)]>, + Requires<[IsThumb, HasV5T, IsDarwin]>, + T1Special<{1,1,1,?}>; // A6.2.3 & A8.6.24 // ARMv4T - def tBXr9 : TIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, - "mov\tlr, pc\n\tbx\t$func", - [(ARMcall_nolink tGPR:$func)]>, + def tBXr9 : TIx2<{?,?,?,?,?}, {?,?}, ?, + (outs), (ins tGPR:$func, variable_ops), IIC_Br, + "mov\tlr, pc\n\tbx\t$func", + [(ARMcall_nolink tGPR:$func)]>, Requires<[IsThumb1Only, IsDarwin]>; } @@ -262,11 +295,12 @@ let isBarrier = 1 in { let isPredicable = 1 in def tB : T1I<(outs), (ins brtarget:$target), IIC_Br, - "b\t$target", [(br bb:$target)]>; + "b\t$target", [(br bb:$target)]>, + T1Encoding<{1,1,1,0,0,?}>; // Far jump let Defs = [LR] in - def tBfar : TIx2<(outs), (ins brtarget:$target), IIC_Br, + def tBfar : TIx2<0b11110, 0b11, 1, (outs), (ins brtarget:$target), IIC_Br, "bl\t$target\t@ far jump",[]>; def tBR_JTr : T1JTI<(outs), @@ -281,15 +315,18 @@ let isBranch = 1, isTerminator = 1 in def tBcc : T1I<(outs), (ins brtarget:$target, pred:$cc), IIC_Br, "b$cc\t$target", - [/*(ARMbrcond bb:$target, imm:$cc)*/]>; + [/*(ARMbrcond bb:$target, imm:$cc)*/]>, + T1Encoding<{1,1,0,1,?,?}>; // Compare and branch on zero / non-zero let isBranch = 1, isTerminator = 1 in { def tCBZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, - "cbz\t$cmp, $target", []>; + "cbz\t$cmp, $target", []>, + T1Misc<{0,0,?,1,?,?,?}>; def tCBNZ : T1I<(outs), (ins tGPR:$cmp, brtarget:$target), IIC_Br, - "cbnz\t$cmp, $target", []>; + "cbnz\t$cmp, $target", []>, + T1Misc<{1,0,?,1,?,?,?}>; } //===----------------------------------------------------------------------===// @@ -299,71 +336,85 @@ let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in def tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, "ldr", "\t$dst, $addr", - [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>; + [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>, + T1LdSt<0b100>; def tLDRB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_s1:$addr), IIC_iLoadr, "ldrb", "\t$dst, $addr", - [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>; + [(set tGPR:$dst, (zextloadi8 t_addrmode_s1:$addr))]>, + T1LdSt<0b110>; def tLDRH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_s2:$addr), IIC_iLoadr, "ldrh", "\t$dst, $addr", - [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>; + [(set tGPR:$dst, (zextloadi16 t_addrmode_s2:$addr))]>, + T1LdSt<0b101>; let AddedComplexity = 10 in def tLDRSB : T1pI1<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, "ldrsb", "\t$dst, $addr", - [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>; + [(set tGPR:$dst, (sextloadi8 t_addrmode_rr:$addr))]>, + T1LdSt<0b011>; let AddedComplexity = 10 in def tLDRSH : T1pI2<(outs tGPR:$dst), (ins t_addrmode_rr:$addr), IIC_iLoadr, "ldrsh", "\t$dst, $addr", - [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>; + [(set tGPR:$dst, (sextloadi16 t_addrmode_rr:$addr))]>, + T1LdSt<0b111>; let canFoldAsLoad = 1 in def tLDRspi : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, "ldr", "\t$dst, $addr", - [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>; + [(set tGPR:$dst, (load t_addrmode_sp:$addr))]>, + T1LdStSP<{1,?,?}>; // Special instruction for restore. It cannot clobber condition register // when it's expanded by eliminateCallFramePseudoInstr(). let canFoldAsLoad = 1, mayLoad = 1 in def tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, - "ldr", "\t$dst, $addr", []>; + "ldr", "\t$dst, $addr", []>, + T1LdStSP<{1,?,?}>; // Load tconstpool // FIXME: Use ldr.n to work around a Darwin assembler bug. let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in def tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, "ldr", ".n\t$dst, $addr", - [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>; + [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>, + T1Encoding<{0,1,0,0,1,?}>; // A6.2 & A8.6.59 // Special LDR for loads from non-pc-relative constpools. let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in def tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, - "ldr", "\t$dst, $addr", []>; + "ldr", "\t$dst, $addr", []>, + T1LdStSP<{1,?,?}>; def tSTR : T1pI4<(outs), (ins tGPR:$src, t_addrmode_s4:$addr), IIC_iStorer, "str", "\t$src, $addr", - [(store tGPR:$src, t_addrmode_s4:$addr)]>; + [(store tGPR:$src, t_addrmode_s4:$addr)]>, + T1LdSt<0b000>; def tSTRB : T1pI1<(outs), (ins tGPR:$src, t_addrmode_s1:$addr), IIC_iStorer, "strb", "\t$src, $addr", - [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>; + [(truncstorei8 tGPR:$src, t_addrmode_s1:$addr)]>, + T1LdSt<0b010>; def tSTRH : T1pI2<(outs), (ins tGPR:$src, t_addrmode_s2:$addr), IIC_iStorer, "strh", "\t$src, $addr", - [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>; + [(truncstorei16 tGPR:$src, t_addrmode_s2:$addr)]>, + T1LdSt<0b001>; def tSTRspi : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, "str", "\t$src, $addr", - [(store tGPR:$src, t_addrmode_sp:$addr)]>; + [(store tGPR:$src, t_addrmode_sp:$addr)]>, + T1LdStSP<{0,?,?}>; let mayStore = 1 in { // Special instruction for spill. It cannot clobber condition register // when it's expanded by eliminateCallFramePseudoInstr(). def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStorei, - "str", "\t$src, $addr", []>; + "str", "\t$src, $addr", []>, + T1LdStSP<{0,?,?}>; } //===----------------------------------------------------------------------===// @@ -375,21 +426,25 @@ def tLDM : T1I<(outs), (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), IIC_iLoadm, - "ldm${addr:submode}${p}\t$addr, $wb", []>; + "ldm${addr:submode}${p}\t$addr, $wb", []>, + T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53 let mayStore = 1, hasExtraSrcRegAllocReq = 1 in def tSTM : T1I<(outs), (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), IIC_iStorem, - "stm${addr:submode}${p}\t$addr, $wb", []>; + "stm${addr:submode}${p}\t$addr, $wb", []>, + T1Encoding<{1,1,0,0,0,?}>; // A6.2 & A8.6.189 let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in def tPOP : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, - "pop${p}\t$wb", []>; + "pop${p}\t$wb", []>, + T1Misc<{1,1,0,?,?,?,?}>; let mayStore = 1, Uses = [SP], Defs = [SP], hasExtraSrcRegAllocReq = 1 in def tPUSH : T1I<(outs), (ins pred:$p, reglist:$wb, variable_ops), IIC_Br, - "push${p}\t$wb", []>; + "push${p}\t$wb", []>, + T1Misc<{0,1,0,?,?,?,?}>; //===----------------------------------------------------------------------===// // Arithmetic Instructions. @@ -399,82 +454,98 @@ let isCommutable = 1, Uses = [CPSR] in def tADC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, "adc", "\t$dst, $rhs", - [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>, + T1DataProcessing<0b0101>; // Add immediate def tADDi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, "add", "\t$dst, $lhs, $rhs", - [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>; + [(set tGPR:$dst, (add tGPR:$lhs, imm0_7:$rhs))]>, + T1General<0b01110>; def tADDi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, "add", "\t$dst, $rhs", - [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>; + [(set tGPR:$dst, (add tGPR:$lhs, imm8_255:$rhs))]>, + T1General<{1,1,0,?,?}>; // Add register let isCommutable = 1 in def tADDrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, "add", "\t$dst, $lhs, $rhs", - [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (add tGPR:$lhs, tGPR:$rhs))]>, + T1General<0b01100>; let neverHasSideEffects = 1 in def tADDhirr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, - "add", "\t$dst, $rhs", []>; + "add", "\t$dst, $rhs", []>, + T1Special<{0,0,?,?}>; // And register let isCommutable = 1 in def tAND : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, "and", "\t$dst, $rhs", - [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>, + T1DataProcessing<0b0000>; // ASR immediate def tASRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, "asr", "\t$dst, $lhs, $rhs", - [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>; + [(set tGPR:$dst, (sra tGPR:$lhs, (i32 imm:$rhs)))]>, + T1General<{0,1,0,?,?}>; // ASR register def tASRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, "asr", "\t$dst, $rhs", - [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (sra tGPR:$lhs, tGPR:$rhs))]>, + T1DataProcessing<0b0100>; // BIC register def tBIC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, "bic", "\t$dst, $rhs", - [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>; + [(set tGPR:$dst, (and tGPR:$lhs, (not tGPR:$rhs)))]>, + T1DataProcessing<0b1110>; // CMN register let Defs = [CPSR] in { def tCMN : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, "cmn", "\t$lhs, $rhs", - [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>; + [(ARMcmp tGPR:$lhs, (ineg tGPR:$rhs))]>, + T1DataProcessing<0b1011>; def tCMNZ : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, "cmn", "\t$lhs, $rhs", - [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>; + [(ARMcmpZ tGPR:$lhs, (ineg tGPR:$rhs))]>, + T1DataProcessing<0b1011>; } // CMP immediate let Defs = [CPSR] in { def tCMPi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, "cmp", "\t$lhs, $rhs", - [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>; + [(ARMcmp tGPR:$lhs, imm0_255:$rhs)]>, + T1General<{1,0,1,?,?}>; def tCMPzi8 : T1pI<(outs), (ins tGPR:$lhs, i32imm:$rhs), IIC_iCMPi, "cmp", "\t$lhs, $rhs", - [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>; - + [(ARMcmpZ tGPR:$lhs, imm0_255:$rhs)]>, + T1General<{1,0,1,?,?}>; } // CMP register let Defs = [CPSR] in { def tCMPr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, "cmp", "\t$lhs, $rhs", - [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>; + [(ARMcmp tGPR:$lhs, tGPR:$rhs)]>, + T1DataProcessing<0b1010>; def tCMPzr : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, "cmp", "\t$lhs, $rhs", - [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>; + [(ARMcmpZ tGPR:$lhs, tGPR:$rhs)]>, + T1DataProcessing<0b1010>; def tCMPhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, - "cmp", "\t$lhs, $rhs", []>; + "cmp", "\t$lhs, $rhs", []>, + T1Special<{0,1,?,?}>; def tCMPzhir : T1pI<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, - "cmp", "\t$lhs, $rhs", []>; + "cmp", "\t$lhs, $rhs", []>, + T1Special<{0,1,?,?}>; } @@ -482,32 +553,38 @@ let isCommutable = 1 in def tEOR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, "eor", "\t$dst, $rhs", - [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>, + T1DataProcessing<0b0001>; // LSL immediate def tLSLri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, "lsl", "\t$dst, $lhs, $rhs", - [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>; + [(set tGPR:$dst, (shl tGPR:$lhs, (i32 imm:$rhs)))]>, + T1General<{0,0,0,?,?}>; // LSL register def tLSLrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, "lsl", "\t$dst, $rhs", - [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (shl tGPR:$lhs, tGPR:$rhs))]>, + T1DataProcessing<0b0010>; // LSR immediate def tLSRri : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iMOVsi, "lsr", "\t$dst, $lhs, $rhs", - [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>; + [(set tGPR:$dst, (srl tGPR:$lhs, (i32 imm:$rhs)))]>, + T1General<{0,0,1,?,?}>; // LSR register def tLSRrr : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, "lsr", "\t$dst, $rhs", - [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (srl tGPR:$lhs, tGPR:$rhs))]>, + T1DataProcessing<0b0011>; // move register def tMOVi8 : T1sI<(outs tGPR:$dst), (ins i32imm:$src), IIC_iMOVi, "mov", "\t$dst, $src", - [(set tGPR:$dst, imm0_255:$src)]>; + [(set tGPR:$dst, imm0_255:$src)]>, + T1General<{1,0,0,?,?}>; // TODO: A7-73: MOV(2) - mov setting flag. @@ -515,42 +592,52 @@ let neverHasSideEffects = 1 in { // FIXME: Make this predicable. def tMOVr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, - "mov\t$dst, $src", []>; + "mov\t$dst, $src", []>, + T1Special<0b1000>; let Defs = [CPSR] in def tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, - "movs\t$dst, $src", []>; + "movs\t$dst, $src", []>, Encoding { + let Inst{15-6} = 0b0000000000; +} // FIXME: Make these predicable. def tMOVgpr2tgpr : T1I<(outs tGPR:$dst), (ins GPR:$src), IIC_iMOVr, - "mov\t$dst, $src", []>; + "mov\t$dst, $src", []>, + T1Special<{1,0,0,1}>; def tMOVtgpr2gpr : T1I<(outs GPR:$dst), (ins tGPR:$src), IIC_iMOVr, - "mov\t$dst, $src", []>; + "mov\t$dst, $src", []>, + T1Special<{1,0,1,0}>; def tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, - "mov\t$dst, $src", []>; + "mov\t$dst, $src", []>, + T1Special<{1,0,1,1}>; } // neverHasSideEffects // multiply register let isCommutable = 1 in def tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMUL32, "mul", "\t$dst, $rhs", - [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>, + T1DataProcessing<0b1101>; // move inverse register def tMVN : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, "mvn", "\t$dst, $src", - [(set tGPR:$dst, (not tGPR:$src))]>; + [(set tGPR:$dst, (not tGPR:$src))]>, + T1DataProcessing<0b1111>; // bitwise or register let isCommutable = 1 in def tORR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, "orr", "\t$dst, $rhs", - [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>, + T1DataProcessing<0b1100>; // swaps def tREV : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "rev", "\t$dst, $src", [(set tGPR:$dst, (bswap tGPR:$src))]>, - Requires<[IsThumb1Only, HasV6]>; + Requires<[IsThumb1Only, HasV6]>, + T1Misc<{1,0,1,0,0,0,?}>; def tREV16 : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "rev16", "\t$dst, $src", @@ -559,7 +646,8 @@ (or (and (shl tGPR:$src, (i32 8)), 0xFF00), (or (and (srl tGPR:$src, (i32 8)), 0xFF0000), (and (shl tGPR:$src, (i32 8)), 0xFF000000)))))]>, - Requires<[IsThumb1Only, HasV6]>; + Requires<[IsThumb1Only, HasV6]>, + T1Misc<{1,0,1,0,0,1,?}>; def tREVSH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "revsh", "\t$dst, $src", @@ -567,37 +655,44 @@ (sext_inreg (or (srl (and tGPR:$src, 0xFF00), (i32 8)), (shl tGPR:$src, (i32 8))), i16))]>, - Requires<[IsThumb1Only, HasV6]>; + Requires<[IsThumb1Only, HasV6]>, + T1Misc<{1,0,1,0,1,1,?}>; // rotate right register def tROR : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMOVsr, "ror", "\t$dst, $rhs", - [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (rotr tGPR:$lhs, tGPR:$rhs))]>, + T1DataProcessing<0b0111>; // negate register def tRSB : T1sI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iALUi, "rsb", "\t$dst, $src, #0", - [(set tGPR:$dst, (ineg tGPR:$src))]>; + [(set tGPR:$dst, (ineg tGPR:$src))]>, + T1DataProcessing<0b1001>; // Subtract with carry register let Uses = [CPSR] in def tSBC : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, "sbc", "\t$dst, $rhs", - [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (sube tGPR:$lhs, tGPR:$rhs))]>, + T1DataProcessing<0b0110>; // Subtract immediate def tSUBi3 : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, "sub", "\t$dst, $lhs, $rhs", - [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>; + [(set tGPR:$dst, (add tGPR:$lhs, imm0_7_neg:$rhs))]>, + T1General<0b01111>; def tSUBi8 : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, i32imm:$rhs), IIC_iALUi, "sub", "\t$dst, $rhs", - [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>; + [(set tGPR:$dst, (add tGPR:$lhs, imm8_255_neg:$rhs))]>, + T1General<{1,1,1,?,?}>; // subtract register def tSUBrr : T1sI<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iALUr, "sub", "\t$dst, $lhs, $rhs", - [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>; + [(set tGPR:$dst, (sub tGPR:$lhs, tGPR:$rhs))]>, + T1General<0b01101>; // TODO: A7-96: STMIA - store multiple. @@ -605,31 +700,36 @@ def tSXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "sxtb", "\t$dst, $src", [(set tGPR:$dst, (sext_inreg tGPR:$src, i8))]>, - Requires<[IsThumb1Only, HasV6]>; + Requires<[IsThumb1Only, HasV6]>, + T1Misc<{0,0,1,0,0,1,?}>; // sign-extend short def tSXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "sxth", "\t$dst, $src", [(set tGPR:$dst, (sext_inreg tGPR:$src, i16))]>, - Requires<[IsThumb1Only, HasV6]>; + Requires<[IsThumb1Only, HasV6]>, + T1Misc<{0,0,1,0,0,0,?}>; // test let isCommutable = 1, Defs = [CPSR] in def tTST : T1pI<(outs), (ins tGPR:$lhs, tGPR:$rhs), IIC_iCMPr, "tst", "\t$lhs, $rhs", - [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>; + [(ARMcmpZ (and tGPR:$lhs, tGPR:$rhs), 0)]>, + T1DataProcessing<0b1000>; // zero-extend byte def tUXTB : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "uxtb", "\t$dst, $src", [(set tGPR:$dst, (and tGPR:$src, 0xFF))]>, - Requires<[IsThumb1Only, HasV6]>; + Requires<[IsThumb1Only, HasV6]>, + T1Misc<{0,0,1,0,1,1,?}>; // zero-extend short def tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, "uxth", "\t$dst, $src", [(set tGPR:$dst, (and tGPR:$src, 0xFFFF))]>, - Requires<[IsThumb1Only, HasV6]>; + Requires<[IsThumb1Only, HasV6]>, + T1Misc<{0,0,1,0,1,0,?}>; // Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation. @@ -643,19 +743,23 @@ // 16-bit movcc in IT blocks for Thumb2. def tMOVCCr : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iCMOVr, - "mov", "\t$dst, $rhs", []>; + "mov", "\t$dst, $rhs", []>, + T1Special<{1,0,?,?}>; def tMOVCCi : T1pIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iCMOVi, - "mov", "\t$dst, $rhs", []>; + "mov", "\t$dst, $rhs", []>, + T1General<{1,0,0,?,?}>; // tLEApcrel - Load a pc-relative address into a register without offending the // assembler. def tLEApcrel : T1I<(outs tGPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi, - "adr$p\t$dst, #$label", []>; + "adr$p\t$dst, #$label", []>, + T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 def tLEApcrelJT : T1I<(outs tGPR:$dst), (ins i32imm:$label, nohash_imm:$id, pred:$p), - IIC_iALUi, "adr$p\t$dst, #${label}_${id}", []>; + IIC_iALUi, "adr$p\t$dst, #${label}_${id}", []>, + T1Encoding<{1,0,1,0,0,?}>; // A6.2 & A8.6.10 //===----------------------------------------------------------------------===// // TLS Instructions @@ -664,9 +768,9 @@ // __aeabi_read_tp preserves the registers r1-r3. let isCall = 1, Defs = [R0, LR] in { - def tTPsoft : TIx2<(outs), (ins), IIC_Br, - "bl\t__aeabi_read_tp", - [(set R0, ARMthread_pointer)]>; + def tTPsoft : TIx2<0b11110, 0b11, 1, (outs), (ins), IIC_Br, + "bl\t__aeabi_read_tp", + [(set R0, ARMthread_pointer)]>; } // SJLJ Exception handling intrinsics Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=91434&r1=91433&r2=91434&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Tue Dec 15 11:24:14 2009 @@ -165,234 +165,465 @@ /// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a /// unary operation that produces a value. These are predicable and can be /// changed to modify CPSR. -multiclass T2I_un_irs{ +multiclass T2I_un_irs opcod, string opc, PatFrag opnode, + bit Cheap = 0, bit ReMat = 0> { // shifted imm def i : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), IIC_iMOVi, opc, "\t$dst, $src", [(set GPR:$dst, (opnode t2_so_imm:$src))]> { let isAsCheapAsAMove = Cheap; let isReMaterializable = ReMat; + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = opcod; + let Inst{20} = ?; // The S bit. + let Inst{19-16} = 0b1111; // Rn + let Inst{15} = 0; } // register def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, opc, ".w\t$dst, $src", - [(set GPR:$dst, (opnode GPR:$src))]>; + [(set GPR:$dst, (opnode GPR:$src))]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = ?; // The S bit. + let Inst{19-16} = 0b1111; // Rn + let Inst{14-12} = 0b000; // imm3 + let Inst{7-6} = 0b00; // imm2 + let Inst{5-4} = 0b00; // type + } // shifted register def s : T2I<(outs GPR:$dst), (ins t2_so_reg:$src), IIC_iMOVsi, opc, ".w\t$dst, $src", - [(set GPR:$dst, (opnode t2_so_reg:$src))]>; + [(set GPR:$dst, (opnode t2_so_reg:$src))]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = ?; // The S bit. + let Inst{19-16} = 0b1111; // Rn + } } /// T2I_bin_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a // binary operation that produces a value. These are predicable and can be /// changed to modify CPSR. -multiclass T2I_bin_irs opcod, string opc, PatFrag opnode, bit Commutable = 0, string wide =""> { // shifted imm def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, opc, "\t$dst, $lhs, $rhs", - [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>; + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = opcod; + let Inst{20} = ?; // The S bit. + let Inst{15} = 0; + } // register def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, opc, !strconcat(wide, "\t$dst, $lhs, $rhs"), [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> { let isCommutable = Commutable; + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = ?; // The S bit. + let Inst{14-12} = 0b000; // imm3 + let Inst{7-6} = 0b00; // imm2 + let Inst{5-4} = 0b00; // type } // shifted register def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, opc, !strconcat(wide, "\t$dst, $lhs, $rhs"), - [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>; + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = ?; // The S bit. + } } /// T2I_bin_w_irs - Same as T2I_bin_irs except these operations need // the ".w" prefix to indicate that they are wide. -multiclass T2I_bin_w_irs : - T2I_bin_irs; +multiclass T2I_bin_w_irs opcod, string opc, PatFrag opnode, + bit Commutable = 0> : + T2I_bin_irs; /// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are /// reversed. It doesn't define the 'rr' form since it's handled by its /// T2I_bin_irs counterpart. -multiclass T2I_rbin_is { +multiclass T2I_rbin_is opcod, string opc, PatFrag opnode> { // shifted imm def ri : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs), IIC_iALUi, opc, ".w\t$dst, $rhs, $lhs", - [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>; + [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = opcod; + let Inst{20} = 0; // The S bit. + let Inst{15} = 0; + } // shifted register def rs : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs), IIC_iALUsi, opc, "\t$dst, $rhs, $lhs", - [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>; + [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = 0; // The S bit. + } } /// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the /// instruction modifies the CPSR register. let Defs = [CPSR] in { -multiclass T2I_bin_s_irs { +multiclass T2I_bin_s_irs opcod, string opc, PatFrag opnode, + bit Commutable = 0> { // shifted imm def ri : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs", - [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>; + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = opcod; + let Inst{20} = 1; // The S bit. + let Inst{15} = 0; + } // register def rr : T2I<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs", [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> { let isCommutable = Commutable; + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = 1; // The S bit. + let Inst{14-12} = 0b000; // imm3 + let Inst{7-6} = 0b00; // imm2 + let Inst{5-4} = 0b00; // type } // shifted register def rs : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, !strconcat(opc, "s"), ".w\t$dst, $lhs, $rhs", - [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>; + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = 1; // The S bit. + } } } /// T2I_bin_ii12rs - Defines a set of (op reg, {so_imm|imm0_4095|r|so_reg}) /// patterns for a binary operation that produces a value. -multiclass T2I_bin_ii12rs { +multiclass T2I_bin_ii12rs op23_21, string opc, PatFrag opnode, + bit Commutable = 0> { // shifted imm def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, opc, ".w\t$dst, $lhs, $rhs", - [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>; + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24} = 1; + let Inst{23-21} = op23_21; + let Inst{20} = 0; // The S bit. + let Inst{15} = 0; + } // 12-bit imm def ri12 : T2sI<(outs GPR:$dst), (ins GPR:$lhs, imm0_4095:$rhs), IIC_iALUi, !strconcat(opc, "w"), "\t$dst, $lhs, $rhs", - [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]>; + [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 1; + let Inst{24} = 0; + let Inst{23-21} = op23_21; + let Inst{20} = 0; // The S bit. + let Inst{15} = 0; + } // register def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, opc, ".w\t$dst, $lhs, $rhs", [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> { let isCommutable = Commutable; + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24} = 1; + let Inst{23-21} = op23_21; + let Inst{20} = 0; // The S bit. + let Inst{14-12} = 0b000; // imm3 + let Inst{7-6} = 0b00; // imm2 + let Inst{5-4} = 0b00; // type } // shifted register def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, opc, ".w\t$dst, $lhs, $rhs", - [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>; + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]> { + let Inst{31-27} = 0b11101; + let Inst{24} = 1; + let Inst{26-25} = 0b01; + let Inst{23-21} = op23_21; + let Inst{20} = 0; // The S bit. + } } /// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns /// for a binary operation that produces a value and use and define the carry /// bit. It's not predicable. let Uses = [CPSR] in { -multiclass T2I_adde_sube_irs { +multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, bit Commutable = 0> { // shifted imm def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, opc, "\t$dst, $lhs, $rhs", [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>, - Requires<[IsThumb2, CarryDefIsUnused]>; + Requires<[IsThumb2, CarryDefIsUnused]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = opcod; + let Inst{20} = 0; // The S bit. + let Inst{15} = 0; + } // register def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, opc, ".w\t$dst, $lhs, $rhs", [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, Requires<[IsThumb2, CarryDefIsUnused]> { let isCommutable = Commutable; + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = 0; // The S bit. + let Inst{14-12} = 0b000; // imm3 + let Inst{7-6} = 0b00; // imm2 + let Inst{5-4} = 0b00; // type } // shifted register def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, opc, ".w\t$dst, $lhs, $rhs", [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, - Requires<[IsThumb2, CarryDefIsUnused]>; + Requires<[IsThumb2, CarryDefIsUnused]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = 0; // The S bit. + } // Carry setting variants // shifted imm def Sri : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, !strconcat(opc, "s\t$dst, $lhs, $rhs"), [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>, Requires<[IsThumb2, CarryDefIsUsed]> { - let Defs = [CPSR]; - } + let Defs = [CPSR]; + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = opcod; + let Inst{20} = 1; // The S bit. + let Inst{15} = 0; + } // register def Srr : T2XI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, !strconcat(opc, "s.w\t$dst, $lhs, $rhs"), [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, Requires<[IsThumb2, CarryDefIsUsed]> { - let Defs = [CPSR]; - let isCommutable = Commutable; + let Defs = [CPSR]; + let isCommutable = Commutable; + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = 1; // The S bit. + let Inst{14-12} = 0b000; // imm3 + let Inst{7-6} = 0b00; // imm2 + let Inst{5-4} = 0b00; // type } // shifted register def Srs : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, !strconcat(opc, "s.w\t$dst, $lhs, $rhs"), [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, Requires<[IsThumb2, CarryDefIsUsed]> { - let Defs = [CPSR]; + let Defs = [CPSR]; + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = 1; // The S bit. } } } /// T2I_rbin_s_is - Same as T2I_rbin_is except sets 's' bit. let Defs = [CPSR] in { -multiclass T2I_rbin_s_is { +multiclass T2I_rbin_s_is opcod, string opc, PatFrag opnode> { // shifted imm def ri : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs, cc_out:$s), IIC_iALUi, !strconcat(opc, "${s}.w\t$dst, $rhs, $lhs"), - [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>; + [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = opcod; + let Inst{20} = 1; // The S bit. + let Inst{15} = 0; + } // shifted register def rs : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs, cc_out:$s), IIC_iALUsi, !strconcat(opc, "${s}\t$dst, $rhs, $lhs"), - [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>; + [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = 1; // The S bit. + } } } /// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift / // rotate operation that produces a value. -multiclass T2I_sh_ir { +multiclass T2I_sh_ir opcod, string opc, PatFrag opnode> { // 5-bit imm def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), IIC_iMOVsi, opc, ".w\t$dst, $lhs, $rhs", - [(set GPR:$dst, (opnode GPR:$lhs, imm1_31:$rhs))]>; + [(set GPR:$dst, (opnode GPR:$lhs, imm1_31:$rhs))]> { + let Inst{31-27} = 0b11101; + let Inst{26-21} = 0b010010; + let Inst{19-16} = 0b1111; // Rn + let Inst{5-4} = opcod; + } // register def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iMOVsr, opc, ".w\t$dst, $lhs, $rhs", - [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>; + [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0100; + let Inst{22-21} = opcod; + let Inst{15-12} = 0b1111; + let Inst{7-4} = 0b0000; + } } -/// T2I_cmp_is - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test +/// T2I_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test /// patterns. Similar to T2I_bin_irs except the instruction does not produce /// a explicit result, only implicitly set CPSR. let Defs = [CPSR] in { -multiclass T2I_cmp_is { +multiclass T2I_cmp_irs opcod, string opc, PatFrag opnode> { // shifted imm def ri : T2I<(outs), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iCMPi, opc, ".w\t$lhs, $rhs", - [(opnode GPR:$lhs, t2_so_imm:$rhs)]>; + [(opnode GPR:$lhs, t2_so_imm:$rhs)]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = opcod; + let Inst{20} = 1; // The S bit. + let Inst{15} = 0; + let Inst{11-8} = 0b1111; // Rd + } // register def rr : T2I<(outs), (ins GPR:$lhs, GPR:$rhs), IIC_iCMPr, opc, ".w\t$lhs, $rhs", - [(opnode GPR:$lhs, GPR:$rhs)]>; + [(opnode GPR:$lhs, GPR:$rhs)]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = 1; // The S bit. + let Inst{14-12} = 0b000; // imm3 + let Inst{11-8} = 0b1111; // Rd + let Inst{7-6} = 0b00; // imm2 + let Inst{5-4} = 0b00; // type + } // shifted register def rs : T2I<(outs), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iCMPsi, opc, ".w\t$lhs, $rhs", - [(opnode GPR:$lhs, t2_so_reg:$rhs)]>; + [(opnode GPR:$lhs, t2_so_reg:$rhs)]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = opcod; + let Inst{20} = 1; // The S bit. + let Inst{11-8} = 0b1111; // Rd + } } } /// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns. -multiclass T2I_ld { +multiclass T2I_ld opcod, string opc, PatFrag opnode> { def i12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr), IIC_iLoadi, opc, ".w\t$dst, $addr", - [(set GPR:$dst, (opnode t2addrmode_imm12:$addr))]>; + [(set GPR:$dst, (opnode t2addrmode_imm12:$addr))]> { + let Inst{31-27} = 0b11111; + let Inst{26-25} = 0b00; + let Inst{24} = signed; + let Inst{23} = 1; + let Inst{22-21} = opcod; + let Inst{20} = 1; // load + } def i8 : T2Ii8 <(outs GPR:$dst), (ins t2addrmode_imm8:$addr), IIC_iLoadi, opc, "\t$dst, $addr", - [(set GPR:$dst, (opnode t2addrmode_imm8:$addr))]>; + [(set GPR:$dst, (opnode t2addrmode_imm8:$addr))]> { + let Inst{31-27} = 0b11111; + let Inst{26-25} = 0b00; + let Inst{24} = signed; + let Inst{23} = 0; + let Inst{22-21} = opcod; + let Inst{20} = 1; // load + let Inst{11} = 1; + // Offset: index==TRUE, wback==FALSE + let Inst{10} = 1; // The P bit. + let Inst{8} = 0; // The W bit. + } def s : T2Iso <(outs GPR:$dst), (ins t2addrmode_so_reg:$addr), IIC_iLoadr, opc, ".w\t$dst, $addr", - [(set GPR:$dst, (opnode t2addrmode_so_reg:$addr))]>; + [(set GPR:$dst, (opnode t2addrmode_so_reg:$addr))]> { + let Inst{31-27} = 0b11111; + let Inst{26-25} = 0b00; + let Inst{24} = signed; + let Inst{23} = 0; + let Inst{22-21} = opcod; + let Inst{20} = 1; // load + let Inst{11-6} = 0b000000; + } def pci : T2Ipc <(outs GPR:$dst), (ins i32imm:$addr), IIC_iLoadi, opc, ".w\t$dst, $addr", [(set GPR:$dst, (opnode (ARMWrapper tconstpool:$addr)))]> { let isReMaterializable = 1; + let Inst{31-27} = 0b11111; + let Inst{26-25} = 0b00; + let Inst{24} = signed; + let Inst{23} = ?; // add = (U == '1') + let Inst{22-21} = opcod; + let Inst{20} = 1; // load + let Inst{19-16} = 0b1111; // Rn } } /// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns. -multiclass T2I_st { +multiclass T2I_st opcod, string opc, PatFrag opnode> { def i12 : T2Ii12<(outs), (ins GPR:$src, t2addrmode_imm12:$addr), IIC_iStorei, opc, ".w\t$src, $addr", - [(opnode GPR:$src, t2addrmode_imm12:$addr)]>; + [(opnode GPR:$src, t2addrmode_imm12:$addr)]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0001; + let Inst{22-21} = opcod; + let Inst{20} = 0; // !load + } def i8 : T2Ii8 <(outs), (ins GPR:$src, t2addrmode_imm8:$addr), IIC_iStorei, opc, "\t$src, $addr", - [(opnode GPR:$src, t2addrmode_imm8:$addr)]>; + [(opnode GPR:$src, t2addrmode_imm8:$addr)]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0000; + let Inst{22-21} = opcod; + let Inst{20} = 0; // !load + let Inst{11} = 1; + // Offset: index==TRUE, wback==FALSE + let Inst{10} = 1; // The P bit. + let Inst{8} = 0; // The W bit. + } def s : T2Iso <(outs), (ins GPR:$src, t2addrmode_so_reg:$addr), IIC_iStorer, opc, ".w\t$src, $addr", - [(opnode GPR:$src, t2addrmode_so_reg:$addr)]>; + [(opnode GPR:$src, t2addrmode_so_reg:$addr)]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0000; + let Inst{22-21} = opcod; + let Inst{20} = 0; // !load + let Inst{11-6} = 0b000000; + } } /// T2I_picld - Defines the PIC load pattern. @@ -410,25 +641,55 @@ /// T2I_unary_rrot - A unary operation with two forms: one whose operand is a /// register and one whose operand is a register rotated by 8/16/24. -multiclass T2I_unary_rrot { +multiclass T2I_unary_rrot opcod, string opc, PatFrag opnode> { def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, opc, ".w\t$dst, $src", - [(set GPR:$dst, (opnode GPR:$src))]>; + [(set GPR:$dst, (opnode GPR:$src))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0100; + let Inst{22-20} = opcod; + let Inst{19-16} = 0b1111; // Rn + let Inst{15-12} = 0b1111; + let Inst{7} = 1; + let Inst{5-4} = 0b00; // rotate + } def r_rot : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$rot), IIC_iUNAsi, opc, ".w\t$dst, $src, ror $rot", - [(set GPR:$dst, (opnode (rotr GPR:$src, rot_imm:$rot)))]>; + [(set GPR:$dst, (opnode (rotr GPR:$src, rot_imm:$rot)))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0100; + let Inst{22-20} = opcod; + let Inst{19-16} = 0b1111; // Rn + let Inst{15-12} = 0b1111; + let Inst{7} = 1; + let Inst{5-4} = {?,?}; // rotate + } } /// T2I_bin_rrot - A binary operation with two forms: one whose operand is a /// register and one whose operand is a register rotated by 8/16/24. -multiclass T2I_bin_rrot { +multiclass T2I_bin_rrot opcod, string opc, PatFrag opnode> { def rr : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS), IIC_iALUr, opc, "\t$dst, $LHS, $RHS", - [(set GPR:$dst, (opnode GPR:$LHS, GPR:$RHS))]>; + [(set GPR:$dst, (opnode GPR:$LHS, GPR:$RHS))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0100; + let Inst{22-20} = opcod; + let Inst{15-12} = 0b1111; + let Inst{7} = 1; + let Inst{5-4} = 0b00; // rotate + } def rr_rot : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS, i32imm:$rot), IIC_iALUsr, opc, "\t$dst, $LHS, $RHS, ror $rot", [(set GPR:$dst, (opnode GPR:$LHS, - (rotr GPR:$RHS, rot_imm:$rot)))]>; + (rotr GPR:$RHS, rot_imm:$rot)))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0100; + let Inst{22-20} = opcod; + let Inst{15-12} = 0b1111; + let Inst{7} = 1; + let Inst{5-4} = {?,?}; // rotate + } } //===----------------------------------------------------------------------===// @@ -442,33 +703,89 @@ // LEApcrel - Load a pc-relative address into a register without offending the // assembler. def t2LEApcrel : T2XI<(outs GPR:$dst), (ins i32imm:$label, pred:$p), IIC_iALUi, - "adr$p.w\t$dst, #$label", []>; - + "adr$p.w\t$dst, #$label", []> { + let Inst{31-27} = 0b11110; + let Inst{25-24} = 0b10; + // Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE) + let Inst{22} = 0; + let Inst{20} = 0; + let Inst{19-16} = 0b1111; // Rn + let Inst{15} = 0; +} def t2LEApcrelJT : T2XI<(outs GPR:$dst), (ins i32imm:$label, nohash_imm:$id, pred:$p), IIC_iALUi, - "adr$p.w\t$dst, #${label}_${id}", []>; + "adr$p.w\t$dst, #${label}_${id}", []> { + let Inst{31-27} = 0b11110; + let Inst{25-24} = 0b10; + // Inst{23:21} = '11' (add = FALSE) or '00' (add = TRUE) + let Inst{22} = 0; + let Inst{20} = 0; + let Inst{19-16} = 0b1111; // Rn + let Inst{15} = 0; +} // ADD r, sp, {so_imm|i12} def t2ADDrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm), - IIC_iALUi, "add", ".w\t$dst, $sp, $imm", []>; + IIC_iALUi, "add", ".w\t$dst, $sp, $imm", []> { + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = 0b1000; + let Inst{20} = ?; // The S bit. + let Inst{19-16} = 0b1101; // Rn = sp + let Inst{15} = 0; +} def t2ADDrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm), - IIC_iALUi, "addw", "\t$dst, $sp, $imm", []>; + IIC_iALUi, "addw", "\t$dst, $sp, $imm", []> { + let Inst{31-27} = 0b11110; + let Inst{25} = 1; + let Inst{24-21} = 0b0000; + let Inst{20} = 0; // The S bit. + let Inst{19-16} = 0b1101; // Rn = sp + let Inst{15} = 0; +} // ADD r, sp, so_reg def t2ADDrSPs : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs), - IIC_iALUsi, "add", ".w\t$dst, $sp, $rhs", []>; + IIC_iALUsi, "add", ".w\t$dst, $sp, $rhs", []> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = 0b1000; + let Inst{20} = ?; // The S bit. + let Inst{19-16} = 0b1101; // Rn = sp + let Inst{15} = 0; +} // SUB r, sp, {so_imm|i12} def t2SUBrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm), - IIC_iALUi, "sub", ".w\t$dst, $sp, $imm", []>; + IIC_iALUi, "sub", ".w\t$dst, $sp, $imm", []> { + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = 0b1101; + let Inst{20} = ?; // The S bit. + let Inst{19-16} = 0b1101; // Rn = sp + let Inst{15} = 0; +} def t2SUBrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm), - IIC_iALUi, "subw", "\t$dst, $sp, $imm", []>; + IIC_iALUi, "subw", "\t$dst, $sp, $imm", []> { + let Inst{31-27} = 0b11110; + let Inst{25} = 1; + let Inst{24-21} = 0b0101; + let Inst{20} = 0; // The S bit. + let Inst{19-16} = 0b1101; // Rn = sp + let Inst{15} = 0; +} // SUB r, sp, so_reg def t2SUBrSPs : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs), IIC_iALUsi, - "sub", "\t$dst, $sp, $rhs", []>; - + "sub", "\t$dst, $sp, $rhs", []> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = 0b1101; + let Inst{20} = ?; // The S bit. + let Inst{19-16} = 0b1101; // Rn = sp + let Inst{15} = 0; +} // Pseudo instruction that will expand into a t2SUBrSPi + a copy. let usesCustomInserter = 1 in { // Expanded after instruction selection. @@ -487,24 +804,26 @@ // Load let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in -defm t2LDR : T2I_ld<"ldr", UnOpFrag<(load node:$Src)>>; +defm t2LDR : T2I_ld<0, 0b10, "ldr", UnOpFrag<(load node:$Src)>>; // Loads with zero extension -defm t2LDRH : T2I_ld<"ldrh", UnOpFrag<(zextloadi16 node:$Src)>>; -defm t2LDRB : T2I_ld<"ldrb", UnOpFrag<(zextloadi8 node:$Src)>>; +defm t2LDRH : T2I_ld<0, 0b01, "ldrh", UnOpFrag<(zextloadi16 node:$Src)>>; +defm t2LDRB : T2I_ld<0, 0b00, "ldrb", UnOpFrag<(zextloadi8 node:$Src)>>; // Loads with sign extension -defm t2LDRSH : T2I_ld<"ldrsh", UnOpFrag<(sextloadi16 node:$Src)>>; -defm t2LDRSB : T2I_ld<"ldrsb", UnOpFrag<(sextloadi8 node:$Src)>>; +defm t2LDRSH : T2I_ld<1, 0b01, "ldrsh", UnOpFrag<(sextloadi16 node:$Src)>>; +defm t2LDRSB : T2I_ld<1, 0b00, "ldrsb", UnOpFrag<(sextloadi8 node:$Src)>>; let mayLoad = 1, hasExtraDefRegAllocReq = 1 in { // Load doubleword -def t2LDRDi8 : T2Ii8s4<(outs GPR:$dst1, GPR:$dst2), +def t2LDRDi8 : T2Ii8s4<1, 0, 1, (outs GPR:$dst1, GPR:$dst2), (ins t2addrmode_imm8s4:$addr), IIC_iLoadi, "ldrd", "\t$dst1, $addr", []>; -def t2LDRDpci : T2Ii8s4<(outs GPR:$dst1, GPR:$dst2), +def t2LDRDpci : T2Ii8s4; + "ldrd", "\t$dst1, $addr", []> { + let Inst{19-16} = 0b1111; // Rn +} } // zextload i1 -> zextload i8 @@ -549,57 +868,57 @@ // Indexed loads let mayLoad = 1 in { -def t2LDR_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), +def t2LDR_PRE : T2Iidxldst<0, 0b10, 1, 1, (outs GPR:$dst, GPR:$base_wb), (ins t2addrmode_imm8:$addr), AddrModeT2_i8, IndexModePre, IIC_iLoadiu, "ldr", "\t$dst, $addr!", "$addr.base = $base_wb", []>; -def t2LDR_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), +def t2LDR_POST : T2Iidxldst<0, 0b10, 1, 0, (outs GPR:$dst, GPR:$base_wb), (ins GPR:$base, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePost, IIC_iLoadiu, "ldr", "\t$dst, [$base], $offset", "$base = $base_wb", []>; -def t2LDRB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), +def t2LDRB_PRE : T2Iidxldst<0, 0b00, 1, 1, (outs GPR:$dst, GPR:$base_wb), (ins t2addrmode_imm8:$addr), AddrModeT2_i8, IndexModePre, IIC_iLoadiu, "ldrb", "\t$dst, $addr!", "$addr.base = $base_wb", []>; -def t2LDRB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), +def t2LDRB_POST : T2Iidxldst<0, 0b00, 1, 0, (outs GPR:$dst, GPR:$base_wb), (ins GPR:$base, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePost, IIC_iLoadiu, "ldrb", "\t$dst, [$base], $offset", "$base = $base_wb", []>; -def t2LDRH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), +def t2LDRH_PRE : T2Iidxldst<0, 0b01, 1, 1, (outs GPR:$dst, GPR:$base_wb), (ins t2addrmode_imm8:$addr), AddrModeT2_i8, IndexModePre, IIC_iLoadiu, "ldrh", "\t$dst, $addr!", "$addr.base = $base_wb", []>; -def t2LDRH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), +def t2LDRH_POST : T2Iidxldst<0, 0b01, 1, 0, (outs GPR:$dst, GPR:$base_wb), (ins GPR:$base, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePost, IIC_iLoadiu, "ldrh", "\t$dst, [$base], $offset", "$base = $base_wb", []>; -def t2LDRSB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), +def t2LDRSB_PRE : T2Iidxldst<1, 0b00, 1, 1, (outs GPR:$dst, GPR:$base_wb), (ins t2addrmode_imm8:$addr), AddrModeT2_i8, IndexModePre, IIC_iLoadiu, "ldrsb", "\t$dst, $addr!", "$addr.base = $base_wb", []>; -def t2LDRSB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), +def t2LDRSB_POST : T2Iidxldst<1, 0b00, 1, 0, (outs GPR:$dst, GPR:$base_wb), (ins GPR:$base, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePost, IIC_iLoadiu, "ldrsb", "\t$dst, [$base], $offset", "$base = $base_wb", []>; -def t2LDRSH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), +def t2LDRSH_PRE : T2Iidxldst<1, 0b01, 1, 1, (outs GPR:$dst, GPR:$base_wb), (ins t2addrmode_imm8:$addr), AddrModeT2_i8, IndexModePre, IIC_iLoadiu, "ldrsh", "\t$dst, $addr!", "$addr.base = $base_wb", []>; -def t2LDRSH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), +def t2LDRSH_POST : T2Iidxldst<1, 0b01, 1, 0, (outs GPR:$dst, GPR:$base_wb), (ins GPR:$base, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePost, IIC_iLoadiu, "ldrsh", "\t$dst, [$base], $offset", "$base = $base_wb", @@ -607,53 +926,53 @@ } // Store -defm t2STR : T2I_st<"str", BinOpFrag<(store node:$LHS, node:$RHS)>>; -defm t2STRB : T2I_st<"strb", BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>; -defm t2STRH : T2I_st<"strh", BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; +defm t2STR : T2I_st<0b10, "str", BinOpFrag<(store node:$LHS, node:$RHS)>>; +defm t2STRB : T2I_st<0b00, "strb", BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>; +defm t2STRH : T2I_st<0b01, "strh", BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; // Store doubleword let mayLoad = 1, hasExtraSrcRegAllocReq = 1 in -def t2STRDi8 : T2Ii8s4<(outs), +def t2STRDi8 : T2Ii8s4<1, 0, 0, (outs), (ins GPR:$src1, GPR:$src2, t2addrmode_imm8s4:$addr), IIC_iStorer, "strd", "\t$src1, $addr", []>; // Indexed stores -def t2STR_PRE : T2Iidxldst<(outs GPR:$base_wb), +def t2STR_PRE : T2Iidxldst<0, 0b10, 0, 1, (outs GPR:$base_wb), (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePre, IIC_iStoreiu, "str", "\t$src, [$base, $offset]!", "$base = $base_wb", [(set GPR:$base_wb, (pre_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; -def t2STR_POST : T2Iidxldst<(outs GPR:$base_wb), +def t2STR_POST : T2Iidxldst<0, 0b10, 0, 0, (outs GPR:$base_wb), (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePost, IIC_iStoreiu, "str", "\t$src, [$base], $offset", "$base = $base_wb", [(set GPR:$base_wb, (post_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; -def t2STRH_PRE : T2Iidxldst<(outs GPR:$base_wb), +def t2STRH_PRE : T2Iidxldst<0, 0b01, 0, 1, (outs GPR:$base_wb), (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePre, IIC_iStoreiu, "strh", "\t$src, [$base, $offset]!", "$base = $base_wb", [(set GPR:$base_wb, (pre_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; -def t2STRH_POST : T2Iidxldst<(outs GPR:$base_wb), +def t2STRH_POST : T2Iidxldst<0, 0b01, 0, 0, (outs GPR:$base_wb), (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePost, IIC_iStoreiu, "strh", "\t$src, [$base], $offset", "$base = $base_wb", [(set GPR:$base_wb, (post_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; -def t2STRB_PRE : T2Iidxldst<(outs GPR:$base_wb), +def t2STRB_PRE : T2Iidxldst<0, 0b00, 0, 1, (outs GPR:$base_wb), (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePre, IIC_iStoreiu, "strb", "\t$src, [$base, $offset]!", "$base = $base_wb", [(set GPR:$base_wb, (pre_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; -def t2STRB_POST : T2Iidxldst<(outs GPR:$base_wb), +def t2STRB_POST : T2Iidxldst<0, 0b00, 0, 0, (outs GPR:$base_wb), (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), AddrModeT2_i8, IndexModePost, IIC_iStoreiu, "strb", "\t$src, [$base], $offset", "$base = $base_wb", @@ -670,12 +989,26 @@ let mayLoad = 1, hasExtraDefRegAllocReq = 1 in def t2LDM : T2XI<(outs), (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), - IIC_iLoadm, "ldm${addr:submode}${p}${addr:wide}\t$addr, $wb", []>; + IIC_iLoadm, "ldm${addr:submode}${p}${addr:wide}\t$addr, $wb", []> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b00; + let Inst{24-23} = {?, ?}; // IA: '01', DB: '10' + let Inst{22} = 0; + let Inst{21} = ?; // The W bit. + let Inst{20} = 1; // Load +} let mayStore = 1, hasExtraSrcRegAllocReq = 1 in def t2STM : T2XI<(outs), (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), - IIC_iStorem, "stm${addr:submode}${p}${addr:wide}\t$addr, $wb", []>; + IIC_iStorem, "stm${addr:submode}${p}${addr:wide}\t$addr, $wb", []> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b00; + let Inst{24-23} = {?, ?}; // IA: '01', DB: '10' + let Inst{22} = 0; + let Inst{21} = ?; // The W bit. + let Inst{20} = 0; // Store +} //===----------------------------------------------------------------------===// // Move Instructions. @@ -683,24 +1016,51 @@ let neverHasSideEffects = 1 in def t2MOVr : T2sI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, - "mov", ".w\t$dst, $src", []>; + "mov", ".w\t$dst, $src", []> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = 0b0010; + let Inst{20} = ?; // The S bit. + let Inst{19-16} = 0b1111; // Rn + let Inst{14-12} = 0b000; + let Inst{7-4} = 0b0000; +} // AddedComplexity to ensure isel tries t2MOVi before t2MOVi16. let isReMaterializable = 1, isAsCheapAsAMove = 1, AddedComplexity = 1 in def t2MOVi : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), IIC_iMOVi, "mov", ".w\t$dst, $src", - [(set GPR:$dst, t2_so_imm:$src)]>; + [(set GPR:$dst, t2_so_imm:$src)]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = 0b0010; + let Inst{20} = ?; // The S bit. + let Inst{19-16} = 0b1111; // Rn + let Inst{15} = 0; +} let isReMaterializable = 1, isAsCheapAsAMove = 1 in def t2MOVi16 : T2I<(outs GPR:$dst), (ins i32imm:$src), IIC_iMOVi, "movw", "\t$dst, $src", - [(set GPR:$dst, imm0_65535:$src)]>; + [(set GPR:$dst, imm0_65535:$src)]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 1; + let Inst{24-21} = 0b0010; + let Inst{20} = 0; // The S bit. + let Inst{15} = 0; +} let Constraints = "$src = $dst" in def t2MOVTi16 : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm), IIC_iMOVi, "movt", "\t$dst, $imm", [(set GPR:$dst, - (or (and GPR:$src, 0xffff), lo16AllZero:$imm))]>; + (or (and GPR:$src, 0xffff), lo16AllZero:$imm))]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 1; + let Inst{24-21} = 0b0110; + let Inst{20} = 0; // The S bit. + let Inst{15} = 0; +} def : T2Pat<(or GPR:$src, 0xffff0000), (t2MOVTi16 GPR:$src, 0xffff)>; @@ -710,12 +1070,14 @@ // Sign extenders -defm t2SXTB : T2I_unary_rrot<"sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>; -defm t2SXTH : T2I_unary_rrot<"sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>; +defm t2SXTB : T2I_unary_rrot<0b100, "sxtb", + UnOpFrag<(sext_inreg node:$Src, i8)>>; +defm t2SXTH : T2I_unary_rrot<0b000, "sxth", + UnOpFrag<(sext_inreg node:$Src, i16)>>; -defm t2SXTAB : T2I_bin_rrot<"sxtab", +defm t2SXTAB : T2I_bin_rrot<0b100, "sxtab", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>; -defm t2SXTAH : T2I_bin_rrot<"sxtah", +defm t2SXTAH : T2I_bin_rrot<0b000, "sxtah", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>; // TODO: SXT(A){B|H}16 @@ -723,18 +1085,21 @@ // Zero extenders let AddedComplexity = 16 in { -defm t2UXTB : T2I_unary_rrot<"uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>; -defm t2UXTH : T2I_unary_rrot<"uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>; -defm t2UXTB16 : T2I_unary_rrot<"uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>; +defm t2UXTB : T2I_unary_rrot<0b101, "uxtb", + UnOpFrag<(and node:$Src, 0x000000FF)>>; +defm t2UXTH : T2I_unary_rrot<0b001, "uxth", + UnOpFrag<(and node:$Src, 0x0000FFFF)>>; +defm t2UXTB16 : T2I_unary_rrot<0b011, "uxtb16", + UnOpFrag<(and node:$Src, 0x00FF00FF)>>; def : T2Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF), (t2UXTB16r_rot GPR:$Src, 24)>; def : T2Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF), (t2UXTB16r_rot GPR:$Src, 8)>; -defm t2UXTAB : T2I_bin_rrot<"uxtab", +defm t2UXTAB : T2I_bin_rrot<0b101, "uxtab", BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>; -defm t2UXTAH : T2I_bin_rrot<"uxtah", +defm t2UXTAH : T2I_bin_rrot<0b001, "uxtah", BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>; } @@ -742,19 +1107,27 @@ // Arithmetic Instructions. // -defm t2ADD : T2I_bin_ii12rs<"add", BinOpFrag<(add node:$LHS, node:$RHS)>, 1>; -defm t2SUB : T2I_bin_ii12rs<"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>; +defm t2ADD : T2I_bin_ii12rs<0b000, "add", + BinOpFrag<(add node:$LHS, node:$RHS)>, 1>; +defm t2SUB : T2I_bin_ii12rs<0b101, "sub", + BinOpFrag<(sub node:$LHS, node:$RHS)>>; // ADD and SUB with 's' bit set. No 12-bit immediate (T4) variants. -defm t2ADDS : T2I_bin_s_irs <"add", BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>; -defm t2SUBS : T2I_bin_s_irs <"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>; - -defm t2ADC : T2I_adde_sube_irs<"adc",BinOpFrag<(adde node:$LHS, node:$RHS)>,1>; -defm t2SBC : T2I_adde_sube_irs<"sbc",BinOpFrag<(sube node:$LHS, node:$RHS)>>; +defm t2ADDS : T2I_bin_s_irs <0b1000, "add", + BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>; +defm t2SUBS : T2I_bin_s_irs <0b1101, "sub", + BinOpFrag<(subc node:$LHS, node:$RHS)>>; + +defm t2ADC : T2I_adde_sube_irs<0b1010, "adc", + BinOpFrag<(adde node:$LHS, node:$RHS)>, 1>; +defm t2SBC : T2I_adde_sube_irs<0b1011, "sbc", + BinOpFrag<(sube node:$LHS, node:$RHS)>>; // RSB -defm t2RSB : T2I_rbin_is <"rsb", BinOpFrag<(sub node:$LHS, node:$RHS)>>; -defm t2RSBS : T2I_rbin_s_is <"rsb", BinOpFrag<(subc node:$LHS, node:$RHS)>>; +defm t2RSB : T2I_rbin_is <0b1110, "rsb", + BinOpFrag<(sub node:$LHS, node:$RHS)>>; +defm t2RSBS : T2I_rbin_s_is <0b1110, "rsb", + BinOpFrag<(subc node:$LHS, node:$RHS)>>; // (sub X, imm) gets canonicalized to (add X, -imm). Match this form. let AddedComplexity = 1 in @@ -770,54 +1143,103 @@ // Shift and rotate Instructions. // -defm t2LSL : T2I_sh_ir<"lsl", BinOpFrag<(shl node:$LHS, node:$RHS)>>; -defm t2LSR : T2I_sh_ir<"lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>; -defm t2ASR : T2I_sh_ir<"asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>; -defm t2ROR : T2I_sh_ir<"ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>; +defm t2LSL : T2I_sh_ir<0b00, "lsl", BinOpFrag<(shl node:$LHS, node:$RHS)>>; +defm t2LSR : T2I_sh_ir<0b01, "lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>; +defm t2ASR : T2I_sh_ir<0b10, "asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>; +defm t2ROR : T2I_sh_ir<0b11, "ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>; let Uses = [CPSR] in { def t2MOVrx : T2sI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, "rrx", "\t$dst, $src", - [(set GPR:$dst, (ARMrrx GPR:$src))]>; + [(set GPR:$dst, (ARMrrx GPR:$src))]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = 0b0010; + let Inst{20} = ?; // The S bit. + let Inst{19-16} = 0b1111; // Rn + let Inst{14-12} = 0b000; + let Inst{7-4} = 0b0011; +} } let Defs = [CPSR] in { def t2MOVsrl_flag : T2XI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, "lsrs.w\t$dst, $src, #1", - [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>; + [(set GPR:$dst, (ARMsrl_flag GPR:$src))]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = 0b0010; + let Inst{20} = 1; // The S bit. + let Inst{19-16} = 0b1111; // Rn + let Inst{5-4} = 0b01; // Shift type. + // Shift amount = Inst{14-12:7-6} = 1. + let Inst{14-12} = 0b000; + let Inst{7-6} = 0b01; +} def t2MOVsra_flag : T2XI<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVsi, "asrs.w\t$dst, $src, #1", - [(set GPR:$dst, (ARMsra_flag GPR:$src))]>; + [(set GPR:$dst, (ARMsra_flag GPR:$src))]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = 0b0010; + let Inst{20} = 1; // The S bit. + let Inst{19-16} = 0b1111; // Rn + let Inst{5-4} = 0b10; // Shift type. + // Shift amount = Inst{14-12:7-6} = 1. + let Inst{14-12} = 0b000; + let Inst{7-6} = 0b01; +} } //===----------------------------------------------------------------------===// // Bitwise Instructions. // -defm t2AND : T2I_bin_w_irs<"and", BinOpFrag<(and node:$LHS, node:$RHS)>, 1>; -defm t2ORR : T2I_bin_w_irs<"orr", BinOpFrag<(or node:$LHS, node:$RHS)>, 1>; -defm t2EOR : T2I_bin_w_irs<"eor", BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>; +defm t2AND : T2I_bin_w_irs<0b0000, "and", + BinOpFrag<(and node:$LHS, node:$RHS)>, 1>; +defm t2ORR : T2I_bin_w_irs<0b0010, "orr", + BinOpFrag<(or node:$LHS, node:$RHS)>, 1>; +defm t2EOR : T2I_bin_w_irs<0b0100, "eor", + BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>; -defm t2BIC : T2I_bin_w_irs<"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>; +defm t2BIC : T2I_bin_w_irs<0b0001, "bic", + BinOpFrag<(and node:$LHS, (not node:$RHS))>>; let Constraints = "$src = $dst" in def t2BFC : T2I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm), IIC_iUNAsi, "bfc", "\t$dst, $imm", - [(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]>; + [(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]> { + let Inst{31-27} = 0b11110; + let Inst{25} = 1; + let Inst{24-20} = 0b10110; + let Inst{19-16} = 0b1111; // Rn + let Inst{15} = 0; +} def t2SBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width), - IIC_iALUi, "sbfx", "\t$dst, $src, $lsb, $width", []>; + IIC_iALUi, "sbfx", "\t$dst, $src, $lsb, $width", []> { + let Inst{31-27} = 0b11110; + let Inst{25} = 1; + let Inst{24-20} = 0b10100; + let Inst{15} = 0; +} def t2UBFX : T2I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width), - IIC_iALUi, "ubfx", "\t$dst, $src, $lsb, $width", []>; + IIC_iALUi, "ubfx", "\t$dst, $src, $lsb, $width", []> { + let Inst{31-27} = 0b11110; + let Inst{25} = 1; + let Inst{24-20} = 0b11100; + let Inst{15} = 0; +} // FIXME: A8.6.18 BFI - Bitfield insert (Encoding T1) -defm t2ORN : T2I_bin_irs<"orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>; +defm t2ORN : T2I_bin_irs<0b0011, "orn", BinOpFrag<(or node:$LHS, + (not node:$RHS))>>; // Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version let AddedComplexity = 1 in -defm t2MVN : T2I_un_irs <"mvn", UnOpFrag<(not node:$Src)>, 1, 1>; +defm t2MVN : T2I_un_irs <0b0011, "mvn", UnOpFrag<(not node:$Src)>, 1, 1>; def : T2Pat<(and GPR:$src, t2_so_imm_not:$imm), @@ -837,81 +1259,184 @@ let isCommutable = 1 in def t2MUL: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, "mul", "\t$dst, $a, $b", - [(set GPR:$dst, (mul GPR:$a, GPR:$b))]>; + [(set GPR:$dst, (mul GPR:$a, GPR:$b))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b000; + let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate) + let Inst{7-4} = 0b0000; // Multiply +} def t2MLA: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, "mla", "\t$dst, $a, $b, $c", - [(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>; + [(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b000; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-4} = 0b0000; // Multiply +} def t2MLS: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, "mls", "\t$dst, $a, $b, $c", - [(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>; + [(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b000; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-4} = 0b0001; // Multiply and Subtract +} // Extra precision multiplies with low / high results let neverHasSideEffects = 1 in { let isCommutable = 1 in { def t2SMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMUL64, - "smull", "\t$ldst, $hdst, $a, $b", []>; + "smull", "\t$ldst, $hdst, $a, $b", []> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0111; + let Inst{22-20} = 0b000; + let Inst{7-4} = 0b0000; +} def t2UMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMUL64, - "umull", "\t$ldst, $hdst, $a, $b", []>; + "umull", "\t$ldst, $hdst, $a, $b", []> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0111; + let Inst{22-20} = 0b010; + let Inst{7-4} = 0b0000; } +} // isCommutable // Multiply + accumulate def t2SMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64, - "smlal", "\t$ldst, $hdst, $a, $b", []>; + "smlal", "\t$ldst, $hdst, $a, $b", []>{ + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0111; + let Inst{22-20} = 0b100; + let Inst{7-4} = 0b0000; +} def t2UMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64, - "umlal", "\t$ldst, $hdst, $a, $b", []>; + "umlal", "\t$ldst, $hdst, $a, $b", []>{ + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0111; + let Inst{22-20} = 0b110; + let Inst{7-4} = 0b0000; +} def t2UMAAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64, - "umaal", "\t$ldst, $hdst, $a, $b", []>; + "umaal", "\t$ldst, $hdst, $a, $b", []>{ + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0111; + let Inst{22-20} = 0b110; + let Inst{7-4} = 0b0110; +} } // neverHasSideEffects // Most significant word multiply def t2SMMUL : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, "smmul", "\t$dst, $a, $b", - [(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>; + [(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b101; + let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate) + let Inst{7-4} = 0b0000; // No Rounding (Inst{4} = 0) +} def t2SMMLA : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, "smmla", "\t$dst, $a, $b, $c", - [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>; + [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b101; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-4} = 0b0000; // No Rounding (Inst{4} = 0) +} def t2SMMLS : T2I <(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, "smmls", "\t$dst, $a, $b, $c", - [(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>; + [(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b110; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-4} = 0b0000; // No Rounding (Inst{4} = 0) +} multiclass T2I_smul { def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, !strconcat(opc, "bb"), "\t$dst, $a, $b", [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16), - (sext_inreg GPR:$b, i16)))]>; + (sext_inreg GPR:$b, i16)))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b001; + let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate) + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b00; + } def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, !strconcat(opc, "bt"), "\t$dst, $a, $b", [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16), - (sra GPR:$b, (i32 16))))]>; + (sra GPR:$b, (i32 16))))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b001; + let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate) + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b01; + } def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, !strconcat(opc, "tb"), "\t$dst, $a, $b", [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)), - (sext_inreg GPR:$b, i16)))]>; + (sext_inreg GPR:$b, i16)))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b001; + let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate) + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b10; + } def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, !strconcat(opc, "tt"), "\t$dst, $a, $b", [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)), - (sra GPR:$b, (i32 16))))]>; + (sra GPR:$b, (i32 16))))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b001; + let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate) + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b11; + } def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL16, !strconcat(opc, "wb"), "\t$dst, $a, $b", [(set GPR:$dst, (sra (opnode GPR:$a, - (sext_inreg GPR:$b, i16)), (i32 16)))]>; + (sext_inreg GPR:$b, i16)), (i32 16)))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b011; + let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate) + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b00; + } def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL16, !strconcat(opc, "wt"), "\t$dst, $a, $b", [(set GPR:$dst, (sra (opnode GPR:$a, - (sra GPR:$b, (i32 16))), (i32 16)))]>; + (sra GPR:$b, (i32 16))), (i32 16)))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b011; + let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate) + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b01; + } } @@ -920,32 +1445,74 @@ !strconcat(opc, "bb"), "\t$dst, $a, $b, $acc", [(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16), - (sext_inreg GPR:$b, i16))))]>; + (sext_inreg GPR:$b, i16))))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b001; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b00; + } def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, !strconcat(opc, "bt"), "\t$dst, $a, $b, $acc", [(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16), - (sra GPR:$b, (i32 16)))))]>; + (sra GPR:$b, (i32 16)))))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b001; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b01; + } def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, !strconcat(opc, "tb"), "\t$dst, $a, $b, $acc", [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)), - (sext_inreg GPR:$b, i16))))]>; + (sext_inreg GPR:$b, i16))))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b001; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b10; + } def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, !strconcat(opc, "tt"), "\t$dst, $a, $b, $acc", [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)), - (sra GPR:$b, (i32 16)))))]>; + (sra GPR:$b, (i32 16)))))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b001; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b11; + } def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, !strconcat(opc, "wb"), "\t$dst, $a, $b, $acc", [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a, - (sext_inreg GPR:$b, i16)), (i32 16))))]>; + (sext_inreg GPR:$b, i16)), (i32 16))))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b011; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b00; + } def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, !strconcat(opc, "wt"), "\t$dst, $a, $b, $acc", [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a, - (sra GPR:$b, (i32 16))), (i32 16))))]>; + (sra GPR:$b, (i32 16))), (i32 16))))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b011; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-6} = 0b00; + let Inst{5-4} = 0b01; + } } defm t2SMUL : T2I_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>; @@ -959,24 +1526,33 @@ // Misc. Arithmetic Instructions. // -def t2CLZ : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, - "clz", "\t$dst, $src", - [(set GPR:$dst, (ctlz GPR:$src))]>; - -def t2REV : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, - "rev", ".w\t$dst, $src", - [(set GPR:$dst, (bswap GPR:$src))]>; +class T2I_misc op1, bits<2> op2, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : T2I { + let Inst{31-27} = 0b11111; + let Inst{26-22} = 0b01010; + let Inst{21-20} = op1; + let Inst{15-12} = 0b1111; + let Inst{7-6} = 0b10; + let Inst{5-4} = op2; +} + +def t2CLZ : T2I_misc<0b11, 0b00, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "clz", "\t$dst, $src", [(set GPR:$dst, (ctlz GPR:$src))]>; -def t2REV16 : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, - "rev16", ".w\t$dst, $src", +def t2REV : T2I_misc<0b01, 0b00, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "rev", ".w\t$dst, $src", [(set GPR:$dst, (bswap GPR:$src))]>; + +def t2REV16 : T2I_misc<0b01, 0b01, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "rev16", ".w\t$dst, $src", [(set GPR:$dst, (or (and (srl GPR:$src, (i32 8)), 0xFF), (or (and (shl GPR:$src, (i32 8)), 0xFF00), (or (and (srl GPR:$src, (i32 8)), 0xFF0000), (and (shl GPR:$src, (i32 8)), 0xFF000000)))))]>; -def t2REVSH : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, - "revsh", ".w\t$dst, $src", +def t2REVSH : T2I_misc<0b01, 0b11, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + "revsh", ".w\t$dst, $src", [(set GPR:$dst, (sext_inreg (or (srl (and GPR:$src, 0xFF00), (i32 8)), @@ -986,7 +1562,13 @@ IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, LSL $shamt", [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF), (and (shl GPR:$src2, (i32 imm:$shamt)), - 0xFFFF0000)))]>; + 0xFFFF0000)))]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-20} = 0b01100; + let Inst{5} = 0; // BT form + let Inst{4} = 0; +} // Alternate cases for PKHBT where identities eliminate some nodes. def : T2Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)), @@ -998,7 +1580,13 @@ IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, ASR $shamt", [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000), (and (sra GPR:$src2, imm16_31:$shamt), - 0xFFFF)))]>; + 0xFFFF)))]> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-20} = 0b01100; + let Inst{5} = 1; // TB form + let Inst{4} = 0; +} // Alternate cases for PKHTB where identities eliminate some nodes. Note that // a shift amount of 0 is *not legal* here, it is PKHBT instead. @@ -1012,15 +1600,15 @@ // Comparison Instructions... // -defm t2CMP : T2I_cmp_is<"cmp", - BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>; -defm t2CMPz : T2I_cmp_is<"cmp", - BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>; - -defm t2CMN : T2I_cmp_is<"cmn", - BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>; -defm t2CMNz : T2I_cmp_is<"cmn", - BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>; +defm t2CMP : T2I_cmp_irs<0b1101, "cmp", + BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>; +defm t2CMPz : T2I_cmp_irs<0b1101, "cmp", + BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>; + +defm t2CMN : T2I_cmp_irs<0b1000, "cmn", + BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>; +defm t2CMNz : T2I_cmp_irs<0b1000, "cmn", + BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>; def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm), (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>; @@ -1028,10 +1616,10 @@ def : T2Pat<(ARMcmpZ GPR:$src, t2_so_imm_neg:$imm), (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>; -defm t2TST : T2I_cmp_is<"tst", - BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>>; -defm t2TEQ : T2I_cmp_is<"teq", - BinOpFrag<(ARMcmpZ (xor node:$LHS, node:$RHS), 0)>>; +defm t2TST : T2I_cmp_irs<0b0000, "tst", + BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>>; +defm t2TEQ : T2I_cmp_irs<0b0100, "teq", + BinOpFrag<(ARMcmpZ (xor node:$LHS, node:$RHS), 0)>>; // A8.6.27 CBNZ, CBZ - Compare and branch on (non)zero. // Short range conditional branch. Looks awesome for loops. Need to figure @@ -1044,25 +1632,54 @@ def t2MOVCCr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true), IIC_iCMOVr, "mov", ".w\t$dst, $true", [/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $dst">; + RegConstraint<"$false = $dst"> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = 0b0010; + let Inst{20} = 0; // The S bit. + let Inst{19-16} = 0b1111; // Rn + let Inst{14-12} = 0b000; + let Inst{7-4} = 0b0000; +} def t2MOVCCi : T2I<(outs GPR:$dst), (ins GPR:$false, t2_so_imm:$true), IIC_iCMOVi, "mov", ".w\t$dst, $true", [/*(set GPR:$dst, (ARMcmov GPR:$false, t2_so_imm:$true, imm:$cc, CCR:$ccr))*/]>, - RegConstraint<"$false = $dst">; - -def t2MOVCClsl : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs), - IIC_iCMOVsi, "lsl", ".w\t$dst, $true, $rhs", []>, - RegConstraint<"$false = $dst">; -def t2MOVCClsr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs), - IIC_iCMOVsi, "lsr", ".w\t$dst, $true, $rhs", []>, - RegConstraint<"$false = $dst">; -def t2MOVCCasr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs), - IIC_iCMOVsi, "asr", ".w\t$dst, $true, $rhs", []>, - RegConstraint<"$false = $dst">; -def t2MOVCCror : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true, i32imm:$rhs), - IIC_iCMOVsi, "ror", ".w\t$dst, $true, $rhs", []>, - RegConstraint<"$false = $dst">; + RegConstraint<"$false = $dst"> { + let Inst{31-27} = 0b11110; + let Inst{25} = 0; + let Inst{24-21} = 0b0010; + let Inst{20} = 0; // The S bit. + let Inst{19-16} = 0b1111; // Rn + let Inst{15} = 0; +} + +class T2I_movcc_sh opcod, dag oops, dag iops, InstrItinClass itin, + string opc, string asm, list pattern> + : T2I { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b01; + let Inst{24-21} = 0b0010; + let Inst{20} = 0; // The S bit. + let Inst{19-16} = 0b1111; // Rn + let Inst{5-4} = opcod; // Shift type. +} +def t2MOVCClsl : T2I_movcc_sh<0b00, (outs GPR:$dst), + (ins GPR:$false, GPR:$true, i32imm:$rhs), + IIC_iCMOVsi, "lsl", ".w\t$dst, $true, $rhs", []>, + RegConstraint<"$false = $dst">; +def t2MOVCClsr : T2I_movcc_sh<0b01, (outs GPR:$dst), + (ins GPR:$false, GPR:$true, i32imm:$rhs), + IIC_iCMOVsi, "lsr", ".w\t$dst, $true, $rhs", []>, + RegConstraint<"$false = $dst">; +def t2MOVCCasr : T2I_movcc_sh<0b10, (outs GPR:$dst), + (ins GPR:$false, GPR:$true, i32imm:$rhs), + IIC_iCMOVsi, "asr", ".w\t$dst, $true, $rhs", []>, + RegConstraint<"$false = $dst">; +def t2MOVCCror : T2I_movcc_sh<0b11, (outs GPR:$dst), + (ins GPR:$false, GPR:$true, i32imm:$rhs), + IIC_iCMOVsi, "ror", ".w\t$dst, $true, $rhs", []>, + RegConstraint<"$false = $dst">; //===----------------------------------------------------------------------===// // Atomic operations intrinsics @@ -1075,7 +1692,9 @@ "dmb", "", [(ARMMemBarrierV7)]>, Requires<[IsThumb2]> { + let Inst{31-4} = 0xF3BF8F5; // FIXME: add support for options other than a full system DMB + let Inst{3-0} = 0b1111; } def t2Int_SyncBarrierV7 : AInoP<(outs), (ins), @@ -1083,47 +1702,76 @@ "dsb", "", [(ARMSyncBarrierV7)]>, Requires<[IsThumb2]> { + let Inst{31-4} = 0xF3BF8F4; // FIXME: add support for options other than a full system DSB + let Inst{3-0} = 0b1111; +} } + +class T2I_ldrex opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, + InstrItinClass itin, string opc, string asm, string cstr, + list pattern, bits<4> rt2 = 0b1111> + : Thumb2I { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0001101; + let Inst{11-8} = rt2; + let Inst{7-6} = 0b01; + let Inst{5-4} = opcod; + let Inst{3-0} = 0b1111; +} +class T2I_strex opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, + InstrItinClass itin, string opc, string asm, string cstr, + list pattern, bits<4> rt2 = 0b1111> + : Thumb2I { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0001100; + let Inst{11-8} = rt2; + let Inst{7-6} = 0b01; + let Inst{5-4} = opcod; } let mayLoad = 1 in { -def t2LDREXB : Thumb2I<(outs GPR:$dest), (ins GPR:$ptr), AddrModeNone, - Size4Bytes, NoItinerary, - "ldrexb", "\t$dest, [$ptr]", "", - []>; -def t2LDREXH : Thumb2I<(outs GPR:$dest), (ins GPR:$ptr), AddrModeNone, - Size4Bytes, NoItinerary, - "ldrexh", "\t$dest, [$ptr]", "", - []>; +def t2LDREXB : T2I_ldrex<0b00, (outs GPR:$dest), (ins GPR:$ptr), AddrModeNone, + Size4Bytes, NoItinerary, "ldrexb", "\t$dest, [$ptr]", + "", []>; +def t2LDREXH : T2I_ldrex<0b01, (outs GPR:$dest), (ins GPR:$ptr), AddrModeNone, + Size4Bytes, NoItinerary, "ldrexh", "\t$dest, [$ptr]", + "", []>; def t2LDREX : Thumb2I<(outs GPR:$dest), (ins GPR:$ptr), AddrModeNone, - Size4Bytes, NoItinerary, - "ldrex", "\t$dest, [$ptr]", "", - []>; -def t2LDREXD : Thumb2I<(outs GPR:$dest, GPR:$dest2), (ins GPR:$ptr), - AddrModeNone, Size4Bytes, NoItinerary, - "ldrexd", "\t$dest, $dest2, [$ptr]", "", - []>; + Size4Bytes, NoItinerary, + "ldrex", "\t$dest, [$ptr]", "", + []> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0000101; + let Inst{11-8} = 0b1111; + let Inst{7-0} = 0b00000000; // imm8 = 0 +} +def t2LDREXD : T2I_ldrex<0b11, (outs GPR:$dest, GPR:$dest2), (ins GPR:$ptr), + AddrModeNone, Size4Bytes, NoItinerary, + "ldrexd", "\t$dest, $dest2, [$ptr]", "", + [], {?, ?, ?, ?}>; } let mayStore = 1 in { -def t2STREXB : Thumb2I<(outs GPR:$success), (ins GPR:$src, GPR:$ptr), - AddrModeNone, Size4Bytes, NoItinerary, - "strexb", "\t$success, $src, [$ptr]", "", - []>; -def t2STREXH : Thumb2I<(outs GPR:$success), (ins GPR:$src, GPR:$ptr), - AddrModeNone, Size4Bytes, NoItinerary, - "strexh", "\t$success, $src, [$ptr]", "", - []>; +def t2STREXB : T2I_strex<0b00, (outs GPR:$success), (ins GPR:$src, GPR:$ptr), + AddrModeNone, Size4Bytes, NoItinerary, + "strexb", "\t$success, $src, [$ptr]", "", []>; +def t2STREXH : T2I_strex<0b01, (outs GPR:$success), (ins GPR:$src, GPR:$ptr), + AddrModeNone, Size4Bytes, NoItinerary, + "strexh", "\t$success, $src, [$ptr]", "", []>; def t2STREX : Thumb2I<(outs GPR:$success), (ins GPR:$src, GPR:$ptr), - AddrModeNone, Size4Bytes, NoItinerary, - "strex", "\t$success, $src, [$ptr]", "", - []>; -def t2STREXD : Thumb2I<(outs GPR:$success), - (ins GPR:$src, GPR:$src2, GPR:$ptr), - AddrModeNone, Size4Bytes, NoItinerary, - "strexd", "\t$success, $src, $src2, [$ptr]", "", - []>; + AddrModeNone, Size4Bytes, NoItinerary, + "strex", "\t$success, $src, [$ptr]", "", + []> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0000100; + let Inst{7-0} = 0b00000000; // imm8 = 0 +} +def t2STREXD : T2I_strex<0b11, (outs GPR:$success), + (ins GPR:$src, GPR:$src2, GPR:$ptr), + AddrModeNone, Size4Bytes, NoItinerary, + "strexd", "\t$success, $src, $src2, [$ptr]", "", [], + {?, ?, ?, ?}>; } //===----------------------------------------------------------------------===// @@ -1135,7 +1783,11 @@ Defs = [R0, R12, LR, CPSR] in { def t2TPsoft : T2XI<(outs), (ins), IIC_Br, "bl\t__aeabi_read_tp", - [(set R0, ARMthread_pointer)]>; + [(set R0, ARMthread_pointer)]> { + let Inst{31-27} = 0b11110; + let Inst{15-14} = 0b11; + let Inst{12} = 1; + } } //===----------------------------------------------------------------------===// @@ -1183,31 +1835,61 @@ def t2LDM_RET : T2XI<(outs), (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), IIC_Br, "ldm${addr:submode}${p}${addr:wide}\t$addr, $wb", - []>; + []> { + let Inst{31-27} = 0b11101; + let Inst{26-25} = 0b00; + let Inst{24-23} = {?, ?}; // IA: '01', DB: '10' + let Inst{22} = 0; + let Inst{21} = ?; // The W bit. + let Inst{20} = 1; // Load +} let isBranch = 1, isTerminator = 1, isBarrier = 1 in { let isPredicable = 1 in def t2B : T2XI<(outs), (ins brtarget:$target), IIC_Br, "b.w\t$target", - [(br bb:$target)]>; + [(br bb:$target)]> { + let Inst{31-27} = 0b11110; + let Inst{15-14} = 0b10; + let Inst{12} = 1; +} let isNotDuplicable = 1, isIndirectBranch = 1 in { def t2BR_JT : T2JTI<(outs), (ins GPR:$target, GPR:$index, jt2block_operand:$jt, i32imm:$id), IIC_Br, "mov\tpc, $target\n$jt", - [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]>; + [(ARMbr2jt GPR:$target, GPR:$index, tjumptable:$jt, imm:$id)]> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0100100; + let Inst{19-16} = 0b1111; + let Inst{14-12} = 0b000; + let Inst{11-8} = 0b1111; // Rd = pc + let Inst{7-4} = 0b0000; +} // FIXME: Add a non-pc based case that can be predicated. def t2TBB : T2JTI<(outs), (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id), - IIC_Br, "tbb\t$index\n$jt", []>; + IIC_Br, "tbb\t$index\n$jt", []> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0001101; + let Inst{19-16} = 0b1111; // Rn = pc (table follows this instruction) + let Inst{15-8} = 0b11110000; + let Inst{7-4} = 0b0000; // B form +} def t2TBH : T2JTI<(outs), (ins tb_addrmode:$index, jt2block_operand:$jt, i32imm:$id), - IIC_Br, "tbh\t$index\n$jt", []>; + IIC_Br, "tbh\t$index\n$jt", []> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0001101; + let Inst{19-16} = 0b1111; // Rn = pc (table follows this instruction) + let Inst{15-8} = 0b11110000; + let Inst{7-4} = 0b0001; // H form +} } // isNotDuplicable, isIndirectBranch } // isBranch, isTerminator, isBarrier @@ -1217,13 +1899,20 @@ let isBranch = 1, isTerminator = 1 in def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br, "b", ".w\t$target", - [/*(ARMbrcond bb:$target, imm:$cc)*/]>; + [/*(ARMbrcond bb:$target, imm:$cc)*/]> { + let Inst{31-27} = 0b11110; + let Inst{15-14} = 0b10; + let Inst{12} = 0; +} // IT block def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask), AddrModeNone, Size2Bytes, IIC_iALUx, - "it$mask\t$cc", "", []>; + "it$mask\t$cc", "", []> { + // 16-bit instruction. + let Inst{15-8} = 0b10111111; +} //===----------------------------------------------------------------------===// // Non-Instruction Patterns From gohman at apple.com Tue Dec 15 12:30:57 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 15 Dec 2009 10:30:57 -0800 Subject: [llvm-commits] [llvm] r91381 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86ISelLowering.h lib/Target/X86/X86Instr64bit.td lib/Target/X86/X86InstrInfo.td test/CodeGen/X86/setcc.ll In-Reply-To: <200912150053.nBF0rhfK025969@zion.cs.uiuc.edu> References: <200912150053.nBF0rhfK025969@zion.cs.uiuc.edu> Message-ID: On Dec 14, 2009, at 4:53 PM, Evan Cheng wrote: > > ============================================================================== > --- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original) > +++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Mon Dec 14 18:53:42 2009 > @@ -1333,6 +1333,15 @@ > X86_COND_NO, EFLAGS))]>, TB; > } // isTwoAddress > > +// Use sbb to materialize carry flag into a GPR. > +let Defs = [EFLAGS], Uses = [EFLAGS], isCodeGenOnly = 1 in > +def SETB_C64r : RI<0x19, MRMDestReg, (outs GR64:$dst), (ins), > + "sbb{q}\t$dst, $dst", > + [(set GR64:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>; An sbbq will set all 64 bits. Why does the pattern here have a zext in it? Dan From gohman at apple.com Tue Dec 15 12:33:22 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 15 Dec 2009 10:33:22 -0800 Subject: [llvm-commits] [llvm] r91381 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86ISelLowering.h lib/Target/X86/X86Instr64bit.td lib/Target/X86/X86InstrInfo.td test/CodeGen/X86/setcc.ll In-Reply-To: <200912150053.nBF0rhfK025969@zion.cs.uiuc.edu> References: <200912150053.nBF0rhfK025969@zion.cs.uiuc.edu> Message-ID: On Dec 14, 2009, at 4:53 PM, Evan Cheng wrote: > > --- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original) > +++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Mon Dec 14 18:53:42 2009 > @@ -1333,6 +1333,15 @@ > X86_COND_NO, EFLAGS))]>, TB; > } // isTwoAddress > > +// Use sbb to materialize carry flag into a GPR. > +let Defs = [EFLAGS], Uses = [EFLAGS], isCodeGenOnly = 1 in > +def SETB_C64r : RI<0x19, MRMDestReg, (outs GR64:$dst), (ins), > + "sbb{q}\t$dst, $dst", > + [(set GR64:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>; An sbbq will set all 64 bits. Why does the pattern here have a zext in it? Dan From rjmccall at apple.com Tue Dec 15 12:34:45 2009 From: rjmccall at apple.com (John McCall) Date: Tue, 15 Dec 2009 10:34:45 -0800 Subject: [llvm-commits] [llvm] r91397 - /llvm/trunk/lib/Analysis/ProfileInfo.cpp In-Reply-To: <9367CAC4-5D67-4A50-A4F2-C4BE12F88A4C@apple.com> References: <200912150235.nBF2ZPTE029607@zion.cs.uiuc.edu> <9367CAC4-5D67-4A50-A4F2-C4BE12F88A4C@apple.com> Message-ID: <7585234D-3D83-4288-B718-8B8092FD6C7E@apple.com> On Dec 14, 2009, at 9:46 PM, Chris Lattner wrote: > > On Dec 14, 2009, at 6:35 PM, John McCall wrote: > >> Author: rjmccall >> Date: Mon Dec 14 20:35:24 2009 >> New Revision: 91397 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=91397&view=rev >> Log: >> You can't use typedefs to declare template member specializations, and >> clang enforces it. > > Does clang produce a good diagnostic (with a fixit hint) for this error? We can't do the fixit hint yet because we don't track locations well enough in nested name specifiers. This also means the caret is not necessarily helpful. The diagnostic is error: cannot use typedef 'ProfileInfo' (a.k.a. 'ProfileInfoT< llvm:: Function,llvm::BasicBlock>') in scope specifier for out-of-line declaration which conveys the idea well enough, but is not exactly my finest diagnostic ever. John. From evan.cheng at apple.com Tue Dec 15 12:36:24 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 15 Dec 2009 10:36:24 -0800 Subject: [llvm-commits] [llvm] r91381 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86ISelLowering.h lib/Target/X86/X86Instr64bit.td lib/Target/X86/X86InstrInfo.td test/CodeGen/X86/setcc.ll In-Reply-To: References: <200912150053.nBF0rhfK025969@zion.cs.uiuc.edu> Message-ID: <0838237D-D73A-4A62-B10D-A86012B247BD@apple.com> On Dec 15, 2009, at 10:30 AM, Dan Gohman wrote: > > On Dec 14, 2009, at 4:53 PM, Evan Cheng wrote: >> >> ============================================================================== >> --- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original) >> +++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Mon Dec 14 18:53:42 2009 >> @@ -1333,6 +1333,15 @@ >> X86_COND_NO, EFLAGS))]>, TB; >> } // isTwoAddress >> >> +// Use sbb to materialize carry flag into a GPR. >> +let Defs = [EFLAGS], Uses = [EFLAGS], isCodeGenOnly = 1 in >> +def SETB_C64r : RI<0x19, MRMDestReg, (outs GR64:$dst), (ins), >> + "sbb{q}\t$dst, $dst", >> + [(set GR64:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>; > > An sbbq will set all 64 bits. Why does the pattern here have a zext in it? X86setcc_c like X86setcc returns a i8 value. Yes, the semantics of is all zero or all one's. That's why x86isellowering will and the result with 1. Evan > > Dan > From clattner at apple.com Tue Dec 15 12:36:54 2009 From: clattner at apple.com (Chris Lattner) Date: Tue, 15 Dec 2009 10:36:54 -0800 Subject: [llvm-commits] [llvm] r91397 - /llvm/trunk/lib/Analysis/ProfileInfo.cpp In-Reply-To: <7585234D-3D83-4288-B718-8B8092FD6C7E@apple.com> References: <200912150235.nBF2ZPTE029607@zion.cs.uiuc.edu> <9367CAC4-5D67-4A50-A4F2-C4BE12F88A4C@apple.com> <7585234D-3D83-4288-B718-8B8092FD6C7E@apple.com> Message-ID: <9B8F37B7-70AB-4E82-9E5A-ED45ADD64979@apple.com> On Dec 15, 2009, at 10:34 AM, John McCall wrote: >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=91397&view=rev >>> Log: >>> You can't use typedefs to declare template member specializations, >>> and >>> clang enforces it. >> >> Does clang produce a good diagnostic (with a fixit hint) for this >> error? > > We can't do the fixit hint yet because we don't track locations well > enough in nested name specifiers. This also means the caret is not > necessarily helpful. > > The diagnostic is > error: cannot use typedef 'ProfileInfo' (a.k.a. 'ProfileInfoT< > llvm:: Function,llvm::BasicBlock>') in scope specifier for out-of- > line declaration > which conveys the idea well enough, but is not exactly my finest > diagnostic ever. Ok, please file a bugzilla about this. This is something that new clang++ users are likely to hit if they've been using GCC, so it would be very nice to give a really pretty diagnostic to explain what is wrong. Thanks John, -Chris From gohman at apple.com Tue Dec 15 12:39:18 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 15 Dec 2009 10:39:18 -0800 Subject: [llvm-commits] [llvm] r91381 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86ISelLowering.h lib/Target/X86/X86Instr64bit.td lib/Target/X86/X86InstrInfo.td test/CodeGen/X86/setcc.ll In-Reply-To: <0838237D-D73A-4A62-B10D-A86012B247BD@apple.com> References: <200912150053.nBF0rhfK025969@zion.cs.uiuc.edu> <0838237D-D73A-4A62-B10D-A86012B247BD@apple.com> Message-ID: <90B7DF90-ACF4-499E-BB73-69AEFDAB14FC@apple.com> On Dec 15, 2009, at 10:36 AM, Evan Cheng wrote: > > On Dec 15, 2009, at 10:30 AM, Dan Gohman wrote: > >> >> On Dec 14, 2009, at 4:53 PM, Evan Cheng wrote: >>> >>> ============================================================================== >>> --- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original) >>> +++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Mon Dec 14 18:53:42 2009 >>> @@ -1333,6 +1333,15 @@ >>> X86_COND_NO, EFLAGS))]>, TB; >>> } // isTwoAddress >>> >>> +// Use sbb to materialize carry flag into a GPR. >>> +let Defs = [EFLAGS], Uses = [EFLAGS], isCodeGenOnly = 1 in >>> +def SETB_C64r : RI<0x19, MRMDestReg, (outs GR64:$dst), (ins), >>> + "sbb{q}\t$dst, $dst", >>> + [(set GR64:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>; >> >> An sbbq will set all 64 bits. Why does the pattern here have a zext in it? > > X86setcc_c like X86setcc returns a i8 value. Yes, the semantics of is all zero or all one's. That's why x86isellowering will and the result with 1. Whatever X86setcc_c is, the current pattern doesn't describe the instruction. The pattern says the instruction will always set the most significant bits of the output to zero, and that's not what the instruction really does. Dan From dalej at apple.com Tue Dec 15 12:43:49 2009 From: dalej at apple.com (Dale Johannesen) Date: Tue, 15 Dec 2009 10:43:49 -0800 Subject: [llvm-commits] [patch] fptr support for PPC64 In-Reply-To: <200912151255.29701.ken@linux.vnet.ibm.com> References: <200912151255.29701.ken@linux.vnet.ibm.com> Message-ID: <310DA270-7D55-4D87-943B-2E1ED4EFE258@apple.com> On Dec 15, 2009, at 3:55 AMPST, Ken Werner wrote: > Hi, > The attached patch adds support for indirect calls (through function > pointer) > according to the ABI (http://refspecs.linuxfoundation.org/ELF/ppc64/PPC- > elf64abi-1.9.html#FUNC-CALLS). The patch was made against revision > 91275. > -ken -------------- next part -------------- A non-text attachment was scrubbed... Name: ppc64-fptr.patch Type: text/x-patch Size: 8130 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20091215/022f9da0/attachment.bin -------------- next part -------------- > _______________________________________________ I can't speak for SVR4 ppc64, but I'm confident these 3 patches won't break any other target. It's preferable to get isPPC64 from PPCSubTarget, as elsewhere (inconsistently). Here that seems to mean an extra parameter. Why did you add a Chain to PPCISD::NOP? Do you have write access? From evan.cheng at apple.com Tue Dec 15 13:05:40 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 15 Dec 2009 11:05:40 -0800 Subject: [llvm-commits] [llvm] r91381 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86ISelLowering.h lib/Target/X86/X86Instr64bit.td lib/Target/X86/X86InstrInfo.td test/CodeGen/X86/setcc.ll In-Reply-To: <90B7DF90-ACF4-499E-BB73-69AEFDAB14FC@apple.com> References: <200912150053.nBF0rhfK025969@zion.cs.uiuc.edu> <0838237D-D73A-4A62-B10D-A86012B247BD@apple.com> <90B7DF90-ACF4-499E-BB73-69AEFDAB14FC@apple.com> Message-ID: <0B8D3D2F-9D9B-41A1-B102-68EA9727F767@apple.com> On Dec 15, 2009, at 10:39 AM, Dan Gohman wrote: > > On Dec 15, 2009, at 10:36 AM, Evan Cheng wrote: > >> >> On Dec 15, 2009, at 10:30 AM, Dan Gohman wrote: >> >>> >>> On Dec 14, 2009, at 4:53 PM, Evan Cheng wrote: >>>> >>>> ============================================================================== >>>> --- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original) >>>> +++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Mon Dec 14 18:53:42 2009 >>>> @@ -1333,6 +1333,15 @@ >>>> X86_COND_NO, EFLAGS))]>, TB; >>>> } // isTwoAddress >>>> >>>> +// Use sbb to materialize carry flag into a GPR. >>>> +let Defs = [EFLAGS], Uses = [EFLAGS], isCodeGenOnly = 1 in >>>> +def SETB_C64r : RI<0x19, MRMDestReg, (outs GR64:$dst), (ins), >>>> + "sbb{q}\t$dst, $dst", >>>> + [(set GR64:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>; >>> >>> An sbbq will set all 64 bits. Why does the pattern here have a zext in it? >> >> X86setcc_c like X86setcc returns a i8 value. Yes, the semantics of is all zero or all one's. That's why x86isellowering will and the result with 1. > > Whatever X86setcc_c is, the current pattern doesn't describe the instruction. > The pattern says the instruction will always set the most significant bits of > the output to zero, and that's not what the instruction really does. You're right. I am going to have to re-implement this. Evan > > Dan > From sabre at nondot.org Tue Dec 15 13:14:40 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 15 Dec 2009 19:14:40 -0000 Subject: [llvm-commits] [llvm] r91438 - in /llvm/trunk: lib/Transforms/Scalar/SimplifyLibCalls.cpp test/Transforms/SimplifyLibCalls/StrStr.ll Message-ID: <200912151914.nBFJEeJp015299@zion.cs.uiuc.edu> Author: lattner Date: Tue Dec 15 13:14:40 2009 New Revision: 91438 URL: http://llvm.org/viewvc/llvm-project?rev=91438&view=rev Log: optimize strstr, PR5783 Added: llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp?rev=91438&r1=91437&r2=91438&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp Tue Dec 15 13:14:40 2009 @@ -76,6 +76,11 @@ /// return value has 'intptr_t' type. Value *EmitStrLen(Value *Ptr, IRBuilder<> &B); + /// EmitStrChr - Emit a call to the strchr function to the builder, for the + /// specified pointer and character. Ptr is required to be some pointer type, + /// and the return value has 'i8*' type. + Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B); + /// EmitMemCpy - Emit a call to the memcpy function to the builder. This /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, @@ -151,6 +156,26 @@ return CI; } +/// EmitStrChr - Emit a call to the strchr function to the builder, for the +/// specified pointer and character. Ptr is required to be some pointer type, +/// and the return value has 'i8*' type. +Value *LibCallOptimization::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B) { + Module *M = Caller->getParent(); + AttributeWithIndex AWI = + AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind); + + const Type *I8Ptr = Type::getInt8PtrTy(*Context); + const Type *I32Ty = Type::getInt32Ty(*Context); + Constant *StrChr = M->getOrInsertFunction("strchr", AttrListPtr::get(&AWI, 1), + I8Ptr, I8Ptr, I32Ty, NULL); + CallInst *CI = B.CreateCall2(StrChr, CastToCStr(Ptr, B), + ConstantInt::get(I32Ty, C), "strchr"); + if (const Function *F = dyn_cast(StrChr->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + return CI; +} + + /// EmitMemCpy - Emit a call to the memcpy function to the builder. This always /// expects that the size has type 'intptr_t' and Dst/Src are pointers. Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len, @@ -890,7 +915,7 @@ }; //===---------------------------------------===// -// 'strto*' Optimizations +// 'strto*' Optimizations. This handles strtol, strtod, strtof, strtoul, etc. struct StrToOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { @@ -910,6 +935,52 @@ } }; +//===---------------------------------------===// +// 'strstr' Optimizations + +struct StrStrOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !isa(FT->getReturnType())) + return 0; + + // fold strstr(x, x) -> x. + if (CI->getOperand(1) == CI->getOperand(2)) + return CI->getOperand(1); + + // See if either input string is a constant string. + std::string SearchStr, ToFindStr; + bool HasStr1 = GetConstantStringInfo(CI->getOperand(1), SearchStr); + bool HasStr2 = GetConstantStringInfo(CI->getOperand(2), ToFindStr); + + // fold strstr(x, "") -> x. + if (HasStr2 && ToFindStr.empty()) + return B.CreateBitCast(CI->getOperand(1), CI->getType()); + + // If both strings are known, constant fold it. + if (HasStr1 && HasStr2) { + std::string::size_type Offset = SearchStr.find(ToFindStr); + + if (Offset == std::string::npos) // strstr("foo", "bar") -> null + return Constant::getNullValue(CI->getType()); + + // strstr("abcd", "bc") -> gep((char*)"abcd", 2) + Value *Result = CastToCStr(CI->getOperand(1), B); + Result = B.CreateConstInBoundsGEP1_64(Result, Offset, "strstr"); + return B.CreateBitCast(Result, CI->getType()); + } + + // fold strstr(x, "y") -> strchr(x, 'y'). + if (HasStr2 && ToFindStr.size() == 1) + return B.CreateBitCast(EmitStrChr(CI->getOperand(1), ToFindStr[0], B), + CI->getType()); + return 0; + } +}; + //===---------------------------------------===// // 'memcmp' Optimizations @@ -1675,8 +1746,8 @@ // String and Memory LibCall Optimizations StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrCmpOpt StrCmp; StrNCmpOpt StrNCmp; StrCpyOpt StrCpy; StrNCpyOpt StrNCpy; StrLenOpt StrLen; - StrToOpt StrTo; MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; - MemSetOpt MemSet; + StrToOpt StrTo; StrStrOpt StrStr; + MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet; // Math Library Optimizations PowOpt Pow; Exp2Opt Exp2; UnaryDoubleFPOpt UnaryDoubleFP; // Integer Optimizations @@ -1738,6 +1809,7 @@ Optimizations["strtoll"] = &StrTo; Optimizations["strtold"] = &StrTo; Optimizations["strtoull"] = &StrTo; + Optimizations["strstr"] = &StrStr; Optimizations["memcmp"] = &MemCmp; Optimizations["memcpy"] = &MemCpy; Optimizations["memmove"] = &MemMove; @@ -2644,12 +2716,6 @@ // * strcspn("",a) -> 0 // * strcspn(s,"") -> strlen(a) // -// strstr: (PR5783) -// * strstr(x,x) -> x -// * strstr(x, "") -> x -// * strstr(x, "a") -> strchr(x, 'a') -// * strstr(s1,s2) -> result (if s1 and s2 are constant strings) -// // tan, tanf, tanl: // * tan(atan(x)) -> x // Added: llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll?rev=91438&view=auto ============================================================================== --- llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll (added) +++ llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll Tue Dec 15 13:14:40 2009 @@ -0,0 +1,48 @@ +; RUN: opt < %s -simplify-libcalls -S | FileCheck %s +; PR5783 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" +target triple = "i386-apple-darwin9.0" + + at .str = private constant [1 x i8] zeroinitializer ; <[1 x i8]*> [#uses=1] + at .str1 = private constant [2 x i8] c"a\00" ; <[2 x i8]*> [#uses=1] + at .str2 = private constant [6 x i8] c"abcde\00" ; <[6 x i8]*> [#uses=1] + at .str3 = private constant [4 x i8] c"bcd\00" ; <[4 x i8]*> [#uses=1] + +define i8* @test1(i8* %P) nounwind readonly { +entry: + %call = tail call i8* @strstr(i8* %P, i8* getelementptr inbounds ([1 x i8]* @.str, i32 0, i32 0)) nounwind ; [#uses=1] + ret i8* %call +; strstr(P, "") -> P +; CHECK: @test1 +; CHECK: ret i8* %P +} + +declare i8* @strstr(i8*, i8* nocapture) nounwind readonly + +define i8* @test2(i8* %P) nounwind readonly { +entry: + %call = tail call i8* @strstr(i8* %P, i8* getelementptr inbounds ([2 x i8]* @.str1, i32 0, i32 0)) nounwind ; [#uses=1] + ret i8* %call +; strstr(P, "a") -> strchr(P, 'a') +; CHECK: @test2 +; CHECK: @strchr(i8* %P, i32 97) +} + +define i8* @test3(i8* nocapture %P) nounwind readonly { +entry: + %call = tail call i8* @strstr(i8* getelementptr inbounds ([6 x i8]* @.str2, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8]* @.str3, i32 0, i32 0)) nounwind ; [#uses=1] + ret i8* %call +; strstr("abcde", "bcd") -> "abcde"+1 +; CHECK: @test3 +; CHECK: getelementptr inbounds ([6 x i8]* @.str2, i32 0, i64 1) +} + +define i8* @test4(i8* %P) nounwind readonly { +entry: + %call = tail call i8* @strstr(i8* %P, i8* %P) nounwind ; [#uses=1] + ret i8* %call +; strstr(P, P) -> P +; CHECK: @test4 +; CHECK: ret i8* %P +} From dpatel at apple.com Tue Dec 15 13:16:48 2009 From: dpatel at apple.com (Devang Patel) Date: Tue, 15 Dec 2009 19:16:48 -0000 Subject: [llvm-commits] [llvm] r91440 - in /llvm/trunk: include/llvm/Analysis/DebugInfo.h lib/Analysis/DebugInfo.cpp lib/CodeGen/AsmPrinter/DIE.h lib/CodeGen/AsmPrinter/DwarfDebug.cpp lib/CodeGen/AsmPrinter/DwarfDebug.h Message-ID: <200912151916.nBFJGnXo015403@zion.cs.uiuc.edu> Author: dpatel Date: Tue Dec 15 13:16:48 2009 New Revision: 91440 URL: http://llvm.org/viewvc/llvm-project?rev=91440&view=rev Log: Add support to emit debug info for C++ namespaces. Modified: llvm/trunk/include/llvm/Analysis/DebugInfo.h llvm/trunk/lib/Analysis/DebugInfo.cpp llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Modified: llvm/trunk/include/llvm/Analysis/DebugInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/DebugInfo.h?rev=91440&r1=91439&r2=91440&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/DebugInfo.h (original) +++ llvm/trunk/include/llvm/Analysis/DebugInfo.h Tue Dec 15 13:16:48 2009 @@ -99,6 +99,7 @@ bool isGlobalVariable() const; bool isScope() const; bool isCompileUnit() const; + bool isNameSpace() const; bool isLexicalBlock() const; bool isSubrange() const; bool isEnumerator() const; @@ -218,7 +219,7 @@ virtual ~DIType() {} DIDescriptor getContext() const { return getDescriptorField(1); } - StringRef getName() const { return getStringField(2); } + StringRef getName() const { return getStringField(2); } DICompileUnit getCompileUnit() const{ return getFieldAs(3); } unsigned getLineNumber() const { return getUnsignedField(4); } uint64_t getSizeInBits() const { return getUInt64Field(5); } @@ -470,6 +471,22 @@ StringRef getFilename() const { return getContext().getFilename(); } }; + /// DINameSpace - A wrapper for a C++ style name space. + class DINameSpace : public DIScope { + public: + explicit DINameSpace(MDNode *N = 0) : DIScope(N) { + if (DbgNode && !isNameSpace()) + DbgNode = 0; + } + + DIScope getContext() const { return getFieldAs(1); } + StringRef getName() const { return getStringField(2); } + StringRef getDirectory() const { return getContext().getDirectory(); } + StringRef getFilename() const { return getContext().getFilename(); } + DICompileUnit getCompileUnit() const { return getFieldAs(3); } + unsigned getLineNumber() const { return getUnsignedField(4); } + }; + /// DILocation - This object holds location information. This object /// is not associated with any DWARF tag. class DILocation : public DIDescriptor { @@ -624,6 +641,11 @@ /// with the specified parent context. DILexicalBlock CreateLexicalBlock(DIDescriptor Context); + /// CreateNameSpace - This creates new descriptor for a namespace + /// with the specified parent context. + DINameSpace CreateNameSpace(DIDescriptor Context, StringRef Name, + DICompileUnit CU, unsigned LineNo); + /// CreateLocation - Creates a debug info location. DILocation CreateLocation(unsigned LineNo, unsigned ColumnNo, DIScope S, DILocation OrigLoc); Modified: llvm/trunk/lib/Analysis/DebugInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/DebugInfo.cpp?rev=91440&r1=91439&r2=91440&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/DebugInfo.cpp (original) +++ llvm/trunk/lib/Analysis/DebugInfo.cpp Tue Dec 15 13:16:48 2009 @@ -227,6 +227,7 @@ case dwarf::DW_TAG_compile_unit: case dwarf::DW_TAG_lexical_block: case dwarf::DW_TAG_subprogram: + case dwarf::DW_TAG_namespace: return true; default: break; @@ -242,6 +243,14 @@ return Tag == dwarf::DW_TAG_compile_unit; } +/// isNameSpace - Return true if the specified tag is DW_TAG_namespace. +bool DIDescriptor::isNameSpace() const { + assert (!isNull() && "Invalid descriptor!"); + unsigned Tag = getTag(); + + return Tag == dwarf::DW_TAG_namespace; +} + /// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block. bool DIDescriptor::isLexicalBlock() const { assert (!isNull() && "Invalid descriptor!"); @@ -438,6 +447,8 @@ return DISubprogram(DbgNode).getFilename(); else if (isCompileUnit()) return DICompileUnit(DbgNode).getFilename(); + else if (isNameSpace()) + return DINameSpace(DbgNode).getFilename(); else assert (0 && "Invalid DIScope!"); return StringRef(); @@ -450,6 +461,8 @@ return DISubprogram(DbgNode).getDirectory(); else if (isCompileUnit()) return DICompileUnit(DbgNode).getDirectory(); + else if (isNameSpace()) + return DINameSpace(DbgNode).getDirectory(); else assert (0 && "Invalid DIScope!"); return StringRef(); @@ -996,6 +1009,21 @@ return DILexicalBlock(MDNode::get(VMContext, &Elts[0], 2)); } +/// CreateNameSpace - This creates new descriptor for a namespace +/// with the specified parent context. +DINameSpace DIFactory::CreateNameSpace(DIDescriptor Context, StringRef Name, + DICompileUnit CompileUnit, + unsigned LineNo) { + Value *Elts[] = { + GetTagConstant(dwarf::DW_TAG_namespace), + Context.getNode(), + MDString::get(VMContext, Name), + CompileUnit.getNode(), + ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) + }; + return DINameSpace(MDNode::get(VMContext, &Elts[0], 5)); +} + /// CreateLocation - Creates a debug info location. DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo, DIScope S, DILocation OrigLoc) { Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h?rev=91440&r1=91439&r2=91440&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DIE.h Tue Dec 15 13:16:48 2009 @@ -68,6 +68,7 @@ /// Data - Raw data bytes for abbreviation. /// SmallVector Data; + public: DIEAbbrev(unsigned T, unsigned C) : Tag(T), ChildrenFlag(C), Data() {} virtual ~DIEAbbrev() {} @@ -131,19 +132,18 @@ /// std::vector Children; + DIE *Parent; + /// Attributes values. /// SmallVector Values; - /// Abstract compile unit. - CompileUnit *AbstractCU; - // Private data for print() mutable unsigned IndentCount; public: explicit DIE(unsigned Tag) : Abbrev(Tag, dwarf::DW_CHILDREN_no), Offset(0), - Size(0), IndentCount(0) {} + Size(0), Parent (0), IndentCount(0) {} virtual ~DIE(); // Accessors. @@ -154,13 +154,12 @@ unsigned getSize() const { return Size; } const std::vector &getChildren() const { return Children; } SmallVector &getValues() { return Values; } - CompileUnit *getAbstractCompileUnit() const { return AbstractCU; } - + DIE *getParent() const { return Parent; } void setTag(unsigned Tag) { Abbrev.setTag(Tag); } void setOffset(unsigned O) { Offset = O; } void setSize(unsigned S) { Size = S; } - void setAbstractCompileUnit(CompileUnit *CU) { AbstractCU = CU; } - + void setParent(DIE *P) { Parent = P; } + /// addValue - Add a value and attributes to a DIE. /// void addValue(unsigned Attribute, unsigned Form, DIEValue *Value) { @@ -179,8 +178,13 @@ /// addChild - Add a child to the DIE. /// void addChild(DIE *Child) { + if (Child->getParent()) { + assert (Child->getParent() == this && "Unexpected DIE Parent!"); + return; + } Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); Children.push_back(Child); + Child->setParent(this); } #ifndef NDEBUG Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=91440&r1=91439&r2=91440&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Dec 15 13:16:48 2009 @@ -112,7 +112,12 @@ /// getDIEEntry - Returns the debug information entry for the speciefied /// debug variable. - DIEEntry *getDIEEntry(MDNode *N) { return GVToDIEEntryMap.lookup(N); } + DIEEntry *getDIEEntry(MDNode *N) { + ValueMap::iterator I = GVToDIEEntryMap.find(N); + if (I == GVToDIEEntryMap.end()) + return NULL; + return I->second; + } /// insertDIEEntry - Insert debug information entry into the map. void insertDIEEntry(MDNode *N, DIEEntry *E) { @@ -446,6 +451,23 @@ addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); } +/// addSourceLine - Add location information to specified debug information +/// entry. +void DwarfDebug::addSourceLine(DIE *Die, const DINameSpace *NS) { + // If there is no compile unit specified, don't add a line #. + if (NS->getCompileUnit().isNull()) + return; + + unsigned Line = NS->getLineNumber(); + StringRef FN = NS->getFilename(); + StringRef Dir = NS->getDirectory(); + + unsigned FileID = GetOrCreateSourceID(Dir, FN); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + /* Byref variables, in Blocks, are declared by the programmer as "SomeType VarName;", but the compiler creates a __Block_byref_x_VarName struct, and gives the variable VarName @@ -745,6 +767,9 @@ else if (Context.isType()) { DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context.getNode())); ContextDIE->addChild(Die); + } else if (Context.isNameSpace()) { + DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context.getNode())); + ContextDIE->addChild(Die); } else if (DIE *ContextDIE = ModuleCU->getDIE(Context.getNode())) ContextDIE->addChild(Die); else @@ -781,7 +806,6 @@ // Check for pre-existence. DIEEntry *Entry = ModuleCU->getDIEEntry(Ty.getNode()); - // If it exists then use the existing value. if (Entry) { Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); @@ -1030,13 +1054,6 @@ addUInt(GVDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); addSourceLine(GVDie, &GV); - // Add address. - DIEBlock *Block = new DIEBlock(); - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); - addObjectLabel(Block, 0, dwarf::DW_FORM_udata, - Asm->Mang->getMangledName(GV.getGlobal())); - addBlock(GVDie, dwarf::DW_AT_location, 0, Block); - return GVDie; } @@ -1285,7 +1302,6 @@ SPDie = new DIE(dwarf::DW_TAG_subprogram); addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, SPDeclDie); - ModuleCU->addDie(SPDie); } @@ -1559,6 +1575,20 @@ return SrcId; } +/// getOrCreateNameSpace - Create a DIE for DINameSpace. +DIE *DwarfDebug::getOrCreateNameSpace(DINameSpace NS) { + DIE *NDie = ModuleCU->getDIE(NS.getNode()); + if (NDie) + return NDie; + NDie = new DIE(dwarf::DW_TAG_namespace); + ModuleCU->insertDIE(NS.getNode(), NDie); + if (!NS.getName().empty()) + addString(NDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, NS.getName()); + addSourceLine(NDie, &NS); + addToContextOwner(NDie, NS.getContext()); + return NDie; +} + CompileUnit *DwarfDebug::constructCompileUnit(MDNode *N) { DICompileUnit DIUnit(N); StringRef FN = DIUnit.getFilename(); @@ -1620,6 +1650,25 @@ ModuleCU->insertDIE(N, VariableDie); // Add to context owner. + if (DI_GV.isDefinition() + && !DI_GV.getContext().isCompileUnit()) { + // Create specification DIE. + DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable); + addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, + dwarf::DW_FORM_ref4, VariableDie); + DIEBlock *Block = new DIEBlock(); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + addObjectLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->Mang->getMangledName(DI_GV.getGlobal())); + addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); + ModuleCU->addDie(VariableSpecDIE); + } else { + DIEBlock *Block = new DIEBlock(); + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + addObjectLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->Mang->getMangledName(DI_GV.getGlobal())); + addBlock(VariableDie, dwarf::DW_AT_location, 0, Block); + } addToContextOwner(VariableDie, DI_GV.getContext()); // Expose as global. FIXME - need to check external flag. @@ -1652,9 +1701,7 @@ ModuleCU->insertDIE(N, SubprogramDie); // Add to context owner. - if (SP.getContext().getNode() == SP.getCompileUnit().getNode()) - if (TopLevelDIEs.insert(SubprogramDie)) - TopLevelDIEsVector.push_back(SubprogramDie); + addToContextOwner(SubprogramDie, SP.getContext()); // Expose as global. ModuleCU->addGlobal(SP.getName(), SubprogramDie); @@ -2365,7 +2412,6 @@ EmitLabel("info_end", ModuleCU->getID()); Asm->EOL(); - } /// emitAbbreviations - Emit the abbreviation section. Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=91440&r1=91439&r2=91440&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Tue Dec 15 13:16:48 2009 @@ -285,6 +285,7 @@ void addSourceLine(DIE *Die, const DIGlobal *G); void addSourceLine(DIE *Die, const DISubprogram *SP); void addSourceLine(DIE *Die, const DIType *Ty); + void addSourceLine(DIE *Die, const DINameSpace *NS); /// addAddress - Add an address attribute to a die based on the location /// provided. @@ -315,6 +316,10 @@ /// addType - Add a new type attribute to the specified entity. void addType(DIE *Entity, DIType Ty); + + /// getOrCreateNameSpace - Create a DIE for DINameSpace. + DIE *getOrCreateNameSpace(DINameSpace NS); + /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the /// given DIType. DIE *getOrCreateTypeDIE(DIType Ty); From dpatel at apple.com Tue Dec 15 13:17:30 2009 From: dpatel at apple.com (Devang Patel) Date: Tue, 15 Dec 2009 19:17:30 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r91441 - in /llvm-gcc-4.2/trunk/gcc: llvm-debug.cpp llvm-debug.h Message-ID: <200912151917.nBFJHUR6015432@zion.cs.uiuc.edu> Author: dpatel Date: Tue Dec 15 13:17:30 2009 New Revision: 91441 URL: http://llvm.org/viewvc/llvm-project?rev=91441&view=rev Log: Emit debug info for C++ namespaces. Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp llvm-gcc-4.2/trunk/gcc/llvm-debug.h Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp?rev=91441&r1=91440&r2=91441&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-debug.cpp Tue Dec 15 13:17:30 2009 @@ -263,10 +263,20 @@ Virtuality = dwarf::DW_VIRTUALITY_virtual; ContainingType = getOrCreateType(DECL_CONTEXT (FnDecl)); } + bool UseModuleContext = false; + // If this artificial function has abstract origin then put this function + // at module scope. The abstract copy will be placed in appropriate region. + if (DECL_ABSTRACT_ORIGIN (FnDecl) != FnDecl + && DECL_ARTIFICIAL(FnDecl)) + UseModuleContext = true; + + const char *FnName = lang_hooks.dwarf_name(FnDecl, 0); DISubprogram SP = - DebugFactory.CreateSubprogram(findRegion(DECL_CONTEXT(FnDecl)), - lang_hooks.dwarf_name(FnDecl, 0), - lang_hooks.dwarf_name(FnDecl, 0), + DebugFactory.CreateSubprogram((UseModuleContext ? + getOrCreateCompileUnit(main_input_filename) : + findRegion(DECL_CONTEXT(FnDecl))), + (UseModuleContext ? FnName : StringRef()), + (UseModuleContext ? FnName : StringRef()), LinkageName, getOrCreateCompileUnit(Loc.file), lineno, FNType, @@ -282,7 +292,23 @@ RegionMap[FnDecl] = WeakVH(SP.getNode()); } - /// findRegion - Find tree_node N's region. +/// getOrCreateNameSpace - Get name space descriptor for the tree node. +DINameSpace DebugInfo::getOrCreateNameSpace(tree Node, DIDescriptor Context) { + std::map::iterator I = + NameSpaceCache.find(Node); + if (I != NameSpaceCache.end()) + return DINameSpace(cast(I->second)); + + expanded_location Loc = GetNodeLocation(Node, false); + DINameSpace DNS = + DebugFactory.CreateNameSpace(Context, GetNodeName(Node), + getOrCreateCompileUnit(Loc.file), Loc.line); + + NameSpaceCache[Node] = WeakVH(DNS.getNode()); + return DNS; +} + +/// findRegion - Find tree_node N's region. DIDescriptor DebugInfo::findRegion(tree Node) { if (Node == NULL_TREE) return getOrCreateCompileUnit(main_input_filename); @@ -295,8 +321,14 @@ if (TYPE_P (Node)) { DIType Ty = getOrCreateType(Node); return DIDescriptor(Ty.getNode()); - } else if (DECL_P (Node)) + } else if (DECL_P (Node)) { + if (TREE_CODE (Node) == NAMESPACE_DECL) { + DIDescriptor NSContext = findRegion(DECL_CONTEXT(Node)); + DINameSpace NS = getOrCreateNameSpace(Node, NSContext); + return DIDescriptor(NS.getNode()); + } return findRegion (DECL_CONTEXT (Node)); + } // Otherwise main compile unit covers everything. return getOrCreateCompileUnit(main_input_filename); Modified: llvm-gcc-4.2/trunk/gcc/llvm-debug.h URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-debug.h?rev=91441&r1=91440&r2=91441&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-debug.h (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-debug.h Tue Dec 15 13:17:30 2009 @@ -68,6 +68,9 @@ std::map SPCache; // Cache of previously constructed // Subprograms. + std::map NameSpaceCache; + // Cache of previously constructed name + // spaces. SmallVector RegionStack; // Stack to track declarative scopes. @@ -136,6 +139,9 @@ /// findRegion - Find tree_node N's region. DIDescriptor findRegion(tree_node *n); + + /// getOrCreateNameSpace - Get name space descriptor for the tree node. + DINameSpace getOrCreateNameSpace(tree_node *Node, DIDescriptor Context); }; } // end namespace llvm From grosbach at apple.com Tue Dec 15 13:28:13 2009 From: grosbach at apple.com (Jim Grosbach) Date: Tue, 15 Dec 2009 19:28:13 -0000 Subject: [llvm-commits] [llvm] r91442 - /llvm/trunk/utils/TableGen/CodeGenInstruction.cpp Message-ID: <200912151928.nBFJSDqN015936@zion.cs.uiuc.edu> Author: grosbach Date: Tue Dec 15 13:28:13 2009 New Revision: 91442 URL: http://llvm.org/viewvc/llvm-project?rev=91442&view=rev Log: whitespace Modified: llvm/trunk/utils/TableGen/CodeGenInstruction.cpp Modified: llvm/trunk/utils/TableGen/CodeGenInstruction.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenInstruction.cpp?rev=91442&r1=91441&r2=91442&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeGenInstruction.cpp (original) +++ llvm/trunk/utils/TableGen/CodeGenInstruction.cpp Tue Dec 15 13:28:13 2009 @@ -23,31 +23,31 @@ assert(pos != std::string::npos && "Unrecognized constraint"); std::string::size_type start = CStr.find_first_not_of(" \t"); std::string Name = CStr.substr(start, pos - start); - + // TIED_TO: $src1 = $dst std::string::size_type wpos = Name.find_first_of(" \t"); if (wpos == std::string::npos) throw "Illegal format for tied-to constraint: '" + CStr + "'"; std::string DestOpName = Name.substr(0, wpos); std::pair DestOp = I->ParseOperandName(DestOpName, false); - + Name = CStr.substr(pos+1); wpos = Name.find_first_not_of(" \t"); if (wpos == std::string::npos) throw "Illegal format for tied-to constraint: '" + CStr + "'"; - + std::pair SrcOp = I->ParseOperandName(Name.substr(wpos), false); if (SrcOp > DestOp) throw "Illegal tied-to operand constraint '" + CStr + "'"; - - + + unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp); // Build the string for the operand. std::string OpConstraint = "((" + utostr(FlatOpNo) + " << 16) | (1 << TOI::TIED_TO))"; - - + + if (!I->OperandList[DestOp.first].Constraints[DestOp.second].empty()) throw "Operand '" + DestOpName + "' cannot have multiple constraints!"; I->OperandList[DestOp.first].Constraints[DestOp.second] = OpConstraint; @@ -56,20 +56,20 @@ static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) { // Make sure the constraints list for each operand is large enough to hold // constraint info, even if none is present. - for (unsigned i = 0, e = I->OperandList.size(); i != e; ++i) + for (unsigned i = 0, e = I->OperandList.size(); i != e; ++i) I->OperandList[i].Constraints.resize(I->OperandList[i].MINumOperands); - + if (CStr.empty()) return; - + const std::string delims(","); std::string::size_type bidx, eidx; - + bidx = CStr.find_first_not_of(delims); while (bidx != std::string::npos) { eidx = CStr.find_first_of(delims, bidx); if (eidx == std::string::npos) eidx = CStr.length(); - + ParseConstraint(CStr.substr(bidx, eidx - bidx), I); bidx = CStr.find_first_not_of(delims, eidx); } @@ -145,7 +145,7 @@ if (Rec->isSubClassOf("Operand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); - + // Verify that MIOpInfo has an 'ops' root value. if (!dynamic_cast(MIOpInfo->getOperator()) || dynamic_cast(MIOpInfo->getOperator()) @@ -165,7 +165,7 @@ } else if (Rec->getName() == "variable_ops") { isVariadic = true; continue; - } else if (!Rec->isSubClassOf("RegisterClass") && + } else if (!Rec->isSubClassOf("RegisterClass") && Rec->getName() != "ptr_rc" && Rec->getName() != "unknown") throw "Unknown operand class '" + Rec->getName() + "' in '" + R->getName() + "' instruction!"; @@ -177,15 +177,15 @@ if (!OperandNames.insert(DI->getArgName(i)).second) throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + " has the same name as a previous operand!"; - - OperandList.push_back(OperandInfo(Rec, DI->getArgName(i), PrintMethod, + + OperandList.push_back(OperandInfo(Rec, DI->getArgName(i), PrintMethod, MIOperandNo, NumOps, MIOpInfo)); MIOperandNo += NumOps; } // Parse Constraints. ParseConstraints(R->getValueAsString("Constraints"), this); - + // For backward compatibility: isTwoAddress means operand 1 is tied to // operand 0. if (isTwoAddress) { @@ -194,13 +194,13 @@ "already has constraint set!"; OperandList[1].Constraints[0] = "((0 << 16) | (1 << TOI::TIED_TO))"; } - + // Any operands with unset constraints get 0 as their constraint. for (unsigned op = 0, e = OperandList.size(); op != e; ++op) for (unsigned j = 0, e = OperandList[op].MINumOperands; j != e; ++j) if (OperandList[op].Constraints[j].empty()) OperandList[op].Constraints[j] = "0"; - + // Parse the DisableEncoding field. std::string DisableEncoding = R->getValueAsString("DisableEncoding"); while (1) { @@ -229,15 +229,15 @@ "' does not have an operand named '$" + Name + "'!"; } -std::pair +std::pair CodeGenInstruction::ParseOperandName(const std::string &Op, bool AllowWholeOp) { if (Op.empty() || Op[0] != '$') throw TheDef->getName() + ": Illegal operand name: '" + Op + "'"; - + std::string OpName = Op.substr(1); std::string SubOpName; - + // Check to see if this is $foo.bar. std::string::size_type DotIdx = OpName.find_first_of("."); if (DotIdx != std::string::npos) { @@ -246,7 +246,7 @@ throw TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'"; OpName = OpName.substr(0, DotIdx); } - + unsigned OpIdx = getOperandNamed(OpName); if (SubOpName.empty()) { // If no suboperand name was specified: @@ -255,16 +255,16 @@ SubOpName.empty()) throw TheDef->getName() + ": Illegal to refer to" " whole operand part of complex operand '" + Op + "'"; - + // Otherwise, return the operand. return std::make_pair(OpIdx, 0U); } - + // Find the suboperand number involved. DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; if (MIOpInfo == 0) throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; - + // Find the operand with the right name. for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) if (MIOpInfo->getArgName(i) == SubOpName) From sabre at nondot.org Tue Dec 15 13:34:21 2009 From: sabre at nondot.org (Chris Lattner) Date: Tue, 15 Dec 2009 19:34:21 -0000 Subject: [llvm-commits] [llvm] r91444 - in /llvm/trunk/lib/Analysis: DbgInfoPrinter.cpp ValueTracking.cpp Message-ID: <200912151934.nBFJYLlW016130@zion.cs.uiuc.edu> Author: lattner Date: Tue Dec 15 13:34:20 2009 New Revision: 91444 URL: http://llvm.org/viewvc/llvm-project?rev=91444&view=rev Log: Fix GetConstantStringInfo to not look into MDString (it works on real data, not metadata) and fix DbgInfoPrinter to not abuse GetConstantStringInfo. Modified: llvm/trunk/lib/Analysis/DbgInfoPrinter.cpp llvm/trunk/lib/Analysis/ValueTracking.cpp Modified: llvm/trunk/lib/Analysis/DbgInfoPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/DbgInfoPrinter.cpp?rev=91444&r1=91443&r2=91444&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/DbgInfoPrinter.cpp (original) +++ llvm/trunk/lib/Analysis/DbgInfoPrinter.cpp Tue Dec 15 13:34:20 2009 @@ -22,7 +22,6 @@ #include "llvm/Assembly/Writer.h" #include "llvm/Analysis/DebugInfo.h" #include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/ValueTracking.h" #include "llvm/Support/CFG.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" @@ -75,18 +74,16 @@ } void PrintDbgInfo::printStopPoint(const DbgStopPointInst *DSI) { - if (PrintDirectory) { - std::string dir; - GetConstantStringInfo(DSI->getDirectory(), dir); - Out << dir << "/"; - } + if (PrintDirectory) + if (MDString *Str = dyn_cast(DSI->getDirectory())) + Out << Str->getString() << '/'; - std::string file; - GetConstantStringInfo(DSI->getFileName(), file); - Out << file << ":" << DSI->getLine(); + if (MDString *Str = dyn_cast(DSI->getFileName())) + Out << Str->getString(); + Out << ':' << DSI->getLine(); if (unsigned Col = DSI->getColumn()) - Out << ":" << Col; + Out << ':' << Col; } void PrintDbgInfo::printFuncStart(const DbgFuncStartInst *FS) { Modified: llvm/trunk/lib/Analysis/ValueTracking.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ValueTracking.cpp?rev=91444&r1=91443&r2=91444&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp (original) +++ llvm/trunk/lib/Analysis/ValueTracking.cpp Tue Dec 15 13:34:20 2009 @@ -1369,11 +1369,6 @@ StopAtNul); } - if (MDString *MDStr = dyn_cast(V)) { - Str = MDStr->getString(); - return true; - } - // The GEP instruction, constant or instruction, must reference a global // variable that is a constant and is initialized. The referenced constant // initializer is the array that we'll use for optimization. From edwintorok at gmail.com Tue Dec 15 13:39:32 2009 From: edwintorok at gmail.com (=?ISO-8859-1?Q?T=F6r=F6k_Edwin?=) Date: Tue, 15 Dec 2009 21:39:32 +0200 Subject: [llvm-commits] [llvm] r91444 - in /llvm/trunk/lib/Analysis: DbgInfoPrinter.cpp ValueTracking.cpp In-Reply-To: <200912151934.nBFJYLlW016130@zion.cs.uiuc.edu> References: <200912151934.nBFJYLlW016130@zion.cs.uiuc.edu> Message-ID: <4B27E5F4.6070104@gmail.com> On 2009-12-15 21:34, Chris Lattner wrote: > Author: lattner > Date: Tue Dec 15 13:34:20 2009 > New Revision: 91444 > > URL: http://llvm.org/viewvc/llvm-project?rev=91444&view=rev > Log: > Fix GetConstantStringInfo to not look into MDString (it works on > real data, not metadata) and fix DbgInfoPrinter to not abuse > GetConstantStringInfo. > > Thanks. The old way of representing debug info is gone now right? Best regards, --Edwin From clattner at apple.com Tue Dec 15 13:44:50 2009 From: clattner at apple.com (Chris Lattner) Date: Tue, 15 Dec 2009 11:44:50 -0800 Subject: [llvm-commits] [llvm] r91444 - in /llvm/trunk/lib/Analysis: DbgInfoPrinter.cpp ValueTracking.cpp In-Reply-To: <4B27E5F4.6070104@gmail.com> References: <200912151934.nBFJYLlW016130@zion.cs.uiuc.edu> <4B27E5F4.6070104@gmail.com> Message-ID: On Dec 15, 2009, at 11:39 AM, T?r?k Edwin wrote: >> >> URL: http://llvm.org/viewvc/llvm-project?rev=91444&view=rev >> Log: >> Fix GetConstantStringInfo to not look into MDString (it works on >> real data, not metadata) and fix DbgInfoPrinter to not abuse >> GetConstantStringInfo. >> >> > > Thanks. The old way of representing debug info is gone now right? I'm not sure what you mean? -Chris From edwintorok at gmail.com Tue Dec 15 13:47:54 2009 From: edwintorok at gmail.com (=?ISO-8859-1?Q?T=F6r=F6k_Edwin?=) Date: Tue, 15 Dec 2009 21:47:54 +0200 Subject: [llvm-commits] [llvm] r91444 - in /llvm/trunk/lib/Analysis: DbgInfoPrinter.cpp ValueTracking.cpp In-Reply-To: References: <200912151934.nBFJYLlW016130@zion.cs.uiuc.edu> <4B27E5F4.6070104@gmail.com> Message-ID: <4B27E7EA.5030005@gmail.com> On 2009-12-15 21:44, Chris Lattner wrote: > > On Dec 15, 2009, at 11:39 AM, T?r?k Edwin wrote: > >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=91444&view=rev >>> Log: >>> Fix GetConstantStringInfo to not look into MDString (it works on >>> real data, not metadata) and fix DbgInfoPrinter to not abuse >>> GetConstantStringInfo. >>> >>> >> >> Thanks. The old way of representing debug info is gone now right? > > I'm not sure what you mean? Debuginfo is only represented using metadata now, and the old way of representing debuginfo (not using metadata) is not supported at all now. Am I right? DbgInfoPrinter calling GetConstantStringInfo was probably the last piece of the old way. Best regards, --Edwin From dpatel at apple.com Tue Dec 15 14:18:58 2009 From: dpatel at apple.com (Devang Patel) Date: Tue, 15 Dec 2009 12:18:58 -0800 Subject: [llvm-commits] [llvm] r91444 - in /llvm/trunk/lib/Analysis: DbgInfoPrinter.cpp ValueTracking.cpp In-Reply-To: <4B27E7EA.5030005@gmail.com> References: <200912151934.nBFJYLlW016130@zion.cs.uiuc.edu> <4B27E5F4.6070104@gmail.com> <4B27E7EA.5030005@gmail.com> Message-ID: <6F41F94E-671C-435E-A1C2-089B343422C8@apple.com> On Dec 15, 2009, at 11:47 AM, T?r?k Edwin wrote: > On 2009-12-15 21:44, Chris Lattner wrote: >> >> On Dec 15, 2009, at 11:39 AM, T?r?k Edwin wrote: >> >>>> >>>> URL: http://llvm.org/viewvc/llvm-project?rev=91444&view=rev >>>> Log: >>>> Fix GetConstantStringInfo to not look into MDString (it works on >>>> real data, not metadata) and fix DbgInfoPrinter to not abuse >>>> GetConstantStringInfo. >>>> >>>> >>> >>> Thanks. The old way of representing debug info is gone now right? >> >> I'm not sure what you mean? > > Debuginfo is only represented using metadata now, and the old > way of representing debuginfo (not using metadata) is not supported at > all now. > Am I right? Yes. - Devang From gohman at apple.com Tue Dec 15 14:21:45 2009 From: gohman at apple.com (Dan Gohman) Date: Tue, 15 Dec 2009 20:21:45 -0000 Subject: [llvm-commits] [llvm] r91448 - in /llvm/trunk/utils/TableGen: CodeEmitterGen.cpp CodeEmitterGen.h Message-ID: <200912152021.nBFKLjPL019720@zion.cs.uiuc.edu> Author: djg Date: Tue Dec 15 14:21:44 2009 New Revision: 91448 URL: http://llvm.org/viewvc/llvm-project?rev=91448&view=rev Log: Revert 90628, which was incorrect. Modified: llvm/trunk/utils/TableGen/CodeEmitterGen.cpp llvm/trunk/utils/TableGen/CodeEmitterGen.h Modified: llvm/trunk/utils/TableGen/CodeEmitterGen.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeEmitterGen.cpp?rev=91448&r1=91447&r2=91448&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeEmitterGen.cpp (original) +++ llvm/trunk/utils/TableGen/CodeEmitterGen.cpp Tue Dec 15 14:21:44 2009 @@ -61,11 +61,14 @@ // If the VarBitInit at position 'bit' matches the specified variable then // return the variable bit position. Otherwise return -1. -int CodeEmitterGen::getVariableBit(const Init *VarVal, +int CodeEmitterGen::getVariableBit(const std::string &VarName, BitsInit *BI, int bit) { if (VarBitInit *VBI = dynamic_cast(BI->getBit(bit))) { TypedInit *TI = VBI->getVariable(); - if (TI == VarVal) return VBI->getBitNum(); + + if (VarInit *VI = dynamic_cast(TI)) { + if (VI->getName() == VarName) return VBI->getBitNum(); + } } return -1; @@ -159,11 +162,11 @@ if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) { // Is the operand continuous? If so, we can just mask and OR it in // instead of doing it bit-by-bit, saving a lot in runtime cost. - const Init *VarVal = Vals[i].getValue(); + const std::string &VarName = Vals[i].getName(); bool gotOp = false; for (int bit = BI->getNumBits()-1; bit >= 0; ) { - int varBit = getVariableBit(VarVal, BI, bit); + int varBit = getVariableBit(VarName, BI, bit); if (varBit == -1) { --bit; @@ -173,7 +176,7 @@ int N = 1; for (--bit; bit >= 0;) { - varBit = getVariableBit(VarVal, BI, bit); + varBit = getVariableBit(VarName, BI, bit); if (varBit == -1 || varBit != (beginVarBit - N)) break; ++N; --bit; @@ -185,7 +188,7 @@ while (CGI.isFlatOperandNotEmitted(op)) ++op; - Case += " // op: " + Vals[i].getName() + "\n" + Case += " // op: " + VarName + "\n" + " op = getMachineOpValue(MI, MI.getOperand(" + utostr(op++) + "));\n"; gotOp = true; Modified: llvm/trunk/utils/TableGen/CodeEmitterGen.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeEmitterGen.h?rev=91448&r1=91447&r2=91448&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/CodeEmitterGen.h (original) +++ llvm/trunk/utils/TableGen/CodeEmitterGen.h Tue Dec 15 14:21:44 2009 @@ -23,7 +23,6 @@ class RecordVal; class BitsInit; -struct Init; class CodeEmitterGen : public TableGenBackend { RecordKeeper &Records; @@ -36,7 +35,7 @@ void emitMachineOpEmitter(raw_ostream &o, const std::string &Namespace); void emitGetValueBit(raw_ostream &o, const std::string &Namespace); void reverseBits(std::vector &Insts); - int getVariableBit(const Init *VarVal, BitsInit *BI, int bit); + int getVariableBit(const std::string &VarName, BitsInit *BI, int bit); }; } // End llvm namespace From bob.wilson at apple.com Tue Dec 15 15:09:00 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 15 Dec 2009 21:09:00 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r91452 - /llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h Message-ID: <200912152109.nBFL907l021380@zion.cs.uiuc.edu> Author: bwilson Date: Tue Dec 15 15:09:00 2009 New Revision: 91452 URL: http://llvm.org/viewvc/llvm-project?rev=91452&view=rev Log: ARM vectors bigger than 128bits cannot be returned in registers. Radar 7387206. Modified: llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h Modified: llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h?rev=91452&r1=91451&r2=91452&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h (original) +++ llvm-gcc-4.2/trunk/gcc/config/arm/llvm-arm-target.h Tue Dec 15 15:09:00 2009 @@ -82,6 +82,10 @@ #define LLVM_SHOULD_NOT_USE_SHADOW_RETURN(X, CC) \ llvm_arm_should_pass_or_return_aggregate_in_regs((X), (CC)) +/* Vectors bigger than 128 are returned using sret. */ +#define LLVM_SHOULD_RETURN_VECTOR_AS_SHADOW(X, isBuiltin) \ + (TREE_INT_CST_LOW(TYPE_SIZE(X)) > 128) + #endif /* LLVM_ABI_H */ #endif /* ENABLE_LLVM */ /* LLVM LOCAL end (ENTIRE FILE!) */ From bob.wilson at apple.com Tue Dec 15 15:19:09 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 15 Dec 2009 21:19:09 -0000 Subject: [llvm-commits] [test-suite] r91454 - /test-suite/trunk/SingleSource/Benchmarks/Misc/lowercase.c Message-ID: <200912152119.nBFLJ9mY021787@zion.cs.uiuc.edu> Author: bwilson Date: Tue Dec 15 15:19:09 2009 New Revision: 91454 URL: http://llvm.org/viewvc/llvm-project?rev=91454&view=rev Log: Fix this test to avoid using . Modified: test-suite/trunk/SingleSource/Benchmarks/Misc/lowercase.c Modified: test-suite/trunk/SingleSource/Benchmarks/Misc/lowercase.c URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/SingleSource/Benchmarks/Misc/lowercase.c?rev=91454&r1=91453&r2=91454&view=diff ============================================================================== --- test-suite/trunk/SingleSource/Benchmarks/Misc/lowercase.c (original) +++ test-suite/trunk/SingleSource/Benchmarks/Misc/lowercase.c Tue Dec 15 15:19:09 2009 @@ -1,6 +1,7 @@ #include #include -#include + +void *malloc(size_t); typedef unsigned short UChar; From bob.wilson at apple.com Tue Dec 15 15:43:20 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 15 Dec 2009 21:43:20 -0000 Subject: [llvm-commits] [test-suite] r91456 - /test-suite/trunk/External/Makefile Message-ID: <200912152143.nBFLhKeX022615@zion.cs.uiuc.edu> Author: bwilson Date: Tue Dec 15 15:43:19 2009 New Revision: 91456 URL: http://llvm.org/viewvc/llvm-project?rev=91456&view=rev Log: Only run Nurbs on x86 and x86_64 architectures. Modified: test-suite/trunk/External/Makefile Modified: test-suite/trunk/External/Makefile URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/External/Makefile?rev=91456&r1=91455&r2=91456&view=diff ============================================================================== --- test-suite/trunk/External/Makefile (original) +++ test-suite/trunk/External/Makefile Tue Dec 15 15:43:19 2009 @@ -8,7 +8,12 @@ # # Create the list of directories to compile # -PARALLEL_DIRS := SPEC Povray Namd FPGrowth BoxedSim Nurbs HMMER +PARALLEL_DIRS := SPEC Povray Namd FPGrowth BoxedSim HMMER + +ifneq (,$(findstring x86,$(ARCH))) +# Nurbs uses SSE and only works on x86 and x86_64. +PARALLEL_DIRS += Nurbs +endif ifndef USE_POVRAY PARALLEL_DIRS := $(filter-out Povray, $(PARALLEL_DIRS)) From daniel at zuster.org Tue Dec 15 16:00:37 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Tue, 15 Dec 2009 22:00:37 -0000 Subject: [llvm-commits] [llvm] r91458 - /llvm/trunk/utils/lit/TestFormats.py Message-ID: <200912152200.nBFM0b7U023223@zion.cs.uiuc.edu> Author: ddunbar Date: Tue Dec 15 16:00:37 2009 New Revision: 91458 URL: http://llvm.org/viewvc/llvm-project?rev=91458&view=rev Log: lit: Improve error when gtest discovery fails. Modified: llvm/trunk/utils/lit/TestFormats.py Modified: llvm/trunk/utils/lit/TestFormats.py URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/lit/TestFormats.py?rev=91458&r1=91457&r2=91458&view=diff ============================================================================== --- llvm/trunk/utils/lit/TestFormats.py (original) +++ llvm/trunk/utils/lit/TestFormats.py Tue Dec 15 16:00:37 2009 @@ -9,12 +9,17 @@ self.test_sub_dir = str(test_sub_dir) self.test_suffix = str(test_suffix) - def getGTestTests(self, path): + def getGTestTests(self, path, litConfig): """getGTestTests(path) - [name] Return the tests available in gtest executable.""" - lines = Util.capture([path, '--gtest_list_tests']).split('\n') + try: + lines = Util.capture([path, '--gtest_list_tests']).split('\n') + except: + litConfig.error("unable to discover google-tests in %r" % path) + raise StopIteration + nested_tests = [] for ln in lines: if not ln.strip(): @@ -47,7 +52,7 @@ execpath = os.path.join(filepath, subfilename) # Discover the tests in this executable. - for name in self.getGTestTests(execpath): + for name in self.getGTestTests(execpath, litConfig): testPath = path_in_suite + (filename, subfilename, name) yield Test.Test(testSuite, testPath, localConfig) From bob.wilson at apple.com Tue Dec 15 16:00:51 2009 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 15 Dec 2009 22:00:51 -0000 Subject: [llvm-commits] [llvm] r91459 - in /llvm/trunk: lib/Transforms/Scalar/ScalarReplAggregates.cpp test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll Message-ID: <200912152200.nBFM0qqN023245@zion.cs.uiuc.edu> Author: bwilson Date: Tue Dec 15 16:00:51 2009 New Revision: 91459 URL: http://llvm.org/viewvc/llvm-project?rev=91459&view=rev Log: Reapply 91184 with fixes and an addition to the testcase to cover the problem found last time. Instead of trying to modify the IR while iterating over it, I've change it to keep a list of WeakVH references to dead instructions, and then delete those instructions later. I also added some special case code to detect and handle the situation when both operands of a memcpy intrinsic are referencing the same alloca. Added: llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=91459&r1=91458&r2=91459&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Tue Dec 15 16:00:51 2009 @@ -74,6 +74,10 @@ private: TargetData *TD; + /// DeadInsts - Keep track of instructions we have made dead, so that + /// we can remove them after we are done working. + SmallVector DeadInsts; + /// AllocaInfo - When analyzing uses of an alloca instruction, this captures /// information about the uses. All these fields are initialized to false /// and set to true when something is learned. @@ -102,25 +106,30 @@ int isSafeAllocaToScalarRepl(AllocaInst *AI); - void isSafeUseOfAllocation(Instruction *User, AllocaInst *AI, - AllocaInfo &Info); - void isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI, - AllocaInfo &Info); - void isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI, - unsigned OpNo, AllocaInfo &Info); - void isSafeUseOfBitCastedAllocation(BitCastInst *User, AllocaInst *AI, - AllocaInfo &Info); + void isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, + uint64_t ArrayOffset, AllocaInfo &Info); + void isSafeGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t &Offset, + uint64_t &ArrayOffset, AllocaInfo &Info); + void isSafeMemAccess(AllocaInst *AI, uint64_t Offset, uint64_t ArrayOffset, + uint64_t MemSize, const Type *MemOpType, bool isStore, + AllocaInfo &Info); + bool TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size); + unsigned FindElementAndOffset(const Type *&T, uint64_t &Offset); void DoScalarReplacement(AllocaInst *AI, std::vector &WorkList); + void DeleteDeadInstructions(); void CleanupGEP(GetElementPtrInst *GEP); - void CleanupAllocaUsers(AllocaInst *AI); + void CleanupAllocaUsers(Value *V); AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocaInst *Base); - void RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocaInst *AI, - SmallVector &NewElts); - - void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst, + void RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, + SmallVector &NewElts); + void RewriteBitCast(BitCastInst *BC, AllocaInst *AI, uint64_t Offset, + SmallVector &NewElts); + void RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset, + SmallVector &NewElts); + void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, AllocaInst *AI, SmallVector &NewElts); void RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI, @@ -360,176 +369,37 @@ } } - // Now that we have created the alloca instructions that we want to use, - // expand the getelementptr instructions to use them. - while (!AI->use_empty()) { - Instruction *User = cast(AI->use_back()); - if (BitCastInst *BCInst = dyn_cast(User)) { - RewriteBitCastUserOfAlloca(BCInst, AI, ElementAllocas); - BCInst->eraseFromParent(); - continue; - } - - // Replace: - // %res = load { i32, i32 }* %alloc - // with: - // %load.0 = load i32* %alloc.0 - // %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0 - // %load.1 = load i32* %alloc.1 - // %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 - // (Also works for arrays instead of structs) - if (LoadInst *LI = dyn_cast(User)) { - Value *Insert = UndefValue::get(LI->getType()); - for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) { - Value *Load = new LoadInst(ElementAllocas[i], "load", LI); - Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI); - } - LI->replaceAllUsesWith(Insert); - LI->eraseFromParent(); - continue; - } + // Now that we have created the new alloca instructions, rewrite all the + // uses of the old alloca. + DeadInsts.push_back(AI); + RewriteForScalarRepl(AI, AI, 0, ElementAllocas); - // Replace: - // store { i32, i32 } %val, { i32, i32 }* %alloc - // with: - // %val.0 = extractvalue { i32, i32 } %val, 0 - // store i32 %val.0, i32* %alloc.0 - // %val.1 = extractvalue { i32, i32 } %val, 1 - // store i32 %val.1, i32* %alloc.1 - // (Also works for arrays instead of structs) - if (StoreInst *SI = dyn_cast(User)) { - Value *Val = SI->getOperand(0); - for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) { - Value *Extract = ExtractValueInst::Create(Val, i, Val->getName(), SI); - new StoreInst(Extract, ElementAllocas[i], SI); - } - SI->eraseFromParent(); - continue; - } - - GetElementPtrInst *GEPI = cast(User); - // We now know that the GEP is of the form: GEP , 0, - unsigned Idx = - (unsigned)cast(GEPI->getOperand(2))->getZExtValue(); - - assert(Idx < ElementAllocas.size() && "Index out of range?"); - AllocaInst *AllocaToUse = ElementAllocas[Idx]; - - Value *RepValue; - if (GEPI->getNumOperands() == 3) { - // Do not insert a new getelementptr instruction with zero indices, only - // to have it optimized out later. - RepValue = AllocaToUse; - } else { - // We are indexing deeply into the structure, so we still need a - // getelement ptr instruction to finish the indexing. This may be - // expanded itself once the worklist is rerun. - // - SmallVector NewArgs; - NewArgs.push_back(Constant::getNullValue( - Type::getInt32Ty(AI->getContext()))); - NewArgs.append(GEPI->op_begin()+3, GEPI->op_end()); - RepValue = GetElementPtrInst::Create(AllocaToUse, NewArgs.begin(), - NewArgs.end(), "", GEPI); - RepValue->takeName(GEPI); - } - - // If this GEP is to the start of the aggregate, check for memcpys. - if (Idx == 0 && GEPI->hasAllZeroIndices()) - RewriteBitCastUserOfAlloca(GEPI, AI, ElementAllocas); - - // Move all of the users over to the new GEP. - GEPI->replaceAllUsesWith(RepValue); - // Delete the old GEP - GEPI->eraseFromParent(); - } + // Now erase any instructions that were made dead while rewriting the alloca. + DeleteDeadInstructions(); - // Finally, delete the Alloca instruction - AI->eraseFromParent(); NumReplaced++; } -/// isSafeElementUse - Check to see if this use is an allowed use for a -/// getelementptr instruction of an array aggregate allocation. isFirstElt -/// indicates whether Ptr is known to the start of the aggregate. -void SROA::isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI, - AllocaInfo &Info) { - for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); - I != E; ++I) { - Instruction *User = cast(*I); - switch (User->getOpcode()) { - case Instruction::Load: break; - case Instruction::Store: - // Store is ok if storing INTO the pointer, not storing the pointer - if (User->getOperand(0) == Ptr) return MarkUnsafe(Info); - break; - case Instruction::GetElementPtr: { - GetElementPtrInst *GEP = cast(User); - bool AreAllZeroIndices = isFirstElt; - if (GEP->getNumOperands() > 1 && - (!isa(GEP->getOperand(1)) || - !cast(GEP->getOperand(1))->isZero())) - // Using pointer arithmetic to navigate the array. - return MarkUnsafe(Info); - - // Verify that any array subscripts are in range. - for (gep_type_iterator GEPIt = gep_type_begin(GEP), - E = gep_type_end(GEP); GEPIt != E; ++GEPIt) { - // Ignore struct elements, no extra checking needed for these. - if (isa(*GEPIt)) - continue; - - // This GEP indexes an array. Verify that this is an in-range - // constant integer. Specifically, consider A[0][i]. We cannot know that - // the user isn't doing invalid things like allowing i to index an - // out-of-range subscript that accesses A[1]. Because of this, we have - // to reject SROA of any accesses into structs where any of the - // components are variables. - ConstantInt *IdxVal = dyn_cast(GEPIt.getOperand()); - if (!IdxVal) return MarkUnsafe(Info); - - // Are all indices still zero? - AreAllZeroIndices &= IdxVal->isZero(); - - if (const ArrayType *AT = dyn_cast(*GEPIt)) { - if (IdxVal->getZExtValue() >= AT->getNumElements()) - return MarkUnsafe(Info); - } else if (const VectorType *VT = dyn_cast(*GEPIt)) { - if (IdxVal->getZExtValue() >= VT->getNumElements()) - return MarkUnsafe(Info); - } +/// DeleteDeadInstructions - Erase instructions on the DeadInstrs list, +/// recursively including all their operands that become trivially dead. +void SROA::DeleteDeadInstructions() { + while (!DeadInsts.empty()) { + Instruction *I = dyn_cast_or_null(DeadInsts.pop_back_val()); + if (I == 0) + continue; + + for (User::op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) + if (Instruction *U = dyn_cast(*OI)) { + // Zero out the operand and see if it becomes trivially dead. + *OI = 0; + if (isInstructionTriviallyDead(U)) + DeadInsts.push_back(U); } - - isSafeElementUse(GEP, AreAllZeroIndices, AI, Info); - if (Info.isUnsafe) return; - break; - } - case Instruction::BitCast: - if (isFirstElt) { - isSafeUseOfBitCastedAllocation(cast(User), AI, Info); - if (Info.isUnsafe) return; - break; - } - DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); - return MarkUnsafe(Info); - case Instruction::Call: - if (MemIntrinsic *MI = dyn_cast(User)) { - if (isFirstElt) { - isSafeMemIntrinsicOnAllocation(MI, AI, I.getOperandNo(), Info); - if (Info.isUnsafe) return; - break; - } - } - DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); - return MarkUnsafe(Info); - default: - DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); - return MarkUnsafe(Info); - } + + I->eraseFromParent(); } - return; // All users look ok :) } - + /// AllUsersAreLoads - Return true if all users of this value are loads. static bool AllUsersAreLoads(Value *Ptr) { for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); @@ -539,72 +409,116 @@ return true; } -/// isSafeUseOfAllocation - Check if this user is an allowed use for an -/// aggregate allocation. -void SROA::isSafeUseOfAllocation(Instruction *User, AllocaInst *AI, - AllocaInfo &Info) { - if (BitCastInst *C = dyn_cast(User)) - return isSafeUseOfBitCastedAllocation(C, AI, Info); - - if (LoadInst *LI = dyn_cast(User)) - if (!LI->isVolatile()) - return;// Loads (returning a first class aggregrate) are always rewritable - - if (StoreInst *SI = dyn_cast(User)) - if (!SI->isVolatile() && SI->getOperand(0) != AI) - return;// Store is ok if storing INTO the pointer, not storing the pointer - - GetElementPtrInst *GEPI = dyn_cast(User); - if (GEPI == 0) - return MarkUnsafe(Info); - - gep_type_iterator I = gep_type_begin(GEPI), E = gep_type_end(GEPI); +/// isSafeForScalarRepl - Check if instruction I is a safe use with regard to +/// performing scalar replacement of alloca AI. The results are flagged in +/// the Info parameter. Offset and ArrayOffset indicate the position within +/// AI that is referenced by this instruction. +void SROA::isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, + uint64_t ArrayOffset, AllocaInfo &Info) { + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI!=E; ++UI) { + Instruction *User = cast(*UI); - // The GEP is not safe to transform if not of the form "GEP , 0, ". - if (I == E || - I.getOperand() != Constant::getNullValue(I.getOperand()->getType())) { - return MarkUnsafe(Info); + if (BitCastInst *BC = dyn_cast(User)) { + isSafeForScalarRepl(BC, AI, Offset, ArrayOffset, Info); + } else if (GetElementPtrInst *GEPI = dyn_cast(User)) { + uint64_t GEPArrayOffset = ArrayOffset; + uint64_t GEPOffset = Offset; + isSafeGEP(GEPI, AI, GEPOffset, GEPArrayOffset, Info); + if (!Info.isUnsafe) + isSafeForScalarRepl(GEPI, AI, GEPOffset, GEPArrayOffset, Info); + } else if (MemIntrinsic *MI = dyn_cast(UI)) { + ConstantInt *Length = dyn_cast(MI->getLength()); + if (Length) + isSafeMemAccess(AI, Offset, ArrayOffset, Length->getZExtValue(), 0, + UI.getOperandNo() == 1, Info); + else + MarkUnsafe(Info); + } else if (LoadInst *LI = dyn_cast(User)) { + if (!LI->isVolatile()) { + const Type *LIType = LI->getType(); + isSafeMemAccess(AI, Offset, ArrayOffset, TD->getTypeAllocSize(LIType), + LIType, false, Info); + } else + MarkUnsafe(Info); + } else if (StoreInst *SI = dyn_cast(User)) { + // Store is ok if storing INTO the pointer, not storing the pointer + if (!SI->isVolatile() && SI->getOperand(0) != I) { + const Type *SIType = SI->getOperand(0)->getType(); + isSafeMemAccess(AI, Offset, ArrayOffset, TD->getTypeAllocSize(SIType), + SIType, true, Info); + } else + MarkUnsafe(Info); + } else if (isa(UI)) { + // If one user is DbgInfoIntrinsic then check if all users are + // DbgInfoIntrinsics. + if (OnlyUsedByDbgInfoIntrinsics(I)) { + Info.needsCleanup = true; + return; + } + MarkUnsafe(Info); + } else { + DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); + MarkUnsafe(Info); + } + if (Info.isUnsafe) return; } +} - ++I; - if (I == E) return MarkUnsafe(Info); // ran out of GEP indices?? +/// isSafeGEP - Check if a GEP instruction can be handled for scalar +/// replacement. It is safe when all the indices are constant, in-bounds +/// references, and when the resulting offset corresponds to an element within +/// the alloca type. The results are flagged in the Info parameter. Upon +/// return, Offset is adjusted as specified by the GEP indices. For the +/// special case of a variable index to a 2-element array, ArrayOffset is set +/// to the array element size. +void SROA::isSafeGEP(GetElementPtrInst *GEPI, AllocaInst *AI, + uint64_t &Offset, uint64_t &ArrayOffset, + AllocaInfo &Info) { + gep_type_iterator GEPIt = gep_type_begin(GEPI), E = gep_type_end(GEPI); + if (GEPIt == E) + return; + + // The first GEP index must be zero. + if (!isa(GEPIt.getOperand()) || + !cast(GEPIt.getOperand())->isZero()) + return MarkUnsafe(Info); + if (++GEPIt == E) + return; - bool IsAllZeroIndices = true; - // If the first index is a non-constant index into an array, see if we can // handle it as a special case. - if (const ArrayType *AT = dyn_cast(*I)) { - if (!isa(I.getOperand())) { - IsAllZeroIndices = 0; - uint64_t NumElements = AT->getNumElements(); - - // If this is an array index and the index is not constant, we cannot - // promote... that is unless the array has exactly one or two elements in - // it, in which case we CAN promote it, but we have to canonicalize this - // out if this is the only problem. - if ((NumElements == 1 || NumElements == 2) && - AllUsersAreLoads(GEPI)) { + const Type *ArrayEltTy = 0; + if (ArrayOffset == 0 && Offset == 0) { + if (const ArrayType *AT = dyn_cast(*GEPIt)) { + if (!isa(GEPIt.getOperand())) { + uint64_t NumElements = AT->getNumElements(); + + // If this is an array index and the index is not constant, we cannot + // promote... that is unless the array has exactly one or two elements + // in it, in which case we CAN promote it, but we have to canonicalize + // this out if this is the only problem. + if ((NumElements != 1 && NumElements != 2) || !AllUsersAreLoads(GEPI)) + return MarkUnsafe(Info); Info.needsCleanup = true; - return; // Canonicalization required! + ArrayOffset = TD->getTypeAllocSizeInBits(AT->getElementType()); + ArrayEltTy = AT->getElementType(); + ++GEPIt; } - return MarkUnsafe(Info); } } - + // Walk through the GEP type indices, checking the types that this indexes // into. - for (; I != E; ++I) { + for (; GEPIt != E; ++GEPIt) { // Ignore struct elements, no extra checking needed for these. - if (isa(*I)) + if (isa(*GEPIt)) continue; - - ConstantInt *IdxVal = dyn_cast(I.getOperand()); - if (!IdxVal) return MarkUnsafe(Info); - // Are all indices still zero? - IsAllZeroIndices &= IdxVal->isZero(); - - if (const ArrayType *AT = dyn_cast(*I)) { + ConstantInt *IdxVal = dyn_cast(GEPIt.getOperand()); + if (!IdxVal) + return MarkUnsafe(Info); + + if (const ArrayType *AT = dyn_cast(*GEPIt)) { // This GEP indexes an array. Verify that this is an in-range constant // integer. Specifically, consider A[0][i]. We cannot know that the user // isn't doing invalid things like allowing i to index an out-of-range @@ -612,147 +526,255 @@ // of any accesses into structs where any of the components are variables. if (IdxVal->getZExtValue() >= AT->getNumElements()) return MarkUnsafe(Info); - } else if (const VectorType *VT = dyn_cast(*I)) { + } else { + const VectorType *VT = dyn_cast(*GEPIt); + assert(VT && "unexpected type in GEP type iterator"); if (IdxVal->getZExtValue() >= VT->getNumElements()) return MarkUnsafe(Info); } } - - // If there are any non-simple uses of this getelementptr, make sure to reject - // them. - return isSafeElementUse(GEPI, IsAllZeroIndices, AI, Info); + + // All the indices are safe. Now compute the offset due to this GEP and + // check if the alloca has a component element at that offset. + if (ArrayOffset == 0) { + SmallVector Indices(GEPI->op_begin() + 1, GEPI->op_end()); + Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(), + &Indices[0], Indices.size()); + } else { + // Both array elements have the same type, so it suffices to check one of + // them. Copy the GEP indices starting from the array index, but replace + // that variable index with a constant zero. + SmallVector Indices(GEPI->op_begin() + 2, GEPI->op_end()); + Indices[0] = Constant::getNullValue(Type::getInt32Ty(GEPI->getContext())); + const Type *ArrayEltPtr = PointerType::getUnqual(ArrayEltTy); + Offset += TD->getIndexedOffset(ArrayEltPtr, &Indices[0], Indices.size()); + } + if (!TypeHasComponent(AI->getAllocatedType(), Offset, 0)) + MarkUnsafe(Info); +} + +/// isSafeMemAccess - Check if a load/store/memcpy operates on the entire AI +/// alloca or has an offset and size that corresponds to a component element +/// within it. The offset checked here may have been formed from a GEP with a +/// pointer bitcasted to a different type. +void SROA::isSafeMemAccess(AllocaInst *AI, uint64_t Offset, + uint64_t ArrayOffset, uint64_t MemSize, + const Type *MemOpType, bool isStore, + AllocaInfo &Info) { + // Check if this is a load/store of the entire alloca. + if (Offset == 0 && ArrayOffset == 0 && + MemSize == TD->getTypeAllocSize(AI->getAllocatedType())) { + bool UsesAggregateType = (MemOpType == AI->getAllocatedType()); + // This is safe for MemIntrinsics (where MemOpType is 0), integer types + // (which are essentially the same as the MemIntrinsics, especially with + // regard to copying padding between elements), or references using the + // aggregate type of the alloca. + if (!MemOpType || isa(MemOpType) || UsesAggregateType) { + if (!UsesAggregateType) { + if (isStore) + Info.isMemCpyDst = true; + else + Info.isMemCpySrc = true; + } + return; + } + } + // Check if the offset/size correspond to a component within the alloca type. + const Type *T = AI->getAllocatedType(); + if (TypeHasComponent(T, Offset, MemSize) && + (ArrayOffset == 0 || TypeHasComponent(T, Offset + ArrayOffset, MemSize))) + return; + + return MarkUnsafe(Info); } -/// isSafeMemIntrinsicOnAllocation - Check if the specified memory -/// intrinsic can be promoted by SROA. At this point, we know that the operand -/// of the memintrinsic is a pointer to the beginning of the allocation. -void SROA::isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI, - unsigned OpNo, AllocaInfo &Info) { - // If not constant length, give up. - ConstantInt *Length = dyn_cast(MI->getLength()); - if (!Length) return MarkUnsafe(Info); - - // If not the whole aggregate, give up. - if (Length->getZExtValue() != - TD->getTypeAllocSize(AI->getType()->getElementType())) - return MarkUnsafe(Info); - - // We only know about memcpy/memset/memmove. - if (!isa(MI)) - return MarkUnsafe(Info); - - // Otherwise, we can transform it. Determine whether this is a memcpy/set - // into or out of the aggregate. - if (OpNo == 1) - Info.isMemCpyDst = true; - else { - assert(OpNo == 2); - Info.isMemCpySrc = true; +/// TypeHasComponent - Return true if T has a component type with the +/// specified offset and size. If Size is zero, do not check the size. +bool SROA::TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size) { + const Type *EltTy; + uint64_t EltSize; + if (const StructType *ST = dyn_cast(T)) { + const StructLayout *Layout = TD->getStructLayout(ST); + unsigned EltIdx = Layout->getElementContainingOffset(Offset); + EltTy = ST->getContainedType(EltIdx); + EltSize = TD->getTypeAllocSize(EltTy); + Offset -= Layout->getElementOffset(EltIdx); + } else if (const ArrayType *AT = dyn_cast(T)) { + EltTy = AT->getElementType(); + EltSize = TD->getTypeAllocSize(EltTy); + Offset %= EltSize; + } else { + return false; } + if (Offset == 0 && (Size == 0 || EltSize == Size)) + return true; + // Check if the component spans multiple elements. + if (Offset + Size > EltSize) + return false; + return TypeHasComponent(EltTy, Offset, Size); } -/// isSafeUseOfBitCastedAllocation - Check if all users of this bitcast -/// from an alloca are safe for SROA of that alloca. -void SROA::isSafeUseOfBitCastedAllocation(BitCastInst *BC, AllocaInst *AI, - AllocaInfo &Info) { - for (Value::use_iterator UI = BC->use_begin(), E = BC->use_end(); - UI != E; ++UI) { - if (BitCastInst *BCU = dyn_cast(UI)) { - isSafeUseOfBitCastedAllocation(BCU, AI, Info); - } else if (MemIntrinsic *MI = dyn_cast(UI)) { - isSafeMemIntrinsicOnAllocation(MI, AI, UI.getOperandNo(), Info); - } else if (StoreInst *SI = dyn_cast(UI)) { - if (SI->isVolatile()) - return MarkUnsafe(Info); - - // If storing the entire alloca in one chunk through a bitcasted pointer - // to integer, we can transform it. This happens (for example) when you - // cast a {i32,i32}* to i64* and store through it. This is similar to the - // memcpy case and occurs in various "byval" cases and emulated memcpys. - if (isa(SI->getOperand(0)->getType()) && - TD->getTypeAllocSize(SI->getOperand(0)->getType()) == - TD->getTypeAllocSize(AI->getType()->getElementType())) { - Info.isMemCpyDst = true; - continue; - } - return MarkUnsafe(Info); - } else if (LoadInst *LI = dyn_cast(UI)) { - if (LI->isVolatile()) - return MarkUnsafe(Info); +/// RewriteForScalarRepl - Alloca AI is being split into NewElts, so rewrite +/// the instruction I, which references it, to use the separate elements. +/// Offset indicates the position within AI that is referenced by this +/// instruction. +void SROA::RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, + SmallVector &NewElts) { + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI!=E; ++UI) { + Instruction *User = cast(*UI); - // If loading the entire alloca in one chunk through a bitcasted pointer - // to integer, we can transform it. This happens (for example) when you - // cast a {i32,i32}* to i64* and load through it. This is similar to the - // memcpy case and occurs in various "byval" cases and emulated memcpys. - if (isa(LI->getType()) && - TD->getTypeAllocSize(LI->getType()) == - TD->getTypeAllocSize(AI->getType()->getElementType())) { - Info.isMemCpySrc = true; - continue; + if (BitCastInst *BC = dyn_cast(User)) { + RewriteBitCast(BC, AI, Offset, NewElts); + } else if (GetElementPtrInst *GEPI = dyn_cast(User)) { + RewriteGEP(GEPI, AI, Offset, NewElts); + } else if (MemIntrinsic *MI = dyn_cast(User)) { + ConstantInt *Length = dyn_cast(MI->getLength()); + uint64_t MemSize = Length->getZExtValue(); + if (Offset == 0 && + MemSize == TD->getTypeAllocSize(AI->getAllocatedType())) + RewriteMemIntrinUserOfAlloca(MI, I, AI, NewElts); + } else if (LoadInst *LI = dyn_cast(User)) { + const Type *LIType = LI->getType(); + if (LIType == AI->getAllocatedType()) { + // Replace: + // %res = load { i32, i32 }* %alloc + // with: + // %load.0 = load i32* %alloc.0 + // %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0 + // %load.1 = load i32* %alloc.1 + // %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 + // (Also works for arrays instead of structs) + Value *Insert = UndefValue::get(LIType); + for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { + Value *Load = new LoadInst(NewElts[i], "load", LI); + Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI); + } + LI->replaceAllUsesWith(Insert); + DeadInsts.push_back(LI); + } else if (isa(LIType) && + TD->getTypeAllocSize(LIType) == + TD->getTypeAllocSize(AI->getAllocatedType())) { + // If this is a load of the entire alloca to an integer, rewrite it. + RewriteLoadUserOfWholeAlloca(LI, AI, NewElts); } - return MarkUnsafe(Info); - } else if (isa(UI)) { - // If one user is DbgInfoIntrinsic then check if all users are - // DbgInfoIntrinsics. - if (OnlyUsedByDbgInfoIntrinsics(BC)) { - Info.needsCleanup = true; - return; + } else if (StoreInst *SI = dyn_cast(User)) { + Value *Val = SI->getOperand(0); + const Type *SIType = Val->getType(); + if (SIType == AI->getAllocatedType()) { + // Replace: + // store { i32, i32 } %val, { i32, i32 }* %alloc + // with: + // %val.0 = extractvalue { i32, i32 } %val, 0 + // store i32 %val.0, i32* %alloc.0 + // %val.1 = extractvalue { i32, i32 } %val, 1 + // store i32 %val.1, i32* %alloc.1 + // (Also works for arrays instead of structs) + for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { + Value *Extract = ExtractValueInst::Create(Val, i, Val->getName(), SI); + new StoreInst(Extract, NewElts[i], SI); + } + DeadInsts.push_back(SI); + } else if (isa(SIType) && + TD->getTypeAllocSize(SIType) == + TD->getTypeAllocSize(AI->getAllocatedType())) { + // If this is a store of the entire alloca from an integer, rewrite it. + RewriteStoreUserOfWholeAlloca(SI, AI, NewElts); } - else - MarkUnsafe(Info); } - else { - return MarkUnsafe(Info); - } - if (Info.isUnsafe) return; } } -/// RewriteBitCastUserOfAlloca - BCInst (transitively) bitcasts AI, or indexes -/// to its first element. Transform users of the cast to use the new values -/// instead. -void SROA::RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocaInst *AI, - SmallVector &NewElts) { - Value::use_iterator UI = BCInst->use_begin(), UE = BCInst->use_end(); - while (UI != UE) { - Instruction *User = cast(*UI++); - if (BitCastInst *BCU = dyn_cast(User)) { - RewriteBitCastUserOfAlloca(BCU, AI, NewElts); - if (BCU->use_empty()) BCU->eraseFromParent(); - continue; - } +/// RewriteBitCast - Update a bitcast reference to the alloca being replaced +/// and recursively continue updating all of its uses. +void SROA::RewriteBitCast(BitCastInst *BC, AllocaInst *AI, uint64_t Offset, + SmallVector &NewElts) { + RewriteForScalarRepl(BC, AI, Offset, NewElts); + if (BC->getOperand(0) != AI) + return; - if (MemIntrinsic *MI = dyn_cast(User)) { - // This must be memcpy/memmove/memset of the entire aggregate. - // Split into one per element. - RewriteMemIntrinUserOfAlloca(MI, BCInst, AI, NewElts); - continue; - } - - if (StoreInst *SI = dyn_cast(User)) { - // If this is a store of the entire alloca from an integer, rewrite it. - RewriteStoreUserOfWholeAlloca(SI, AI, NewElts); - continue; - } + // The bitcast references the original alloca. Replace its uses with + // references to the first new element alloca. + Instruction *Val = NewElts[0]; + if (Val->getType() != BC->getDestTy()) { + Val = new BitCastInst(Val, BC->getDestTy(), "", BC); + Val->takeName(BC); + } + BC->replaceAllUsesWith(Val); + DeadInsts.push_back(BC); +} + +/// FindElementAndOffset - Return the index of the element containing Offset +/// within the specified type, which must be either a struct or an array. +/// Sets T to the type of the element and Offset to the offset within that +/// element. +unsigned SROA::FindElementAndOffset(const Type *&T, uint64_t &Offset) { + unsigned Idx = 0; + if (const StructType *ST = dyn_cast(T)) { + const StructLayout *Layout = TD->getStructLayout(ST); + Idx = Layout->getElementContainingOffset(Offset); + T = ST->getContainedType(Idx); + Offset -= Layout->getElementOffset(Idx); + } else { + const ArrayType *AT = dyn_cast(T); + assert(AT && "unexpected type for scalar replacement"); + T = AT->getElementType(); + uint64_t EltSize = TD->getTypeAllocSize(T); + Idx = (unsigned)(Offset / EltSize); + Offset -= Idx * EltSize; + } + return Idx; +} + +/// RewriteGEP - Check if this GEP instruction moves the pointer across +/// elements of the alloca that are being split apart, and if so, rewrite +/// the GEP to be relative to the new element. +void SROA::RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset, + SmallVector &NewElts) { + uint64_t OldOffset = Offset; + SmallVector Indices(GEPI->op_begin() + 1, GEPI->op_end()); + Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(), + &Indices[0], Indices.size()); + + RewriteForScalarRepl(GEPI, AI, Offset, NewElts); + + const Type *T = AI->getAllocatedType(); + unsigned OldIdx = FindElementAndOffset(T, OldOffset); + if (GEPI->getOperand(0) == AI) + OldIdx = ~0U; // Force the GEP to be rewritten. + + T = AI->getAllocatedType(); + uint64_t EltOffset = Offset; + unsigned Idx = FindElementAndOffset(T, EltOffset); + + // If this GEP does not move the pointer across elements of the alloca + // being split, then it does not needs to be rewritten. + if (Idx == OldIdx) + return; - if (LoadInst *LI = dyn_cast(User)) { - // If this is a load of the entire alloca to an integer, rewrite it. - RewriteLoadUserOfWholeAlloca(LI, AI, NewElts); - continue; - } - - // Otherwise it must be some other user of a gep of the first pointer. Just - // leave these alone. - continue; - } + const Type *i32Ty = Type::getInt32Ty(AI->getContext()); + SmallVector NewArgs; + NewArgs.push_back(Constant::getNullValue(i32Ty)); + while (EltOffset != 0) { + unsigned EltIdx = FindElementAndOffset(T, EltOffset); + NewArgs.push_back(ConstantInt::get(i32Ty, EltIdx)); + } + Instruction *Val = NewElts[Idx]; + if (NewArgs.size() > 1) { + Val = GetElementPtrInst::CreateInBounds(Val, NewArgs.begin(), + NewArgs.end(), "", GEPI); + Val->takeName(GEPI); + } + if (Val->getType() != GEPI->getType()) + Val = new BitCastInst(Val, GEPI->getType(), Val->getNameStr(), GEPI); + GEPI->replaceAllUsesWith(Val); + DeadInsts.push_back(GEPI); } /// RewriteMemIntrinUserOfAlloca - MI is a memcpy/memset/memmove from or to AI. /// Rewrite it to copy or set the elements of the scalarized memory. -void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst, +void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, AllocaInst *AI, SmallVector &NewElts) { - // If this is a memcpy/memmove, construct the other pointer as the // appropriate type. The "Other" pointer is the pointer that goes to memory // that doesn't have anything to do with the alloca that we are promoting. For @@ -761,28 +783,41 @@ LLVMContext &Context = MI->getContext(); unsigned MemAlignment = MI->getAlignment(); if (MemTransferInst *MTI = dyn_cast(MI)) { // memmove/memcopy - if (BCInst == MTI->getRawDest()) + if (Inst == MTI->getRawDest()) OtherPtr = MTI->getRawSource(); else { - assert(BCInst == MTI->getRawSource()); + assert(Inst == MTI->getRawSource()); OtherPtr = MTI->getRawDest(); } } - // Keep track of the other intrinsic argument, so it can be removed if it - // is dead when the intrinsic is replaced. - Value *PossiblyDead = OtherPtr; - // If there is an other pointer, we want to convert it to the same pointer // type as AI has, so we can GEP through it safely. if (OtherPtr) { - // It is likely that OtherPtr is a bitcast, if so, remove it. - if (BitCastInst *BC = dyn_cast(OtherPtr)) - OtherPtr = BC->getOperand(0); - // All zero GEPs are effectively bitcasts. - if (GetElementPtrInst *GEP = dyn_cast(OtherPtr)) - if (GEP->hasAllZeroIndices()) - OtherPtr = GEP->getOperand(0); + + // Remove bitcasts and all-zero GEPs from OtherPtr. This is an + // optimization, but it's also required to detect the corner case where + // both pointer operands are referencing the same memory, and where + // OtherPtr may be a bitcast or GEP that currently being rewritten. (This + // function is only called for mem intrinsics that access the whole + // aggregate, so non-zero GEPs are not an issue here.) + while (1) { + if (BitCastInst *BC = dyn_cast(OtherPtr)) { + OtherPtr = BC->getOperand(0); + continue; + } + if (GetElementPtrInst *GEP = dyn_cast(OtherPtr)) { + // All zero GEPs are effectively bitcasts. + if (GEP->hasAllZeroIndices()) { + OtherPtr = GEP->getOperand(0); + continue; + } + } + break; + } + // If OtherPtr has already been rewritten, this intrinsic will be dead. + if (OtherPtr == NewElts[0]) + return; if (ConstantExpr *BCE = dyn_cast(OtherPtr)) if (BCE->getOpcode() == Instruction::BitCast) @@ -798,7 +833,7 @@ // Process each element of the aggregate. Value *TheFn = MI->getOperand(0); const Type *BytePtrTy = MI->getRawDest()->getType(); - bool SROADest = MI->getRawDest() == BCInst; + bool SROADest = MI->getRawDest() == Inst; Constant *Zero = Constant::getNullValue(Type::getInt32Ty(MI->getContext())); @@ -807,12 +842,15 @@ Value *OtherElt = 0; unsigned OtherEltAlign = MemAlignment; - if (OtherPtr) { + if (OtherPtr == AI) { + OtherElt = NewElts[i]; + OtherEltAlign = 0; + } else if (OtherPtr) { Value *Idx[2] = { Zero, ConstantInt::get(Type::getInt32Ty(MI->getContext()), i) }; - OtherElt = GetElementPtrInst::Create(OtherPtr, Idx, Idx + 2, + OtherElt = GetElementPtrInst::CreateInBounds(OtherPtr, Idx, Idx + 2, OtherPtr->getNameStr()+"."+Twine(i), - MI); + MI); uint64_t EltOffset; const PointerType *OtherPtrTy = cast(OtherPtr->getType()); if (const StructType *ST = @@ -924,9 +962,7 @@ CallInst::Create(TheFn, Ops, Ops + 4, "", MI); } } - MI->eraseFromParent(); - if (PossiblyDead) - RecursivelyDeleteTriviallyDeadInstructions(PossiblyDead); + DeadInsts.push_back(MI); } /// RewriteStoreUserOfWholeAlloca - We found a store of an integer that @@ -937,15 +973,9 @@ // Extract each element out of the integer according to its structure offset // and store the element value to the individual alloca. Value *SrcVal = SI->getOperand(0); - const Type *AllocaEltTy = AI->getType()->getElementType(); + const Type *AllocaEltTy = AI->getAllocatedType(); uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy); - // If this isn't a store of an integer to the whole alloca, it may be a store - // to the first element. Just ignore the store in this case and normal SROA - // will handle it. - if (!isa(SrcVal->getType()) || - TD->getTypeAllocSizeInBits(SrcVal->getType()) != AllocaSizeBits) - return; // Handle tail padding by extending the operand if (TD->getTypeSizeInBits(SrcVal->getType()) != AllocaSizeBits) SrcVal = new ZExtInst(SrcVal, @@ -1050,7 +1080,7 @@ } } - SI->eraseFromParent(); + DeadInsts.push_back(SI); } /// RewriteLoadUserOfWholeAlloca - We found a load of the entire allocation to @@ -1059,16 +1089,9 @@ SmallVector &NewElts) { // Extract each element out of the NewElts according to its structure offset // and form the result value. - const Type *AllocaEltTy = AI->getType()->getElementType(); + const Type *AllocaEltTy = AI->getAllocatedType(); uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy); - // If this isn't a load of the whole alloca to an integer, it may be a load - // of the first element. Just ignore the load in this case and normal SROA - // will handle it. - if (!isa(LI->getType()) || - TD->getTypeAllocSizeInBits(LI->getType()) != AllocaSizeBits) - return; - DEBUG(errs() << "PROMOTING LOAD OF WHOLE ALLOCA: " << *AI << '\n' << *LI << '\n'); @@ -1139,10 +1162,9 @@ ResultVal = new TruncInst(ResultVal, LI->getType(), "", LI); LI->replaceAllUsesWith(ResultVal); - LI->eraseFromParent(); + DeadInsts.push_back(LI); } - /// HasPadding - Return true if the specified type has any structure or /// alignment padding, false otherwise. static bool HasPadding(const Type *Ty, const TargetData &TD) { @@ -1192,14 +1214,10 @@ // the users are safe to transform. AllocaInfo Info; - for (Value::use_iterator I = AI->use_begin(), E = AI->use_end(); - I != E; ++I) { - isSafeUseOfAllocation(cast(*I), AI, Info); - if (Info.isUnsafe) { - DEBUG(errs() << "Cannot transform: " << *AI << "\n due to user: " - << **I << '\n'); - return 0; - } + isSafeForScalarRepl(AI, AI, 0, 0, Info); + if (Info.isUnsafe) { + DEBUG(errs() << "Cannot transform: " << *AI << '\n'); + return 0; } // Okay, we know all the users are promotable. If the aggregate is a memcpy @@ -1208,7 +1226,7 @@ // types, but may actually be used. In these cases, we refuse to promote the // struct. if (Info.isMemCpySrc && Info.isMemCpyDst && - HasPadding(AI->getType()->getElementType(), *TD)) + HasPadding(AI->getAllocatedType(), *TD)) return 0; // If we require cleanup, return 1, otherwise return 3. @@ -1245,15 +1263,15 @@ // Insert the new GEP instructions, which are properly indexed. SmallVector Indices(GEPI->op_begin()+1, GEPI->op_end()); Indices[1] = Constant::getNullValue(Type::getInt32Ty(GEPI->getContext())); - Value *ZeroIdx = GetElementPtrInst::Create(GEPI->getOperand(0), - Indices.begin(), - Indices.end(), - GEPI->getName()+".0", GEPI); + Value *ZeroIdx = GetElementPtrInst::CreateInBounds(GEPI->getOperand(0), + Indices.begin(), + Indices.end(), + GEPI->getName()+".0",GEPI); Indices[1] = ConstantInt::get(Type::getInt32Ty(GEPI->getContext()), 1); - Value *OneIdx = GetElementPtrInst::Create(GEPI->getOperand(0), - Indices.begin(), - Indices.end(), - GEPI->getName()+".1", GEPI); + Value *OneIdx = GetElementPtrInst::CreateInBounds(GEPI->getOperand(0), + Indices.begin(), + Indices.end(), + GEPI->getName()+".1", GEPI); // Replace all loads of the variable index GEP with loads from both // indexes and a select. while (!GEPI->use_empty()) { @@ -1264,22 +1282,24 @@ LI->replaceAllUsesWith(R); LI->eraseFromParent(); } - GEPI->eraseFromParent(); } - /// CleanupAllocaUsers - If SROA reported that it can promote the specified /// allocation, but only if cleaned up, perform the cleanups required. -void SROA::CleanupAllocaUsers(AllocaInst *AI) { +void SROA::CleanupAllocaUsers(Value *V) { // At this point, we know that the end result will be SROA'd and promoted, so // we can insert ugly code if required so long as sroa+mem2reg will clean it // up. - for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); + for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ) { User *U = *UI++; - if (GetElementPtrInst *GEPI = dyn_cast(U)) + if (isa(U)) { + CleanupAllocaUsers(U); + } else if (GetElementPtrInst *GEPI = dyn_cast(U)) { CleanupGEP(GEPI); - else { + CleanupAllocaUsers(GEPI); + if (GEPI->use_empty()) GEPI->eraseFromParent(); + } else { Instruction *I = cast(U); SmallVector DbgInUses; if (!isa(I) && OnlyUsedByDbgInfoIntrinsics(I, &DbgInUses)) { @@ -1395,7 +1415,7 @@ // Compute the offset that this GEP adds to the pointer. SmallVector Indices(GEP->op_begin()+1, GEP->op_end()); - uint64_t GEPOffset = TD->getIndexedOffset(GEP->getOperand(0)->getType(), + uint64_t GEPOffset = TD->getIndexedOffset(GEP->getPointerOperandType(), &Indices[0], Indices.size()); // See if all uses can be converted. if (!CanConvertToScalar(GEP, IsNotTrivial, VecTy, SawVec,Offset+GEPOffset, @@ -1457,7 +1477,7 @@ if (GetElementPtrInst *GEP = dyn_cast(User)) { // Compute the offset that this GEP adds to the pointer. SmallVector Indices(GEP->op_begin()+1, GEP->op_end()); - uint64_t GEPOffset = TD->getIndexedOffset(GEP->getOperand(0)->getType(), + uint64_t GEPOffset = TD->getIndexedOffset(GEP->getPointerOperandType(), &Indices[0], Indices.size()); ConvertUsesToScalar(GEP, NewAI, Offset+GEPOffset*8); GEP->eraseFromParent(); Added: llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll?rev=91459&view=auto ============================================================================== --- llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll (added) +++ llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll Tue Dec 15 16:00:51 2009 @@ -0,0 +1,89 @@ +; RUN: opt < %s -scalarrepl -S | FileCheck %s +; Radar 7441282 + +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32" +target triple = "thumbv7-apple-darwin10" + +%struct.__neon_int16x8x2_t = type { <8 x i16>, <8 x i16> } +%struct.int16x8_t = type { <8 x i16> } +%struct.int16x8x2_t = type { [2 x %struct.int16x8_t] } +%union..0anon = type { %struct.int16x8x2_t } + +define arm_apcscc void @test(<8 x i16> %tmp.0, %struct.int16x8x2_t* %dst) nounwind { +; CHECK: @test +; CHECK-NOT: alloca +; CHECK: "alloca point" +entry: + %tmp_addr = alloca %struct.int16x8_t ; <%struct.int16x8_t*> [#uses=3] + %dst_addr = alloca %struct.int16x8x2_t* ; <%struct.int16x8x2_t**> [#uses=2] + %__rv = alloca %union..0anon ; <%union..0anon*> [#uses=2] + %__bx = alloca %struct.int16x8_t ; <%struct.int16x8_t*> [#uses=2] + %__ax = alloca %struct.int16x8_t ; <%struct.int16x8_t*> [#uses=2] + %tmp2 = alloca %struct.int16x8x2_t ; <%struct.int16x8x2_t*> [#uses=2] + %0 = alloca %struct.int16x8x2_t ; <%struct.int16x8x2_t*> [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + %1 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] + store <8 x i16> %tmp.0, <8 x i16>* %1 + store %struct.int16x8x2_t* %dst, %struct.int16x8x2_t** %dst_addr + %2 = getelementptr inbounds %struct.int16x8_t* %__ax, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] + %3 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] + %4 = load <8 x i16>* %3, align 16 ; <<8 x i16>> [#uses=1] + store <8 x i16> %4, <8 x i16>* %2, align 16 + %5 = getelementptr inbounds %struct.int16x8_t* %__bx, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] + %6 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] + %7 = load <8 x i16>* %6, align 16 ; <<8 x i16>> [#uses=1] + store <8 x i16> %7, <8 x i16>* %5, align 16 + %8 = getelementptr inbounds %struct.int16x8_t* %__ax, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] + %9 = load <8 x i16>* %8, align 16 ; <<8 x i16>> [#uses=2] + %10 = getelementptr inbounds %struct.int16x8_t* %__bx, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] + %11 = load <8 x i16>* %10, align 16 ; <<8 x i16>> [#uses=2] + %12 = getelementptr inbounds %union..0anon* %__rv, i32 0, i32 0 ; <%struct.int16x8x2_t*> [#uses=1] + %13 = bitcast %struct.int16x8x2_t* %12 to %struct.__neon_int16x8x2_t* ; <%struct.__neon_int16x8x2_t*> [#uses=2] + %14 = shufflevector <8 x i16> %9, <8 x i16> %11, <8 x i32> ; <<8 x i16>> [#uses=1] + %15 = getelementptr inbounds %struct.__neon_int16x8x2_t* %13, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] + store <8 x i16> %14, <8 x i16>* %15 + %16 = shufflevector <8 x i16> %9, <8 x i16> %11, <8 x i32> ; <<8 x i16>> [#uses=1] + %17 = getelementptr inbounds %struct.__neon_int16x8x2_t* %13, i32 0, i32 1 ; <<8 x i16>*> [#uses=1] + store <8 x i16> %16, <8 x i16>* %17 + %18 = getelementptr inbounds %union..0anon* %__rv, i32 0, i32 0 ; <%struct.int16x8x2_t*> [#uses=1] + %19 = bitcast %struct.int16x8x2_t* %0 to i8* ; [#uses=1] + %20 = bitcast %struct.int16x8x2_t* %18 to i8* ; [#uses=1] + call void @llvm.memcpy.i32(i8* %19, i8* %20, i32 32, i32 16) + %tmp21 = bitcast %struct.int16x8x2_t* %tmp2 to i8* ; [#uses=1] + %21 = bitcast %struct.int16x8x2_t* %0 to i8* ; [#uses=1] + call void @llvm.memcpy.i32(i8* %tmp21, i8* %21, i32 32, i32 16) + %22 = load %struct.int16x8x2_t** %dst_addr, align 4 ; <%struct.int16x8x2_t*> [#uses=1] + %23 = bitcast %struct.int16x8x2_t* %22 to i8* ; [#uses=1] + %tmp22 = bitcast %struct.int16x8x2_t* %tmp2 to i8* ; [#uses=1] + call void @llvm.memcpy.i32(i8* %23, i8* %tmp22, i32 32, i32 16) + br label %return + +; CHECK: store <8 x i16> +; CHECK: store <8 x i16> + +return: ; preds = %entry + ret void +} + +; Radar 7466574 +%struct._NSRange = type { i64 } + +define arm_apcscc void @test_memcpy_self() nounwind { +; CHECK: @test_memcpy_self +; CHECK-NOT: alloca +; CHECK: br i1 +entry: + %range = alloca %struct._NSRange ; <%struct._NSRange*> [#uses=2] + br i1 undef, label %cond.true, label %cond.false + +cond.true: ; preds = %entry + %tmp3 = bitcast %struct._NSRange* %range to i8* ; [#uses=1] + %tmp4 = bitcast %struct._NSRange* %range to i8* ; [#uses=1] + call void @llvm.memcpy.i32(i8* %tmp3, i8* %tmp4, i32 8, i32 8) + ret void + +cond.false: ; preds = %entry + ret void +} + +declare void @llvm.memcpy.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind From isanbard at gmail.com Tue Dec 15 16:42:20 2009 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 15 Dec 2009 22:42:20 -0000 Subject: [llvm-commits] [llvm] r91463 - /llvm/trunk/utils/buildit/build_llvm Message-ID: <200912152242.nBFMgKCf025008@zion.cs.uiuc.edu> Author: void Date: Tue Dec 15 16:42:19 2009 New Revision: 91463 URL: http://llvm.org/viewvc/llvm-project?rev=91463&view=rev Log: Some command lines don't like numbers with leading zeros. Remove them. Modified: llvm/trunk/utils/buildit/build_llvm Modified: llvm/trunk/utils/buildit/build_llvm URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/buildit/build_llvm?rev=91463&r1=91462&r2=91463&view=diff ============================================================================== --- llvm/trunk/utils/buildit/build_llvm (original) +++ llvm/trunk/utils/buildit/build_llvm Tue Dec 15 16:42:19 2009 @@ -243,7 +243,11 @@ fi # Install Version.h -RC_ProjectSourceSubversion=`printf "%d" $LLVM_SUBMIT_SUBVERSION` +LLVM_MINOR_VERSION=`echo $LLVM_SUBMIT_SUBVERSION | sed -e 's,0*\([1-9][0-9]*\),\1,'` +if [ "x$LLVM_MINOR_VERSION" = "x" ]; then + LLVM_MINOR_VERSION=0 +fi +RC_ProjectSourceSubversion=`printf "%d" $LLVM_MINOR_VERSION` echo "#define LLVM_VERSION ${RC_ProjectSourceVersion}" > $DEST_DIR$DEST_ROOT/include/llvm/Version.h echo "#define LLVM_MINOR_VERSION ${RC_ProjectSourceSubversion}" >> $DEST_DIR$DEST_ROOT/include/llvm/Version.h From jyasskin at google.com Tue Dec 15 16:42:46 2009 From: jyasskin at google.com (Jeffrey Yasskin) Date: Tue, 15 Dec 2009 22:42:46 -0000 Subject: [llvm-commits] [llvm] r91464 - in /llvm/trunk: include/llvm/CodeGen/JITCodeEmitter.h include/llvm/CodeGen/MachineCodeEmitter.h lib/ExecutionEngine/JIT/JITEmitter.cpp lib/Target/ARM/ARMJITInfo.cpp lib/Target/Alpha/AlphaJITInfo.cpp lib/Target/PowerPC/PPCJITInfo.cpp lib/Target/X86/X86JITInfo.cpp Message-ID: <200912152242.nBFMgkQt025040@zion.cs.uiuc.edu> Author: jyasskin Date: Tue Dec 15 16:42:46 2009 New Revision: 91464 URL: http://llvm.org/viewvc/llvm-project?rev=91464&view=rev Log: Change indirect-globals to use a dedicated allocIndirectGV. This lets us remove start/finishGVStub and the BufferState helper class from the MachineCodeEmitter interface. It has the side-effect of not setting the indirect global writable and then executable on ARM, but that shouldn't be necessary. Modified: llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp llvm/trunk/lib/Target/ARM/ARMJITInfo.cpp llvm/trunk/lib/Target/Alpha/AlphaJITInfo.cpp llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp llvm/trunk/lib/Target/X86/X86JITInfo.cpp Modified: llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h?rev=91464&r1=91463&r2=91464&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h (original) +++ llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h Tue Dec 15 16:42:46 2009 @@ -68,29 +68,11 @@ /// virtual bool finishFunction(MachineFunction &F) = 0; - /// startGVStub - This callback is invoked when the JIT needs the address of a - /// GV (e.g. function) that has not been code generated yet. The StubSize - /// specifies the total size required by the stub. The BufferState must be - /// passed to finishGVStub, and start/finish pairs with the same BufferState - /// must be properly nested. - /// - virtual void startGVStub(BufferState &BS, const GlobalValue* GV, - unsigned StubSize, unsigned Alignment = 1) = 0; - - /// startGVStub - This callback is invoked when the JIT needs the address of a - /// GV (e.g. function) that has not been code generated yet. Buffer points to - /// memory already allocated for this stub. The BufferState must be passed to - /// finishGVStub, and start/finish pairs with the same BufferState must be - /// properly nested. - /// - virtual void startGVStub(BufferState &BS, void *Buffer, - unsigned StubSize) = 0; - - /// finishGVStub - This callback is invoked to terminate a GV stub and returns - /// the start address of the stub. The BufferState must first have been - /// passed to startGVStub. - /// - virtual void *finishGVStub(BufferState &BS) = 0; + /// allocIndirectGV - Allocates and fills storage for an indirect + /// GlobalValue, and returns the address. + virtual void *allocIndirectGV(const GlobalValue *GV, + const uint8_t *Buffer, size_t Size, + unsigned Alignment) = 0; /// emitByte - This callback is invoked when a byte needs to be written to the /// output stream. Modified: llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h?rev=91464&r1=91463&r2=91464&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h (original) +++ llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h Tue Dec 15 16:42:46 2009 @@ -48,41 +48,16 @@ /// occurred, more memory is allocated, and we reemit the code into it. /// class MachineCodeEmitter { -public: - class BufferState { - friend class MachineCodeEmitter; - /// BufferBegin/BufferEnd - Pointers to the start and end of the memory - /// allocated for this code buffer. - uint8_t *BufferBegin, *BufferEnd; - - /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting - /// code. This is guranteed to be in the range [BufferBegin,BufferEnd]. If - /// this pointer is at BufferEnd, it will never move due to code emission, - /// and all code emission requests will be ignored (this is the buffer - /// overflow condition). - uint8_t *CurBufferPtr; - public: - BufferState() : BufferBegin(NULL), BufferEnd(NULL), CurBufferPtr(NULL) {} - }; - protected: - /// These have the same meanings as the fields in BufferState - uint8_t *BufferBegin, *BufferEnd, *CurBufferPtr; - - /// Save or restore the current buffer state. The BufferState objects must be - /// used as a stack. - void SaveStateTo(BufferState &BS) { - assert(BS.BufferBegin == NULL && - "Can't save state into the same BufferState twice."); - BS.BufferBegin = BufferBegin; - BS.BufferEnd = BufferEnd; - BS.CurBufferPtr = CurBufferPtr; - } - void RestoreStateFrom(BufferState &BS) { - BufferBegin = BS.BufferBegin; - BufferEnd = BS.BufferEnd; - CurBufferPtr = BS.CurBufferPtr; - } + /// BufferBegin/BufferEnd - Pointers to the start and end of the memory + /// allocated for this code buffer. + uint8_t *BufferBegin, *BufferEnd; + /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting + /// code. This is guranteed to be in the range [BufferBegin,BufferEnd]. If + /// this pointer is at BufferEnd, it will never move due to code emission, and + /// all code emission requests will be ignored (this is the buffer overflow + /// condition). + uint8_t *CurBufferPtr; public: virtual ~MachineCodeEmitter() {} @@ -113,15 +88,23 @@ /// void emitWordLE(uint32_t W) { if (4 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 0); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 24); + emitWordLEInto(CurBufferPtr, W); } else { CurBufferPtr = BufferEnd; } } - + + /// emitWordLEInto - This callback is invoked when a 32-bit word needs to be + /// written to an arbitrary buffer in little-endian format. Buf must have at + /// least 4 bytes of available space. + /// + static void emitWordLEInto(uint8_t *&Buf, uint32_t W) { + *Buf++ = (uint8_t)(W >> 0); + *Buf++ = (uint8_t)(W >> 8); + *Buf++ = (uint8_t)(W >> 16); + *Buf++ = (uint8_t)(W >> 24); + } + /// emitWordBE - This callback is invoked when a 32-bit word needs to be /// written to the output stream in big-endian format. /// Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp?rev=91464&r1=91463&r2=91464&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp Tue Dec 15 16:42:46 2009 @@ -271,6 +271,10 @@ class JITEmitter : public JITCodeEmitter { JITMemoryManager *MemMgr; + // When outputting a function stub in the context of some other function, we + // save BufferBegin/BufferEnd/CurBufferPtr here. + uint8_t *SavedBufferBegin, *SavedBufferEnd, *SavedCurBufferPtr; + // When reattempting to JIT a function after running out of space, we store // the estimated size of the function we're trying to JIT here, so we can // ask the memory manager for at least this much space. When we @@ -396,11 +400,13 @@ void initJumpTableInfo(MachineJumpTableInfo *MJTI); void emitJumpTableInfo(MachineJumpTableInfo *MJTI); - virtual void startGVStub(BufferState &BS, const GlobalValue* GV, - unsigned StubSize, unsigned Alignment = 1); - virtual void startGVStub(BufferState &BS, void *Buffer, - unsigned StubSize); - virtual void* finishGVStub(BufferState &BS); + void startGVStub(const GlobalValue* GV, + unsigned StubSize, unsigned Alignment = 1); + void startGVStub(void *Buffer, unsigned StubSize); + void finishGVStub(); + virtual void *allocIndirectGV(const GlobalValue *GV, + const uint8_t *Buffer, size_t Size, + unsigned Alignment); /// allocateSpace - Reserves space in the current block if any, or /// allocate a new one of the given size. @@ -521,13 +527,12 @@ if (!Actual) return 0; } - MachineCodeEmitter::BufferState BS; TargetJITInfo::StubLayout SL = TheJIT->getJITInfo().getStubLayout(); - JE.startGVStub(BS, F, SL.Size, SL.Alignment); + JE.startGVStub(F, SL.Size, SL.Alignment); // Codegen a new stub, calling the lazy resolver or the actual address of the // external function, if it was resolved. Stub = TheJIT->getJITInfo().emitFunctionStub(F, Actual, JE); - JE.finishGVStub(BS); + JE.finishGVStub(); if (Actual != (void*)(intptr_t)LazyResolverFn) { // If we are getting the stub for an external function, we really want the @@ -579,11 +584,10 @@ void *&Stub = ExternalFnToStubMap[FnAddr]; if (Stub) return Stub; - MachineCodeEmitter::BufferState BS; TargetJITInfo::StubLayout SL = TheJIT->getJITInfo().getStubLayout(); - JE.startGVStub(BS, 0, SL.Size, SL.Alignment); + JE.startGVStub(0, SL.Size, SL.Alignment); Stub = TheJIT->getJITInfo().emitFunctionStub(0, FnAddr, JE); - JE.finishGVStub(BS); + JE.finishGVStub(); DEBUG(errs() << "JIT: Stub emitted at [" << Stub << "] for external function at '" << FnAddr << "'\n"); @@ -1215,8 +1219,9 @@ if (DwarfExceptionHandling || JITEmitDebugInfo) { uintptr_t ActualSize = 0; - BufferState BS; - SaveStateTo(BS); + SavedBufferBegin = BufferBegin; + SavedBufferEnd = BufferEnd; + SavedCurBufferPtr = CurBufferPtr; if (MemMgr->NeedsExactSize()) { ActualSize = DE->GetDwarfTableSizeInBytes(F, *this, FnStart, FnEnd); @@ -1232,7 +1237,9 @@ MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, FrameRegister); uint8_t *EhEnd = CurBufferPtr; - RestoreStateFrom(BS); + BufferBegin = SavedBufferBegin; + BufferEnd = SavedBufferEnd; + CurBufferPtr = SavedCurBufferPtr; if (DwarfExceptionHandling) { TheJIT->RegisterTable(FrameRegister); @@ -1438,27 +1445,39 @@ } } -void JITEmitter::startGVStub(BufferState &BS, const GlobalValue* GV, +void JITEmitter::startGVStub(const GlobalValue* GV, unsigned StubSize, unsigned Alignment) { - SaveStateTo(BS); + SavedBufferBegin = BufferBegin; + SavedBufferEnd = BufferEnd; + SavedCurBufferPtr = CurBufferPtr; BufferBegin = CurBufferPtr = MemMgr->allocateStub(GV, StubSize, Alignment); BufferEnd = BufferBegin+StubSize+1; } -void JITEmitter::startGVStub(BufferState &BS, void *Buffer, unsigned StubSize) { - SaveStateTo(BS); +void JITEmitter::startGVStub(void *Buffer, unsigned StubSize) { + SavedBufferBegin = BufferBegin; + SavedBufferEnd = BufferEnd; + SavedCurBufferPtr = CurBufferPtr; BufferBegin = CurBufferPtr = (uint8_t *)Buffer; BufferEnd = BufferBegin+StubSize+1; } -void *JITEmitter::finishGVStub(BufferState &BS) { +void JITEmitter::finishGVStub() { assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space."); NumBytes += getCurrentPCOffset(); - void *Result = BufferBegin; - RestoreStateFrom(BS); - return Result; + BufferBegin = SavedBufferBegin; + BufferEnd = SavedBufferEnd; + CurBufferPtr = SavedCurBufferPtr; +} + +void *JITEmitter::allocIndirectGV(const GlobalValue *GV, + const uint8_t *Buffer, size_t Size, + unsigned Alignment) { + uint8_t *IndGV = MemMgr->allocateStub(GV, Size, Alignment); + memcpy(IndGV, Buffer, Size); + return IndGV; } // getConstantPoolEntryAddress - Return the address of the 'ConstantNum' entry @@ -1546,11 +1565,10 @@ // Tell the target jit info to rewrite the stub at the specified address, // rather than creating a new one. - MachineCodeEmitter::BufferState BS; TargetJITInfo::StubLayout layout = getJITInfo().getStubLayout(); - JE->startGVStub(BS, Stub, layout.Size); + JE->startGVStub(Stub, layout.Size); getJITInfo().emitFunctionStub(F, Addr, *getCodeEmitter()); - JE->finishGVStub(BS); + JE->finishGVStub(); } /// freeMachineCodeForFunction - release machine code memory for given Function. Modified: llvm/trunk/lib/Target/ARM/ARMJITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMJITInfo.cpp?rev=91464&r1=91463&r2=91464&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMJITInfo.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMJITInfo.cpp Tue Dec 15 16:42:46 2009 @@ -139,17 +139,11 @@ void *ARMJITInfo::emitGlobalValueIndirectSym(const GlobalValue *GV, void *Ptr, JITCodeEmitter &JCE) { - MachineCodeEmitter::BufferState BS; - JCE.startGVStub(BS, GV, 4, 4); - intptr_t Addr = (intptr_t)JCE.getCurrentPCValue(); - if (!sys::Memory::setRangeWritable((void*)Addr, 4)) { - llvm_unreachable("ERROR: Unable to mark indirect symbol writable"); - } - JCE.emitWordLE((intptr_t)Ptr); - if (!sys::Memory::setRangeExecutable((void*)Addr, 4)) { - llvm_unreachable("ERROR: Unable to mark indirect symbol executable"); - } - void *PtrAddr = JCE.finishGVStub(BS); + uint8_t Buffer[4]; + uint8_t *Cur = Buffer; + MachineCodeEmitter::emitWordLEInto(Cur, (intptr_t)Ptr); + void *PtrAddr = JCE.allocIndirectGV( + GV, Buffer, sizeof(Buffer), /*Alignment=*/4); addIndirectSymAddr(Ptr, (intptr_t)PtrAddr); return PtrAddr; } Modified: llvm/trunk/lib/Target/Alpha/AlphaJITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Alpha/AlphaJITInfo.cpp?rev=91464&r1=91463&r2=91464&view=diff ============================================================================== --- llvm/trunk/lib/Target/Alpha/AlphaJITInfo.cpp (original) +++ llvm/trunk/lib/Target/Alpha/AlphaJITInfo.cpp Tue Dec 15 16:42:46 2009 @@ -202,7 +202,6 @@ void *AlphaJITInfo::emitFunctionStub(const Function* F, void *Fn, JITCodeEmitter &JCE) { - MachineCodeEmitter::BufferState BS; //assert(Fn == AlphaCompilationCallback && "Where are you going?\n"); //Do things in a stupid slow way! void* Addr = (void*)(intptr_t)JCE.getCurrentPCValue(); Modified: llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp?rev=91464&r1=91463&r2=91464&view=diff ============================================================================== --- llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp (original) +++ llvm/trunk/lib/Target/PowerPC/PPCJITInfo.cpp Tue Dec 15 16:42:46 2009 @@ -339,7 +339,6 @@ void *PPCJITInfo::emitFunctionStub(const Function* F, void *Fn, JITCodeEmitter &JCE) { - MachineCodeEmitter::BufferState BS; // If this is just a call to an external function, emit a branch instead of a // call. The code is the same except for one bit of the last instruction. if (Fn != (void*)(intptr_t)PPC32CompilationCallback && Modified: llvm/trunk/lib/Target/X86/X86JITInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86JITInfo.cpp?rev=91464&r1=91463&r2=91464&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86JITInfo.cpp (original) +++ llvm/trunk/lib/Target/X86/X86JITInfo.cpp Tue Dec 15 16:42:46 2009 @@ -426,16 +426,19 @@ void *X86JITInfo::emitGlobalValueIndirectSym(const GlobalValue* GV, void *ptr, JITCodeEmitter &JCE) { - MachineCodeEmitter::BufferState BS; #if defined (X86_64_JIT) - JCE.startGVStub(BS, GV, 8, 8); - JCE.emitWordLE((unsigned)(intptr_t)ptr); - JCE.emitWordLE((unsigned)(((intptr_t)ptr) >> 32)); -#else - JCE.startGVStub(BS, GV, 4, 4); - JCE.emitWordLE((intptr_t)ptr); + const unsigned Alignment = 8; + uint8_t Buffer[8]; + uint8_t *Cur = Buffer; + MachineCodeEmitter::emitWordLEInto(Cur, (unsigned)(intptr_t)ptr); + MachineCodeEmitter::emitWordLEInto(Cur, (unsigned)(((intptr_t)ptr) >> 32)); +#else + const unsigned Alignment = 4; + uint8_t Buffer[4]; + uint8_t *Cur = Buffer; + MachineCodeEmitter::emitWordLEInto(Cur, (intptr_t)ptr); #endif - return JCE.finishGVStub(BS); + return JCE.allocIndirectGV(GV, Buffer, sizeof(Buffer), Alignment); } TargetJITInfo::StubLayout X86JITInfo::getStubLayout() { @@ -451,7 +454,6 @@ void *X86JITInfo::emitFunctionStub(const Function* F, void *Target, JITCodeEmitter &JCE) { - MachineCodeEmitter::BufferState BS; // Note, we cast to intptr_t here to silence a -pedantic warning that // complains about casting a function pointer to a normal pointer. #if defined (X86_32_JIT) && !defined (_MSC_VER) From isanbard at gmail.com Tue Dec 15 18:00:19 2009 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 16 Dec 2009 00:00:19 -0000 Subject: [llvm-commits] [llvm] r91475 - /llvm/trunk/lib/CodeGen/BranchFolding.cpp Message-ID: <200912160000.nBG00JU2027930@zion.cs.uiuc.edu> Author: void Date: Tue Dec 15 18:00:18 2009 New Revision: 91475 URL: http://llvm.org/viewvc/llvm-project?rev=91475&view=rev Log: Initialize uninitialized variables. Modified: llvm/trunk/lib/CodeGen/BranchFolding.cpp Modified: llvm/trunk/lib/CodeGen/BranchFolding.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/BranchFolding.cpp?rev=91475&r1=91474&r2=91475&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/BranchFolding.cpp (original) +++ llvm/trunk/lib/CodeGen/BranchFolding.cpp Tue Dec 15 18:00:18 2009 @@ -1222,7 +1222,7 @@ // Analyze the branch at the end of the pred. MachineBasicBlock *PredBB = *PI; MachineFunction::iterator PredFallthrough = PredBB; ++PredFallthrough; - MachineBasicBlock *PredTBB, *PredFBB; + MachineBasicBlock *PredTBB = 0, *PredFBB = 0; SmallVector PredCond; if (PredBB != MBB && !PredBB->canFallThrough() && !TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true) From isanbard at gmail.com Tue Dec 15 18:01:27 2009 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 16 Dec 2009 00:01:27 -0000 Subject: [llvm-commits] [llvm] r91477 - /llvm/trunk/lib/CodeGen/BranchFolding.cpp Message-ID: <200912160001.nBG01SRj027999@zion.cs.uiuc.edu> Author: void Date: Tue Dec 15 18:01:27 2009 New Revision: 91477 URL: http://llvm.org/viewvc/llvm-project?rev=91477&view=rev Log: Initialize uninitialized variables. Modified: llvm/trunk/lib/CodeGen/BranchFolding.cpp Modified: llvm/trunk/lib/CodeGen/BranchFolding.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/BranchFolding.cpp?rev=91477&r1=91476&r2=91477&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/BranchFolding.cpp (original) +++ llvm/trunk/lib/CodeGen/BranchFolding.cpp Tue Dec 15 18:01:27 2009 @@ -1274,7 +1274,7 @@ // Okay, there is no really great place to put this block. If, however, // the block before this one would be a fall-through if this block were // removed, move this block to the end of the function. - MachineBasicBlock *PrevTBB, *PrevFBB; + MachineBasicBlock *PrevTBB = 0, *PrevFBB = 0; SmallVector PrevCond; if (FallThrough != MF.end() && !TII->AnalyzeBranch(PrevBB, PrevTBB, PrevFBB, PrevCond, true) && From isanbard at gmail.com Tue Dec 15 18:08:36 2009 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 16 Dec 2009 00:08:36 -0000 Subject: [llvm-commits] [llvm] r91479 - /llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp Message-ID: <200912160008.nBG08bbj028247@zion.cs.uiuc.edu> Author: void Date: Tue Dec 15 18:08:36 2009 New Revision: 91479 URL: http://llvm.org/viewvc/llvm-project?rev=91479&view=rev Log: Helpful comment added. Some code cleanup. No functional change. Modified: llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp Modified: llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp?rev=91479&r1=91478&r2=91479&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp (original) +++ llvm/trunk/lib/CodeGen/MachineBasicBlock.cpp Tue Dec 15 18:08:36 2009 @@ -450,14 +450,29 @@ /// CorrectExtraCFGEdges - Various pieces of code can cause excess edges in the /// CFG to be inserted. If we have proven that MBB can only branch to DestA and -/// DestB, remove any other MBB successors from the CFG. DestA and DestB can -/// be null. +/// DestB, remove any other MBB successors from the CFG. DestA and DestB can be +/// null. +/// /// Besides DestA and DestB, retain other edges leading to LandingPads /// (currently there can be only one; we don't check or require that here). /// Note it is possible that DestA and/or DestB are LandingPads. bool MachineBasicBlock::CorrectExtraCFGEdges(MachineBasicBlock *DestA, MachineBasicBlock *DestB, bool isCond) { + // The values of DestA and DestB frequently come from a call to the + // 'TargetInstrInfo::AnalyzeBranch' method. We take our meaning of the initial + // values from there. + // + // 1. If both DestA and DestB are null, then the block ends with no branches + // (it falls through to its successor). + // 2. If DestA is set, DestB is null, and isCond is false, then the block ends + // with only an unconditional branch. + // 3. If DestA is set, DestB is null, and isCond is true, then the block ends + // with a conditional branch that falls through to a successor (DestB). + // 4. If DestA and DestB is set and isCond is true, then the block ends with a + // conditional branch followed by an unconditional branch. DestA is the + // 'true' destination and DestB is the 'false' destination. + bool MadeChange = false; bool AddedFallThrough = false; @@ -483,14 +498,15 @@ MachineBasicBlock::succ_iterator SI = succ_begin(); MachineBasicBlock *OrigDestA = DestA, *OrigDestB = DestB; while (SI != succ_end()) { - if (*SI == DestA) { + const MachineBasicBlock *MBB = *SI; + if (MBB == DestA) { DestA = 0; ++SI; - } else if (*SI == DestB) { + } else if (MBB == DestB) { DestB = 0; ++SI; - } else if ((*SI)->isLandingPad() && - *SI!=OrigDestA && *SI!=OrigDestB) { + } else if (MBB->isLandingPad() && + MBB != OrigDestA && MBB != OrigDestB) { ++SI; } else { // Otherwise, this is a superfluous edge, remove it. @@ -498,12 +514,12 @@ MadeChange = true; } } - if (!AddedFallThrough) { - assert(DestA == 0 && DestB == 0 && - "MachineCFG is missing edges!"); - } else if (isCond) { + + if (!AddedFallThrough) + assert(DestA == 0 && DestB == 0 && "MachineCFG is missing edges!"); + else if (isCond) assert(DestA == 0 && "MachineCFG is missing edges!"); - } + return MadeChange; } From rjmccall at apple.com Tue Dec 15 18:13:25 2009 From: rjmccall at apple.com (John McCall) Date: Wed, 16 Dec 2009 00:13:25 -0000 Subject: [llvm-commits] [llvm] r91480 - in /llvm/trunk/lib/CodeGen: MachineDominators.cpp MachineLoopInfo.cpp Message-ID: <200912160013.nBG0DPm6028423@zion.cs.uiuc.edu> Author: rjmccall Date: Tue Dec 15 18:13:24 2009 New Revision: 91480 URL: http://llvm.org/viewvc/llvm-project?rev=91480&view=rev Log: Explicit template instantiations must happen in the template's immediately enclosing namespace. Caught by clang++. Modified: llvm/trunk/lib/CodeGen/MachineDominators.cpp llvm/trunk/lib/CodeGen/MachineLoopInfo.cpp Modified: llvm/trunk/lib/CodeGen/MachineDominators.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineDominators.cpp?rev=91480&r1=91479&r2=91480&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/MachineDominators.cpp (original) +++ llvm/trunk/lib/CodeGen/MachineDominators.cpp Tue Dec 15 18:13:24 2009 @@ -17,8 +17,10 @@ using namespace llvm; +namespace llvm { TEMPLATE_INSTANTIATION(class DomTreeNodeBase); TEMPLATE_INSTANTIATION(class DominatorTreeBase); +} char MachineDominatorTree::ID = 0; Modified: llvm/trunk/lib/CodeGen/MachineLoopInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineLoopInfo.cpp?rev=91480&r1=91479&r2=91480&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/MachineLoopInfo.cpp (original) +++ llvm/trunk/lib/CodeGen/MachineLoopInfo.cpp Tue Dec 15 18:13:24 2009 @@ -19,12 +19,14 @@ #include "llvm/CodeGen/Passes.h" using namespace llvm; +namespace llvm { #define MLB class LoopBase TEMPLATE_INSTANTIATION(MLB); #undef MLB #define MLIB class LoopInfoBase TEMPLATE_INSTANTIATION(MLIB); #undef MLIB +} char MachineLoopInfo::ID = 0; static RegisterPass From rjmccall at apple.com Tue Dec 15 18:15:28 2009 From: rjmccall at apple.com (John McCall) Date: Wed, 16 Dec 2009 00:15:28 -0000 Subject: [llvm-commits] [llvm] r91481 - /llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Message-ID: <200912160015.nBG0FSRb028494@zion.cs.uiuc.edu> Author: rjmccall Date: Tue Dec 15 18:15:28 2009 New Revision: 91481 URL: http://llvm.org/viewvc/llvm-project?rev=91481&view=rev Log: Every anonymous namespace is different. Caught by clang++. Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=91481&r1=91480&r2=91481&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original) +++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Tue Dec 15 18:15:28 2009 @@ -98,10 +98,6 @@ virtual bool ParseDirective(AsmToken DirectiveID); }; -} // end anonymous namespace - -namespace { - /// ARMOperand - Instances of this class represent a parsed ARM machine /// instruction. struct ARMOperand { From mrs at apple.com Tue Dec 15 18:24:48 2009 From: mrs at apple.com (Mike Stump) Date: Tue, 15 Dec 2009 16:24:48 -0800 Subject: [llvm-commits] [llvm] r91481 - /llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp In-Reply-To: <200912160015.nBG0FSRb028494@zion.cs.uiuc.edu> References: <200912160015.nBG0FSRb028494@zion.cs.uiuc.edu> Message-ID: On Dec 15, 2009, at 4:15 PM, John McCall wrote: > Author: rjmccall > Date: Tue Dec 15 18:15:28 2009 > New Revision: 91481 > Every anonymous namespace is different. Caught by clang++. But each unnamed namespace in a translation unit is in fact the same namespace. From dalej at apple.com Tue Dec 15 18:29:42 2009 From: dalej at apple.com (Dale Johannesen) Date: Wed, 16 Dec 2009 00:29:42 -0000 Subject: [llvm-commits] [llvm] r91485 - in /llvm/trunk: lib/CodeGen/RegAllocLocal.cpp test/CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll test/CodeGen/X86/phys-reg-local-regalloc.ll Message-ID: <200912160029.nBG0TgcE028980@zion.cs.uiuc.edu> Author: johannes Date: Tue Dec 15 18:29:41 2009 New Revision: 91485 URL: http://llvm.org/viewvc/llvm-project?rev=91485&view=rev Log: Do better with physical reg operands (typically, from inline asm) in local register allocator. If a reg-reg copy has a phys reg input and a virt reg output, and this is the last use of the phys reg, assign the phys reg to the virt reg. If a reg-reg copy has a phys reg output and we need to reload its spilled input, reload it directly into the phys reg than passing it through another reg. Following 76208, there is sometimes no dependency between the def of a phys reg and its use; this creates a window where that phys reg can be used for spilling (this is true in linear scan also). This is bad and needs to be fixed a better way, although 76208 works too well in practice to be reverted. However, there should normally be no spilling within inline asm blocks. The patch here goes a long way towards making this actually be true. Added: llvm/trunk/test/CodeGen/X86/phys-reg-local-regalloc.ll Modified: llvm/trunk/lib/CodeGen/RegAllocLocal.cpp llvm/trunk/test/CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll Modified: llvm/trunk/lib/CodeGen/RegAllocLocal.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocLocal.cpp?rev=91485&r1=91484&r2=91485&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocLocal.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocLocal.cpp Tue Dec 15 18:29:41 2009 @@ -233,14 +233,17 @@ /// in one of several ways: if the register is available in a physical /// register already, it uses that physical register. If the value is not /// in a physical register, and if there are physical registers available, - /// it loads it into a register. If register pressure is high, and it is - /// possible, it tries to fold the load of the virtual register into the - /// instruction itself. It avoids doing this if register pressure is low to - /// improve the chance that subsequent instructions can use the reloaded - /// value. This method returns the modified instruction. + /// it loads it into a register: PhysReg if that is an available physical + /// register, otherwise any physical register of the right class. + /// If register pressure is high, and it is possible, it tries to fold the + /// load of the virtual register into the instruction itself. It avoids + /// doing this if register pressure is low to improve the chance that + /// subsequent instructions can use the reloaded value. This method + /// returns the modified instruction. /// MachineInstr *reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI, - unsigned OpNum, SmallSet &RRegs); + unsigned OpNum, SmallSet &RRegs, + unsigned PhysReg); /// ComputeLocalLiveness - Computes liveness of registers within a basic /// block, setting the killed/dead flags as appropriate. @@ -471,15 +474,17 @@ /// one of several ways: if the register is available in a physical register /// already, it uses that physical register. If the value is not in a physical /// register, and if there are physical registers available, it loads it into a +/// register: PhysReg if that is an available physical register, otherwise any /// register. If register pressure is high, and it is possible, it tries to /// fold the load of the virtual register into the instruction itself. It /// avoids doing this if register pressure is low to improve the chance that -/// subsequent instructions can use the reloaded value. This method returns the -/// modified instruction. +/// subsequent instructions can use the reloaded value. This method returns +/// the modified instruction. /// MachineInstr *RALocal::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI, unsigned OpNum, - SmallSet &ReloadedRegs) { + SmallSet &ReloadedRegs, + unsigned PhysReg) { unsigned VirtReg = MI->getOperand(OpNum).getReg(); // If the virtual register is already available, just update the instruction @@ -494,7 +499,11 @@ // Otherwise, we need to fold it into the current instruction, or reload it. // If we have registers available to hold the value, use them. const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg); - unsigned PhysReg = getFreeReg(RC); + // If we already have a PhysReg (this happens when the instruction is a + // reg-to-reg copy with a PhysReg destination) use that. + if (!PhysReg || !TargetRegisterInfo::isPhysicalRegister(PhysReg) || + !isPhysRegAvailable(PhysReg)) + PhysReg = getFreeReg(RC); int FrameIndex = getStackSpaceFor(VirtReg, RC); if (PhysReg) { // Register is available, allocate it! @@ -752,6 +761,12 @@ errs() << '\n'; }); + // Determine whether this is a copy instruction. The cases where the + // source or destination are phys regs are handled specially. + unsigned SrcCopyReg, DstCopyReg, SrcCopySubReg, DstCopySubReg; + bool isCopy = TII->isMoveInstr(*MI, SrcCopyReg, DstCopyReg, + SrcCopySubReg, DstCopySubReg); + // Loop over the implicit uses, making sure that they are at the head of the // use order list, so they don't get reallocated. if (TID.ImplicitUses) { @@ -835,7 +850,8 @@ // here we are looking for only used operands (never def&use) if (MO.isReg() && !MO.isDef() && MO.getReg() && !MO.isImplicit() && TargetRegisterInfo::isVirtualRegister(MO.getReg())) - MI = reloadVirtReg(MBB, MI, i, ReloadedRegs); + MI = reloadVirtReg(MBB, MI, i, ReloadedRegs, + isCopy ? DstCopyReg : 0); } // If this instruction is the last user of this register, kill the @@ -948,8 +964,17 @@ unsigned DestPhysReg; // If DestVirtReg already has a value, use it. - if (!(DestPhysReg = getVirt2PhysRegMapSlot(DestVirtReg))) - DestPhysReg = getReg(MBB, MI, DestVirtReg); + if (!(DestPhysReg = getVirt2PhysRegMapSlot(DestVirtReg))) { + // If this is a copy, the source reg is a phys reg, and + // that reg is available, use that phys reg for DestPhysReg. + if (isCopy && + TargetRegisterInfo::isPhysicalRegister(SrcCopyReg) && + isPhysRegAvailable(SrcCopyReg)) { + DestPhysReg = SrcCopyReg; + assignVirtToPhysReg(DestVirtReg, DestPhysReg); + } else + DestPhysReg = getReg(MBB, MI, DestVirtReg); + } MF->getRegInfo().setPhysRegUsed(DestPhysReg); markVirtRegModified(DestVirtReg); getVirtRegLastUse(DestVirtReg) = std::make_pair((MachineInstr*)0, 0); @@ -995,9 +1020,9 @@ // Finally, if this is a noop copy instruction, zap it. (Except that if // the copy is dead, it must be kept to avoid messing up liveness info for // the register scavenger. See pr4100.) - unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; - if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg) && - SrcReg == DstReg && DeadDefs.empty()) + if (TII->isMoveInstr(*MI, SrcCopyReg, DstCopyReg, + SrcCopySubReg, DstCopySubReg) && + SrcCopyReg == DstCopyReg && DeadDefs.empty()) MBB.erase(MI); } Modified: llvm/trunk/test/CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll?rev=91485&r1=91484&r2=91485&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll (original) +++ llvm/trunk/test/CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll Tue Dec 15 18:29:41 2009 @@ -1,7 +1,7 @@ ; RUN: llc < %s | grep {subfc r3,r5,r4} ; RUN: llc < %s | grep {subfze r4,r2} -; RUN: llc < %s -regalloc=local | grep {subfc r5,r2,r4} -; RUN: llc < %s -regalloc=local | grep {subfze r2,r3} +; RUN: llc < %s -regalloc=local | grep {subfc r5,r4,r3} +; RUN: llc < %s -regalloc=local | grep {subfze r2,r2} ; The first argument of subfc must not be the same as any other register. ; PR1357 Added: llvm/trunk/test/CodeGen/X86/phys-reg-local-regalloc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/phys-reg-local-regalloc.ll?rev=91485&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/phys-reg-local-regalloc.ll (added) +++ llvm/trunk/test/CodeGen/X86/phys-reg-local-regalloc.ll Tue Dec 15 18:29:41 2009 @@ -0,0 +1,49 @@ +; RUN: llc < %s -march=x86 -mtriple=i386-apple-darwin9 -regalloc=local | FileCheck %s + + at .str = private constant [12 x i8] c"x + y = %i\0A\00", align 1 ; <[12 x i8]*> [#uses=1] + +define i32 @main() nounwind { +entry: +; CHECK: movl 24(%esp), %eax +; CHECK-NOT: movl +; CHECK: movl %eax, 36(%esp) +; CHECK-NOT: movl +; CHECK: movl 28(%esp), %ebx +; CHECK-NOT: movl +; CHECK: movl %ebx, 40(%esp) +; CHECK-NOT: movl +; CHECK: addl %ebx, %eax + %retval = alloca i32 ; [#uses=2] + %"%ebx" = alloca i32 ; [#uses=1] + %"%eax" = alloca i32 ; [#uses=2] + %result = alloca i32 ; [#uses=2] + %y = alloca i32 ; [#uses=2] + %x = alloca i32 ; [#uses=2] + %0 = alloca i32 ; [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i32 1, i32* %x, align 4 + store i32 2, i32* %y, align 4 + call void asm sideeffect alignstack "# top of block", "~{dirflag},~{fpsr},~{flags},~{edi},~{esi},~{edx},~{ecx},~{eax}"() nounwind + %asmtmp = call i32 asm sideeffect alignstack "movl $1, $0", "=={eax},*m,~{dirflag},~{fpsr},~{flags},~{memory}"(i32* %x) nounwind ; [#uses=1] + store i32 %asmtmp, i32* %"%eax" + %asmtmp1 = call i32 asm sideeffect alignstack "movl $1, $0", "=={ebx},*m,~{dirflag},~{fpsr},~{flags},~{memory}"(i32* %y) nounwind ; [#uses=1] + store i32 %asmtmp1, i32* %"%ebx" + %1 = call i32 asm "", "={bx}"() nounwind ; [#uses=1] + %2 = call i32 asm "", "={ax}"() nounwind ; [#uses=1] + %asmtmp2 = call i32 asm sideeffect alignstack "addl $1, $0", "=={eax},{ebx},{eax},~{dirflag},~{fpsr},~{flags},~{memory}"(i32 %1, i32 %2) nounwind ; [#uses=1] + store i32 %asmtmp2, i32* %"%eax" + %3 = call i32 asm "", "={ax}"() nounwind ; [#uses=1] + call void asm sideeffect alignstack "movl $0, $1", "{eax},*m,~{dirflag},~{fpsr},~{flags},~{memory}"(i32 %3, i32* %result) nounwind + %4 = load i32* %result, align 4 ; [#uses=1] + %5 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([12 x i8]* @.str, i32 0, i32 0), i32 %4) nounwind ; [#uses=0] + store i32 0, i32* %0, align 4 + %6 = load i32* %0, align 4 ; [#uses=1] + store i32 %6, i32* %retval, align 4 + br label %return + +return: ; preds = %entry + %retval3 = load i32* %retval ; [#uses=1] + ret i32 %retval3 +} + +declare i32 @printf(i8*, ...) nounwind From rjmccall at apple.com Tue Dec 15 18:37:39 2009 From: rjmccall at apple.com (John McCall) Date: Tue, 15 Dec 2009 16:37:39 -0800 Subject: [llvm-commits] [llvm] r91481 - /llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp In-Reply-To: References: <200912160015.nBG0FSRb028494@zion.cs.uiuc.edu> Message-ID: <08E52D79-3953-4203-ABAC-41FB422FC3E4@apple.com> On Dec 15, 2009, at 4:24 PM, Mike Stump wrote: > On Dec 15, 2009, at 4:15 PM, John McCall wrote: >> Author: rjmccall >> Date: Tue Dec 15 18:15:28 2009 >> New Revision: 91481 > >> Every anonymous namespace is different. Caught by clang++. > > But each unnamed namespace in a translation unit is in fact the same namespace. You're right! We're enforcing the wrong rule in clang++. This is my mistake. The cleanup is harmless, though. John. From sabre at nondot.org Tue Dec 15 18:46:02 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 00:46:02 -0000 Subject: [llvm-commits] [llvm] r91486 - in /llvm/trunk: lib/Transforms/Scalar/SimplifyLibCalls.cpp test/Transforms/SimplifyLibCalls/StrStr.ll Message-ID: <200912160046.nBG0k2Uf029630@zion.cs.uiuc.edu> Author: lattner Date: Tue Dec 15 18:46:02 2009 New Revision: 91486 URL: http://llvm.org/viewvc/llvm-project?rev=91486&view=rev Log: revert my strstr optimization, I'm told it breaks x86-64 bootstrap. Will reapply with a fix when I get a chance. Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp?rev=91486&r1=91485&r2=91486&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp Tue Dec 15 18:46:02 2009 @@ -76,11 +76,6 @@ /// return value has 'intptr_t' type. Value *EmitStrLen(Value *Ptr, IRBuilder<> &B); - /// EmitStrChr - Emit a call to the strchr function to the builder, for the - /// specified pointer and character. Ptr is required to be some pointer type, - /// and the return value has 'i8*' type. - Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B); - /// EmitMemCpy - Emit a call to the memcpy function to the builder. This /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, @@ -156,26 +151,6 @@ return CI; } -/// EmitStrChr - Emit a call to the strchr function to the builder, for the -/// specified pointer and character. Ptr is required to be some pointer type, -/// and the return value has 'i8*' type. -Value *LibCallOptimization::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B) { - Module *M = Caller->getParent(); - AttributeWithIndex AWI = - AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind); - - const Type *I8Ptr = Type::getInt8PtrTy(*Context); - const Type *I32Ty = Type::getInt32Ty(*Context); - Constant *StrChr = M->getOrInsertFunction("strchr", AttrListPtr::get(&AWI, 1), - I8Ptr, I8Ptr, I32Ty, NULL); - CallInst *CI = B.CreateCall2(StrChr, CastToCStr(Ptr, B), - ConstantInt::get(I32Ty, C), "strchr"); - if (const Function *F = dyn_cast(StrChr->stripPointerCasts())) - CI->setCallingConv(F->getCallingConv()); - return CI; -} - - /// EmitMemCpy - Emit a call to the memcpy function to the builder. This always /// expects that the size has type 'intptr_t' and Dst/Src are pointers. Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len, @@ -915,7 +890,7 @@ }; //===---------------------------------------===// -// 'strto*' Optimizations. This handles strtol, strtod, strtof, strtoul, etc. +// 'strto*' Optimizations struct StrToOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { @@ -935,52 +910,6 @@ } }; -//===---------------------------------------===// -// 'strstr' Optimizations - -struct StrStrOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 2 || - !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || - !isa(FT->getReturnType())) - return 0; - - // fold strstr(x, x) -> x. - if (CI->getOperand(1) == CI->getOperand(2)) - return CI->getOperand(1); - - // See if either input string is a constant string. - std::string SearchStr, ToFindStr; - bool HasStr1 = GetConstantStringInfo(CI->getOperand(1), SearchStr); - bool HasStr2 = GetConstantStringInfo(CI->getOperand(2), ToFindStr); - - // fold strstr(x, "") -> x. - if (HasStr2 && ToFindStr.empty()) - return B.CreateBitCast(CI->getOperand(1), CI->getType()); - - // If both strings are known, constant fold it. - if (HasStr1 && HasStr2) { - std::string::size_type Offset = SearchStr.find(ToFindStr); - - if (Offset == std::string::npos) // strstr("foo", "bar") -> null - return Constant::getNullValue(CI->getType()); - - // strstr("abcd", "bc") -> gep((char*)"abcd", 2) - Value *Result = CastToCStr(CI->getOperand(1), B); - Result = B.CreateConstInBoundsGEP1_64(Result, Offset, "strstr"); - return B.CreateBitCast(Result, CI->getType()); - } - - // fold strstr(x, "y") -> strchr(x, 'y'). - if (HasStr2 && ToFindStr.size() == 1) - return B.CreateBitCast(EmitStrChr(CI->getOperand(1), ToFindStr[0], B), - CI->getType()); - return 0; - } -}; - //===---------------------------------------===// // 'memcmp' Optimizations @@ -1746,8 +1675,8 @@ // String and Memory LibCall Optimizations StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrCmpOpt StrCmp; StrNCmpOpt StrNCmp; StrCpyOpt StrCpy; StrNCpyOpt StrNCpy; StrLenOpt StrLen; - StrToOpt StrTo; StrStrOpt StrStr; - MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet; + StrToOpt StrTo; MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; + MemSetOpt MemSet; // Math Library Optimizations PowOpt Pow; Exp2Opt Exp2; UnaryDoubleFPOpt UnaryDoubleFP; // Integer Optimizations @@ -1809,7 +1738,6 @@ Optimizations["strtoll"] = &StrTo; Optimizations["strtold"] = &StrTo; Optimizations["strtoull"] = &StrTo; - Optimizations["strstr"] = &StrStr; Optimizations["memcmp"] = &MemCmp; Optimizations["memcpy"] = &MemCpy; Optimizations["memmove"] = &MemMove; @@ -2716,6 +2644,12 @@ // * strcspn("",a) -> 0 // * strcspn(s,"") -> strlen(a) // +// strstr: (PR5783) +// * strstr(x,x) -> x +// * strstr(x, "") -> x +// * strstr(x, "a") -> strchr(x, 'a') +// * strstr(s1,s2) -> result (if s1 and s2 are constant strings) +// // tan, tanf, tanl: // * tan(atan(x)) -> x // Modified: llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll?rev=91486&r1=91485&r2=91486&view=diff ============================================================================== --- llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll (original) +++ llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll Tue Dec 15 18:46:02 2009 @@ -1,48 +0,0 @@ -; RUN: opt < %s -simplify-libcalls -S | FileCheck %s -; PR5783 - -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" -target triple = "i386-apple-darwin9.0" - - at .str = private constant [1 x i8] zeroinitializer ; <[1 x i8]*> [#uses=1] - at .str1 = private constant [2 x i8] c"a\00" ; <[2 x i8]*> [#uses=1] - at .str2 = private constant [6 x i8] c"abcde\00" ; <[6 x i8]*> [#uses=1] - at .str3 = private constant [4 x i8] c"bcd\00" ; <[4 x i8]*> [#uses=1] - -define i8* @test1(i8* %P) nounwind readonly { -entry: - %call = tail call i8* @strstr(i8* %P, i8* getelementptr inbounds ([1 x i8]* @.str, i32 0, i32 0)) nounwind ; [#uses=1] - ret i8* %call -; strstr(P, "") -> P -; CHECK: @test1 -; CHECK: ret i8* %P -} - -declare i8* @strstr(i8*, i8* nocapture) nounwind readonly - -define i8* @test2(i8* %P) nounwind readonly { -entry: - %call = tail call i8* @strstr(i8* %P, i8* getelementptr inbounds ([2 x i8]* @.str1, i32 0, i32 0)) nounwind ; [#uses=1] - ret i8* %call -; strstr(P, "a") -> strchr(P, 'a') -; CHECK: @test2 -; CHECK: @strchr(i8* %P, i32 97) -} - -define i8* @test3(i8* nocapture %P) nounwind readonly { -entry: - %call = tail call i8* @strstr(i8* getelementptr inbounds ([6 x i8]* @.str2, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8]* @.str3, i32 0, i32 0)) nounwind ; [#uses=1] - ret i8* %call -; strstr("abcde", "bcd") -> "abcde"+1 -; CHECK: @test3 -; CHECK: getelementptr inbounds ([6 x i8]* @.str2, i32 0, i64 1) -} - -define i8* @test4(i8* %P) nounwind readonly { -entry: - %call = tail call i8* @strstr(i8* %P, i8* %P) nounwind ; [#uses=1] - ret i8* %call -; strstr(P, P) -> P -; CHECK: @test4 -; CHECK: ret i8* %P -} From evan.cheng at apple.com Tue Dec 15 18:53:12 2009 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 16 Dec 2009 00:53:12 -0000 Subject: [llvm-commits] [llvm] r91489 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86Instr64bit.td lib/Target/X86/X86InstrInfo.td test/CodeGen/X86/setcc.ll Message-ID: <200912160053.nBG0rDDv029906@zion.cs.uiuc.edu> Author: evancheng Date: Tue Dec 15 18:53:11 2009 New Revision: 91489 URL: http://llvm.org/viewvc/llvm-project?rev=91489&view=rev Log: Re-enable 91381 with fixes. Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/lib/Target/X86/X86Instr64bit.td llvm/trunk/lib/Target/X86/X86InstrInfo.td llvm/trunk/test/CodeGen/X86/setcc.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=91489&r1=91488&r2=91489&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Dec 15 18:53:11 2009 @@ -980,6 +980,7 @@ setTargetDAGCombine(ISD::SRL); setTargetDAGCombine(ISD::STORE); setTargetDAGCombine(ISD::MEMBARRIER); + setTargetDAGCombine(ISD::ZERO_EXTEND); if (Subtarget->is64Bit()) setTargetDAGCombine(ISD::MUL); @@ -5752,14 +5753,11 @@ SDValue Cond = EmitCmp(Op0, Op1, X86CC, DAG); // Use sbb x, x to materialize carry bit into a GPR. - // FIXME: Temporarily disabled since it breaks self-hosting. It's apparently - // miscompiling ARMISelDAGToDAG.cpp. - if (0 && !isFP && X86CC == X86::COND_B) { + if (X86CC == X86::COND_B) return DAG.getNode(ISD::AND, dl, MVT::i8, DAG.getNode(X86ISD::SETCC_CARRY, dl, MVT::i8, DAG.getConstant(X86CC, MVT::i8), Cond), DAG.getConstant(1, MVT::i8)); - } return DAG.getNode(X86ISD::SETCC, dl, MVT::i8, DAG.getConstant(X86CC, MVT::i8), Cond); @@ -9349,6 +9347,32 @@ } } +static SDValue PerformZExtCombine(SDNode *N, SelectionDAG &DAG) { + // (i32 zext (and (i8 x86isd::setcc_carry), 1)) -> + // (and (i32 x86isd::setcc_carry), 1) + // This eliminates the zext. This transformation is necessary because + // ISD::SETCC is always legalized to i8. + DebugLoc dl = N->getDebugLoc(); + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + if (N0.getOpcode() == ISD::AND && + N0.hasOneUse() && + N0.getOperand(0).hasOneUse()) { + SDValue N00 = N0.getOperand(0); + if (N00.getOpcode() != X86ISD::SETCC_CARRY) + return SDValue(); + ConstantSDNode *C = dyn_cast(N0.getOperand(1)); + if (!C || C->getZExtValue() != 1) + return SDValue(); + return DAG.getNode(ISD::AND, dl, VT, + DAG.getNode(X86ISD::SETCC_CARRY, dl, VT, + N00.getOperand(0), N00.getOperand(1)), + DAG.getConstant(1, VT)); + } + + return SDValue(); +} + SDValue X86TargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -9368,6 +9392,7 @@ case X86ISD::BT: return PerformBTCombine(N, DAG, DCI); case X86ISD::VZEXT_MOVL: return PerformVZEXT_MOVLCombine(N, DAG); case ISD::MEMBARRIER: return PerformMEMBARRIERCombine(N, DAG); + case ISD::ZERO_EXTEND: return PerformZExtCombine(N, DAG); } return SDValue(); Modified: llvm/trunk/lib/Target/X86/X86Instr64bit.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Instr64bit.td?rev=91489&r1=91488&r2=91489&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86Instr64bit.td (original) +++ llvm/trunk/lib/Target/X86/X86Instr64bit.td Tue Dec 15 18:53:11 2009 @@ -1337,9 +1337,9 @@ let Defs = [EFLAGS], Uses = [EFLAGS], isCodeGenOnly = 1 in def SETB_C64r : RI<0x19, MRMInitReg, (outs GR64:$dst), (ins), "sbb{q}\t$dst, $dst", - [(set GR64:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>; + [(set GR64:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; -def : Pat<(i64 (anyext (X86setcc_c X86_COND_B, EFLAGS))), +def : Pat<(i64 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), (SETB_C64r)>; //===----------------------------------------------------------------------===// Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=91489&r1=91488&r2=91489&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Tue Dec 15 18:53:11 2009 @@ -41,6 +41,9 @@ def SDTX86SetCC : SDTypeProfile<1, 2, [SDTCisVT<0, i8>, SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; +def SDTX86SetCC_C : SDTypeProfile<1, 2, + [SDTCisInt<0>, + SDTCisVT<1, i8>, SDTCisVT<2, i32>]>; def SDTX86cas : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisInt<1>, SDTCisVT<2, i8>]>; @@ -87,7 +90,7 @@ def X86brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>; def X86setcc : SDNode<"X86ISD::SETCC", SDTX86SetCC>; -def X86setcc_c : SDNode<"X86ISD::SETCC_CARRY", SDTX86SetCC>; +def X86setcc_c : SDNode<"X86ISD::SETCC_CARRY", SDTX86SetCC_C>; def X86cas : SDNode<"X86ISD::LCMPXCHG_DAG", SDTX86cas, [SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore, @@ -3068,11 +3071,11 @@ [(set GR8:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; def SETB_C16r : I<0x19, MRMInitReg, (outs GR16:$dst), (ins), "sbb{w}\t$dst, $dst", - [(set GR16:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>, + [(set GR16:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>, OpSize; def SETB_C32r : I<0x19, MRMInitReg, (outs GR32:$dst), (ins), "sbb{l}\t$dst, $dst", - [(set GR32:$dst, (zext (X86setcc_c X86_COND_B, EFLAGS)))]>; + [(set GR32:$dst, (X86setcc_c X86_COND_B, EFLAGS))]>; } // isCodeGenOnly def SETEr : I<0x94, MRM0r, @@ -4185,10 +4188,10 @@ GR16:$src2, (i8 imm:$amt2)), addr:$dst), (SHLD16mri8 addr:$dst, GR16:$src2, (i8 imm:$amt1))>; -// (anyext (setcc_carry)) -> (zext (setcc_carry)) -def : Pat<(i16 (anyext (X86setcc_c X86_COND_B, EFLAGS))), +// (anyext (setcc_carry)) -> (setcc_carry) +def : Pat<(i16 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), (SETB_C16r)>; -def : Pat<(i32 (anyext (X86setcc_c X86_COND_B, EFLAGS))), +def : Pat<(i32 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), (SETB_C32r)>; //===----------------------------------------------------------------------===// Modified: llvm/trunk/test/CodeGen/X86/setcc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=91489&r1=91488&r2=91489&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/setcc.ll (original) +++ llvm/trunk/test/CodeGen/X86/setcc.ll Tue Dec 15 18:53:11 2009 @@ -1,5 +1,4 @@ ; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s -; XFAIL: * ; rdar://7329206 ; Use sbb x, x to materialize carry bit in a GPR. The value is either From dpatel at apple.com Tue Dec 15 20:11:38 2009 From: dpatel at apple.com (Devang Patel) Date: Wed, 16 Dec 2009 02:11:38 -0000 Subject: [llvm-commits] [llvm] r91495 - /llvm/trunk/test/DebugInfo/2009-12-01-CurrentFn.ll Message-ID: <200912160211.nBG2Bc9I032637@zion.cs.uiuc.edu> Author: dpatel Date: Tue Dec 15 20:11:38 2009 New Revision: 91495 URL: http://llvm.org/viewvc/llvm-project?rev=91495&view=rev Log: XFAIL on ppc-darwin. Modified: llvm/trunk/test/DebugInfo/2009-12-01-CurrentFn.ll Modified: llvm/trunk/test/DebugInfo/2009-12-01-CurrentFn.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/2009-12-01-CurrentFn.ll?rev=91495&r1=91494&r2=91495&view=diff ============================================================================== --- llvm/trunk/test/DebugInfo/2009-12-01-CurrentFn.ll (original) +++ llvm/trunk/test/DebugInfo/2009-12-01-CurrentFn.ll Tue Dec 15 20:11:38 2009 @@ -1,5 +1,5 @@ ; RUN: llc < %s | grep "func_end1:" | count 1 - +; XFAIL: powerpc-apple-darwin declare void @foo() define void @bar(i32 %i) nounwind ssp { From johnny.chen at apple.com Tue Dec 15 20:32:54 2009 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 16 Dec 2009 02:32:54 -0000 Subject: [llvm-commits] [llvm] r91496 - in /llvm/trunk/lib/Target/ARM: ARMInstrFormats.td ARMInstrThumb.td ARMInstrThumb2.td Message-ID: <200912160232.nBG2WsJC001077@zion.cs.uiuc.edu> Author: johnny Date: Tue Dec 15 20:32:54 2009 New Revision: 91496 URL: http://llvm.org/viewvc/llvm-project?rev=91496&view=rev Log: Add encoding bits for some Thumb instructions. Plus explicitly set the top two bytes of Inst to 0x0000 for the benefit of the Thumb decoder. Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td llvm/trunk/lib/Target/ARM/ARMInstrThumb.td llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=91496&r1=91495&r2=91496&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Tue Dec 15 20:32:54 2009 @@ -920,8 +920,7 @@ : Thumb1I; class T1JTI pattern> - : Thumb1I, - Encoding; + : Thumb1I; // Two-address instructions class T1It pattern> : Thumb1pI; +class Encoding16 : Encoding { + let Inst{31-16} = 0x0000; +} + // A6.2 16-bit Thumb instruction encoding -class T1Encoding opcode> : Encoding { +class T1Encoding opcode> : Encoding16 { let Inst{15-10} = opcode; } // A6.2.1 Shift (immediate), add, subtract, move, and compare encoding. -class T1General opcode> : Encoding { +class T1General opcode> : Encoding16 { let Inst{15-14} = 0b00; let Inst{13-9} = opcode; } // A6.2.2 Data-processing encoding. -class T1DataProcessing opcode> : Encoding { +class T1DataProcessing opcode> : Encoding16 { let Inst{15-10} = 0b010000; let Inst{9-6} = opcode; } // A6.2.3 Special data instructions and branch and exchange encoding. -class T1Special opcode> : Encoding { +class T1Special opcode> : Encoding16 { let Inst{15-10} = 0b010001; let Inst{9-6} = opcode; } // A6.2.4 Load/store single data item encoding. -class T1LoadStore opA, bits<3> opB> : Encoding { +class T1LoadStore opA, bits<3> opB> : Encoding16 { let Inst{15-12} = opA; let Inst{11-9} = opB; } @@ -1021,7 +1024,7 @@ class T1LdStSP opB> : T1LoadStore<0b1001, opB>; // SP relative // A6.2.5 Miscellaneous 16-bit instructions encoding. -class T1Misc opcode> : Encoding { +class T1Misc opcode> : Encoding16 { let Inst{15-12} = 0b1011; let Inst{11-5} = opcode; } Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=91496&r1=91495&r2=91496&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Tue Dec 15 20:32:54 2009 @@ -306,7 +306,11 @@ def tBR_JTr : T1JTI<(outs), (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id), IIC_Br, "mov\tpc, $target\n\t.align\t2\n$jt", - [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>; + [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>, + Encoding16 { + let Inst{15-7} = 0b010001101; + let Inst{2-0} = 0b111; + } } } @@ -596,7 +600,7 @@ T1Special<0b1000>; let Defs = [CPSR] in def tMOVSr : T1I<(outs tGPR:$dst), (ins tGPR:$src), IIC_iMOVr, - "movs\t$dst, $src", []>, Encoding { + "movs\t$dst, $src", []>, Encoding16 { let Inst{15-6} = 0b0000000000; } Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=91496&r1=91495&r2=91496&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Tue Dec 15 20:32:54 2009 @@ -1911,6 +1911,7 @@ AddrModeNone, Size2Bytes, IIC_iALUx, "it$mask\t$cc", "", []> { // 16-bit instruction. + let Inst{31-16} = 0x0000; let Inst{15-8} = 0b10111111; } From vhernandez at apple.com Tue Dec 15 20:52:09 2009 From: vhernandez at apple.com (Victor Hernandez) Date: Wed, 16 Dec 2009 02:52:09 -0000 Subject: [llvm-commits] [llvm] r91497 - in /llvm/trunk: include/llvm/Metadata.h lib/VMCore/Metadata.cpp Message-ID: <200912160252.nBG2q9FI001712@zion.cs.uiuc.edu> Author: hernande Date: Tue Dec 15 20:52:09 2009 New Revision: 91497 URL: http://llvm.org/viewvc/llvm-project?rev=91497&view=rev Log: MDNodes that refer to an instruction are local to a function; in that case, explicitly keep track of the function they are local to Modified: llvm/trunk/include/llvm/Metadata.h llvm/trunk/lib/VMCore/Metadata.cpp Modified: llvm/trunk/include/llvm/Metadata.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Metadata.h?rev=91497&r1=91496&r2=91497&view=diff ============================================================================== --- llvm/trunk/include/llvm/Metadata.h (original) +++ llvm/trunk/include/llvm/Metadata.h Tue Dec 15 20:52:09 2009 @@ -111,13 +111,16 @@ ElementVH *Node; unsigned NodeSize; + Function *LocalFunction; protected: - explicit MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals); + explicit MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals, + Function *LocalFunction = NULL); public: // Constructors and destructors. static MDNode *get(LLVMContext &Context, - Value *const *Vals, unsigned NumVals); + Value *const *Vals, unsigned NumVals, + Function *LocalFunction = NULL); /// ~MDNode - Destroy MDNode. ~MDNode(); @@ -130,6 +133,9 @@ /// getNumElements - Return number of MDNode elements. unsigned getNumElements() const { return NodeSize; } + + /// isFunctionLocal - Return whether MDNode is local to a function. + bool isFunctionLocal() const { return LocalFunction; } /// Profile - calculate a unique identifier for this MDNode to collapse /// duplicates Modified: llvm/trunk/lib/VMCore/Metadata.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Metadata.cpp?rev=91497&r1=91496&r2=91497&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Metadata.cpp (original) +++ llvm/trunk/lib/VMCore/Metadata.cpp Tue Dec 15 20:52:09 2009 @@ -49,13 +49,15 @@ //===----------------------------------------------------------------------===// // MDNode implementation. // -MDNode::MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals) +MDNode::MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals, + Function *LocalFunction) : MetadataBase(Type::getMetadataTy(C), Value::MDNodeVal) { NodeSize = NumVals; Node = new ElementVH[NodeSize]; ElementVH *Ptr = Node; for (unsigned i = 0; i != NumVals; ++i) *Ptr++ = ElementVH(Vals[i], this); + LocalFunction = LocalFunction; } void MDNode::Profile(FoldingSetNodeID &ID) const { @@ -63,17 +65,20 @@ ID.AddPointer(getElement(i)); } -MDNode *MDNode::get(LLVMContext &Context, Value*const* Vals, unsigned NumVals) { +MDNode *MDNode::get(LLVMContext &Context, Value*const* Vals, unsigned NumVals, + Function *LocalFunction) { LLVMContextImpl *pImpl = Context.pImpl; FoldingSetNodeID ID; for (unsigned i = 0; i != NumVals; ++i) ID.AddPointer(Vals[i]); + if (LocalFunction) + ID.AddPointer(LocalFunction); void *InsertPoint; MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint); if (!N) { // InsertPoint will have been set by the FindNodeOrInsertPos call. - N = new MDNode(Context, Vals, NumVals); + N = new MDNode(Context, Vals, NumVals, LocalFunction); pImpl->MDNodeSet.InsertNode(N, InsertPoint); } return N; From nicholas at mxc.ca Wed Dec 16 00:47:45 2009 From: nicholas at mxc.ca (Nick Lewycky) Date: Tue, 15 Dec 2009 22:47:45 -0800 Subject: [llvm-commits] [llvm] r91497 - in /llvm/trunk: include/llvm/Metadata.h lib/VMCore/Metadata.cpp In-Reply-To: <200912160252.nBG2q9FI001712@zion.cs.uiuc.edu> References: <200912160252.nBG2q9FI001712@zion.cs.uiuc.edu> Message-ID: <4B288291.3090704@mxc.ca> Victor Hernandez wrote: > Author: hernande > Date: Tue Dec 15 20:52:09 2009 > New Revision: 91497 > > URL: http://llvm.org/viewvc/llvm-project?rev=91497&view=rev > Log: > MDNodes that refer to an instruction are local to a function; in that case, explicitly keep track of the function they are local to So what's the semantic here? What if the MDNode refers to an Instruction that gets spliced from one Function to another? What happens if the MDNode is attached to an Instruction that's RAUW'd with a Constant? Is this new field copied by MetadataContextImpl::copyMD? You also need to assert that any Instructions passed in also belong to LocalFunction. > Modified: > llvm/trunk/include/llvm/Metadata.h > llvm/trunk/lib/VMCore/Metadata.cpp > > Modified: llvm/trunk/include/llvm/Metadata.h > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Metadata.h?rev=91497&r1=91496&r2=91497&view=diff > > ============================================================================== > --- llvm/trunk/include/llvm/Metadata.h (original) > +++ llvm/trunk/include/llvm/Metadata.h Tue Dec 15 20:52:09 2009 > @@ -111,13 +111,16 @@ > > ElementVH *Node; > unsigned NodeSize; > + Function *LocalFunction; > > protected: > - explicit MDNode(LLVMContext&C, Value *const *Vals, unsigned NumVals); > + explicit MDNode(LLVMContext&C, Value *const *Vals, unsigned NumVals, > + Function *LocalFunction = NULL); > public: > // Constructors and destructors. > static MDNode *get(LLVMContext&Context, > - Value *const *Vals, unsigned NumVals); > + Value *const *Vals, unsigned NumVals, > + Function *LocalFunction = NULL); > > /// ~MDNode - Destroy MDNode. > ~MDNode(); > @@ -130,6 +133,9 @@ > > /// getNumElements - Return number of MDNode elements. > unsigned getNumElements() const { return NodeSize; } > + > + /// isFunctionLocal - Return whether MDNode is local to a function. > + bool isFunctionLocal() const { return LocalFunction; } > > /// Profile - calculate a unique identifier for this MDNode to collapse > /// duplicates > > Modified: llvm/trunk/lib/VMCore/Metadata.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Metadata.cpp?rev=91497&r1=91496&r2=91497&view=diff > > ============================================================================== > --- llvm/trunk/lib/VMCore/Metadata.cpp (original) > +++ llvm/trunk/lib/VMCore/Metadata.cpp Tue Dec 15 20:52:09 2009 > @@ -49,13 +49,15 @@ > //===----------------------------------------------------------------------===// > // MDNode implementation. > // > -MDNode::MDNode(LLVMContext&C, Value *const *Vals, unsigned NumVals) > +MDNode::MDNode(LLVMContext&C, Value *const *Vals, unsigned NumVals, > + Function *LocalFunction) > : MetadataBase(Type::getMetadataTy(C), Value::MDNodeVal) { > NodeSize = NumVals; > Node = new ElementVH[NodeSize]; > ElementVH *Ptr = Node; > for (unsigned i = 0; i != NumVals; ++i) > *Ptr++ = ElementVH(Vals[i], this); > + LocalFunction = LocalFunction; Perhaps you meant this->LocalFunction = LocalFunction? Nick > } > > void MDNode::Profile(FoldingSetNodeID&ID) const { > @@ -63,17 +65,20 @@ > ID.AddPointer(getElement(i)); > } > > -MDNode *MDNode::get(LLVMContext&Context, Value*const* Vals, unsigned NumVals) { > +MDNode *MDNode::get(LLVMContext&Context, Value*const* Vals, unsigned NumVals, > + Function *LocalFunction) { > LLVMContextImpl *pImpl = Context.pImpl; > FoldingSetNodeID ID; > for (unsigned i = 0; i != NumVals; ++i) > ID.AddPointer(Vals[i]); > + if (LocalFunction) > + ID.AddPointer(LocalFunction); > > void *InsertPoint; > MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint); > if (!N) { > // InsertPoint will have been set by the FindNodeOrInsertPos call. > - N = new MDNode(Context, Vals, NumVals); > + N = new MDNode(Context, Vals, NumVals, LocalFunction); > pImpl->MDNodeSet.InsertNode(N, InsertPoint); > } > return N; > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From sabre at nondot.org Wed Dec 16 00:55:45 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 06:55:45 -0000 Subject: [llvm-commits] [llvm] r91518 - /llvm/trunk/include/llvm/ADT/SmallVector.h Message-ID: <200912160655.nBG6tjcZ009938@zion.cs.uiuc.edu> Author: lattner Date: Wed Dec 16 00:55:45 2009 New Revision: 91518 URL: http://llvm.org/viewvc/llvm-project?rev=91518&view=rev Log: substantial refactoring of SmallVector, now most code is in SmallVectorTemplateCommon, and there is a new SmallVectorTemplateBase class in between it and SmallVectorImpl. SmallVectorTemplateBase can be specialized based on isPodLike. Modified: llvm/trunk/include/llvm/ADT/SmallVector.h Modified: llvm/trunk/include/llvm/ADT/SmallVector.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=91518&r1=91517&r2=91518&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/SmallVector.h (original) +++ llvm/trunk/include/llvm/ADT/SmallVector.h Wed Dec 16 00:55:45 2009 @@ -80,55 +80,49 @@ return BeginX == static_cast(&FirstEl); } - public: bool empty() const { return BeginX == EndX; } }; - -/// SmallVectorImpl - This class consists of common code factored out of the -/// SmallVector class to reduce code duplication based on the SmallVector 'N' -/// template parameter. + template -class SmallVectorImpl : public SmallVectorBase { - void setEnd(T *P) { EndX = P; } +class SmallVectorTemplateCommon : public SmallVectorBase { + void setEnd(T *P) { this->EndX = P; } public: - // Default ctor - Initialize to empty. - explicit SmallVectorImpl(unsigned N) : SmallVectorBase(N*sizeof(T)) { - } - - ~SmallVectorImpl() { + SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(Size) {} + + ~SmallVectorTemplateCommon() { // Destroy the constructed elements in the vector. destroy_range(begin(), end()); - + // If this wasn't grown from the inline copy, deallocate the old space. - if (!isSmall()) + if (!this->isSmall()) operator delete(begin()); } - + typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T value_type; typedef T *iterator; typedef const T *const_iterator; - + typedef std::reverse_iterator const_reverse_iterator; typedef std::reverse_iterator reverse_iterator; - + typedef T &reference; typedef const T &const_reference; typedef T *pointer; typedef const T *const_pointer; - + // forward iterator creation methods. - iterator begin() { return (iterator)BeginX; } - const_iterator begin() const { return (const_iterator)BeginX; } - iterator end() { return (iterator)EndX; } - const_iterator end() const { return (const_iterator)EndX; } + iterator begin() { return (iterator)this->BeginX; } + const_iterator begin() const { return (const_iterator)this->BeginX; } + iterator end() { return (iterator)this->EndX; } + const_iterator end() const { return (const_iterator)this->EndX; } private: - iterator capacity_ptr() { return (iterator)CapacityX; } - const_iterator capacity_ptr() const { return (const_iterator)CapacityX; } + iterator capacity_ptr() { return (iterator)this->CapacityX; } + const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} public: - + // reverse iterator creation methods. reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } @@ -171,7 +165,7 @@ } void push_back(const_reference Elt) { - if (EndX < CapacityX) { + if (this->EndX < this->CapacityX) { Retry: new (end()) T(Elt); setEnd(end()+1); @@ -194,7 +188,7 @@ void clear() { destroy_range(begin(), end()); - EndX = BeginX; + this->EndX = this->BeginX; } void resize(unsigned N) { @@ -226,7 +220,7 @@ grow(N); } - void swap(SmallVectorImpl &RHS); + void swap(SmallVectorTemplateCommon &RHS); /// append - Add the specified range to the end of the SmallVector. /// @@ -238,6 +232,8 @@ grow(size()+NumInputs); // Copy the new elements over. + // TODO: NEED To compile time dispatch on whether in_iter is a random access + // iterator to use the fast uninitialized_copy. std::uninitialized_copy(in_start, in_end, end()); setEnd(end() + NumInputs); } @@ -287,7 +283,7 @@ return end()-1; } - if (EndX < CapacityX) { + if (this->EndX < this->CapacityX) { Retry: new (end()) T(back()); setEnd(end()+1); @@ -339,7 +335,7 @@ T *OldEnd = end(); setEnd(end() + NumToInsert); size_t NumOverwritten = OldEnd-I; - std::uninitialized_copy(I, OldEnd, end()-NumOverwritten); + uninitialized_copy(I, OldEnd, end()-NumOverwritten); // Replace the overwritten part. std::fill_n(I, NumOverwritten, Elt); @@ -388,25 +384,28 @@ T *OldEnd = end(); setEnd(end() + NumToInsert); size_t NumOverwritten = OldEnd-I; - std::uninitialized_copy(I, OldEnd, end()-NumOverwritten); + uninitialized_copy(I, OldEnd, end()-NumOverwritten); // Replace the overwritten part. std::copy(From, From+NumOverwritten, I); // Insert the non-overwritten middle part. - std::uninitialized_copy(From+NumOverwritten, To, OldEnd); + uninitialized_copy(From+NumOverwritten, To, OldEnd); return I; } - const SmallVectorImpl &operator=(const SmallVectorImpl &RHS); + const SmallVectorTemplateCommon + &operator=(const SmallVectorTemplateCommon &RHS); - bool operator==(const SmallVectorImpl &RHS) const { + bool operator==(const SmallVectorTemplateCommon &RHS) const { if (size() != RHS.size()) return false; return std::equal(begin(), end(), RHS.begin()); } - bool operator!=(const SmallVectorImpl &RHS) const { return !(*this == RHS); } + bool operator!=(const SmallVectorTemplateCommon &RHS) const { + return !(*this == RHS); + } - bool operator<(const SmallVectorImpl &RHS) const { + bool operator<(const SmallVectorTemplateCommon &RHS) const { return std::lexicographical_compare(begin(), end(), RHS.begin(), RHS.end()); } @@ -430,12 +429,12 @@ /// least one more element or MinSize if specified. void grow(size_type MinSize = 0); - void construct_range(T *S, T *E, const T &Elt) { + static void construct_range(T *S, T *E, const T &Elt) { for (; S != E; ++S) new (S) T(Elt); } - void destroy_range(T *S, T *E) { + static void destroy_range(T *S, T *E) { // No need to do a destroy loop for POD's. if (isPodLike::value) return; @@ -444,11 +443,23 @@ E->~T(); } } + + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + // Use memcpy for PODs: std::uninitialized_copy optimizes to memmove. + if (isPodLike::value) + memcpy(&*Dest, &*I, (E-I)*sizeof(T)); + else + std::uninitialized_copy(I, E, Dest); + } }; + // Define this out-of-line to dissuade the C++ compiler from inlining it. template -void SmallVectorImpl::grow(size_t MinSize) { +void SmallVectorTemplateCommon::grow(size_t MinSize) { size_t CurCapacity = capacity(); size_t CurSize = size(); size_t NewCapacity = 2*CurCapacity; @@ -457,33 +468,29 @@ T *NewElts = static_cast(operator new(NewCapacity*sizeof(T))); // Copy the elements over. - if (isPodLike::value) - // Use memcpy for PODs: std::uninitialized_copy optimizes to memmove. - memcpy(NewElts, begin(), CurSize * sizeof(T)); - else - std::uninitialized_copy(begin(), end(), NewElts); + uninitialized_copy(begin(), end(), NewElts); // Destroy the original elements. destroy_range(begin(), end()); // If this wasn't grown from the inline copy, deallocate the old space. - if (!isSmall()) + if (!this->isSmall()) operator delete(begin()); setEnd(NewElts+CurSize); - BeginX = NewElts; - CapacityX = begin()+NewCapacity; + this->BeginX = NewElts; + this->CapacityX = begin()+NewCapacity; } template -void SmallVectorImpl::swap(SmallVectorImpl &RHS) { +void SmallVectorTemplateCommon::swap(SmallVectorTemplateCommon &RHS) { if (this == &RHS) return; // We can only avoid copying elements if neither vector is small. - if (!isSmall() && !RHS.isSmall()) { - std::swap(BeginX, RHS.BeginX); - std::swap(EndX, RHS.EndX); - std::swap(CapacityX, RHS.CapacityX); + if (!this->isSmall() && !RHS.isSmall()) { + std::swap(this->BeginX, RHS.BeginX); + std::swap(this->EndX, RHS.EndX); + std::swap(this->CapacityX, RHS.CapacityX); return; } if (RHS.size() > capacity()) @@ -500,13 +507,13 @@ // Copy over the extra elts. if (size() > RHS.size()) { size_t EltDiff = size() - RHS.size(); - std::uninitialized_copy(begin()+NumShared, end(), RHS.end()); + uninitialized_copy(begin()+NumShared, end(), RHS.end()); RHS.setEnd(RHS.end()+EltDiff); destroy_range(begin()+NumShared, end()); setEnd(begin()+NumShared); } else if (RHS.size() > size()) { size_t EltDiff = RHS.size() - size(); - std::uninitialized_copy(RHS.begin()+NumShared, RHS.end(), end()); + uninitialized_copy(RHS.begin()+NumShared, RHS.end(), end()); setEnd(end() + EltDiff); destroy_range(RHS.begin()+NumShared, RHS.end()); RHS.setEnd(RHS.begin()+NumShared); @@ -514,8 +521,9 @@ } template -const SmallVectorImpl & -SmallVectorImpl::operator=(const SmallVectorImpl &RHS) { +const SmallVectorTemplateCommon & +SmallVectorTemplateCommon:: + operator=(const SmallVectorTemplateCommon &RHS) { // Avoid self-assignment. if (this == &RHS) return *this; @@ -553,13 +561,41 @@ } // Copy construct the new elements in place. - std::uninitialized_copy(RHS.begin()+CurSize, RHS.end(), begin()+CurSize); + uninitialized_copy(RHS.begin()+CurSize, RHS.end(), begin()+CurSize); // Set end. setEnd(begin()+RHSSize); return *this; } + +template +class SmallVectorTemplateBase : public SmallVectorTemplateCommon { +public: + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} + +}; + +template +class SmallVectorTemplateBase : public SmallVectorTemplateCommon { +public: + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} + +}; + + +/// SmallVectorImpl - This class consists of common code factored out of the +/// SmallVector class to reduce code duplication based on the SmallVector 'N' +/// template parameter. +template +class SmallVectorImpl : public SmallVectorTemplateBase::value> { +public: + // Default ctor - Initialize to empty. + explicit SmallVectorImpl(unsigned N) + : SmallVectorTemplateBase::value>(N*sizeof(T)) { + } +}; + /// SmallVector - This is a 'vector' (really, a variable-sized array), optimized /// for the case when the array is small. It contains some number of elements /// in-place, which allows it to avoid heap allocation when the actual number of From nicholas at mxc.ca Wed Dec 16 01:35:25 2009 From: nicholas at mxc.ca (Nick Lewycky) Date: Wed, 16 Dec 2009 07:35:25 -0000 Subject: [llvm-commits] [llvm] r91521 - /llvm/trunk/test/CodeGen/Thumb2/large-stack.ll Message-ID: <200912160735.nBG7ZPtx011326@zion.cs.uiuc.edu> Author: nicholas Date: Wed Dec 16 01:35:25 2009 New Revision: 91521 URL: http://llvm.org/viewvc/llvm-project?rev=91521&view=rev Log: Make this test pass on Linux. Modified: llvm/trunk/test/CodeGen/Thumb2/large-stack.ll Modified: llvm/trunk/test/CodeGen/Thumb2/large-stack.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/large-stack.ll?rev=91521&r1=91520&r2=91521&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/Thumb2/large-stack.ll (original) +++ llvm/trunk/test/CodeGen/Thumb2/large-stack.ll Wed Dec 16 01:35:25 2009 @@ -1,24 +1,35 @@ -; RUN: llc < %s -march=thumb -mattr=+thumb2 | FileCheck %s +; RUN: llc < %s -march=thumb -mattr=+thumb2 -mtriple=arm-apple-darwin | FileCheck %s -check-prefix=DARWIN +; RUN: llc < %s -march=thumb -mattr=+thumb2 -mtriple=arm-linux-gnueabi | FileCheck %s -check-prefix=LINUX define void @test1() { -; CHECK: test1: -; CHECK: sub sp, #256 +; DARWIN: test1: +; DARWIN: sub sp, #256 +; LINUX: test1: +; LINUX: sub sp, #256 %tmp = alloca [ 64 x i32 ] , align 4 ret void } define void @test2() { -; CHECK: test2: -; CHECK: sub.w sp, sp, #4160 -; CHECK: sub sp, #8 +; DARWIN: test2: +; DARWIN: sub.w sp, sp, #4160 +; DARWIN: sub sp, #8 +; LINUX: test2: +; LINUX: sub.w sp, sp, #4160 +; LINUX: sub sp, #8 %tmp = alloca [ 4168 x i8 ] , align 4 ret void } define i32 @test3() { -; CHECK: test3: -; CHECK: sub.w sp, sp, #805306368 -; CHECK: sub sp, #20 +; DARWIN: test3: +; DARWIN: push {r4, r7, lr} +; DARWIN: sub.w sp, sp, #805306368 +; DARWIN: sub sp, #20 +; LINUX: test3: +; LINUX: stmfd sp!, {r4, r7, r11, lr} +; LINUX: sub.w sp, sp, #805306368 +; LINUX: sub sp, #16 %retval = alloca i32, align 4 %tmp = alloca i32, align 4 %a = alloca [805306369 x i8], align 16 From sabre at nondot.org Wed Dec 16 02:05:48 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 08:05:48 -0000 Subject: [llvm-commits] [llvm] r91522 - /llvm/trunk/include/llvm/ADT/SmallVector.h Message-ID: <200912160805.nBG85mgl012563@zion.cs.uiuc.edu> Author: lattner Date: Wed Dec 16 02:05:48 2009 New Revision: 91522 URL: http://llvm.org/viewvc/llvm-project?rev=91522&view=rev Log: sink most of the meat in smallvector back from SmallVectorTemplateCommon down into SmallVectorImpl. This requires sprinking a ton of this->'s in, but gives us a place to factor. Modified: llvm/trunk/include/llvm/ADT/SmallVector.h Modified: llvm/trunk/include/llvm/ADT/SmallVector.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=91522&r1=91521&r2=91522&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/SmallVector.h (original) +++ llvm/trunk/include/llvm/ADT/SmallVector.h Wed Dec 16 02:05:48 2009 @@ -86,19 +86,11 @@ template class SmallVectorTemplateCommon : public SmallVectorBase { +protected: void setEnd(T *P) { this->EndX = P; } public: SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(Size) {} - ~SmallVectorTemplateCommon() { - // Destroy the constructed elements in the vector. - destroy_range(begin(), end()); - - // If this wasn't grown from the inline copy, deallocate the old space. - if (!this->isSmall()) - operator delete(begin()); - } - typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T value_type; @@ -118,7 +110,7 @@ const_iterator begin() const { return (const_iterator)this->BeginX; } iterator end() { return (iterator)this->EndX; } const_iterator end() const { return (const_iterator)this->EndX; } -private: +protected: iterator capacity_ptr() { return (iterator)this->CapacityX; } const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;} public: @@ -163,253 +155,297 @@ const_reference back() const { return end()[-1]; } +}; + + +template +class SmallVectorTemplateBase : public SmallVectorTemplateCommon { +public: + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} - void push_back(const_reference Elt) { - if (this->EndX < this->CapacityX) { - Retry: - new (end()) T(Elt); - setEnd(end()+1); - return; - } - grow(); - goto Retry; - } +}; - void pop_back() { - setEnd(end()-1); - end()->~T(); +template +class SmallVectorTemplateBase : public SmallVectorTemplateCommon { +public: + SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} + +}; + + +/// SmallVectorImpl - This class consists of common code factored out of the +/// SmallVector class to reduce code duplication based on the SmallVector 'N' +/// template parameter. +template +class SmallVectorImpl : public SmallVectorTemplateBase::value> { +public: + typedef typename SmallVectorTemplateBase::value >::iterator + iterator; + typedef typename SmallVectorTemplateBase::value >::size_type + size_type; + + // Default ctor - Initialize to empty. + explicit SmallVectorImpl(unsigned N) + : SmallVectorTemplateBase::value>(N*sizeof(T)) { } - - T pop_back_val() { - T Result = back(); - pop_back(); - return Result; + + ~SmallVectorImpl() { + // Destroy the constructed elements in the vector. + destroy_range(this->begin(), this->end()); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!this->isSmall()) + operator delete(this->begin()); } - + + void clear() { - destroy_range(begin(), end()); + destroy_range(this->begin(), this->end()); this->EndX = this->BeginX; } void resize(unsigned N) { - if (N < size()) { - destroy_range(begin()+N, end()); - setEnd(begin()+N); - } else if (N > size()) { - if (capacity() < N) + if (N < this->size()) { + this->destroy_range(this->begin()+N, this->end()); + this->setEnd(this->begin()+N); + } else if (N > this->size()) { + if (this->capacity() < N) grow(N); - construct_range(end(), begin()+N, T()); - setEnd(begin()+N); + this->construct_range(this->end(), this->begin()+N, T()); + this->setEnd(this->begin()+N); } } void resize(unsigned N, const T &NV) { - if (N < size()) { - destroy_range(begin()+N, end()); - setEnd(begin()+N); - } else if (N > size()) { - if (capacity() < N) + if (N < this->size()) { + destroy_range(this->begin()+N, this->end()); + setEnd(this->begin()+N); + } else if (N > this->size()) { + if (this->capacity() < N) grow(N); - construct_range(end(), begin()+N, NV); - setEnd(begin()+N); + construct_range(this->end(), this->begin()+N, NV); + setEnd(this->begin()+N); } } void reserve(unsigned N) { - if (capacity() < N) + if (this->capacity() < N) grow(N); } - - void swap(SmallVectorTemplateCommon &RHS); - + + void push_back(const T &Elt) { + if (this->EndX < this->CapacityX) { + Retry: + new (this->end()) T(Elt); + setEnd(this->end()+1); + return; + } + this->grow(); + goto Retry; + } + + void pop_back() { + setEnd(this->end()-1); + this->end()->~T(); + } + + T pop_back_val() { + T Result = this->back(); + pop_back(); + return Result; + } + + + void swap(SmallVectorImpl &RHS); + /// append - Add the specified range to the end of the SmallVector. /// template void append(in_iter in_start, in_iter in_end) { size_type NumInputs = std::distance(in_start, in_end); // Grow allocated space if needed. - if (NumInputs > size_type(capacity_ptr()-end())) - grow(size()+NumInputs); - + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + grow(this->size()+NumInputs); + // Copy the new elements over. // TODO: NEED To compile time dispatch on whether in_iter is a random access // iterator to use the fast uninitialized_copy. - std::uninitialized_copy(in_start, in_end, end()); - setEnd(end() + NumInputs); + std::uninitialized_copy(in_start, in_end, this->end()); + setEnd(this->end() + NumInputs); } - + /// append - Add the specified range to the end of the SmallVector. /// void append(size_type NumInputs, const T &Elt) { // Grow allocated space if needed. - if (NumInputs > size_type(capacity_ptr()-end())) - grow(size()+NumInputs); - + if (NumInputs > size_type(this->capacity_ptr()-this->end())) + grow(this->size()+NumInputs); + // Copy the new elements over. - std::uninitialized_fill_n(end(), NumInputs, Elt); - setEnd(end() + NumInputs); + std::uninitialized_fill_n(this->end(), NumInputs, Elt); + setEnd(this->end() + NumInputs); } - + void assign(unsigned NumElts, const T &Elt) { clear(); - if (capacity() < NumElts) + if (this->capacity() < NumElts) grow(NumElts); - setEnd(begin()+NumElts); - construct_range(begin(), end(), Elt); + setEnd(this->begin()+NumElts); + construct_range(this->begin(), this->end(), Elt); } - + iterator erase(iterator I) { iterator N = I; // Shift all elts down one. - std::copy(I+1, end(), I); + std::copy(I+1, this->end(), I); // Drop the last elt. pop_back(); return(N); } - + iterator erase(iterator S, iterator E) { iterator N = S; // Shift all elts down. - iterator I = std::copy(E, end(), S); + iterator I = std::copy(E, this->end(), S); // Drop the last elts. - destroy_range(I, end()); + destroy_range(I, this->end()); setEnd(I); return(N); } - + iterator insert(iterator I, const T &Elt) { - if (I == end()) { // Important special case for empty vector. + if (I == this->end()) { // Important special case for empty vector. push_back(Elt); - return end()-1; + return this->end()-1; } - + if (this->EndX < this->CapacityX) { - Retry: - new (end()) T(back()); - setEnd(end()+1); + Retry: + new (this->end()) T(this->back()); + this->setEnd(this->end()+1); // Push everything else over. - std::copy_backward(I, end()-1, end()); + std::copy_backward(I, this->end()-1, this->end()); *I = Elt; return I; } - size_t EltNo = I-begin(); - grow(); - I = begin()+EltNo; + size_t EltNo = I-this->begin(); + this->grow(); + I = this->begin()+EltNo; goto Retry; } - + iterator insert(iterator I, size_type NumToInsert, const T &Elt) { - if (I == end()) { // Important special case for empty vector. + if (I == this->end()) { // Important special case for empty vector. append(NumToInsert, Elt); - return end()-1; + return this->end()-1; } - + // Convert iterator to elt# to avoid invalidating iterator when we reserve() - size_t InsertElt = I-begin(); - + size_t InsertElt = I - this->begin(); + // Ensure there is enough space. - reserve(static_cast(size() + NumToInsert)); - + reserve(static_cast(this->size() + NumToInsert)); + // Uninvalidate the iterator. - I = begin()+InsertElt; - + I = this->begin()+InsertElt; + // If there are more elements between the insertion point and the end of the // range than there are being inserted, we can use a simple approach to // insertion. Since we already reserved space, we know that this won't // reallocate the vector. - if (size_t(end()-I) >= NumToInsert) { - T *OldEnd = end(); - append(end()-NumToInsert, end()); - + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(this->end()-NumToInsert, this->end()); + // Copy the existing elements that get replaced. std::copy_backward(I, OldEnd-NumToInsert, OldEnd); - + std::fill_n(I, NumToInsert, Elt); return I; } - + // Otherwise, we're inserting more elements than exist already, and we're // not inserting at the end. - + // Copy over the elements that we're about to overwrite. - T *OldEnd = end(); - setEnd(end() + NumToInsert); + T *OldEnd = this->end(); + setEnd(this->end() + NumToInsert); size_t NumOverwritten = OldEnd-I; - uninitialized_copy(I, OldEnd, end()-NumOverwritten); - + uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + // Replace the overwritten part. std::fill_n(I, NumOverwritten, Elt); - + // Insert the non-overwritten middle part. std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt); return I; } - + template iterator insert(iterator I, ItTy From, ItTy To) { - if (I == end()) { // Important special case for empty vector. + if (I == this->end()) { // Important special case for empty vector. append(From, To); - return end()-1; + return this->end()-1; } - + size_t NumToInsert = std::distance(From, To); // Convert iterator to elt# to avoid invalidating iterator when we reserve() - size_t InsertElt = I-begin(); - + size_t InsertElt = I - this->begin(); + // Ensure there is enough space. - reserve(static_cast(size() + NumToInsert)); - + reserve(static_cast(this->size() + NumToInsert)); + // Uninvalidate the iterator. - I = begin()+InsertElt; - + I = this->begin()+InsertElt; + // If there are more elements between the insertion point and the end of the // range than there are being inserted, we can use a simple approach to // insertion. Since we already reserved space, we know that this won't // reallocate the vector. - if (size_t(end()-I) >= NumToInsert) { - T *OldEnd = end(); - append(end()-NumToInsert, end()); - + if (size_t(this->end()-I) >= NumToInsert) { + T *OldEnd = this->end(); + append(this->end()-NumToInsert, this->end()); + // Copy the existing elements that get replaced. std::copy_backward(I, OldEnd-NumToInsert, OldEnd); - + std::copy(From, To, I); return I; } - + // Otherwise, we're inserting more elements than exist already, and we're // not inserting at the end. - + // Copy over the elements that we're about to overwrite. - T *OldEnd = end(); - setEnd(end() + NumToInsert); + T *OldEnd = this->end(); + setEnd(this->end() + NumToInsert); size_t NumOverwritten = OldEnd-I; - uninitialized_copy(I, OldEnd, end()-NumOverwritten); - + uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + // Replace the overwritten part. std::copy(From, From+NumOverwritten, I); - + // Insert the non-overwritten middle part. uninitialized_copy(From+NumOverwritten, To, OldEnd); return I; } - - const SmallVectorTemplateCommon - &operator=(const SmallVectorTemplateCommon &RHS); - - bool operator==(const SmallVectorTemplateCommon &RHS) const { - if (size() != RHS.size()) return false; - return std::equal(begin(), end(), RHS.begin()); + + const SmallVectorImpl + &operator=(const SmallVectorImpl &RHS); + + bool operator==(const SmallVectorImpl &RHS) const { + if (this->size() != RHS.size()) return false; + return std::equal(this->begin(), this->end(), RHS.begin()); } - bool operator!=(const SmallVectorTemplateCommon &RHS) const { + bool operator!=(const SmallVectorImpl &RHS) const { return !(*this == RHS); } - - bool operator<(const SmallVectorTemplateCommon &RHS) const { - return std::lexicographical_compare(begin(), end(), + + bool operator<(const SmallVectorImpl &RHS) const { + return std::lexicographical_compare(this->begin(), this->end(), RHS.begin(), RHS.end()); } - + /// set_size - Set the array size to \arg N, which the current array must have /// enough capacity for. /// @@ -420,20 +456,20 @@ /// update the size later. This avoids the cost of value initializing elements /// which will only be overwritten. void set_size(unsigned N) { - assert(N <= capacity()); - setEnd(begin() + N); + assert(N <= this->capacity()); + setEnd(this->begin() + N); } - + private: /// grow - double the size of the allocated memory, guaranteeing space for at /// least one more element or MinSize if specified. - void grow(size_type MinSize = 0); - + void grow(size_t MinSize = 0); + static void construct_range(T *S, T *E, const T &Elt) { for (; S != E; ++S) new (S) T(Elt); } - + static void destroy_range(T *S, T *E) { // No need to do a destroy loop for POD's. if (isPodLike::value) return; @@ -459,31 +495,31 @@ // Define this out-of-line to dissuade the C++ compiler from inlining it. template -void SmallVectorTemplateCommon::grow(size_t MinSize) { - size_t CurCapacity = capacity(); - size_t CurSize = size(); +void SmallVectorImpl::grow(size_t MinSize) { + size_t CurCapacity = this->capacity(); + size_t CurSize = this->size(); size_t NewCapacity = 2*CurCapacity; if (NewCapacity < MinSize) NewCapacity = MinSize; T *NewElts = static_cast(operator new(NewCapacity*sizeof(T))); // Copy the elements over. - uninitialized_copy(begin(), end(), NewElts); + uninitialized_copy(this->begin(), this->end(), NewElts); // Destroy the original elements. - destroy_range(begin(), end()); + destroy_range(this->begin(), this->end()); // If this wasn't grown from the inline copy, deallocate the old space. if (!this->isSmall()) - operator delete(begin()); + operator delete(this->begin()); setEnd(NewElts+CurSize); this->BeginX = NewElts; - this->CapacityX = begin()+NewCapacity; + this->CapacityX = this->begin()+NewCapacity; } template -void SmallVectorTemplateCommon::swap(SmallVectorTemplateCommon &RHS) { +void SmallVectorImpl::swap(SmallVectorImpl &RHS) { if (this == &RHS) return; // We can only avoid copying elements if neither vector is small. @@ -493,54 +529,53 @@ std::swap(this->CapacityX, RHS.CapacityX); return; } - if (RHS.size() > capacity()) + if (RHS.size() > this->capacity()) grow(RHS.size()); - if (size() > RHS.capacity()) - RHS.grow(size()); + if (this->size() > RHS.capacity()) + RHS.grow(this->size()); // Swap the shared elements. - size_t NumShared = size(); + size_t NumShared = this->size(); if (NumShared > RHS.size()) NumShared = RHS.size(); for (unsigned i = 0; i != static_cast(NumShared); ++i) std::swap((*this)[i], RHS[i]); // Copy over the extra elts. - if (size() > RHS.size()) { - size_t EltDiff = size() - RHS.size(); - uninitialized_copy(begin()+NumShared, end(), RHS.end()); + if (this->size() > RHS.size()) { + size_t EltDiff = this->size() - RHS.size(); + uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); RHS.setEnd(RHS.end()+EltDiff); - destroy_range(begin()+NumShared, end()); - setEnd(begin()+NumShared); - } else if (RHS.size() > size()) { - size_t EltDiff = RHS.size() - size(); - uninitialized_copy(RHS.begin()+NumShared, RHS.end(), end()); - setEnd(end() + EltDiff); + destroy_range(this->begin()+NumShared, this->end()); + setEnd(this->begin()+NumShared); + } else if (RHS.size() > this->size()) { + size_t EltDiff = RHS.size() - this->size(); + uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); + setEnd(this->end() + EltDiff); destroy_range(RHS.begin()+NumShared, RHS.end()); RHS.setEnd(RHS.begin()+NumShared); } } template -const SmallVectorTemplateCommon & -SmallVectorTemplateCommon:: - operator=(const SmallVectorTemplateCommon &RHS) { +const SmallVectorImpl &SmallVectorImpl:: + operator=(const SmallVectorImpl &RHS) { // Avoid self-assignment. if (this == &RHS) return *this; // If we already have sufficient space, assign the common elements, then // destroy any excess. size_t RHSSize = RHS.size(); - size_t CurSize = size(); + size_t CurSize = this->size(); if (CurSize >= RHSSize) { // Assign common elements. iterator NewEnd; if (RHSSize) - NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, begin()); + NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); else - NewEnd = begin(); + NewEnd = this->begin(); // Destroy excess elements. - destroy_range(NewEnd, end()); + destroy_range(NewEnd, this->end()); // Trim. setEnd(NewEnd); @@ -549,52 +584,25 @@ // If we have to grow to have enough elements, destroy the current elements. // This allows us to avoid copying them during the grow. - if (capacity() < RHSSize) { + if (this->capacity() < RHSSize) { // Destroy current elements. - destroy_range(begin(), end()); - setEnd(begin()); + destroy_range(this->begin(), this->end()); + setEnd(this->begin()); CurSize = 0; grow(RHSSize); } else if (CurSize) { // Otherwise, use assignment for the already-constructed elements. - std::copy(RHS.begin(), RHS.begin()+CurSize, begin()); + std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); } // Copy construct the new elements in place. - uninitialized_copy(RHS.begin()+CurSize, RHS.end(), begin()+CurSize); + uninitialized_copy(RHS.begin()+CurSize, RHS.end(), this->begin()+CurSize); // Set end. - setEnd(begin()+RHSSize); + setEnd(this->begin()+RHSSize); return *this; } - -template -class SmallVectorTemplateBase : public SmallVectorTemplateCommon { -public: - SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} - -}; - -template -class SmallVectorTemplateBase : public SmallVectorTemplateCommon { -public: - SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} - -}; - - -/// SmallVectorImpl - This class consists of common code factored out of the -/// SmallVector class to reduce code duplication based on the SmallVector 'N' -/// template parameter. -template -class SmallVectorImpl : public SmallVectorTemplateBase::value> { -public: - // Default ctor - Initialize to empty. - explicit SmallVectorImpl(unsigned N) - : SmallVectorTemplateBase::value>(N*sizeof(T)) { - } -}; /// SmallVector - This is a 'vector' (really, a variable-sized array), optimized /// for the case when the array is small. It contains some number of elements From sabre at nondot.org Wed Dec 16 02:09:23 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 08:09:23 -0000 Subject: [llvm-commits] [llvm] r91523 - /llvm/trunk/include/llvm/ADT/SmallVector.h Message-ID: <200912160809.nBG89NOL012710@zion.cs.uiuc.edu> Author: lattner Date: Wed Dec 16 02:09:23 2009 New Revision: 91523 URL: http://llvm.org/viewvc/llvm-project?rev=91523&view=rev Log: pull destroy_range and uninitialized_copy up to the SmallVectorTemplateBase class, which allows us to statically dispatch on isPodLike instead of dynamically. Modified: llvm/trunk/include/llvm/ADT/SmallVector.h Modified: llvm/trunk/include/llvm/ADT/SmallVector.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=91523&r1=91522&r2=91523&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/SmallVector.h (original) +++ llvm/trunk/include/llvm/ADT/SmallVector.h Wed Dec 16 02:09:23 2009 @@ -157,19 +157,47 @@ } }; - +/// SmallVectorTemplateBase - This is where we put method +/// implementations that are designed to work with non-POD-like T's. template class SmallVectorTemplateBase : public SmallVectorTemplateCommon { public: SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} + static void destroy_range(T *S, T *E) { + while (S != E) { + --E; + E->~T(); + } + } + + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + std::uninitialized_copy(I, E, Dest); + } + }; +/// SmallVectorTemplateBase - This is where we put method +/// implementations that are designed to work with POD-like T's. template class SmallVectorTemplateBase : public SmallVectorTemplateCommon { public: SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon(Size) {} + // No need to do a destroy loop for POD's. + static void destroy_range(T *S, T *E) {} + + /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// starting with "Dest", constructing elements into it as needed. + template + static void uninitialized_copy(It1 I, It1 E, It2 Dest) { + // Use memcpy for PODs: std::uninitialized_copy optimizes to memmove, memcpy + // is better. + memcpy(&*Dest, &*I, (E-I)*sizeof(T)); + } }; @@ -178,11 +206,10 @@ /// template parameter. template class SmallVectorImpl : public SmallVectorTemplateBase::value> { + typedef SmallVectorTemplateBase::value > SuperClass; public: - typedef typename SmallVectorTemplateBase::value >::iterator - iterator; - typedef typename SmallVectorTemplateBase::value >::size_type - size_type; + typedef typename SuperClass::iterator iterator; + typedef typename SuperClass::size_type size_type; // Default ctor - Initialize to empty. explicit SmallVectorImpl(unsigned N) @@ -469,27 +496,6 @@ for (; S != E; ++S) new (S) T(Elt); } - - static void destroy_range(T *S, T *E) { - // No need to do a destroy loop for POD's. - if (isPodLike::value) return; - - while (S != E) { - --E; - E->~T(); - } - } - - /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory - /// starting with "Dest", constructing elements into it as needed. - template - static void uninitialized_copy(It1 I, It1 E, It2 Dest) { - // Use memcpy for PODs: std::uninitialized_copy optimizes to memmove. - if (isPodLike::value) - memcpy(&*Dest, &*I, (E-I)*sizeof(T)); - else - std::uninitialized_copy(I, E, Dest); - } }; From vhernandez at apple.com Wed Dec 16 02:10:57 2009 From: vhernandez at apple.com (Victor Hernandez) Date: Wed, 16 Dec 2009 08:10:57 -0000 Subject: [llvm-commits] [llvm] r91524 - in /llvm/trunk: include/llvm/Metadata.h lib/VMCore/Metadata.cpp Message-ID: <200912160810.nBG8AvmD012861@zion.cs.uiuc.edu> Author: hernande Date: Wed Dec 16 02:10:57 2009 New Revision: 91524 URL: http://llvm.org/viewvc/llvm-project?rev=91524&view=rev Log: Use different name for argument and field Modified: llvm/trunk/include/llvm/Metadata.h llvm/trunk/lib/VMCore/Metadata.cpp Modified: llvm/trunk/include/llvm/Metadata.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Metadata.h?rev=91524&r1=91523&r2=91524&view=diff ============================================================================== --- llvm/trunk/include/llvm/Metadata.h (original) +++ llvm/trunk/include/llvm/Metadata.h Wed Dec 16 02:10:57 2009 @@ -115,7 +115,7 @@ protected: explicit MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals, - Function *LocalFunction = NULL); + Function *LocalFunc = NULL); public: // Constructors and destructors. static MDNode *get(LLVMContext &Context, Modified: llvm/trunk/lib/VMCore/Metadata.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Metadata.cpp?rev=91524&r1=91523&r2=91524&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Metadata.cpp (original) +++ llvm/trunk/lib/VMCore/Metadata.cpp Wed Dec 16 02:10:57 2009 @@ -50,14 +50,14 @@ // MDNode implementation. // MDNode::MDNode(LLVMContext &C, Value *const *Vals, unsigned NumVals, - Function *LocalFunction) + Function *LocalFunc) : MetadataBase(Type::getMetadataTy(C), Value::MDNodeVal) { NodeSize = NumVals; Node = new ElementVH[NodeSize]; ElementVH *Ptr = Node; for (unsigned i = 0; i != NumVals; ++i) *Ptr++ = ElementVH(Vals[i], this); - LocalFunction = LocalFunction; + LocalFunction = LocalFunc; } void MDNode::Profile(FoldingSetNodeID &ID) const { From vhernandez at apple.com Wed Dec 16 02:13:19 2009 From: vhernandez at apple.com (Victor Hernandez) Date: Wed, 16 Dec 2009 00:13:19 -0800 Subject: [llvm-commits] [llvm] r91497 - in /llvm/trunk: include/llvm/Metadata.h lib/VMCore/Metadata.cpp In-Reply-To: <4B288291.3090704@mxc.ca> References: <200912160252.nBG2q9FI001712@zion.cs.uiuc.edu> <4B288291.3090704@mxc.ca> Message-ID: Nick, Thanks for the review. On Dec 15, 2009, at 10:47 PM, Nick Lewycky wrote: > Victor Hernandez wrote: >> Author: hernande >> Date: Tue Dec 15 20:52:09 2009 >> New Revision: 91497 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=91497&view=rev >> Log: >> MDNodes that refer to an instruction are local to a function; in that case, explicitly keep track of the function they are local to > > So what's the semantic here? What if the MDNode refers to an Instruction that gets spliced from one Function to another? What happens if the MDNode is attached to an Instruction that's RAUW'd with a Constant? > > Is this new field copied by MetadataContextImpl::copyMD? The semantic is that if an MDNode is created function-local, then it will continue to be function-local even if its operands are modified to no longer refer to any function-specific IR. I need to add that documentation to Metadata.h. If an instruction is copied from on Function to another, any function-local metadata that refers to it will have to point to the new instruction (and update its LocalFunction), or that operand can be replaced with null. The changes to the copying logic and the necessary asserts and verification are still in progress. > You also need to assert that any Instructions passed in also belong to LocalFunction. Good call. I will add that assert. I will also be adding Verification of function-local MDNodes that verifies the same. > >> Modified: >> llvm/trunk/include/llvm/Metadata.h >> llvm/trunk/lib/VMCore/Metadata.cpp >> >> Modified: llvm/trunk/include/llvm/Metadata.h >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Metadata.h?rev=91497&r1=91496&r2=91497&view=diff >> >> ============================================================================== >> --- llvm/trunk/include/llvm/Metadata.h (original) >> +++ llvm/trunk/include/llvm/Metadata.h Tue Dec 15 20:52:09 2009 >> @@ -111,13 +111,16 @@ >> >> ElementVH *Node; >> unsigned NodeSize; >> + Function *LocalFunction; >> >> protected: >> - explicit MDNode(LLVMContext&C, Value *const *Vals, unsigned NumVals); >> + explicit MDNode(LLVMContext&C, Value *const *Vals, unsigned NumVals, >> + Function *LocalFunction = NULL); >> public: >> // Constructors and destructors. >> static MDNode *get(LLVMContext&Context, >> - Value *const *Vals, unsigned NumVals); >> + Value *const *Vals, unsigned NumVals, >> + Function *LocalFunction = NULL); >> >> /// ~MDNode - Destroy MDNode. >> ~MDNode(); >> @@ -130,6 +133,9 @@ >> >> /// getNumElements - Return number of MDNode elements. >> unsigned getNumElements() const { return NodeSize; } >> + >> + /// isFunctionLocal - Return whether MDNode is local to a function. >> + bool isFunctionLocal() const { return LocalFunction; } >> >> /// Profile - calculate a unique identifier for this MDNode to collapse >> /// duplicates >> >> Modified: llvm/trunk/lib/VMCore/Metadata.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Metadata.cpp?rev=91497&r1=91496&r2=91497&view=diff >> >> ============================================================================== >> --- llvm/trunk/lib/VMCore/Metadata.cpp (original) >> +++ llvm/trunk/lib/VMCore/Metadata.cpp Tue Dec 15 20:52:09 2009 >> @@ -49,13 +49,15 @@ >> //===----------------------------------------------------------------------===// >> // MDNode implementation. >> // >> -MDNode::MDNode(LLVMContext&C, Value *const *Vals, unsigned NumVals) >> +MDNode::MDNode(LLVMContext&C, Value *const *Vals, unsigned NumVals, >> + Function *LocalFunction) >> : MetadataBase(Type::getMetadataTy(C), Value::MDNodeVal) { >> NodeSize = NumVals; >> Node = new ElementVH[NodeSize]; >> ElementVH *Ptr = Node; >> for (unsigned i = 0; i != NumVals; ++i) >> *Ptr++ = ElementVH(Vals[i], this); >> + LocalFunction = LocalFunction; > > Perhaps you meant this->LocalFunction = LocalFunction? Good catch. I fixed this in r91524. > > Nick > >> } >> >> void MDNode::Profile(FoldingSetNodeID&ID) const { >> @@ -63,17 +65,20 @@ >> ID.AddPointer(getElement(i)); >> } >> >> -MDNode *MDNode::get(LLVMContext&Context, Value*const* Vals, unsigned NumVals) { >> +MDNode *MDNode::get(LLVMContext&Context, Value*const* Vals, unsigned NumVals, >> + Function *LocalFunction) { >> LLVMContextImpl *pImpl = Context.pImpl; >> FoldingSetNodeID ID; >> for (unsigned i = 0; i != NumVals; ++i) >> ID.AddPointer(Vals[i]); >> + if (LocalFunction) >> + ID.AddPointer(LocalFunction); >> >> void *InsertPoint; >> MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint); >> if (!N) { >> // InsertPoint will have been set by the FindNodeOrInsertPos call. >> - N = new MDNode(Context, Vals, NumVals); >> + N = new MDNode(Context, Vals, NumVals, LocalFunction); >> pImpl->MDNodeSet.InsertNode(N, InsertPoint); >> } >> return N; >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20091216/3a807d4b/attachment.html From sabre at nondot.org Wed Dec 16 02:34:40 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 08:34:40 -0000 Subject: [llvm-commits] [llvm] r91526 - /llvm/trunk/include/llvm/ADT/SmallVector.h Message-ID: <200912160834.nBG8YejB013845@zion.cs.uiuc.edu> Author: lattner Date: Wed Dec 16 02:34:40 2009 New Revision: 91526 URL: http://llvm.org/viewvc/llvm-project?rev=91526&view=rev Log: factor out the grow() method for all pod implementations into one common function. It is still an inline method, which will be fixed next. Modified: llvm/trunk/include/llvm/ADT/SmallVector.h Modified: llvm/trunk/include/llvm/ADT/SmallVector.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=91526&r1=91525&r2=91526&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/SmallVector.h (original) +++ llvm/trunk/include/llvm/ADT/SmallVector.h Wed Dec 16 02:34:40 2009 @@ -80,9 +80,42 @@ return BeginX == static_cast(&FirstEl); } + /// size_in_bytes - This returns size()*sizeof(T). + size_t size_in_bytes() const { + return size_t((char*)EndX - (char*)BeginX); + } + + /// capacity_in_bytes - This returns capacity()*sizeof(T). + size_t capacity_in_bytes() const { + return size_t((char*)CapacityX - (char*)BeginX); + } + + inline void grow_pod(size_t MinSizeInBytes, size_t TSize); + public: bool empty() const { return BeginX == EndX; } }; + +inline void SmallVectorBase::grow_pod(size_t MinSizeInBytes, size_t TSize) { + size_t CurSizeBytes = size_in_bytes(); + size_t NewCapacityInBytes = 2 * capacity_in_bytes(); + if (NewCapacityInBytes < MinSizeInBytes) + NewCapacityInBytes = MinSizeInBytes; + void *NewElts = operator new(NewCapacityInBytes); + + // Copy the elements over. + memcpy(NewElts, this->BeginX, CurSizeBytes); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!this->isSmall()) + operator delete(this->BeginX); + + this->EndX = (char*)NewElts+CurSizeBytes; + this->BeginX = NewElts; + this->CapacityX = (char*)this->BeginX + NewCapacityInBytes; +} + + template class SmallVectorTemplateCommon : public SmallVectorBase { @@ -178,8 +211,37 @@ std::uninitialized_copy(I, E, Dest); } + /// grow - double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(size_t MinSize = 0); }; +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template +void SmallVectorTemplateBase::grow(size_t MinSize) { + size_t CurCapacity = this->capacity(); + size_t CurSize = this->size(); + size_t NewCapacity = 2*CurCapacity; + if (NewCapacity < MinSize) + NewCapacity = MinSize; + T *NewElts = static_cast(operator new(NewCapacity*sizeof(T))); + + // Copy the elements over. + uninitialized_copy(this->begin(), this->end(), NewElts); + + // Destroy the original elements. + destroy_range(this->begin(), this->end()); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!this->isSmall()) + operator delete(this->begin()); + + setEnd(NewElts+CurSize); + this->BeginX = NewElts; + this->CapacityX = this->begin()+NewCapacity; +} + + /// SmallVectorTemplateBase - This is where we put method /// implementations that are designed to work with POD-like T's. template @@ -198,6 +260,12 @@ // is better. memcpy(&*Dest, &*I, (E-I)*sizeof(T)); } + + /// grow - double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(size_t MinSize = 0) { + this->grow_pod(MinSize*sizeof(T), sizeof(T)); + } }; @@ -237,7 +305,7 @@ this->setEnd(this->begin()+N); } else if (N > this->size()) { if (this->capacity() < N) - grow(N); + this->grow(N); this->construct_range(this->end(), this->begin()+N, T()); this->setEnd(this->begin()+N); } @@ -249,7 +317,7 @@ setEnd(this->begin()+N); } else if (N > this->size()) { if (this->capacity() < N) - grow(N); + this->grow(N); construct_range(this->end(), this->begin()+N, NV); setEnd(this->begin()+N); } @@ -257,7 +325,7 @@ void reserve(unsigned N) { if (this->capacity() < N) - grow(N); + this->grow(N); } void push_back(const T &Elt) { @@ -292,7 +360,7 @@ size_type NumInputs = std::distance(in_start, in_end); // Grow allocated space if needed. if (NumInputs > size_type(this->capacity_ptr()-this->end())) - grow(this->size()+NumInputs); + this->grow(this->size()+NumInputs); // Copy the new elements over. // TODO: NEED To compile time dispatch on whether in_iter is a random access @@ -306,7 +374,7 @@ void append(size_type NumInputs, const T &Elt) { // Grow allocated space if needed. if (NumInputs > size_type(this->capacity_ptr()-this->end())) - grow(this->size()+NumInputs); + this->grow(this->size()+NumInputs); // Copy the new elements over. std::uninitialized_fill_n(this->end(), NumInputs, Elt); @@ -316,7 +384,7 @@ void assign(unsigned NumElts, const T &Elt) { clear(); if (this->capacity() < NumElts) - grow(NumElts); + this->grow(NumElts); setEnd(this->begin()+NumElts); construct_range(this->begin(), this->end(), Elt); } @@ -488,10 +556,6 @@ } private: - /// grow - double the size of the allocated memory, guaranteeing space for at - /// least one more element or MinSize if specified. - void grow(size_t MinSize = 0); - static void construct_range(T *S, T *E, const T &Elt) { for (; S != E; ++S) new (S) T(Elt); @@ -499,31 +563,6 @@ }; -// Define this out-of-line to dissuade the C++ compiler from inlining it. -template -void SmallVectorImpl::grow(size_t MinSize) { - size_t CurCapacity = this->capacity(); - size_t CurSize = this->size(); - size_t NewCapacity = 2*CurCapacity; - if (NewCapacity < MinSize) - NewCapacity = MinSize; - T *NewElts = static_cast(operator new(NewCapacity*sizeof(T))); - - // Copy the elements over. - uninitialized_copy(this->begin(), this->end(), NewElts); - - // Destroy the original elements. - destroy_range(this->begin(), this->end()); - - // If this wasn't grown from the inline copy, deallocate the old space. - if (!this->isSmall()) - operator delete(this->begin()); - - setEnd(NewElts+CurSize); - this->BeginX = NewElts; - this->CapacityX = this->begin()+NewCapacity; -} - template void SmallVectorImpl::swap(SmallVectorImpl &RHS) { if (this == &RHS) return; @@ -536,7 +575,7 @@ return; } if (RHS.size() > this->capacity()) - grow(RHS.size()); + this->grow(RHS.size()); if (this->size() > RHS.capacity()) RHS.grow(this->size()); @@ -595,7 +634,7 @@ destroy_range(this->begin(), this->end()); setEnd(this->begin()); CurSize = 0; - grow(RHSSize); + this->grow(RHSSize); } else if (CurSize) { // Otherwise, use assignment for the already-constructed elements. std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); From sabre at nondot.org Wed Dec 16 02:35:55 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 08:35:55 -0000 Subject: [llvm-commits] [llvm] r91527 - /llvm/trunk/lib/System/Unix/Path.inc Message-ID: <200912160835.nBG8ZtFq013885@zion.cs.uiuc.edu> Author: lattner Date: Wed Dec 16 02:35:54 2009 New Revision: 91527 URL: http://llvm.org/viewvc/llvm-project?rev=91527&view=rev Log: eliminate an extraneous use of SmallVector in a case where a fixed size buffer is perfectly fine. Modified: llvm/trunk/lib/System/Unix/Path.inc Modified: llvm/trunk/lib/System/Unix/Path.inc URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Unix/Path.inc?rev=91527&r1=91526&r2=91527&view=diff ============================================================================== --- llvm/trunk/lib/System/Unix/Path.inc (original) +++ llvm/trunk/lib/System/Unix/Path.inc Wed Dec 16 02:35:54 2009 @@ -414,21 +414,19 @@ return path.substr(dot + 1); } -bool Path::getMagicNumber(std::string& Magic, unsigned len) const { +bool Path::getMagicNumber(std::string &Magic, unsigned len) const { assert(len < 1024 && "Request for magic string too long"); - SmallVector Buf; - Buf.resize(1 + len); - char* buf = Buf.data(); + char Buf[1025]; int fd = ::open(path.c_str(), O_RDONLY); if (fd < 0) return false; - ssize_t bytes_read = ::read(fd, buf, len); + ssize_t bytes_read = ::read(fd, Buf, len); ::close(fd); if (ssize_t(len) != bytes_read) { Magic.clear(); return false; } - Magic.assign(buf,len); + Magic.assign(Buf, len); return true; } From sabre at nondot.org Wed Dec 16 02:40:45 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 08:40:45 -0000 Subject: [llvm-commits] [llvm] r91528 - /llvm/trunk/lib/System/Unix/Path.inc Message-ID: <200912160840.nBG8ejwC016798@zion.cs.uiuc.edu> Author: lattner Date: Wed Dec 16 02:40:44 2009 New Revision: 91528 URL: http://llvm.org/viewvc/llvm-project?rev=91528&view=rev Log: remove use of SmallVector from Path::makeUnique. Path::makeUnique is not used by anything performance sensitive, so just use std::string. Modified: llvm/trunk/lib/System/Unix/Path.inc Modified: llvm/trunk/lib/System/Unix/Path.inc URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/System/Unix/Path.inc?rev=91528&r1=91527&r2=91528&view=diff ============================================================================== --- llvm/trunk/lib/System/Unix/Path.inc (original) +++ llvm/trunk/lib/System/Unix/Path.inc Wed Dec 16 02:40:44 2009 @@ -16,7 +16,6 @@ //=== is guaranteed to work on *all* UNIX variants. //===----------------------------------------------------------------------===// -#include "llvm/ADT/SmallVector.h" #include "Unix.h" #if HAVE_SYS_STAT_H #include @@ -859,18 +858,15 @@ // Append an XXXXXX pattern to the end of the file for use with mkstemp, // mktemp or our own implementation. - SmallVector Buf; - Buf.resize(path.size()+8); - char *FNBuffer = Buf.data(); - path.copy(FNBuffer,path.size()); + std::string Buf(path); if (isDirectory()) - strcpy(FNBuffer+path.size(), "/XXXXXX"); + Buf += "/XXXXXX"; else - strcpy(FNBuffer+path.size(), "-XXXXXX"); + Buf += "-XXXXXX"; #if defined(HAVE_MKSTEMP) int TempFD; - if ((TempFD = mkstemp(FNBuffer)) == -1) + if ((TempFD = mkstemp((char*)Buf.c_str())) == -1) return MakeErrMsg(ErrMsg, path + ": can't make unique filename"); // We don't need to hold the temp file descriptor... we will trust that no one @@ -878,21 +874,21 @@ close(TempFD); // Save the name - path = FNBuffer; + path = Buf; #elif defined(HAVE_MKTEMP) // If we don't have mkstemp, use the old and obsolete mktemp function. - if (mktemp(FNBuffer) == 0) + if (mktemp(Buf.c_str()) == 0) return MakeErrMsg(ErrMsg, path + ": can't make unique filename"); // Save the name - path = FNBuffer; + path = Buf; #else // Okay, looks like we have to do it all by our lonesome. static unsigned FCounter = 0; unsigned offset = path.size() + 1; - while ( FCounter < 999999 && exists()) { - sprintf(FNBuffer+offset,"%06u",++FCounter); - path = FNBuffer; + while (FCounter < 999999 && exists()) { + sprintf(Buf.data()+offset, "%06u", ++FCounter); + path = Buf; } if (FCounter > 999999) return MakeErrMsg(ErrMsg, From sabre at nondot.org Wed Dec 16 02:44:25 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 08:44:25 -0000 Subject: [llvm-commits] [llvm] r91529 - in /llvm/trunk: include/llvm/ADT/SmallVector.h lib/Support/CMakeLists.txt lib/Support/SmallVector.cpp Message-ID: <200912160844.nBG8iPJ2019156@zion.cs.uiuc.edu> Author: lattner Date: Wed Dec 16 02:44:24 2009 New Revision: 91529 URL: http://llvm.org/viewvc/llvm-project?rev=91529&view=rev Log: now that libsystem no longer uses SmallVector, we can move SmallVectorBase::grow_pod out of line, finally satisfying PR3758. Added: llvm/trunk/lib/Support/SmallVector.cpp Modified: llvm/trunk/include/llvm/ADT/SmallVector.h llvm/trunk/lib/Support/CMakeLists.txt Modified: llvm/trunk/include/llvm/ADT/SmallVector.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=91529&r1=91528&r2=91529&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/SmallVector.h (original) +++ llvm/trunk/include/llvm/ADT/SmallVector.h Wed Dec 16 02:44:24 2009 @@ -90,32 +90,14 @@ return size_t((char*)CapacityX - (char*)BeginX); } - inline void grow_pod(size_t MinSizeInBytes, size_t TSize); + /// grow_pod - This is an implementation of the grow() method which only works + /// on POD-like datatypes and is out of line to reduce code duplication. + void grow_pod(size_t MinSizeInBytes, size_t TSize); public: bool empty() const { return BeginX == EndX; } }; -inline void SmallVectorBase::grow_pod(size_t MinSizeInBytes, size_t TSize) { - size_t CurSizeBytes = size_in_bytes(); - size_t NewCapacityInBytes = 2 * capacity_in_bytes(); - if (NewCapacityInBytes < MinSizeInBytes) - NewCapacityInBytes = MinSizeInBytes; - void *NewElts = operator new(NewCapacityInBytes); - - // Copy the elements over. - memcpy(NewElts, this->BeginX, CurSizeBytes); - - // If this wasn't grown from the inline copy, deallocate the old space. - if (!this->isSmall()) - operator delete(this->BeginX); - - this->EndX = (char*)NewElts+CurSizeBytes; - this->BeginX = NewElts; - this->CapacityX = (char*)this->BeginX + NewCapacityInBytes; -} - - template class SmallVectorTemplateCommon : public SmallVectorBase { Modified: llvm/trunk/lib/Support/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/CMakeLists.txt?rev=91529&r1=91528&r2=91529&view=diff ============================================================================== --- llvm/trunk/lib/Support/CMakeLists.txt (original) +++ llvm/trunk/lib/Support/CMakeLists.txt Wed Dec 16 02:44:24 2009 @@ -23,6 +23,7 @@ Regex.cpp SlowOperationInformer.cpp SmallPtrSet.cpp + SmallVector.cpp SourceMgr.cpp Statistic.cpp StringExtras.cpp Added: llvm/trunk/lib/Support/SmallVector.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/SmallVector.cpp?rev=91529&view=auto ============================================================================== --- llvm/trunk/lib/Support/SmallVector.cpp (added) +++ llvm/trunk/lib/Support/SmallVector.cpp Wed Dec 16 02:44:24 2009 @@ -0,0 +1,37 @@ +//===- llvm/ADT/SmallVector.cpp - 'Normally small' vectors ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SmallVector class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +using namespace llvm; + +/// grow_pod - This is an implementation of the grow() method which only works +/// on POD-like datatypes and is out of line to reduce code duplication. +void SmallVectorBase::grow_pod(size_t MinSizeInBytes, size_t TSize) { + size_t CurSizeBytes = size_in_bytes(); + size_t NewCapacityInBytes = 2 * capacity_in_bytes(); + if (NewCapacityInBytes < MinSizeInBytes) + NewCapacityInBytes = MinSizeInBytes; + void *NewElts = operator new(NewCapacityInBytes); + + // Copy the elements over. No need to run dtors on PODs. + memcpy(NewElts, this->BeginX, CurSizeBytes); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!this->isSmall()) + operator delete(this->BeginX); + + this->EndX = (char*)NewElts+CurSizeBytes; + this->BeginX = NewElts; + this->CapacityX = (char*)this->BeginX + NewCapacityInBytes; +} + From sabre at nondot.org Wed Dec 16 03:05:34 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 03:05:34 -0600 Subject: [llvm-commits] CVS: llvm-www/OpenProjects.html Message-ID: <200912160905.nBG95YP7028981@zion.cs.uiuc.edu> Changes in directory llvm-www: OpenProjects.html updated: 1.56 -> 1.57 --- Log message: update a few entries, add super optimizer idea from John. --- Diffs of the changes: (+20 -28) OpenProjects.html | 48 ++++++++++++++++++++---------------------------- 1 files changed, 20 insertions(+), 28 deletions(-) Index: llvm-www/OpenProjects.html diff -u llvm-www/OpenProjects.html:1.56 llvm-www/OpenProjects.html:1.57 --- llvm-www/OpenProjects.html:1.56 Wed Nov 11 00:41:50 2009 +++ llvm-www/OpenProjects.html Wed Dec 16 03:03:23 2009 @@ -22,7 +22,6 @@
  • Code Compaction
  • New Transformations and Analyses
  • Code Generator Improvements
  • -
  • Emit objects directly
  • Miscellaneous Additions
  • @@ -409,19 +408,15 @@ analysis machinery from LiveIntervals. Making the stack smaller is good for cache use and very important on targets where loads have limited displacement like ppc, thumb, mips, sparc, etc. This should be done as - a pass before prolog epilog insertion. + a pass before prolog epilog insertion. This is now done for register + allocator temporaries, but not for allocas.
  • Implement 'shrink wrapping', which is the intelligent placement of callee saved register save/restores. Right now PrologEpilogInsertion always saves every (modified) callee save reg in the prolog and restores it in the epilog. However, some paths through a function (e.g. an early exit) may not use all regs. Sinking the save down the CFG avoids useless work on - these paths.
  • + these paths. Work has started on this, please inquire on llvmdev.
  • Rename ISD::BIT_CONVERT to ISD::BITCAST to match the llvm ir concept
  • -
  • Change the VECTOR_SHUFFLE to be variadic. Right now, a VECTOR_SHUFFLE - takes three operands: two vectors and a shuffle mask. The shuffle mask is - required to be a BUILD_VECTOR node of N indices. It would be much better - (for several reasons) to eliminate the BUILD_VECTOR and make VECTOR_SHUFFLE - take 2+N operands instead.
  • Finish adapting existing targets to use the calling convention description mechanism (see lib/Target/X86/X86CallingConv.td for an example).
  • Implement interprocedural register allocation. The CallGraphSCCPass can be @@ -431,25 +426,6 @@
  • Implement a verifier for codegen level instructions. To help track down malformed machineinstrs sooner and make debugging problems easier.
  • -
  • Write a new backend for a target - (VAX, i960, PA-RISC, - MMIX?)
  • - - - - - - - -
    - -
      -
    1. Implement MachOWriter and ELFWriter to allow LLVM-based compilers to - bypass an external assembler.
    2. -
    3. Implement an assembler for inline assembly. Reuse the tablegen files - from each backend.
    @@ -486,6 +462,22 @@ for gcc compiled code.
  • Write LLVM IR level debugger (extend Interpreter?)
  • +
  • Write an LLVM Superoptimizer. It would be interesting to take ideas from + this superoptimizer for x86: +paper #1 and paper #2 and adapt them to run on LLVM code.

    + +It would seem that operating on LLVM code would save a lot of time +because its semantics are much simpler than x86. The cost of operating +on LLVM is that target-specific tricks would be missed.

    + +The outcome would be a new LLVM pass that subsumes at least the +instruction combiner, and probably a few other passes as well. Benefits +would include not missing cases missed by the current combiner and also +more easily adapting to changes in the LLVM IR.

    + +All previous superoptimizers have worked on linear sequences of code. +It would seem much better to operate on small subgraphs of the program +dependency graph.

  • @@ -500,7 +492,7 @@ src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!"> LLVM Compiler Infrastructure
    - Last modified: $Date: 2009/11/11 06:41:50 $ + Last modified: $Date: 2009/12/16 09:03:23 $ From sabre at nondot.org Wed Dec 16 03:09:56 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 09:09:56 -0000 Subject: [llvm-commits] [llvm] r91530 - /llvm/trunk/include/llvm/ADT/SmallVector.h Message-ID: <200912160909.nBG99umD029625@zion.cs.uiuc.edu> Author: lattner Date: Wed Dec 16 03:09:54 2009 New Revision: 91530 URL: http://llvm.org/viewvc/llvm-project?rev=91530&view=rev Log: Fix a missing this-> that clang++ notices. Modified: llvm/trunk/include/llvm/ADT/SmallVector.h Modified: llvm/trunk/include/llvm/ADT/SmallVector.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=91530&r1=91529&r2=91530&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/SmallVector.h (original) +++ llvm/trunk/include/llvm/ADT/SmallVector.h Wed Dec 16 03:09:54 2009 @@ -314,7 +314,7 @@ if (this->EndX < this->CapacityX) { Retry: new (this->end()) T(Elt); - setEnd(this->end()+1); + this->setEnd(this->end()+1); return; } this->grow(); From sabre at nondot.org Wed Dec 16 03:17:12 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 09:17:12 -0000 Subject: [llvm-commits] [llvm] r91531 - /llvm/trunk/include/llvm/ADT/SmallVector.h Message-ID: <200912160917.nBG9HC4W029882@zion.cs.uiuc.edu> Author: lattner Date: Wed Dec 16 03:17:12 2009 New Revision: 91531 URL: http://llvm.org/viewvc/llvm-project?rev=91531&view=rev Log: fix more missing this->'s to placate clang++ Modified: llvm/trunk/include/llvm/ADT/SmallVector.h Modified: llvm/trunk/include/llvm/ADT/SmallVector.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/SmallVector.h?rev=91531&r1=91530&r2=91531&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/SmallVector.h (original) +++ llvm/trunk/include/llvm/ADT/SmallVector.h Wed Dec 16 03:17:12 2009 @@ -268,7 +268,7 @@ ~SmallVectorImpl() { // Destroy the constructed elements in the vector. - destroy_range(this->begin(), this->end()); + this->destroy_range(this->begin(), this->end()); // If this wasn't grown from the inline copy, deallocate the old space. if (!this->isSmall()) @@ -277,7 +277,7 @@ void clear() { - destroy_range(this->begin(), this->end()); + this->destroy_range(this->begin(), this->end()); this->EndX = this->BeginX; } @@ -295,13 +295,13 @@ void resize(unsigned N, const T &NV) { if (N < this->size()) { - destroy_range(this->begin()+N, this->end()); - setEnd(this->begin()+N); + this->destroy_range(this->begin()+N, this->end()); + this->setEnd(this->begin()+N); } else if (N > this->size()) { if (this->capacity() < N) this->grow(N); construct_range(this->end(), this->begin()+N, NV); - setEnd(this->begin()+N); + this->setEnd(this->begin()+N); } } @@ -322,7 +322,7 @@ } void pop_back() { - setEnd(this->end()-1); + this->setEnd(this->end()-1); this->end()->~T(); } @@ -348,7 +348,7 @@ // TODO: NEED To compile time dispatch on whether in_iter is a random access // iterator to use the fast uninitialized_copy. std::uninitialized_copy(in_start, in_end, this->end()); - setEnd(this->end() + NumInputs); + this->setEnd(this->end() + NumInputs); } /// append - Add the specified range to the end of the SmallVector. @@ -360,14 +360,14 @@ // Copy the new elements over. std::uninitialized_fill_n(this->end(), NumInputs, Elt); - setEnd(this->end() + NumInputs); + this->setEnd(this->end() + NumInputs); } void assign(unsigned NumElts, const T &Elt) { clear(); if (this->capacity() < NumElts) this->grow(NumElts); - setEnd(this->begin()+NumElts); + this->setEnd(this->begin()+NumElts); construct_range(this->begin(), this->end(), Elt); } @@ -385,8 +385,8 @@ // Shift all elts down. iterator I = std::copy(E, this->end(), S); // Drop the last elts. - destroy_range(I, this->end()); - setEnd(I); + this->destroy_range(I, this->end()); + this->setEnd(I); return(N); } @@ -446,9 +446,9 @@ // Copy over the elements that we're about to overwrite. T *OldEnd = this->end(); - setEnd(this->end() + NumToInsert); + this->setEnd(this->end() + NumToInsert); size_t NumOverwritten = OldEnd-I; - uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); + this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten); // Replace the overwritten part. std::fill_n(I, NumOverwritten, Elt); @@ -534,7 +534,7 @@ /// which will only be overwritten. void set_size(unsigned N) { assert(N <= this->capacity()); - setEnd(this->begin() + N); + this->setEnd(this->begin() + N); } private: @@ -570,15 +570,15 @@ // Copy over the extra elts. if (this->size() > RHS.size()) { size_t EltDiff = this->size() - RHS.size(); - uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); + this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); RHS.setEnd(RHS.end()+EltDiff); - destroy_range(this->begin()+NumShared, this->end()); - setEnd(this->begin()+NumShared); + this->destroy_range(this->begin()+NumShared, this->end()); + this->setEnd(this->begin()+NumShared); } else if (RHS.size() > this->size()) { size_t EltDiff = RHS.size() - this->size(); - uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); - setEnd(this->end() + EltDiff); - destroy_range(RHS.begin()+NumShared, RHS.end()); + this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); + this->setEnd(this->end() + EltDiff); + this->destroy_range(RHS.begin()+NumShared, RHS.end()); RHS.setEnd(RHS.begin()+NumShared); } } @@ -602,10 +602,10 @@ NewEnd = this->begin(); // Destroy excess elements. - destroy_range(NewEnd, this->end()); + this->destroy_range(NewEnd, this->end()); // Trim. - setEnd(NewEnd); + this->setEnd(NewEnd); return *this; } @@ -613,8 +613,8 @@ // This allows us to avoid copying them during the grow. if (this->capacity() < RHSSize) { // Destroy current elements. - destroy_range(this->begin(), this->end()); - setEnd(this->begin()); + this->destroy_range(this->begin(), this->end()); + this->setEnd(this->begin()); CurSize = 0; this->grow(RHSSize); } else if (CurSize) { @@ -623,10 +623,11 @@ } // Copy construct the new elements in place. - uninitialized_copy(RHS.begin()+CurSize, RHS.end(), this->begin()+CurSize); + this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), + this->begin()+CurSize); // Set end. - setEnd(this->begin()+RHSSize); + this->setEnd(this->begin()+RHSSize); return *this; } From sabre at nondot.org Wed Dec 16 03:32:05 2009 From: sabre at nondot.org (Chris Lattner) Date: Wed, 16 Dec 2009 09:32:05 -0000 Subject: [llvm-commits] [llvm] r91532 - in /llvm/trunk: lib/Transforms/Scalar/SimplifyLibCalls.cpp test/Transforms/SimplifyLibCalls/StrStr.ll Message-ID: <200912160932.nBG9W5a5030421@zion.cs.uiuc.edu> Author: lattner Date: Wed Dec 16 03:32:05 2009 New Revision: 91532 URL: http://llvm.org/viewvc/llvm-project?rev=91532&view=rev Log: reapply my strstr optimization. I have reproduced the x86-64 bootstrap miscompile (i386.o miscompares) but it happens both with and without this patch. Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll Modified: llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp?rev=91532&r1=91531&r2=91532&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/SimplifyLibCalls.cpp Wed Dec 16 03:32:05 2009 @@ -76,6 +76,11 @@ /// return value has 'intptr_t' type. Value *EmitStrLen(Value *Ptr, IRBuilder<> &B); + /// EmitStrChr - Emit a call to the strchr function to the builder, for the + /// specified pointer and character. Ptr is required to be some pointer type, + /// and the return value has 'i8*' type. + Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B); + /// EmitMemCpy - Emit a call to the memcpy function to the builder. This /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, @@ -151,6 +156,26 @@ return CI; } +/// EmitStrChr - Emit a call to the strchr function to the builder, for the +/// specified pointer and character. Ptr is required to be some pointer type, +/// and the return value has 'i8*' type. +Value *LibCallOptimization::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B) { + Module *M = Caller->getParent(); + AttributeWithIndex AWI = + AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind); + + const Type *I8Ptr = Type::getInt8PtrTy(*Context); + const Type *I32Ty = Type::getInt32Ty(*Context); + Constant *StrChr = M->getOrInsertFunction("strchr", AttrListPtr::get(&AWI, 1), + I8Ptr, I8Ptr, I32Ty, NULL); + CallInst *CI = B.CreateCall2(StrChr, CastToCStr(Ptr, B), + ConstantInt::get(I32Ty, C), "strchr"); + if (const Function *F = dyn_cast(StrChr->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + return CI; +} + + /// EmitMemCpy - Emit a call to the memcpy function to the builder. This always /// expects that the size has type 'intptr_t' and Dst/Src are pointers. Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len, @@ -890,7 +915,7 @@ }; //===---------------------------------------===// -// 'strto*' Optimizations +// 'strto*' Optimizations. This handles strtol, strtod, strtof, strtoul, etc. struct StrToOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { @@ -910,6 +935,52 @@ } }; +//===---------------------------------------===// +// 'strstr' Optimizations + +struct StrStrOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !isa(FT->getReturnType())) + return 0; + + // fold strstr(x, x) -> x. + if (CI->getOperand(1) == CI->getOperand(2)) + return B.CreateBitCast(CI->getOperand(1), CI->getType()); + + // See if either input string is a constant string. + std::string SearchStr, ToFindStr; + bool HasStr1 = GetConstantStringInfo(CI->getOperand(1), SearchStr); + bool HasStr2 = GetConstantStringInfo(CI->getOperand(2), ToFindStr); + + // fold strstr(x, "") -> x. + if (HasStr2 && ToFindStr.empty()) + return B.CreateBitCast(CI->getOperand(1), CI->getType()); + + // If both strings are known, constant fold it. + if (HasStr1 && HasStr2) { + std::string::size_type Offset = SearchStr.find(ToFindStr); + + if (Offset == std::string::npos) // strstr("foo", "bar") -> null + return Constant::getNullValue(CI->getType()); + + // strstr("abcd", "bc") -> gep((char*)"abcd", 1) + Value *Result = CastToCStr(CI->getOperand(1), B); + Result = B.CreateConstInBoundsGEP1_64(Result, Offset, "strstr"); + return B.CreateBitCast(Result, CI->getType()); + } + + // fold strstr(x, "y") -> strchr(x, 'y'). + if (HasStr2 && ToFindStr.size() == 1) + return B.CreateBitCast(EmitStrChr(CI->getOperand(1), ToFindStr[0], B), + CI->getType()); + return 0; + } +}; + //===---------------------------------------===// // 'memcmp' Optimizations @@ -1675,8 +1746,8 @@ // String and Memory LibCall Optimizations StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; StrCmpOpt StrCmp; StrNCmpOpt StrNCmp; StrCpyOpt StrCpy; StrNCpyOpt StrNCpy; StrLenOpt StrLen; - StrToOpt StrTo; MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; - MemSetOpt MemSet; + StrToOpt StrTo; StrStrOpt StrStr; + MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet; // Math Library Optimizations PowOpt Pow; Exp2Opt Exp2; UnaryDoubleFPOpt UnaryDoubleFP; // Integer Optimizations @@ -1738,6 +1809,7 @@ Optimizations["strtoll"] = &StrTo; Optimizations["strtold"] = &StrTo; Optimizations["strtoull"] = &StrTo; + Optimizations["strstr"] = &StrStr; Optimizations["memcmp"] = &MemCmp; Optimizations["memcpy"] = &MemCpy; Optimizations["memmove"] = &MemMove; @@ -2644,12 +2716,6 @@ // * strcspn("",a) -> 0 // * strcspn(s,"") -> strlen(a) // -// strstr: (PR5783) -// * strstr(x,x) -> x -// * strstr(x, "") -> x -// * strstr(x, "a") -> strchr(x, 'a') -// * strstr(s1,s2) -> result (if s1 and s2 are constant strings) -// // tan, tanf, tanl: // * tan(atan(x)) -> x // Modified: llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll?rev=91532&r1=91531&r2=91532&view=diff ============================================================================== --- llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll (original) +++ llvm/trunk/test/Transforms/SimplifyLibCalls/StrStr.ll Wed Dec 16 03:32:05 2009 @@ -0,0 +1,48 @@ +; RUN: opt < %s -simplify-libcalls -S | FileCheck %s +; PR5783 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" +target triple = "i386-apple-darwin9.0" + + at .str = private constant [1 x i8] zeroinitializer ; <[1 x i8]*> [#uses=1] + at .str1 = private constant [2 x i8] c"a\00" ; <[2 x i8]*> [#uses=1] + at .str2 = private constant [6 x i8] c"abcde\00" ; <[6 x i8]*> [#uses=1] + at .str3 = private constant [4 x i8] c"bcd\00" ; <[4 x i8]*> [#uses=1] + +define i8* @test1(i8* %P) nounwind readonly { +entry: + %call = tail call i8* @strstr(i8* %P, i8* getelementptr inbounds ([1 x i8]* @.str, i32 0, i32 0)) nounwind ; [#uses=1] + ret i8* %call +; strstr(P, "") -> P +; CHECK: @test1 +; CHECK: ret i8* %P +} + +declare i8* @strstr(i8*, i8* nocapture) nounwind readonly + +define i8* @test2(i8* %P) nounwind readonly { +entry: + %call = tail call i8* @strstr(i8* %P, i8* getelementptr inbounds ([2 x i8]* @.str1, i32 0, i32 0)) nounwind ; [#uses=1] + ret i8* %call +; strstr(P, "a") -> strchr(P, 'a') +; CHECK: @test2 +; CHECK: @strchr(i8* %P, i32 97) +} + +define i8* @test3(i8* nocapture %P) nounwind readonly { +entry: + %call = tail call i8* @strstr(i8* getelementptr inbounds ([6 x i8]* @.str2, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8]* @.str3, i32 0, i32 0)) nounwind ; [#uses=1] + ret i8* %call +; strstr("abcde", "bcd") -> "abcde"+1 +; CHECK: @test3 +; CHECK: getelementptr inbounds ([6 x i8]* @.str2, i32 0, i64 1) +} + +define i8* @test4(i8* %P) nounwind readonly { +entry: + %call = tail call i8* @strstr(i8* %P, i8* %P) nounwind ; [#uses=1] + ret i8* %call +; strstr(P, P) -> P +; CHECK: @test4 +; CHECK: ret i8* %P +} From clattner at apple.com Wed Dec 16 03:35:02 2009 From: clattner at apple.com (Chris Lattner) Date: Wed, 16 Dec 2009 01:35:02 -0800 Subject: [llvm-commits] x86-64 miscompile Message-ID: <4635215F-70B3-4414-9B9F-52CE43810B4C@apple.com> I suspect a scheduling nondeterminism. The file that miscompares is i386.o and the only difference is: 1c1 < stage2-gcc/i386.o: --- > stage3-gcc/i386.o: 22171,22172c22171,22172 < 0000000000014a87 movq %rax,%rbx < 0000000000014a8a movq %rbx,0xc8(%rbp) --- > 0000000000014a87 movq %rax,0xc8(%rbp) > 0000000000014a8b movq %rax,%rbx It could also be a copy elimination or folding thing I guess. -Chris From edwintorok at gmail.com Wed Dec 16 04:38:01 2009 From: edwintorok at gmail.com (=?ISO-8859-1?Q?T=F6r=F6k_Edwin?=) Date: Wed, 16 Dec 2009 12:38:01 +0200 Subject: [llvm-commits] [llvm] r91489 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86Instr64bit.td lib/Target/X86/X86InstrInfo.td test/CodeGen/X86/setcc.ll In-Reply-To: <200912160053.nBG0rDDv029906@zion.cs.uiuc.edu> References: <200912160053.nBG0rDDv029906@zion.cs.uiuc.edu> Message-ID: <4B28B889.4060107@gmail.com> On 2009-12-16 02:53, Evan Cheng wrote: > Author: evancheng > Date: Tue Dec 15 18:53:11 2009 > New Revision: 91489 > > URL: http://llvm.org/viewvc/llvm-project?rev=91489&view=rev > Log: > Re-enable 91381 with fixes. > > Modified: > llvm/trunk/lib/Target/X86/X86ISelLowering.cpp > llvm/trunk/lib/Target/X86/X86Instr64bit.td > llvm/trunk/lib/Target/X86/X86InstrInfo.td > llvm/trunk/test/CodeGen/X86/setcc.ll > > Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=91489&r1=91488&r2=91489&view=diff > > ============================================================================== > --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) > +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Dec 15 18:53:11 2009 > @@ -980,6 +980,7 @@ > setTargetDAGCombine(ISD::SRL); > setTargetDAGCombine(ISD::STORE); > setTargetDAGCombine(ISD::MEMBARRIER); > + setTargetDAGCombine(ISD::ZERO_EXTEND); > Hi Evan, I noticed an infloop convertin and->zero_extend->and, could this patch be the cause? http://llvm.org/bugs/show_bug.cgi?id=5802 Best regards, --Edwin From daniel at zuster.org Wed Dec 16 04:56:03 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Wed, 16 Dec 2009 10:56:03 -0000 Subject: [llvm-commits] [llvm] r91533 - in /llvm/trunk: include/llvm/CodeGen/SelectionDAG.h lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp lib/CodeGen/SelectionDAG/SelectionDAG.cpp lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Message-ID: <200912161056.nBGAu3JU007956@zion.cs.uiuc.edu> Author: ddunbar Date: Wed Dec 16 04:56:02 2009 New Revision: 91533 URL: http://llvm.org/viewvc/llvm-project?rev=91533&view=rev Log: Revert "Initial work on disabling the scheduler. This is a work in progress, and this", this broke llvm-gcc bootstrap for release builds on x86_64-apple-darwin10. Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=91533&r1=91532&r2=91533&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Wed Dec 16 04:56:02 2009 @@ -110,46 +110,6 @@ /// SelectionDAG. BumpPtrAllocator Allocator; - /// NodeOrdering - Assigns a "line number" value to each SDNode that - /// corresponds to the "line number" of the original LLVM instruction. This - /// used for turning off scheduling, because we'll forgo the normal scheduling - /// algorithm and output the instructions according to this ordering. - class NodeOrdering { - /// LineNo - The line of the instruction the node corresponds to. A value of - /// `0' means it's not assigned. - unsigned LineNo; - std::map Order; - - void operator=(const NodeOrdering&); // Do not implement. - NodeOrdering(const NodeOrdering&); // Do not implement. - public: - NodeOrdering() : LineNo(0) {} - - void add(const SDNode *Node) { - assert(LineNo && "Invalid line number!"); - Order[Node] = LineNo; - } - void remove(const SDNode *Node) { - std::map::iterator Itr = Order.find(Node); - if (Itr != Order.end()) - Order.erase(Itr); - } - void clear() { - Order.clear(); - LineNo = 1; - } - unsigned getLineNo(const SDNode *Node) { - unsigned LN = Order[Node]; - assert(LN && "Node isn't in ordering map!"); - return LN; - } - void newInst() { - ++LineNo; - } - - void dump() const; - } *Ordering; - /// VerifyNode - Sanity check the given node. Aborts if it is invalid. void VerifyNode(SDNode *N); @@ -160,9 +120,6 @@ DenseSet &visited, int level, bool &printed); - void operator=(const SelectionDAG&); // Do not implement. - SelectionDAG(const SelectionDAG&); // Do not implement. - public: SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli); ~SelectionDAG(); @@ -242,13 +199,6 @@ return Root = N; } - /// NewInst - Tell the ordering object that we're processing a new - /// instruction. - void NewInst() { - if (Ordering) - Ordering->newInst(); - } - /// Combine - This iterates over the nodes in the SelectionDAG, folding /// certain types of nodes together, or eliminating superfluous nodes. The /// Level argument controls whether Combine is allowed to produce nodes and Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp?rev=91533&r1=91532&r2=91533&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp Wed Dec 16 04:56:02 2009 @@ -20,16 +20,10 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtarget.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; -cl::opt -DisableInstScheduling("disable-inst-scheduling", - cl::init(false), - cl::desc("Disable instruction scheduling")); - ScheduleDAGSDNodes::ScheduleDAGSDNodes(MachineFunction &mf) : ScheduleDAG(mf) { } Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=91533&r1=91532&r2=91533&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Wed Dec 16 04:56:02 2009 @@ -48,8 +48,6 @@ #include using namespace llvm; -extern cl::opt DisableInstScheduling; - /// makeVTList - Return an instance of the SDVTList struct initialized with the /// specified members. static SDVTList makeVTList(const EVT *VTs, unsigned NumVTs) { @@ -554,9 +552,6 @@ } DeallocateNode(N); - - // Remove the ordering of this node. - if (Ordering) Ordering->remove(N); } } @@ -582,9 +577,6 @@ N->DropOperands(); DeallocateNode(N); - - // Remove the ordering of this node. - if (Ordering) Ordering->remove(N); } void SelectionDAG::DeallocateNode(SDNode *N) { @@ -596,9 +588,6 @@ N->NodeType = ISD::DELETED_NODE; NodeAllocator.Deallocate(AllNodes.remove(N)); - - // Remove the ordering of this node. - if (Ordering) Ordering->remove(N); } /// RemoveNodeFromCSEMaps - Take the specified node out of the CSE map that @@ -702,9 +691,7 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, 1); AddNodeIDCustom(ID, N); - SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); - if (Ordering) Ordering->remove(Node); - return Node; + return CSEMap.FindNodeOrInsertPos(ID, InsertPos); } /// FindModifiedNodeSlot - Find a slot for the specified node if its operands @@ -721,9 +708,7 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, 2); AddNodeIDCustom(ID, N); - SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); - if (Ordering) Ordering->remove(Node); - return Node; + return CSEMap.FindNodeOrInsertPos(ID, InsertPos); } @@ -740,9 +725,7 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, NumOps); AddNodeIDCustom(ID, N); - SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); - if (Ordering) Ordering->remove(Node); - return Node; + return CSEMap.FindNodeOrInsertPos(ID, InsertPos); } /// VerifyNode - Sanity check the given node. Aborts if it is invalid. @@ -795,13 +778,8 @@ SelectionDAG::SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli) : TLI(tli), FLI(fli), DW(0), EntryNode(ISD::EntryToken, DebugLoc::getUnknownLoc(), - getVTList(MVT::Other)), - Root(getEntryNode()), Ordering(0) { + getVTList(MVT::Other)), Root(getEntryNode()) { AllNodes.push_back(&EntryNode); - if (DisableInstScheduling) { - Ordering = new NodeOrdering(); - Ordering->add(&EntryNode); - } } void SelectionDAG::init(MachineFunction &mf, MachineModuleInfo *mmi, @@ -814,7 +792,6 @@ SelectionDAG::~SelectionDAG() { allnodes_clear(); - delete Ordering; } void SelectionDAG::allnodes_clear() { @@ -840,10 +817,6 @@ EntryNode.UseList = 0; AllNodes.push_back(&EntryNode); Root = getEntryNode(); - if (DisableInstScheduling) { - Ordering = new NodeOrdering(); - Ordering->add(&EntryNode); - } } SDValue SelectionDAG::getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) { @@ -904,17 +877,14 @@ ID.AddPointer(&Val); void *IP = 0; SDNode *N = NULL; - if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) { - if (Ordering) Ordering->add(N); + if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) if (!VT.isVector()) return SDValue(N, 0); - } if (!N) { N = NodeAllocator.Allocate(); new (N) ConstantSDNode(isT, &Val, EltVT); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); } SDValue Result(N, 0); @@ -951,17 +921,14 @@ ID.AddPointer(&V); void *IP = 0; SDNode *N = NULL; - if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) { - if (Ordering) Ordering->add(N); + if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) if (!VT.isVector()) return SDValue(N, 0); - } if (!N) { N = NodeAllocator.Allocate(); new (N) ConstantFPSDNode(isTarget, &V, EltVT); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); } SDValue Result(N, 0); @@ -1016,15 +983,12 @@ ID.AddInteger(Offset); ID.AddInteger(TargetFlags); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) GlobalAddressSDNode(Opc, GV, VT, Offset, TargetFlags); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1034,15 +998,12 @@ AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); ID.AddInteger(FI); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) FrameIndexSDNode(FI, VT, isTarget); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1056,15 +1017,12 @@ ID.AddInteger(JTI); ID.AddInteger(TargetFlags); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) JumpTableSDNode(JTI, VT, isTarget, TargetFlags); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1084,15 +1042,12 @@ ID.AddPointer(C); ID.AddInteger(TargetFlags); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) ConstantPoolSDNode(isTarget, C, VT, Offset, Alignment, TargetFlags); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1113,15 +1068,12 @@ C->AddSelectionDAGCSEId(ID); ID.AddInteger(TargetFlags); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) ConstantPoolSDNode(isTarget, C, VT, Offset, Alignment, TargetFlags); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1130,15 +1082,12 @@ AddNodeIDNode(ID, ISD::BasicBlock, getVTList(MVT::Other), 0, 0); ID.AddPointer(MBB); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) BasicBlockSDNode(MBB); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1154,7 +1103,6 @@ N = NodeAllocator.Allocate(); new (N) VTSDNode(VT); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1164,7 +1112,6 @@ N = NodeAllocator.Allocate(); new (N) ExternalSymbolSDNode(false, Sym, 0, VT); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1177,7 +1124,6 @@ N = NodeAllocator.Allocate(); new (N) ExternalSymbolSDNode(true, Sym, TargetFlags, VT); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1190,7 +1136,6 @@ new (N) CondCodeSDNode(Cond); CondCodeNodes[Cond] = N; AllNodes.push_back(N); - if (Ordering) Ordering->add(N); } return SDValue(CondCodeNodes[Cond], 0); } @@ -1283,10 +1228,8 @@ ID.AddInteger(MaskVec[i]); void* IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } // Allocate the mask array for the node out of the BumpPtrAllocator, since // SDNode doesn't have access to it. This memory will be "leaked" when @@ -1298,7 +1241,6 @@ new (N) ShuffleVectorSDNode(VT, dl, N1, N2, MaskAlloc); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1316,15 +1258,12 @@ SDValue Ops[] = { Val, DTy, STy, Rnd, Sat }; AddNodeIDNode(ID, ISD::CONVERT_RNDSAT, getVTList(VT), &Ops[0], 5); void* IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } CvtRndSatSDNode *N = NodeAllocator.Allocate(); new (N) CvtRndSatSDNode(VT, dl, Ops, 5, Code); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1333,15 +1272,12 @@ AddNodeIDNode(ID, ISD::Register, getVTList(VT), 0, 0); ID.AddInteger(RegNo); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) RegisterSDNode(RegNo, VT); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1353,15 +1289,12 @@ AddNodeIDNode(ID, Opcode, getVTList(MVT::Other), &Ops[0], 1); ID.AddInteger(LabelID); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) LabelSDNode(Opcode, dl, Root, LabelID); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1375,15 +1308,12 @@ ID.AddPointer(BA); ID.AddInteger(TargetFlags); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) BlockAddressSDNode(Opc, VT, BA, TargetFlags); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -1396,16 +1326,13 @@ ID.AddPointer(V); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) SrcValueSDNode(V); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -2316,16 +2243,13 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, getVTList(VT), 0, 0); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) SDNode(Opcode, DL, getVTList(VT)); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -2549,10 +2473,8 @@ SDValue Ops[1] = { Operand }; AddNodeIDNode(ID, Opcode, VTs, Ops, 1); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } N = NodeAllocator.Allocate(); new (N) UnarySDNode(Opcode, DL, VTs, Operand); CSEMap.InsertNode(N, IP); @@ -2562,7 +2484,6 @@ } AllNodes.push_back(N); - if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -2970,10 +2891,8 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTs, Ops, 2); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } N = NodeAllocator.Allocate(); new (N) BinarySDNode(Opcode, DL, VTs, N1, N2); CSEMap.InsertNode(N, IP); @@ -2983,7 +2902,6 @@ } AllNodes.push_back(N); - if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -3050,10 +2968,8 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTs, Ops, 3); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } N = NodeAllocator.Allocate(); new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); CSEMap.InsertNode(N, IP); @@ -3061,9 +2977,7 @@ N = NodeAllocator.Allocate(); new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); } - AllNodes.push_back(N); - if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -3659,14 +3573,12 @@ void* IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); - if (Ordering) Ordering->add(E); return SDValue(E, 0); } SDNode* N = NodeAllocator.Allocate(); new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Cmp, Swp, MMO); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -3724,14 +3636,12 @@ void* IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); - if (Ordering) Ordering->add(E); return SDValue(E, 0); } SDNode* N = NodeAllocator.Allocate(); new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Val, MMO); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -3804,7 +3714,6 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); - if (Ordering) Ordering->add(E); return SDValue(E, 0); } @@ -3816,7 +3725,6 @@ new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO); } AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -3881,14 +3789,12 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); - if (Ordering) Ordering->add(E); return SDValue(E, 0); } SDNode *N = NodeAllocator.Allocate(); new (N) LoadSDNode(Ops, dl, VTs, AM, ExtType, MemVT, MMO); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -3959,14 +3865,12 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); - if (Ordering) Ordering->add(E); return SDValue(E, 0); } SDNode *N = NodeAllocator.Allocate(); new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, false, VT, MMO); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -4021,14 +3925,12 @@ void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); - if (Ordering) Ordering->add(E); return SDValue(E, 0); } SDNode *N = NodeAllocator.Allocate(); new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, true, SVT, MMO); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -4045,17 +3947,14 @@ ID.AddInteger(ST->getMemoryVT().getRawBits()); ID.AddInteger(ST->getRawSubclassData()); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } SDNode *N = NodeAllocator.Allocate(); new (N) StoreSDNode(Ops, dl, VTs, AM, ST->isTruncatingStore(), ST->getMemoryVT(), ST->getMemOperand()); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); return SDValue(N, 0); } @@ -4121,10 +4020,8 @@ AddNodeIDNode(ID, Opcode, VTs, Ops, NumOps); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } N = NodeAllocator.Allocate(); new (N) SDNode(Opcode, DL, VTs, Ops, NumOps); @@ -4135,7 +4032,6 @@ } AllNodes.push_back(N); - if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -4191,10 +4087,8 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - } if (NumOps == 1) { N = NodeAllocator.Allocate(); new (N) UnarySDNode(Opcode, DL, VTList, Ops[0]); @@ -4225,7 +4119,6 @@ } } AllNodes.push_back(N); - if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -4688,10 +4581,8 @@ if (VTs.VTs[VTs.NumVTs-1] != MVT::Flag) { FoldingSetNodeID ID; AddNodeIDNode(ID, Opc, VTs, Ops, NumOps); - if (SDNode *ON = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(ON); + if (SDNode *ON = CSEMap.FindNodeOrInsertPos(ID, IP)) return ON; - } } if (!RemoveNodeFromCSEMaps(N)) @@ -4755,7 +4646,6 @@ if (IP) CSEMap.InsertNode(N, IP); // Memoize the new node. - if (Ordering) Ordering->add(N); return N; } @@ -4894,10 +4784,8 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, ~Opcode, VTs, Ops, NumOps); IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return cast(E); - } } // Allocate a new MachineSDNode. @@ -4919,7 +4807,6 @@ CSEMap.InsertNode(N, IP); AllNodes.push_back(N); - if (Ordering) Ordering->add(N); #ifndef NDEBUG VerifyNode(N); #endif @@ -4956,10 +4843,8 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); void *IP = 0; - if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { - if (Ordering) Ordering->add(E); + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return E; - } } return NULL; } @@ -6126,9 +6011,6 @@ errs() << "\n\n"; } -void SelectionDAG::NodeOrdering::dump() const { -} - void SDNode::printr(raw_ostream &OS, const SelectionDAG *G) const { print_types(OS, G); print_details(OS, G); @@ -6269,3 +6151,4 @@ return false; return true; } + Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=91533&r1=91532&r2=91533&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Wed Dec 16 04:56:02 2009 @@ -583,9 +583,6 @@ } void SelectionDAGBuilder::visit(unsigned Opcode, User &I) { - // Tell the DAG that we're processing a new instruction. - DAG.NewInst(); - // Note: this doesn't use InstVisitor, because it has to work with // ConstantExpr's in addition to instructions. switch (Opcode) { From daniel at zuster.org Wed Dec 16 04:56:17 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Wed, 16 Dec 2009 10:56:17 -0000 Subject: [llvm-commits] [llvm] r91534 - in /llvm/trunk: lib/Transforms/Scalar/ScalarReplAggregates.cpp test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll Message-ID: <200912161056.nBGAuHVk007975@zion.cs.uiuc.edu> Author: ddunbar Date: Wed Dec 16 04:56:17 2009 New Revision: 91534 URL: http://llvm.org/viewvc/llvm-project?rev=91534&view=rev Log: Revert "Reapply 91184 with fixes and an addition to the testcase to cover the problem", this broke llvm-gcc bootstrap for release builds on x86_64-apple-darwin10. This reverts commit db22309800b224a9f5f51baf76071d7a93ce59c9. Removed: llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=91534&r1=91533&r2=91534&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Wed Dec 16 04:56:17 2009 @@ -74,10 +74,6 @@ private: TargetData *TD; - /// DeadInsts - Keep track of instructions we have made dead, so that - /// we can remove them after we are done working. - SmallVector DeadInsts; - /// AllocaInfo - When analyzing uses of an alloca instruction, this captures /// information about the uses. All these fields are initialized to false /// and set to true when something is learned. @@ -106,30 +102,25 @@ int isSafeAllocaToScalarRepl(AllocaInst *AI); - void isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, - uint64_t ArrayOffset, AllocaInfo &Info); - void isSafeGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t &Offset, - uint64_t &ArrayOffset, AllocaInfo &Info); - void isSafeMemAccess(AllocaInst *AI, uint64_t Offset, uint64_t ArrayOffset, - uint64_t MemSize, const Type *MemOpType, bool isStore, - AllocaInfo &Info); - bool TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size); - unsigned FindElementAndOffset(const Type *&T, uint64_t &Offset); + void isSafeUseOfAllocation(Instruction *User, AllocaInst *AI, + AllocaInfo &Info); + void isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI, + AllocaInfo &Info); + void isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI, + unsigned OpNo, AllocaInfo &Info); + void isSafeUseOfBitCastedAllocation(BitCastInst *User, AllocaInst *AI, + AllocaInfo &Info); void DoScalarReplacement(AllocaInst *AI, std::vector &WorkList); - void DeleteDeadInstructions(); void CleanupGEP(GetElementPtrInst *GEP); - void CleanupAllocaUsers(Value *V); + void CleanupAllocaUsers(AllocaInst *AI); AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocaInst *Base); - void RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, - SmallVector &NewElts); - void RewriteBitCast(BitCastInst *BC, AllocaInst *AI, uint64_t Offset, - SmallVector &NewElts); - void RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset, - SmallVector &NewElts); - void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, + void RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocaInst *AI, + SmallVector &NewElts); + + void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst, AllocaInst *AI, SmallVector &NewElts); void RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI, @@ -369,37 +360,176 @@ } } - // Now that we have created the new alloca instructions, rewrite all the - // uses of the old alloca. - DeadInsts.push_back(AI); - RewriteForScalarRepl(AI, AI, 0, ElementAllocas); + // Now that we have created the alloca instructions that we want to use, + // expand the getelementptr instructions to use them. + while (!AI->use_empty()) { + Instruction *User = cast(AI->use_back()); + if (BitCastInst *BCInst = dyn_cast(User)) { + RewriteBitCastUserOfAlloca(BCInst, AI, ElementAllocas); + BCInst->eraseFromParent(); + continue; + } + + // Replace: + // %res = load { i32, i32 }* %alloc + // with: + // %load.0 = load i32* %alloc.0 + // %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0 + // %load.1 = load i32* %alloc.1 + // %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 + // (Also works for arrays instead of structs) + if (LoadInst *LI = dyn_cast(User)) { + Value *Insert = UndefValue::get(LI->getType()); + for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) { + Value *Load = new LoadInst(ElementAllocas[i], "load", LI); + Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI); + } + LI->replaceAllUsesWith(Insert); + LI->eraseFromParent(); + continue; + } - // Now erase any instructions that were made dead while rewriting the alloca. - DeleteDeadInstructions(); + // Replace: + // store { i32, i32 } %val, { i32, i32 }* %alloc + // with: + // %val.0 = extractvalue { i32, i32 } %val, 0 + // store i32 %val.0, i32* %alloc.0 + // %val.1 = extractvalue { i32, i32 } %val, 1 + // store i32 %val.1, i32* %alloc.1 + // (Also works for arrays instead of structs) + if (StoreInst *SI = dyn_cast(User)) { + Value *Val = SI->getOperand(0); + for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) { + Value *Extract = ExtractValueInst::Create(Val, i, Val->getName(), SI); + new StoreInst(Extract, ElementAllocas[i], SI); + } + SI->eraseFromParent(); + continue; + } + + GetElementPtrInst *GEPI = cast(User); + // We now know that the GEP is of the form: GEP , 0, + unsigned Idx = + (unsigned)cast(GEPI->getOperand(2))->getZExtValue(); + + assert(Idx < ElementAllocas.size() && "Index out of range?"); + AllocaInst *AllocaToUse = ElementAllocas[Idx]; + + Value *RepValue; + if (GEPI->getNumOperands() == 3) { + // Do not insert a new getelementptr instruction with zero indices, only + // to have it optimized out later. + RepValue = AllocaToUse; + } else { + // We are indexing deeply into the structure, so we still need a + // getelement ptr instruction to finish the indexing. This may be + // expanded itself once the worklist is rerun. + // + SmallVector NewArgs; + NewArgs.push_back(Constant::getNullValue( + Type::getInt32Ty(AI->getContext()))); + NewArgs.append(GEPI->op_begin()+3, GEPI->op_end()); + RepValue = GetElementPtrInst::Create(AllocaToUse, NewArgs.begin(), + NewArgs.end(), "", GEPI); + RepValue->takeName(GEPI); + } + + // If this GEP is to the start of the aggregate, check for memcpys. + if (Idx == 0 && GEPI->hasAllZeroIndices()) + RewriteBitCastUserOfAlloca(GEPI, AI, ElementAllocas); + + // Move all of the users over to the new GEP. + GEPI->replaceAllUsesWith(RepValue); + // Delete the old GEP + GEPI->eraseFromParent(); + } + // Finally, delete the Alloca instruction + AI->eraseFromParent(); NumReplaced++; } -/// DeleteDeadInstructions - Erase instructions on the DeadInstrs list, -/// recursively including all their operands that become trivially dead. -void SROA::DeleteDeadInstructions() { - while (!DeadInsts.empty()) { - Instruction *I = dyn_cast_or_null(DeadInsts.pop_back_val()); - if (I == 0) - continue; - - for (User::op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) - if (Instruction *U = dyn_cast(*OI)) { - // Zero out the operand and see if it becomes trivially dead. - *OI = 0; - if (isInstructionTriviallyDead(U)) - DeadInsts.push_back(U); - } +/// isSafeElementUse - Check to see if this use is an allowed use for a +/// getelementptr instruction of an array aggregate allocation. isFirstElt +/// indicates whether Ptr is known to the start of the aggregate. +void SROA::isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI, + AllocaInfo &Info) { + for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); + I != E; ++I) { + Instruction *User = cast(*I); + switch (User->getOpcode()) { + case Instruction::Load: break; + case Instruction::Store: + // Store is ok if storing INTO the pointer, not storing the pointer + if (User->getOperand(0) == Ptr) return MarkUnsafe(Info); + break; + case Instruction::GetElementPtr: { + GetElementPtrInst *GEP = cast(User); + bool AreAllZeroIndices = isFirstElt; + if (GEP->getNumOperands() > 1 && + (!isa(GEP->getOperand(1)) || + !cast(GEP->getOperand(1))->isZero())) + // Using pointer arithmetic to navigate the array. + return MarkUnsafe(Info); + + // Verify that any array subscripts are in range. + for (gep_type_iterator GEPIt = gep_type_begin(GEP), + E = gep_type_end(GEP); GEPIt != E; ++GEPIt) { + // Ignore struct elements, no extra checking needed for these. + if (isa(*GEPIt)) + continue; - I->eraseFromParent(); + // This GEP indexes an array. Verify that this is an in-range + // constant integer. Specifically, consider A[0][i]. We cannot know that + // the user isn't doing invalid things like allowing i to index an + // out-of-range subscript that accesses A[1]. Because of this, we have + // to reject SROA of any accesses into structs where any of the + // components are variables. + ConstantInt *IdxVal = dyn_cast(GEPIt.getOperand()); + if (!IdxVal) return MarkUnsafe(Info); + + // Are all indices still zero? + AreAllZeroIndices &= IdxVal->isZero(); + + if (const ArrayType *AT = dyn_cast(*GEPIt)) { + if (IdxVal->getZExtValue() >= AT->getNumElements()) + return MarkUnsafe(Info); + } else if (const VectorType *VT = dyn_cast(*GEPIt)) { + if (IdxVal->getZExtValue() >= VT->getNumElements()) + return MarkUnsafe(Info); + } + } + + isSafeElementUse(GEP, AreAllZeroIndices, AI, Info); + if (Info.isUnsafe) return; + break; + } + case Instruction::BitCast: + if (isFirstElt) { + isSafeUseOfBitCastedAllocation(cast(User), AI, Info); + if (Info.isUnsafe) return; + break; + } + DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); + return MarkUnsafe(Info); + case Instruction::Call: + if (MemIntrinsic *MI = dyn_cast(User)) { + if (isFirstElt) { + isSafeMemIntrinsicOnAllocation(MI, AI, I.getOperandNo(), Info); + if (Info.isUnsafe) return; + break; + } + } + DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); + return MarkUnsafe(Info); + default: + DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); + return MarkUnsafe(Info); + } } + return; // All users look ok :) } - + /// AllUsersAreLoads - Return true if all users of this value are loads. static bool AllUsersAreLoads(Value *Ptr) { for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); @@ -409,116 +539,72 @@ return true; } -/// isSafeForScalarRepl - Check if instruction I is a safe use with regard to -/// performing scalar replacement of alloca AI. The results are flagged in -/// the Info parameter. Offset and ArrayOffset indicate the position within -/// AI that is referenced by this instruction. -void SROA::isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, - uint64_t ArrayOffset, AllocaInfo &Info) { - for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI!=E; ++UI) { - Instruction *User = cast(*UI); - - if (BitCastInst *BC = dyn_cast(User)) { - isSafeForScalarRepl(BC, AI, Offset, ArrayOffset, Info); - } else if (GetElementPtrInst *GEPI = dyn_cast(User)) { - uint64_t GEPArrayOffset = ArrayOffset; - uint64_t GEPOffset = Offset; - isSafeGEP(GEPI, AI, GEPOffset, GEPArrayOffset, Info); - if (!Info.isUnsafe) - isSafeForScalarRepl(GEPI, AI, GEPOffset, GEPArrayOffset, Info); - } else if (MemIntrinsic *MI = dyn_cast(UI)) { - ConstantInt *Length = dyn_cast(MI->getLength()); - if (Length) - isSafeMemAccess(AI, Offset, ArrayOffset, Length->getZExtValue(), 0, - UI.getOperandNo() == 1, Info); - else - MarkUnsafe(Info); - } else if (LoadInst *LI = dyn_cast(User)) { - if (!LI->isVolatile()) { - const Type *LIType = LI->getType(); - isSafeMemAccess(AI, Offset, ArrayOffset, TD->getTypeAllocSize(LIType), - LIType, false, Info); - } else - MarkUnsafe(Info); - } else if (StoreInst *SI = dyn_cast(User)) { - // Store is ok if storing INTO the pointer, not storing the pointer - if (!SI->isVolatile() && SI->getOperand(0) != I) { - const Type *SIType = SI->getOperand(0)->getType(); - isSafeMemAccess(AI, Offset, ArrayOffset, TD->getTypeAllocSize(SIType), - SIType, true, Info); - } else - MarkUnsafe(Info); - } else if (isa(UI)) { - // If one user is DbgInfoIntrinsic then check if all users are - // DbgInfoIntrinsics. - if (OnlyUsedByDbgInfoIntrinsics(I)) { - Info.needsCleanup = true; - return; - } - MarkUnsafe(Info); - } else { - DEBUG(errs() << " Transformation preventing inst: " << *User << '\n'); - MarkUnsafe(Info); - } - if (Info.isUnsafe) return; - } -} +/// isSafeUseOfAllocation - Check if this user is an allowed use for an +/// aggregate allocation. +void SROA::isSafeUseOfAllocation(Instruction *User, AllocaInst *AI, + AllocaInfo &Info) { + if (BitCastInst *C = dyn_cast(User)) + return isSafeUseOfBitCastedAllocation(C, AI, Info); + + if (LoadInst *LI = dyn_cast(User)) + if (!LI->isVolatile()) + return;// Loads (returning a first class aggregrate) are always rewritable + + if (StoreInst *SI = dyn_cast(User)) + if (!SI->isVolatile() && SI->getOperand(0) != AI) + return;// Store is ok if storing INTO the pointer, not storing the pointer + + GetElementPtrInst *GEPI = dyn_cast(User); + if (GEPI == 0) + return MarkUnsafe(Info); -/// isSafeGEP - Check if a GEP instruction can be handled for scalar -/// replacement. It is safe when all the indices are constant, in-bounds -/// references, and when the resulting offset corresponds to an element within -/// the alloca type. The results are flagged in the Info parameter. Upon -/// return, Offset is adjusted as specified by the GEP indices. For the -/// special case of a variable index to a 2-element array, ArrayOffset is set -/// to the array element size. -void SROA::isSafeGEP(GetElementPtrInst *GEPI, AllocaInst *AI, - uint64_t &Offset, uint64_t &ArrayOffset, - AllocaInfo &Info) { - gep_type_iterator GEPIt = gep_type_begin(GEPI), E = gep_type_end(GEPI); - if (GEPIt == E) - return; + gep_type_iterator I = gep_type_begin(GEPI), E = gep_type_end(GEPI); - // The first GEP index must be zero. - if (!isa(GEPIt.getOperand()) || - !cast(GEPIt.getOperand())->isZero()) + // The GEP is not safe to transform if not of the form "GEP , 0, ". + if (I == E || + I.getOperand() != Constant::getNullValue(I.getOperand()->getType())) { return MarkUnsafe(Info); - if (++GEPIt == E) - return; + } + ++I; + if (I == E) return MarkUnsafe(Info); // ran out of GEP indices?? + + bool IsAllZeroIndices = true; + // If the first index is a non-constant index into an array, see if we can // handle it as a special case. - const Type *ArrayEltTy = 0; - if (ArrayOffset == 0 && Offset == 0) { - if (const ArrayType *AT = dyn_cast(*GEPIt)) { - if (!isa(GEPIt.getOperand())) { - uint64_t NumElements = AT->getNumElements(); - - // If this is an array index and the index is not constant, we cannot - // promote... that is unless the array has exactly one or two elements - // in it, in which case we CAN promote it, but we have to canonicalize - // this out if this is the only problem. - if ((NumElements != 1 && NumElements != 2) || !AllUsersAreLoads(GEPI)) - return MarkUnsafe(Info); + if (const ArrayType *AT = dyn_cast(*I)) { + if (!isa(I.getOperand())) { + IsAllZeroIndices = 0; + uint64_t NumElements = AT->getNumElements(); + + // If this is an array index and the index is not constant, we cannot + // promote... that is unless the array has exactly one or two elements in + // it, in which case we CAN promote it, but we have to canonicalize this + // out if this is the only problem. + if ((NumElements == 1 || NumElements == 2) && + AllUsersAreLoads(GEPI)) { Info.needsCleanup = true; - ArrayOffset = TD->getTypeAllocSizeInBits(AT->getElementType()); - ArrayEltTy = AT->getElementType(); - ++GEPIt; + return; // Canonicalization required! } + return MarkUnsafe(Info); } } - + // Walk through the GEP type indices, checking the types that this indexes // into. - for (; GEPIt != E; ++GEPIt) { + for (; I != E; ++I) { // Ignore struct elements, no extra checking needed for these. - if (isa(*GEPIt)) + if (isa(*I)) continue; + + ConstantInt *IdxVal = dyn_cast(I.getOperand()); + if (!IdxVal) return MarkUnsafe(Info); - ConstantInt *IdxVal = dyn_cast(GEPIt.getOperand()); - if (!IdxVal) - return MarkUnsafe(Info); - - if (const ArrayType *AT = dyn_cast(*GEPIt)) { + // Are all indices still zero? + IsAllZeroIndices &= IdxVal->isZero(); + + if (const ArrayType *AT = dyn_cast(*I)) { // This GEP indexes an array. Verify that this is an in-range constant // integer. Specifically, consider A[0][i]. We cannot know that the user // isn't doing invalid things like allowing i to index an out-of-range @@ -526,255 +612,147 @@ // of any accesses into structs where any of the components are variables. if (IdxVal->getZExtValue() >= AT->getNumElements()) return MarkUnsafe(Info); - } else { - const VectorType *VT = dyn_cast(*GEPIt); - assert(VT && "unexpected type in GEP type iterator"); + } else if (const VectorType *VT = dyn_cast(*I)) { if (IdxVal->getZExtValue() >= VT->getNumElements()) return MarkUnsafe(Info); } } - - // All the indices are safe. Now compute the offset due to this GEP and - // check if the alloca has a component element at that offset. - if (ArrayOffset == 0) { - SmallVector Indices(GEPI->op_begin() + 1, GEPI->op_end()); - Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(), - &Indices[0], Indices.size()); - } else { - // Both array elements have the same type, so it suffices to check one of - // them. Copy the GEP indices starting from the array index, but replace - // that variable index with a constant zero. - SmallVector Indices(GEPI->op_begin() + 2, GEPI->op_end()); - Indices[0] = Constant::getNullValue(Type::getInt32Ty(GEPI->getContext())); - const Type *ArrayEltPtr = PointerType::getUnqual(ArrayEltTy); - Offset += TD->getIndexedOffset(ArrayEltPtr, &Indices[0], Indices.size()); - } - if (!TypeHasComponent(AI->getAllocatedType(), Offset, 0)) - MarkUnsafe(Info); -} - -/// isSafeMemAccess - Check if a load/store/memcpy operates on the entire AI -/// alloca or has an offset and size that corresponds to a component element -/// within it. The offset checked here may have been formed from a GEP with a -/// pointer bitcasted to a different type. -void SROA::isSafeMemAccess(AllocaInst *AI, uint64_t Offset, - uint64_t ArrayOffset, uint64_t MemSize, - const Type *MemOpType, bool isStore, - AllocaInfo &Info) { - // Check if this is a load/store of the entire alloca. - if (Offset == 0 && ArrayOffset == 0 && - MemSize == TD->getTypeAllocSize(AI->getAllocatedType())) { - bool UsesAggregateType = (MemOpType == AI->getAllocatedType()); - // This is safe for MemIntrinsics (where MemOpType is 0), integer types - // (which are essentially the same as the MemIntrinsics, especially with - // regard to copying padding between elements), or references using the - // aggregate type of the alloca. - if (!MemOpType || isa(MemOpType) || UsesAggregateType) { - if (!UsesAggregateType) { - if (isStore) - Info.isMemCpyDst = true; - else - Info.isMemCpySrc = true; - } - return; - } - } - // Check if the offset/size correspond to a component within the alloca type. - const Type *T = AI->getAllocatedType(); - if (TypeHasComponent(T, Offset, MemSize) && - (ArrayOffset == 0 || TypeHasComponent(T, Offset + ArrayOffset, MemSize))) - return; - - return MarkUnsafe(Info); + + // If there are any non-simple uses of this getelementptr, make sure to reject + // them. + return isSafeElementUse(GEPI, IsAllZeroIndices, AI, Info); } -/// TypeHasComponent - Return true if T has a component type with the -/// specified offset and size. If Size is zero, do not check the size. -bool SROA::TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size) { - const Type *EltTy; - uint64_t EltSize; - if (const StructType *ST = dyn_cast(T)) { - const StructLayout *Layout = TD->getStructLayout(ST); - unsigned EltIdx = Layout->getElementContainingOffset(Offset); - EltTy = ST->getContainedType(EltIdx); - EltSize = TD->getTypeAllocSize(EltTy); - Offset -= Layout->getElementOffset(EltIdx); - } else if (const ArrayType *AT = dyn_cast(T)) { - EltTy = AT->getElementType(); - EltSize = TD->getTypeAllocSize(EltTy); - Offset %= EltSize; - } else { - return false; +/// isSafeMemIntrinsicOnAllocation - Check if the specified memory +/// intrinsic can be promoted by SROA. At this point, we know that the operand +/// of the memintrinsic is a pointer to the beginning of the allocation. +void SROA::isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI, + unsigned OpNo, AllocaInfo &Info) { + // If not constant length, give up. + ConstantInt *Length = dyn_cast(MI->getLength()); + if (!Length) return MarkUnsafe(Info); + + // If not the whole aggregate, give up. + if (Length->getZExtValue() != + TD->getTypeAllocSize(AI->getType()->getElementType())) + return MarkUnsafe(Info); + + // We only know about memcpy/memset/memmove. + if (!isa(MI)) + return MarkUnsafe(Info); + + // Otherwise, we can transform it. Determine whether this is a memcpy/set + // into or out of the aggregate. + if (OpNo == 1) + Info.isMemCpyDst = true; + else { + assert(OpNo == 2); + Info.isMemCpySrc = true; } - if (Offset == 0 && (Size == 0 || EltSize == Size)) - return true; - // Check if the component spans multiple elements. - if (Offset + Size > EltSize) - return false; - return TypeHasComponent(EltTy, Offset, Size); } -/// RewriteForScalarRepl - Alloca AI is being split into NewElts, so rewrite -/// the instruction I, which references it, to use the separate elements. -/// Offset indicates the position within AI that is referenced by this -/// instruction. -void SROA::RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, - SmallVector &NewElts) { - for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI!=E; ++UI) { - Instruction *User = cast(*UI); +/// isSafeUseOfBitCastedAllocation - Check if all users of this bitcast +/// from an alloca are safe for SROA of that alloca. +void SROA::isSafeUseOfBitCastedAllocation(BitCastInst *BC, AllocaInst *AI, + AllocaInfo &Info) { + for (Value::use_iterator UI = BC->use_begin(), E = BC->use_end(); + UI != E; ++UI) { + if (BitCastInst *BCU = dyn_cast(UI)) { + isSafeUseOfBitCastedAllocation(BCU, AI, Info); + } else if (MemIntrinsic *MI = dyn_cast(UI)) { + isSafeMemIntrinsicOnAllocation(MI, AI, UI.getOperandNo(), Info); + } else if (StoreInst *SI = dyn_cast(UI)) { + if (SI->isVolatile()) + return MarkUnsafe(Info); + + // If storing the entire alloca in one chunk through a bitcasted pointer + // to integer, we can transform it. This happens (for example) when you + // cast a {i32,i32}* to i64* and store through it. This is similar to the + // memcpy case and occurs in various "byval" cases and emulated memcpys. + if (isa(SI->getOperand(0)->getType()) && + TD->getTypeAllocSize(SI->getOperand(0)->getType()) == + TD->getTypeAllocSize(AI->getType()->getElementType())) { + Info.isMemCpyDst = true; + continue; + } + return MarkUnsafe(Info); + } else if (LoadInst *LI = dyn_cast(UI)) { + if (LI->isVolatile()) + return MarkUnsafe(Info); - if (BitCastInst *BC = dyn_cast(User)) { - RewriteBitCast(BC, AI, Offset, NewElts); - } else if (GetElementPtrInst *GEPI = dyn_cast(User)) { - RewriteGEP(GEPI, AI, Offset, NewElts); - } else if (MemIntrinsic *MI = dyn_cast(User)) { - ConstantInt *Length = dyn_cast(MI->getLength()); - uint64_t MemSize = Length->getZExtValue(); - if (Offset == 0 && - MemSize == TD->getTypeAllocSize(AI->getAllocatedType())) - RewriteMemIntrinUserOfAlloca(MI, I, AI, NewElts); - } else if (LoadInst *LI = dyn_cast(User)) { - const Type *LIType = LI->getType(); - if (LIType == AI->getAllocatedType()) { - // Replace: - // %res = load { i32, i32 }* %alloc - // with: - // %load.0 = load i32* %alloc.0 - // %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0 - // %load.1 = load i32* %alloc.1 - // %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 - // (Also works for arrays instead of structs) - Value *Insert = UndefValue::get(LIType); - for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { - Value *Load = new LoadInst(NewElts[i], "load", LI); - Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI); - } - LI->replaceAllUsesWith(Insert); - DeadInsts.push_back(LI); - } else if (isa(LIType) && - TD->getTypeAllocSize(LIType) == - TD->getTypeAllocSize(AI->getAllocatedType())) { - // If this is a load of the entire alloca to an integer, rewrite it. - RewriteLoadUserOfWholeAlloca(LI, AI, NewElts); + // If loading the entire alloca in one chunk through a bitcasted pointer + // to integer, we can transform it. This happens (for example) when you + // cast a {i32,i32}* to i64* and load through it. This is similar to the + // memcpy case and occurs in various "byval" cases and emulated memcpys. + if (isa(LI->getType()) && + TD->getTypeAllocSize(LI->getType()) == + TD->getTypeAllocSize(AI->getType()->getElementType())) { + Info.isMemCpySrc = true; + continue; } - } else if (StoreInst *SI = dyn_cast(User)) { - Value *Val = SI->getOperand(0); - const Type *SIType = Val->getType(); - if (SIType == AI->getAllocatedType()) { - // Replace: - // store { i32, i32 } %val, { i32, i32 }* %alloc - // with: - // %val.0 = extractvalue { i32, i32 } %val, 0 - // store i32 %val.0, i32* %alloc.0 - // %val.1 = extractvalue { i32, i32 } %val, 1 - // store i32 %val.1, i32* %alloc.1 - // (Also works for arrays instead of structs) - for (unsigned i = 0, e = NewElts.size(); i != e; ++i) { - Value *Extract = ExtractValueInst::Create(Val, i, Val->getName(), SI); - new StoreInst(Extract, NewElts[i], SI); - } - DeadInsts.push_back(SI); - } else if (isa(SIType) && - TD->getTypeAllocSize(SIType) == - TD->getTypeAllocSize(AI->getAllocatedType())) { - // If this is a store of the entire alloca from an integer, rewrite it. - RewriteStoreUserOfWholeAlloca(SI, AI, NewElts); + return MarkUnsafe(Info); + } else if (isa(UI)) { + // If one user is DbgInfoIntrinsic then check if all users are + // DbgInfoIntrinsics. + if (OnlyUsedByDbgInfoIntrinsics(BC)) { + Info.needsCleanup = true; + return; } + else + MarkUnsafe(Info); } + else { + return MarkUnsafe(Info); + } + if (Info.isUnsafe) return; } } -/// RewriteBitCast - Update a bitcast reference to the alloca being replaced -/// and recursively continue updating all of its uses. -void SROA::RewriteBitCast(BitCastInst *BC, AllocaInst *AI, uint64_t Offset, - SmallVector &NewElts) { - RewriteForScalarRepl(BC, AI, Offset, NewElts); - if (BC->getOperand(0) != AI) - return; +/// RewriteBitCastUserOfAlloca - BCInst (transitively) bitcasts AI, or indexes +/// to its first element. Transform users of the cast to use the new values +/// instead. +void SROA::RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocaInst *AI, + SmallVector &NewElts) { + Value::use_iterator UI = BCInst->use_begin(), UE = BCInst->use_end(); + while (UI != UE) { + Instruction *User = cast(*UI++); + if (BitCastInst *BCU = dyn_cast(User)) { + RewriteBitCastUserOfAlloca(BCU, AI, NewElts); + if (BCU->use_empty()) BCU->eraseFromParent(); + continue; + } - // The bitcast references the original alloca. Replace its uses with - // references to the first new element alloca. - Instruction *Val = NewElts[0]; - if (Val->getType() != BC->getDestTy()) { - Val = new BitCastInst(Val, BC->getDestTy(), "", BC); - Val->takeName(BC); - } - BC->replaceAllUsesWith(Val); - DeadInsts.push_back(BC); -} - -/// FindElementAndOffset - Return the index of the element containing Offset -/// within the specified type, which must be either a struct or an array. -/// Sets T to the type of the element and Offset to the offset within that -/// element. -unsigned SROA::FindElementAndOffset(const Type *&T, uint64_t &Offset) { - unsigned Idx = 0; - if (const StructType *ST = dyn_cast(T)) { - const StructLayout *Layout = TD->getStructLayout(ST); - Idx = Layout->getElementContainingOffset(Offset); - T = ST->getContainedType(Idx); - Offset -= Layout->getElementOffset(Idx); - } else { - const ArrayType *AT = dyn_cast(T); - assert(AT && "unexpected type for scalar replacement"); - T = AT->getElementType(); - uint64_t EltSize = TD->getTypeAllocSize(T); - Idx = (unsigned)(Offset / EltSize); - Offset -= Idx * EltSize; - } - return Idx; -} - -/// RewriteGEP - Check if this GEP instruction moves the pointer across -/// elements of the alloca that are being split apart, and if so, rewrite -/// the GEP to be relative to the new element. -void SROA::RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset, - SmallVector &NewElts) { - uint64_t OldOffset = Offset; - SmallVector Indices(GEPI->op_begin() + 1, GEPI->op_end()); - Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(), - &Indices[0], Indices.size()); - - RewriteForScalarRepl(GEPI, AI, Offset, NewElts); - - const Type *T = AI->getAllocatedType(); - unsigned OldIdx = FindElementAndOffset(T, OldOffset); - if (GEPI->getOperand(0) == AI) - OldIdx = ~0U; // Force the GEP to be rewritten. - - T = AI->getAllocatedType(); - uint64_t EltOffset = Offset; - unsigned Idx = FindElementAndOffset(T, EltOffset); - - // If this GEP does not move the pointer across elements of the alloca - // being split, then it does not needs to be rewritten. - if (Idx == OldIdx) - return; + if (MemIntrinsic *MI = dyn_cast(User)) { + // This must be memcpy/memmove/memset of the entire aggregate. + // Split into one per element. + RewriteMemIntrinUserOfAlloca(MI, BCInst, AI, NewElts); + continue; + } + + if (StoreInst *SI = dyn_cast(User)) { + // If this is a store of the entire alloca from an integer, rewrite it. + RewriteStoreUserOfWholeAlloca(SI, AI, NewElts); + continue; + } - const Type *i32Ty = Type::getInt32Ty(AI->getContext()); - SmallVector NewArgs; - NewArgs.push_back(Constant::getNullValue(i32Ty)); - while (EltOffset != 0) { - unsigned EltIdx = FindElementAndOffset(T, EltOffset); - NewArgs.push_back(ConstantInt::get(i32Ty, EltIdx)); - } - Instruction *Val = NewElts[Idx]; - if (NewArgs.size() > 1) { - Val = GetElementPtrInst::CreateInBounds(Val, NewArgs.begin(), - NewArgs.end(), "", GEPI); - Val->takeName(GEPI); - } - if (Val->getType() != GEPI->getType()) - Val = new BitCastInst(Val, GEPI->getType(), Val->getNameStr(), GEPI); - GEPI->replaceAllUsesWith(Val); - DeadInsts.push_back(GEPI); + if (LoadInst *LI = dyn_cast(User)) { + // If this is a load of the entire alloca to an integer, rewrite it. + RewriteLoadUserOfWholeAlloca(LI, AI, NewElts); + continue; + } + + // Otherwise it must be some other user of a gep of the first pointer. Just + // leave these alone. + continue; + } } /// RewriteMemIntrinUserOfAlloca - MI is a memcpy/memset/memmove from or to AI. /// Rewrite it to copy or set the elements of the scalarized memory. -void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, +void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst, AllocaInst *AI, SmallVector &NewElts) { + // If this is a memcpy/memmove, construct the other pointer as the // appropriate type. The "Other" pointer is the pointer that goes to memory // that doesn't have anything to do with the alloca that we are promoting. For @@ -783,41 +761,28 @@ LLVMContext &Context = MI->getContext(); unsigned MemAlignment = MI->getAlignment(); if (MemTransferInst *MTI = dyn_cast(MI)) { // memmove/memcopy - if (Inst == MTI->getRawDest()) + if (BCInst == MTI->getRawDest()) OtherPtr = MTI->getRawSource(); else { - assert(Inst == MTI->getRawSource()); + assert(BCInst == MTI->getRawSource()); OtherPtr = MTI->getRawDest(); } } + // Keep track of the other intrinsic argument, so it can be removed if it + // is dead when the intrinsic is replaced. + Value *PossiblyDead = OtherPtr; + // If there is an other pointer, we want to convert it to the same pointer // type as AI has, so we can GEP through it safely. if (OtherPtr) { - - // Remove bitcasts and all-zero GEPs from OtherPtr. This is an - // optimization, but it's also required to detect the corner case where - // both pointer operands are referencing the same memory, and where - // OtherPtr may be a bitcast or GEP that currently being rewritten. (This - // function is only called for mem intrinsics that access the whole - // aggregate, so non-zero GEPs are not an issue here.) - while (1) { - if (BitCastInst *BC = dyn_cast(OtherPtr)) { - OtherPtr = BC->getOperand(0); - continue; - } - if (GetElementPtrInst *GEP = dyn_cast(OtherPtr)) { - // All zero GEPs are effectively bitcasts. - if (GEP->hasAllZeroIndices()) { - OtherPtr = GEP->getOperand(0); - continue; - } - } - break; - } - // If OtherPtr has already been rewritten, this intrinsic will be dead. - if (OtherPtr == NewElts[0]) - return; + // It is likely that OtherPtr is a bitcast, if so, remove it. + if (BitCastInst *BC = dyn_cast(OtherPtr)) + OtherPtr = BC->getOperand(0); + // All zero GEPs are effectively bitcasts. + if (GetElementPtrInst *GEP = dyn_cast(OtherPtr)) + if (GEP->hasAllZeroIndices()) + OtherPtr = GEP->getOperand(0); if (ConstantExpr *BCE = dyn_cast(OtherPtr)) if (BCE->getOpcode() == Instruction::BitCast) @@ -833,7 +798,7 @@ // Process each element of the aggregate. Value *TheFn = MI->getOperand(0); const Type *BytePtrTy = MI->getRawDest()->getType(); - bool SROADest = MI->getRawDest() == Inst; + bool SROADest = MI->getRawDest() == BCInst; Constant *Zero = Constant::getNullValue(Type::getInt32Ty(MI->getContext())); @@ -842,15 +807,12 @@ Value *OtherElt = 0; unsigned OtherEltAlign = MemAlignment; - if (OtherPtr == AI) { - OtherElt = NewElts[i]; - OtherEltAlign = 0; - } else if (OtherPtr) { + if (OtherPtr) { Value *Idx[2] = { Zero, ConstantInt::get(Type::getInt32Ty(MI->getContext()), i) }; - OtherElt = GetElementPtrInst::CreateInBounds(OtherPtr, Idx, Idx + 2, + OtherElt = GetElementPtrInst::Create(OtherPtr, Idx, Idx + 2, OtherPtr->getNameStr()+"."+Twine(i), - MI); + MI); uint64_t EltOffset; const PointerType *OtherPtrTy = cast(OtherPtr->getType()); if (const StructType *ST = @@ -962,7 +924,9 @@ CallInst::Create(TheFn, Ops, Ops + 4, "", MI); } } - DeadInsts.push_back(MI); + MI->eraseFromParent(); + if (PossiblyDead) + RecursivelyDeleteTriviallyDeadInstructions(PossiblyDead); } /// RewriteStoreUserOfWholeAlloca - We found a store of an integer that @@ -973,9 +937,15 @@ // Extract each element out of the integer according to its structure offset // and store the element value to the individual alloca. Value *SrcVal = SI->getOperand(0); - const Type *AllocaEltTy = AI->getAllocatedType(); + const Type *AllocaEltTy = AI->getType()->getElementType(); uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy); + // If this isn't a store of an integer to the whole alloca, it may be a store + // to the first element. Just ignore the store in this case and normal SROA + // will handle it. + if (!isa(SrcVal->getType()) || + TD->getTypeAllocSizeInBits(SrcVal->getType()) != AllocaSizeBits) + return; // Handle tail padding by extending the operand if (TD->getTypeSizeInBits(SrcVal->getType()) != AllocaSizeBits) SrcVal = new ZExtInst(SrcVal, @@ -1080,7 +1050,7 @@ } } - DeadInsts.push_back(SI); + SI->eraseFromParent(); } /// RewriteLoadUserOfWholeAlloca - We found a load of the entire allocation to @@ -1089,9 +1059,16 @@ SmallVector &NewElts) { // Extract each element out of the NewElts according to its structure offset // and form the result value. - const Type *AllocaEltTy = AI->getAllocatedType(); + const Type *AllocaEltTy = AI->getType()->getElementType(); uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy); + // If this isn't a load of the whole alloca to an integer, it may be a load + // of the first element. Just ignore the load in this case and normal SROA + // will handle it. + if (!isa(LI->getType()) || + TD->getTypeAllocSizeInBits(LI->getType()) != AllocaSizeBits) + return; + DEBUG(errs() << "PROMOTING LOAD OF WHOLE ALLOCA: " << *AI << '\n' << *LI << '\n'); @@ -1162,9 +1139,10 @@ ResultVal = new TruncInst(ResultVal, LI->getType(), "", LI); LI->replaceAllUsesWith(ResultVal); - DeadInsts.push_back(LI); + LI->eraseFromParent(); } + /// HasPadding - Return true if the specified type has any structure or /// alignment padding, false otherwise. static bool HasPadding(const Type *Ty, const TargetData &TD) { @@ -1214,10 +1192,14 @@ // the users are safe to transform. AllocaInfo Info; - isSafeForScalarRepl(AI, AI, 0, 0, Info); - if (Info.isUnsafe) { - DEBUG(errs() << "Cannot transform: " << *AI << '\n'); - return 0; + for (Value::use_iterator I = AI->use_begin(), E = AI->use_end(); + I != E; ++I) { + isSafeUseOfAllocation(cast(*I), AI, Info); + if (Info.isUnsafe) { + DEBUG(errs() << "Cannot transform: " << *AI << "\n due to user: " + << **I << '\n'); + return 0; + } } // Okay, we know all the users are promotable. If the aggregate is a memcpy @@ -1226,7 +1208,7 @@ // types, but may actually be used. In these cases, we refuse to promote the // struct. if (Info.isMemCpySrc && Info.isMemCpyDst && - HasPadding(AI->getAllocatedType(), *TD)) + HasPadding(AI->getType()->getElementType(), *TD)) return 0; // If we require cleanup, return 1, otherwise return 3. @@ -1263,15 +1245,15 @@ // Insert the new GEP instructions, which are properly indexed. SmallVector Indices(GEPI->op_begin()+1, GEPI->op_end()); Indices[1] = Constant::getNullValue(Type::getInt32Ty(GEPI->getContext())); - Value *ZeroIdx = GetElementPtrInst::CreateInBounds(GEPI->getOperand(0), - Indices.begin(), - Indices.end(), - GEPI->getName()+".0",GEPI); + Value *ZeroIdx = GetElementPtrInst::Create(GEPI->getOperand(0), + Indices.begin(), + Indices.end(), + GEPI->getName()+".0", GEPI); Indices[1] = ConstantInt::get(Type::getInt32Ty(GEPI->getContext()), 1); - Value *OneIdx = GetElementPtrInst::CreateInBounds(GEPI->getOperand(0), - Indices.begin(), - Indices.end(), - GEPI->getName()+".1", GEPI); + Value *OneIdx = GetElementPtrInst::Create(GEPI->getOperand(0), + Indices.begin(), + Indices.end(), + GEPI->getName()+".1", GEPI); // Replace all loads of the variable index GEP with loads from both // indexes and a select. while (!GEPI->use_empty()) { @@ -1282,24 +1264,22 @@ LI->replaceAllUsesWith(R); LI->eraseFromParent(); } + GEPI->eraseFromParent(); } + /// CleanupAllocaUsers - If SROA reported that it can promote the specified /// allocation, but only if cleaned up, perform the cleanups required. -void SROA::CleanupAllocaUsers(Value *V) { +void SROA::CleanupAllocaUsers(AllocaInst *AI) { // At this point, we know that the end result will be SROA'd and promoted, so // we can insert ugly code if required so long as sroa+mem2reg will clean it // up. - for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); + for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E; ) { User *U = *UI++; - if (isa(U)) { - CleanupAllocaUsers(U); - } else if (GetElementPtrInst *GEPI = dyn_cast(U)) { + if (GetElementPtrInst *GEPI = dyn_cast(U)) CleanupGEP(GEPI); - CleanupAllocaUsers(GEPI); - if (GEPI->use_empty()) GEPI->eraseFromParent(); - } else { + else { Instruction *I = cast(U); SmallVector DbgInUses; if (!isa(I) && OnlyUsedByDbgInfoIntrinsics(I, &DbgInUses)) { @@ -1415,7 +1395,7 @@ // Compute the offset that this GEP adds to the pointer. SmallVector Indices(GEP->op_begin()+1, GEP->op_end()); - uint64_t GEPOffset = TD->getIndexedOffset(GEP->getPointerOperandType(), + uint64_t GEPOffset = TD->getIndexedOffset(GEP->getOperand(0)->getType(), &Indices[0], Indices.size()); // See if all uses can be converted. if (!CanConvertToScalar(GEP, IsNotTrivial, VecTy, SawVec,Offset+GEPOffset, @@ -1477,7 +1457,7 @@ if (GetElementPtrInst *GEP = dyn_cast(User)) { // Compute the offset that this GEP adds to the pointer. SmallVector Indices(GEP->op_begin()+1, GEP->op_end()); - uint64_t GEPOffset = TD->getIndexedOffset(GEP->getPointerOperandType(), + uint64_t GEPOffset = TD->getIndexedOffset(GEP->getOperand(0)->getType(), &Indices[0], Indices.size()); ConvertUsesToScalar(GEP, NewAI, Offset+GEPOffset*8); GEP->eraseFromParent(); Removed: llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll?rev=91533&view=auto ============================================================================== --- llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll (original) +++ llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll (removed) @@ -1,89 +0,0 @@ -; RUN: opt < %s -scalarrepl -S | FileCheck %s -; Radar 7441282 - -target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32" -target triple = "thumbv7-apple-darwin10" - -%struct.__neon_int16x8x2_t = type { <8 x i16>, <8 x i16> } -%struct.int16x8_t = type { <8 x i16> } -%struct.int16x8x2_t = type { [2 x %struct.int16x8_t] } -%union..0anon = type { %struct.int16x8x2_t } - -define arm_apcscc void @test(<8 x i16> %tmp.0, %struct.int16x8x2_t* %dst) nounwind { -; CHECK: @test -; CHECK-NOT: alloca -; CHECK: "alloca point" -entry: - %tmp_addr = alloca %struct.int16x8_t ; <%struct.int16x8_t*> [#uses=3] - %dst_addr = alloca %struct.int16x8x2_t* ; <%struct.int16x8x2_t**> [#uses=2] - %__rv = alloca %union..0anon ; <%union..0anon*> [#uses=2] - %__bx = alloca %struct.int16x8_t ; <%struct.int16x8_t*> [#uses=2] - %__ax = alloca %struct.int16x8_t ; <%struct.int16x8_t*> [#uses=2] - %tmp2 = alloca %struct.int16x8x2_t ; <%struct.int16x8x2_t*> [#uses=2] - %0 = alloca %struct.int16x8x2_t ; <%struct.int16x8x2_t*> [#uses=2] - %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] - %1 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] - store <8 x i16> %tmp.0, <8 x i16>* %1 - store %struct.int16x8x2_t* %dst, %struct.int16x8x2_t** %dst_addr - %2 = getelementptr inbounds %struct.int16x8_t* %__ax, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] - %3 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] - %4 = load <8 x i16>* %3, align 16 ; <<8 x i16>> [#uses=1] - store <8 x i16> %4, <8 x i16>* %2, align 16 - %5 = getelementptr inbounds %struct.int16x8_t* %__bx, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] - %6 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] - %7 = load <8 x i16>* %6, align 16 ; <<8 x i16>> [#uses=1] - store <8 x i16> %7, <8 x i16>* %5, align 16 - %8 = getelementptr inbounds %struct.int16x8_t* %__ax, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] - %9 = load <8 x i16>* %8, align 16 ; <<8 x i16>> [#uses=2] - %10 = getelementptr inbounds %struct.int16x8_t* %__bx, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] - %11 = load <8 x i16>* %10, align 16 ; <<8 x i16>> [#uses=2] - %12 = getelementptr inbounds %union..0anon* %__rv, i32 0, i32 0 ; <%struct.int16x8x2_t*> [#uses=1] - %13 = bitcast %struct.int16x8x2_t* %12 to %struct.__neon_int16x8x2_t* ; <%struct.__neon_int16x8x2_t*> [#uses=2] - %14 = shufflevector <8 x i16> %9, <8 x i16> %11, <8 x i32> ; <<8 x i16>> [#uses=1] - %15 = getelementptr inbounds %struct.__neon_int16x8x2_t* %13, i32 0, i32 0 ; <<8 x i16>*> [#uses=1] - store <8 x i16> %14, <8 x i16>* %15 - %16 = shufflevector <8 x i16> %9, <8 x i16> %11, <8 x i32> ; <<8 x i16>> [#uses=1] - %17 = getelementptr inbounds %struct.__neon_int16x8x2_t* %13, i32 0, i32 1 ; <<8 x i16>*> [#uses=1] - store <8 x i16> %16, <8 x i16>* %17 - %18 = getelementptr inbounds %union..0anon* %__rv, i32 0, i32 0 ; <%struct.int16x8x2_t*> [#uses=1] - %19 = bitcast %struct.int16x8x2_t* %0 to i8* ; [#uses=1] - %20 = bitcast %struct.int16x8x2_t* %18 to i8* ; [#uses=1] - call void @llvm.memcpy.i32(i8* %19, i8* %20, i32 32, i32 16) - %tmp21 = bitcast %struct.int16x8x2_t* %tmp2 to i8* ; [#uses=1] - %21 = bitcast %struct.int16x8x2_t* %0 to i8* ; [#uses=1] - call void @llvm.memcpy.i32(i8* %tmp21, i8* %21, i32 32, i32 16) - %22 = load %struct.int16x8x2_t** %dst_addr, align 4 ; <%struct.int16x8x2_t*> [#uses=1] - %23 = bitcast %struct.int16x8x2_t* %22 to i8* ; [#uses=1] - %tmp22 = bitcast %struct.int16x8x2_t* %tmp2 to i8* ; [#uses=1] - call void @llvm.memcpy.i32(i8* %23, i8* %tmp22, i32 32, i32 16) - br label %return - -; CHECK: store <8 x i16> -; CHECK: store <8 x i16> - -return: ; preds = %entry - ret void -} - -; Radar 7466574 -%struct._NSRange = type { i64 } - -define arm_apcscc void @test_memcpy_self() nounwind { -; CHECK: @test_memcpy_self -; CHECK-NOT: alloca -; CHECK: br i1 -entry: - %range = alloca %struct._NSRange ; <%struct._NSRange*> [#uses=2] - br i1 undef, label %cond.true, label %cond.false - -cond.true: ; preds = %entry - %tmp3 = bitcast %struct._NSRange* %range to i8* ; [#uses=1] - %tmp4 = bitcast %struct._NSRange* %range to i8* ; [#uses=1] - call void @llvm.memcpy.i32(i8* %tmp3, i8* %tmp4, i32 8, i32 8) - ret void - -cond.false: ; preds = %entry - ret void -} - -declare void @llvm.memcpy.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind From daniel at zuster.org Wed Dec 16 04:57:29 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Wed, 16 Dec 2009 02:57:29 -0800 Subject: [llvm-commits] [llvm] r91392 - in /llvm/trunk: include/llvm/CodeGen/SelectionDAG.h lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp lib/CodeGen/SelectionDAG/SelectionDAG.cpp lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp In-Reply-To: <200912150154.nBF1spun028126@zion.cs.uiuc.edu> References: <200912150154.nBF1spun028126@zion.cs.uiuc.edu> Message-ID: <6a8523d60912160257ia276cc5ya1e6a1437867ce79@mail.gmail.com> Hi Bill, I reverted this, it was one of the patches responsible for the failing x86_64-apple-darwin10 bootstrap in my testing. - Daniel On Mon, Dec 14, 2009 at 5:54 PM, Bill Wendling wrote: > Author: void > Date: Mon Dec 14 19:54:51 2009 > New Revision: 91392 > > URL: http://llvm.org/viewvc/llvm-project?rev=91392&view=rev > Log: > Initial work on disabling the scheduler. This is a work in progress, and this > stuff isn't used just yet. > > We want to model the GCC `-fno-schedule-insns' and `-fno-schedule-insns2' > flags. The hypothesis is that the people who use these flags know what they are > doing, and have hand-optimized the C code to reduce latencies and other > conflicts. > > The idea behind our scheme to turn off scheduling is to create a map "on the > side" during DAG generation. It will order the nodes by how they appeared in the > code. This map is then used during scheduling to get the ordering. > > Modified: > ? ?llvm/trunk/include/llvm/CodeGen/SelectionDAG.h > ? ?llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp > ? ?llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp > ? ?llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp > > Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=91392&r1=91391&r2=91392&view=diff > > ============================================================================== > --- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original) > +++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Mon Dec 14 19:54:51 2009 > @@ -110,6 +110,46 @@ > ? /// SelectionDAG. > ? BumpPtrAllocator Allocator; > > + ?/// NodeOrdering - Assigns a "line number" value to each SDNode that > + ?/// corresponds to the "line number" of the original LLVM instruction. This > + ?/// used for turning off scheduling, because we'll forgo the normal scheduling > + ?/// algorithm and output the instructions according to this ordering. > + ?class NodeOrdering { > + ? ?/// LineNo - The line of the instruction the node corresponds to. A value of > + ? ?/// `0' means it's not assigned. > + ? ?unsigned LineNo; > + ? ?std::map Order; > + > + ? ?void operator=(const NodeOrdering&); // Do not implement. > + ? ?NodeOrdering(const NodeOrdering&); ? // Do not implement. > + ?public: > + ? ?NodeOrdering() : LineNo(0) {} > + > + ? ?void add(const SDNode *Node) { > + ? ? ?assert(LineNo && "Invalid line number!"); > + ? ? ?Order[Node] = LineNo; > + ? ?} > + ? ?void remove(const SDNode *Node) { > + ? ? ?std::map::iterator Itr = Order.find(Node); > + ? ? ?if (Itr != Order.end()) > + ? ? ? ?Order.erase(Itr); > + ? ?} > + ? ?void clear() { > + ? ? ?Order.clear(); > + ? ? ?LineNo = 1; > + ? ?} > + ? ?unsigned getLineNo(const SDNode *Node) { > + ? ? ?unsigned LN = Order[Node]; > + ? ? ?assert(LN && "Node isn't in ordering map!"); > + ? ? ?return LN; > + ? ?} > + ? ?void newInst() { > + ? ? ?++LineNo; > + ? ?} > + > + ? ?void dump() const; > + ?} *Ordering; > + > ? /// VerifyNode - Sanity check the given node. ?Aborts if it is invalid. > ? void VerifyNode(SDNode *N); > > @@ -120,6 +160,9 @@ > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DenseSet &visited, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? int level, bool &printed); > > + ?void operator=(const SelectionDAG&); // Do not implement. > + ?SelectionDAG(const SelectionDAG&); ? // Do not implement. > + > ?public: > ? SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli); > ? ~SelectionDAG(); > @@ -199,6 +242,13 @@ > ? ? return Root = N; > ? } > > + ?/// NewInst - Tell the ordering object that we're processing a new > + ?/// instruction. > + ?void NewInst() { > + ? ?if (Ordering) > + ? ? ?Ordering->newInst(); > + ?} > + > ? /// Combine - This iterates over the nodes in the SelectionDAG, folding > ? /// certain types of nodes together, or eliminating superfluous nodes. ?The > ? /// Level argument controls whether Combine is allowed to produce nodes and > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp?rev=91392&r1=91391&r2=91392&view=diff > > ============================================================================== > --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp Mon Dec 14 19:54:51 2009 > @@ -20,10 +20,16 @@ > ?#include "llvm/Target/TargetInstrInfo.h" > ?#include "llvm/Target/TargetRegisterInfo.h" > ?#include "llvm/Target/TargetSubtarget.h" > +#include "llvm/Support/CommandLine.h" > ?#include "llvm/Support/Debug.h" > ?#include "llvm/Support/raw_ostream.h" > ?using namespace llvm; > > +cl::opt > +DisableInstScheduling("disable-inst-scheduling", > + ? ? ? ? ? ? ? ? ? ? ?cl::init(false), > + ? ? ? ? ? ? ? ? ? ? ?cl::desc("Disable instruction scheduling")); > + > ?ScheduleDAGSDNodes::ScheduleDAGSDNodes(MachineFunction &mf) > ? : ScheduleDAG(mf) { > ?} > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=91392&r1=91391&r2=91392&view=diff > > ============================================================================== > --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Mon Dec 14 19:54:51 2009 > @@ -48,6 +48,8 @@ > ?#include > ?using namespace llvm; > > +extern cl::opt DisableInstScheduling; > + > ?/// makeVTList - Return an instance of the SDVTList struct initialized with the > ?/// specified members. > ?static SDVTList makeVTList(const EVT *VTs, unsigned NumVTs) { > @@ -552,6 +554,9 @@ > ? ? } > > ? ? DeallocateNode(N); > + > + ? ?// Remove the ordering of this node. > + ? ?if (Ordering) Ordering->remove(N); > ? } > ?} > > @@ -577,6 +582,9 @@ > ? N->DropOperands(); > > ? DeallocateNode(N); > + > + ?// Remove the ordering of this node. > + ?if (Ordering) Ordering->remove(N); > ?} > > ?void SelectionDAG::DeallocateNode(SDNode *N) { > @@ -588,6 +596,9 @@ > ? N->NodeType = ISD::DELETED_NODE; > > ? NodeAllocator.Deallocate(AllNodes.remove(N)); > + > + ?// Remove the ordering of this node. > + ?if (Ordering) Ordering->remove(N); > ?} > > ?/// RemoveNodeFromCSEMaps - Take the specified node out of the CSE map that > @@ -691,7 +702,9 @@ > ? FoldingSetNodeID ID; > ? AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, 1); > ? AddNodeIDCustom(ID, N); > - ?return CSEMap.FindNodeOrInsertPos(ID, InsertPos); > + ?SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); > + ?if (Ordering) Ordering->remove(Node); > + ?return Node; > ?} > > ?/// FindModifiedNodeSlot - Find a slot for the specified node if its operands > @@ -708,7 +721,9 @@ > ? FoldingSetNodeID ID; > ? AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, 2); > ? AddNodeIDCustom(ID, N); > - ?return CSEMap.FindNodeOrInsertPos(ID, InsertPos); > + ?SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); > + ?if (Ordering) Ordering->remove(Node); > + ?return Node; > ?} > > > @@ -725,7 +740,9 @@ > ? FoldingSetNodeID ID; > ? AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, NumOps); > ? AddNodeIDCustom(ID, N); > - ?return CSEMap.FindNodeOrInsertPos(ID, InsertPos); > + ?SDNode *Node = CSEMap.FindNodeOrInsertPos(ID, InsertPos); > + ?if (Ordering) Ordering->remove(Node); > + ?return Node; > ?} > > ?/// VerifyNode - Sanity check the given node. ?Aborts if it is invalid. > @@ -778,8 +795,13 @@ > ?SelectionDAG::SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli) > ? : TLI(tli), FLI(fli), DW(0), > ? ? EntryNode(ISD::EntryToken, DebugLoc::getUnknownLoc(), > - ? ?getVTList(MVT::Other)), Root(getEntryNode()) { > + ? ? ? ? ? ? ?getVTList(MVT::Other)), > + ? ?Root(getEntryNode()), Ordering(0) { > ? AllNodes.push_back(&EntryNode); > + ?if (DisableInstScheduling) { > + ? ?Ordering = new NodeOrdering(); > + ? ?Ordering->add(&EntryNode); > + ?} > ?} > > ?void SelectionDAG::init(MachineFunction &mf, MachineModuleInfo *mmi, > @@ -792,6 +814,7 @@ > > ?SelectionDAG::~SelectionDAG() { > ? allnodes_clear(); > + ?delete Ordering; > ?} > > ?void SelectionDAG::allnodes_clear() { > @@ -817,6 +840,10 @@ > ? EntryNode.UseList = 0; > ? AllNodes.push_back(&EntryNode); > ? Root = getEntryNode(); > + ?if (DisableInstScheduling) { > + ? ?Ordering = new NodeOrdering(); > + ? ?Ordering->add(&EntryNode); > + ?} > ?} > > ?SDValue SelectionDAG::getSExtOrTrunc(SDValue Op, DebugLoc DL, EVT VT) { > @@ -877,14 +904,17 @@ > ? ID.AddPointer(&Val); > ? void *IP = 0; > ? SDNode *N = NULL; > - ?if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) > + ?if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) { > + ? ?if (Ordering) Ordering->add(N); > ? ? if (!VT.isVector()) > ? ? ? return SDValue(N, 0); > + ?} > ? if (!N) { > ? ? N = NodeAllocator.Allocate(); > ? ? new (N) ConstantSDNode(isT, &Val, EltVT); > ? ? CSEMap.InsertNode(N, IP); > ? ? AllNodes.push_back(N); > + ? ?if (Ordering) Ordering->add(N); > ? } > > ? SDValue Result(N, 0); > @@ -921,14 +951,17 @@ > ? ID.AddPointer(&V); > ? void *IP = 0; > ? SDNode *N = NULL; > - ?if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) > + ?if ((N = CSEMap.FindNodeOrInsertPos(ID, IP))) { > + ? ?if (Ordering) Ordering->add(N); > ? ? if (!VT.isVector()) > ? ? ? return SDValue(N, 0); > + ?} > ? if (!N) { > ? ? N = NodeAllocator.Allocate(); > ? ? new (N) ConstantFPSDNode(isTarget, &V, EltVT); > ? ? CSEMap.InsertNode(N, IP); > ? ? AllNodes.push_back(N); > + ? ?if (Ordering) Ordering->add(N); > ? } > > ? SDValue Result(N, 0); > @@ -983,12 +1016,15 @@ > ? ID.AddInteger(Offset); > ? ID.AddInteger(TargetFlags); > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) GlobalAddressSDNode(Opc, GV, VT, Offset, TargetFlags); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -998,12 +1034,15 @@ > ? AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0); > ? ID.AddInteger(FI); > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) FrameIndexSDNode(FI, VT, isTarget); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1017,12 +1056,15 @@ > ? ID.AddInteger(JTI); > ? ID.AddInteger(TargetFlags); > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) JumpTableSDNode(JTI, VT, isTarget, TargetFlags); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1042,12 +1084,15 @@ > ? ID.AddPointer(C); > ? ID.AddInteger(TargetFlags); > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) ConstantPoolSDNode(isTarget, C, VT, Offset, Alignment, TargetFlags); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1068,12 +1113,15 @@ > ? C->AddSelectionDAGCSEId(ID); > ? ID.AddInteger(TargetFlags); > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) ConstantPoolSDNode(isTarget, C, VT, Offset, Alignment, TargetFlags); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1082,12 +1130,15 @@ > ? AddNodeIDNode(ID, ISD::BasicBlock, getVTList(MVT::Other), 0, 0); > ? ID.AddPointer(MBB); > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) BasicBlockSDNode(MBB); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1103,6 +1154,7 @@ > ? N = NodeAllocator.Allocate(); > ? new (N) VTSDNode(VT); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1112,6 +1164,7 @@ > ? N = NodeAllocator.Allocate(); > ? new (N) ExternalSymbolSDNode(false, Sym, 0, VT); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1124,6 +1177,7 @@ > ? N = NodeAllocator.Allocate(); > ? new (N) ExternalSymbolSDNode(true, Sym, TargetFlags, VT); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1136,6 +1190,7 @@ > ? ? new (N) CondCodeSDNode(Cond); > ? ? CondCodeNodes[Cond] = N; > ? ? AllNodes.push_back(N); > + ? ?if (Ordering) Ordering->add(N); > ? } > ? return SDValue(CondCodeNodes[Cond], 0); > ?} > @@ -1228,8 +1283,10 @@ > ? ? ID.AddInteger(MaskVec[i]); > > ? void* IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > > ? // Allocate the mask array for the node out of the BumpPtrAllocator, since > ? // SDNode doesn't have access to it. ?This memory will be "leaked" when > @@ -1241,6 +1298,7 @@ > ? new (N) ShuffleVectorSDNode(VT, dl, N1, N2, MaskAlloc); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1258,12 +1316,15 @@ > ? SDValue Ops[] = { Val, DTy, STy, Rnd, Sat }; > ? AddNodeIDNode(ID, ISD::CONVERT_RNDSAT, getVTList(VT), &Ops[0], 5); > ? void* IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? CvtRndSatSDNode *N = NodeAllocator.Allocate(); > ? new (N) CvtRndSatSDNode(VT, dl, Ops, 5, Code); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1272,12 +1333,15 @@ > ? AddNodeIDNode(ID, ISD::Register, getVTList(VT), 0, 0); > ? ID.AddInteger(RegNo); > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) RegisterSDNode(RegNo, VT); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1289,12 +1353,15 @@ > ? AddNodeIDNode(ID, Opcode, getVTList(MVT::Other), &Ops[0], 1); > ? ID.AddInteger(LabelID); > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) LabelSDNode(Opcode, dl, Root, LabelID); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1308,12 +1375,15 @@ > ? ID.AddPointer(BA); > ? ID.AddInteger(TargetFlags); > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) BlockAddressSDNode(Opc, VT, BA, TargetFlags); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -1326,13 +1396,16 @@ > ? ID.AddPointer(V); > > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) SrcValueSDNode(V); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -2243,13 +2316,16 @@ > ? FoldingSetNodeID ID; > ? AddNodeIDNode(ID, Opcode, getVTList(VT), 0, 0); > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) SDNode(Opcode, DL, getVTList(VT)); > ? CSEMap.InsertNode(N, IP); > > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ?#ifndef NDEBUG > ? VerifyNode(N); > ?#endif > @@ -2473,8 +2549,10 @@ > ? ? SDValue Ops[1] = { Operand }; > ? ? AddNodeIDNode(ID, Opcode, VTs, Ops, 1); > ? ? void *IP = 0; > - ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ? ?if (Ordering) Ordering->add(E); > ? ? ? return SDValue(E, 0); > + ? ?} > ? ? N = NodeAllocator.Allocate(); > ? ? new (N) UnarySDNode(Opcode, DL, VTs, Operand); > ? ? CSEMap.InsertNode(N, IP); > @@ -2484,6 +2562,7 @@ > ? } > > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ?#ifndef NDEBUG > ? VerifyNode(N); > ?#endif > @@ -2891,8 +2970,10 @@ > ? ? FoldingSetNodeID ID; > ? ? AddNodeIDNode(ID, Opcode, VTs, Ops, 2); > ? ? void *IP = 0; > - ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ? ?if (Ordering) Ordering->add(E); > ? ? ? return SDValue(E, 0); > + ? ?} > ? ? N = NodeAllocator.Allocate(); > ? ? new (N) BinarySDNode(Opcode, DL, VTs, N1, N2); > ? ? CSEMap.InsertNode(N, IP); > @@ -2902,6 +2983,7 @@ > ? } > > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ?#ifndef NDEBUG > ? VerifyNode(N); > ?#endif > @@ -2968,8 +3050,10 @@ > ? ? FoldingSetNodeID ID; > ? ? AddNodeIDNode(ID, Opcode, VTs, Ops, 3); > ? ? void *IP = 0; > - ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ? ?if (Ordering) Ordering->add(E); > ? ? ? return SDValue(E, 0); > + ? ?} > ? ? N = NodeAllocator.Allocate(); > ? ? new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); > ? ? CSEMap.InsertNode(N, IP); > @@ -2977,7 +3061,9 @@ > ? ? N = NodeAllocator.Allocate(); > ? ? new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); > ? } > + > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ?#ifndef NDEBUG > ? VerifyNode(N); > ?#endif > @@ -3573,12 +3659,14 @@ > ? void* IP = 0; > ? if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > ? ? cast(E)->refineAlignment(MMO); > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > ? } > ? SDNode* N = NodeAllocator.Allocate(); > ? new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Cmp, Swp, MMO); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -3636,12 +3724,14 @@ > ? void* IP = 0; > ? if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > ? ? cast(E)->refineAlignment(MMO); > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > ? } > ? SDNode* N = NodeAllocator.Allocate(); > ? new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Val, MMO); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -3714,6 +3804,7 @@ > ? ? void *IP = 0; > ? ? if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > ? ? ? cast(E)->refineAlignment(MMO); > + ? ? ?if (Ordering) Ordering->add(E); > ? ? ? return SDValue(E, 0); > ? ? } > > @@ -3725,6 +3816,7 @@ > ? ? new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO); > ? } > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -3789,12 +3881,14 @@ > ? void *IP = 0; > ? if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > ? ? cast(E)->refineAlignment(MMO); > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > ? } > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) LoadSDNode(Ops, dl, VTs, AM, ExtType, MemVT, MMO); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -3865,12 +3959,14 @@ > ? void *IP = 0; > ? if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > ? ? cast(E)->refineAlignment(MMO); > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > ? } > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, false, VT, MMO); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -3925,12 +4021,14 @@ > ? void *IP = 0; > ? if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > ? ? cast(E)->refineAlignment(MMO); > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > ? } > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, true, SVT, MMO); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -3947,14 +4045,17 @@ > ? ID.AddInteger(ST->getMemoryVT().getRawBits()); > ? ID.AddInteger(ST->getRawSubclassData()); > ? void *IP = 0; > - ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ?if (Ordering) Ordering->add(E); > ? ? return SDValue(E, 0); > + ?} > ? SDNode *N = NodeAllocator.Allocate(); > ? new (N) StoreSDNode(Ops, dl, VTs, AM, > ? ? ? ? ? ? ? ? ? ? ? ST->isTruncatingStore(), ST->getMemoryVT(), > ? ? ? ? ? ? ? ? ? ? ? ST->getMemOperand()); > ? CSEMap.InsertNode(N, IP); > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ? return SDValue(N, 0); > ?} > > @@ -4020,8 +4121,10 @@ > ? ? AddNodeIDNode(ID, Opcode, VTs, Ops, NumOps); > ? ? void *IP = 0; > > - ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ? ?if (Ordering) Ordering->add(E); > ? ? ? return SDValue(E, 0); > + ? ?} > > ? ? N = NodeAllocator.Allocate(); > ? ? new (N) SDNode(Opcode, DL, VTs, Ops, NumOps); > @@ -4032,6 +4135,7 @@ > ? } > > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ?#ifndef NDEBUG > ? VerifyNode(N); > ?#endif > @@ -4087,8 +4191,10 @@ > ? ? FoldingSetNodeID ID; > ? ? AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); > ? ? void *IP = 0; > - ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ? ?if (Ordering) Ordering->add(E); > ? ? ? return SDValue(E, 0); > + ? ?} > ? ? if (NumOps == 1) { > ? ? ? N = NodeAllocator.Allocate(); > ? ? ? new (N) UnarySDNode(Opcode, DL, VTList, Ops[0]); > @@ -4119,6 +4225,7 @@ > ? ? } > ? } > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ?#ifndef NDEBUG > ? VerifyNode(N); > ?#endif > @@ -4581,8 +4688,10 @@ > ? if (VTs.VTs[VTs.NumVTs-1] != MVT::Flag) { > ? ? FoldingSetNodeID ID; > ? ? AddNodeIDNode(ID, Opc, VTs, Ops, NumOps); > - ? ?if (SDNode *ON = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ? ?if (SDNode *ON = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ? ?if (Ordering) Ordering->add(ON); > ? ? ? return ON; > + ? ?} > ? } > > ? if (!RemoveNodeFromCSEMaps(N)) > @@ -4646,6 +4755,7 @@ > > ? if (IP) > ? ? CSEMap.InsertNode(N, IP); ? // Memoize the new node. > + ?if (Ordering) Ordering->add(N); > ? return N; > ?} > > @@ -4784,8 +4894,10 @@ > ? ? FoldingSetNodeID ID; > ? ? AddNodeIDNode(ID, ~Opcode, VTs, Ops, NumOps); > ? ? IP = 0; > - ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ? ?if (Ordering) Ordering->add(E); > ? ? ? return cast(E); > + ? ?} > ? } > > ? // Allocate a new MachineSDNode. > @@ -4807,6 +4919,7 @@ > ? ? CSEMap.InsertNode(N, IP); > > ? AllNodes.push_back(N); > + ?if (Ordering) Ordering->add(N); > ?#ifndef NDEBUG > ? VerifyNode(N); > ?#endif > @@ -4843,8 +4956,10 @@ > ? ? FoldingSetNodeID ID; > ? ? AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); > ? ? void *IP = 0; > - ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) > + ? ?if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { > + ? ? ?if (Ordering) Ordering->add(E); > ? ? ? return E; > + ? ?} > ? } > ? return NULL; > ?} > @@ -6011,6 +6126,9 @@ > ? errs() << "\n\n"; > ?} > > +void SelectionDAG::NodeOrdering::dump() const { > +} > + > ?void SDNode::printr(raw_ostream &OS, const SelectionDAG *G) const { > ? print_types(OS, G); > ? print_details(OS, G); > @@ -6151,4 +6269,3 @@ > ? ? ? return false; > ? return true; > ?} > - > > Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=91392&r1=91391&r2=91392&view=diff > > ============================================================================== > --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original) > +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Mon Dec 14 19:54:51 2009 > @@ -583,6 +583,9 @@ > ?} > > ?void SelectionDAGBuilder::visit(unsigned Opcode, User &I) { > + ?// Tell the DAG that we're processing a new instruction. > + ?DAG.NewInst(); > + > ? // Note: this doesn't use InstVisitor, because it has to work with > ? // ConstantExpr's in addition to instructions. > ? switch (Opcode) { > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From daniel at zuster.org Wed Dec 16 04:58:08 2009 From: daniel at zuster.org (Daniel Dunbar) Date: Wed, 16 Dec 2009 02:58:08 -0800 Subject: [llvm-commits] [llvm] r91459 - in /llvm/trunk: lib/Transforms/Scalar/ScalarReplAggregates.cpp test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll In-Reply-To: <200912152200.nBFM0qqN023245@zion.cs.uiuc.edu> References: <200912152200.nBFM0qqN023245@zion.cs.uiuc.edu> Message-ID: <6a8523d60912160258p2d1b3458qcf76cabb26a1a5d0@mail.gmail.com> Hi Bob, I reverted this, it was one of the patches responsible for the failing x86_64-apple-darwin10 bootstrap in my testing. - Daniel On Tue, Dec 15, 2009 at 2:00 PM, Bob Wilson wrote: > Author: bwilson > Date: Tue Dec 15 16:00:51 2009 > New Revision: 91459 > > URL: http://llvm.org/viewvc/llvm-project?rev=91459&view=rev > Log: > Reapply 91184 with fixes and an addition to the testcase to cover the problem > found last time. ?Instead of trying to modify the IR while iterating over it, > I've change it to keep a list of WeakVH references to dead instructions, and > then delete those instructions later. ?I also added some special case code to > detect and handle the situation when both operands of a memcpy intrinsic are > referencing the same alloca. > > Added: > ? ?llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll > Modified: > ? ?llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp > > Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=91459&r1=91458&r2=91459&view=diff > > ============================================================================== > --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original) > +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Tue Dec 15 16:00:51 2009 > @@ -74,6 +74,10 @@ > ? private: > ? ? TargetData *TD; > > + ? ?/// DeadInsts - Keep track of instructions we have made dead, so that > + ? ?/// we can remove them after we are done working. > + ? ?SmallVector DeadInsts; > + > ? ? /// AllocaInfo - When analyzing uses of an alloca instruction, this captures > ? ? /// information about the uses. ?All these fields are initialized to false > ? ? /// and set to true when something is learned. > @@ -102,25 +106,30 @@ > > ? ? int isSafeAllocaToScalarRepl(AllocaInst *AI); > > - ? ?void isSafeUseOfAllocation(Instruction *User, AllocaInst *AI, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AllocaInfo &Info); > - ? ?void isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI, > - ? ? ? ? ? ? ? ? ? ? ? ? ?AllocaInfo &Info); > - ? ?void isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned OpNo, AllocaInfo &Info); > - ? ?void isSafeUseOfBitCastedAllocation(BitCastInst *User, AllocaInst *AI, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AllocaInfo &Info); > + ? ?void isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? uint64_t ArrayOffset, AllocaInfo &Info); > + ? ?void isSafeGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t &Offset, > + ? ? ? ? ? ? ? ? ? uint64_t &ArrayOffset, AllocaInfo &Info); > + ? ?void isSafeMemAccess(AllocaInst *AI, uint64_t Offset, uint64_t ArrayOffset, > + ? ? ? ? ? ? ? ? ? ? ? ? uint64_t MemSize, const Type *MemOpType, bool isStore, > + ? ? ? ? ? ? ? ? ? ? ? ? AllocaInfo &Info); > + ? ?bool TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size); > + ? ?unsigned FindElementAndOffset(const Type *&T, uint64_t &Offset); > > ? ? void DoScalarReplacement(AllocaInst *AI, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?std::vector &WorkList); > + ? ?void DeleteDeadInstructions(); > ? ? void CleanupGEP(GetElementPtrInst *GEP); > - ? ?void CleanupAllocaUsers(AllocaInst *AI); > + ? ?void CleanupAllocaUsers(Value *V); > ? ? AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocaInst *Base); > > - ? ?void RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocaInst *AI, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SmallVector &NewElts); > - > - ? ?void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst, > + ? ?void RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SmallVector &NewElts); > + ? ?void RewriteBitCast(BitCastInst *BC, AllocaInst *AI, uint64_t Offset, > + ? ? ? ? ? ? ? ? ? ? ? ?SmallVector &NewElts); > + ? ?void RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset, > + ? ? ? ? ? ? ? ? ? ?SmallVector &NewElts); > + ? ?void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AllocaInst *AI, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? SmallVector &NewElts); > ? ? void RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI, > @@ -360,176 +369,37 @@ > ? ? } > ? } > > - ?// Now that we have created the alloca instructions that we want to use, > - ?// expand the getelementptr instructions to use them. > - ?while (!AI->use_empty()) { > - ? ?Instruction *User = cast(AI->use_back()); > - ? ?if (BitCastInst *BCInst = dyn_cast(User)) { > - ? ? ?RewriteBitCastUserOfAlloca(BCInst, AI, ElementAllocas); > - ? ? ?BCInst->eraseFromParent(); > - ? ? ?continue; > - ? ?} > - > - ? ?// Replace: > - ? ?// ? %res = load { i32, i32 }* %alloc > - ? ?// with: > - ? ?// ? %load.0 = load i32* %alloc.0 > - ? ?// ? %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0 > - ? ?// ? %load.1 = load i32* %alloc.1 > - ? ?// ? %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 > - ? ?// (Also works for arrays instead of structs) > - ? ?if (LoadInst *LI = dyn_cast(User)) { > - ? ? ?Value *Insert = UndefValue::get(LI->getType()); > - ? ? ?for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) { > - ? ? ? ?Value *Load = new LoadInst(ElementAllocas[i], "load", LI); > - ? ? ? ?Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI); > - ? ? ?} > - ? ? ?LI->replaceAllUsesWith(Insert); > - ? ? ?LI->eraseFromParent(); > - ? ? ?continue; > - ? ?} > + ?// Now that we have created the new alloca instructions, rewrite all the > + ?// uses of the old alloca. > + ?DeadInsts.push_back(AI); > + ?RewriteForScalarRepl(AI, AI, 0, ElementAllocas); > > - ? ?// Replace: > - ? ?// ? store { i32, i32 } %val, { i32, i32 }* %alloc > - ? ?// with: > - ? ?// ? %val.0 = extractvalue { i32, i32 } %val, 0 > - ? ?// ? store i32 %val.0, i32* %alloc.0 > - ? ?// ? %val.1 = extractvalue { i32, i32 } %val, 1 > - ? ?// ? store i32 %val.1, i32* %alloc.1 > - ? ?// (Also works for arrays instead of structs) > - ? ?if (StoreInst *SI = dyn_cast(User)) { > - ? ? ?Value *Val = SI->getOperand(0); > - ? ? ?for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) { > - ? ? ? ?Value *Extract = ExtractValueInst::Create(Val, i, Val->getName(), SI); > - ? ? ? ?new StoreInst(Extract, ElementAllocas[i], SI); > - ? ? ?} > - ? ? ?SI->eraseFromParent(); > - ? ? ?continue; > - ? ?} > - > - ? ?GetElementPtrInst *GEPI = cast(User); > - ? ?// We now know that the GEP is of the form: GEP , 0, > - ? ?unsigned Idx = > - ? ? ? (unsigned)cast(GEPI->getOperand(2))->getZExtValue(); > - > - ? ?assert(Idx < ElementAllocas.size() && "Index out of range?"); > - ? ?AllocaInst *AllocaToUse = ElementAllocas[Idx]; > - > - ? ?Value *RepValue; > - ? ?if (GEPI->getNumOperands() == 3) { > - ? ? ?// Do not insert a new getelementptr instruction with zero indices, only > - ? ? ?// to have it optimized out later. > - ? ? ?RepValue = AllocaToUse; > - ? ?} else { > - ? ? ?// We are indexing deeply into the structure, so we still need a > - ? ? ?// getelement ptr instruction to finish the indexing. ?This may be > - ? ? ?// expanded itself once the worklist is rerun. > - ? ? ?// > - ? ? ?SmallVector NewArgs; > - ? ? ?NewArgs.push_back(Constant::getNullValue( > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Type::getInt32Ty(AI->getContext()))); > - ? ? ?NewArgs.append(GEPI->op_begin()+3, GEPI->op_end()); > - ? ? ?RepValue = GetElementPtrInst::Create(AllocaToUse, NewArgs.begin(), > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NewArgs.end(), "", GEPI); > - ? ? ?RepValue->takeName(GEPI); > - ? ?} > - > - ? ?// If this GEP is to the start of the aggregate, check for memcpys. > - ? ?if (Idx == 0 && GEPI->hasAllZeroIndices()) > - ? ? ?RewriteBitCastUserOfAlloca(GEPI, AI, ElementAllocas); > - > - ? ?// Move all of the users over to the new GEP. > - ? ?GEPI->replaceAllUsesWith(RepValue); > - ? ?// Delete the old GEP > - ? ?GEPI->eraseFromParent(); > - ?} > + ?// Now erase any instructions that were made dead while rewriting the alloca. > + ?DeleteDeadInstructions(); > > - ?// Finally, delete the Alloca instruction > - ?AI->eraseFromParent(); > ? NumReplaced++; > ?} > > -/// isSafeElementUse - Check to see if this use is an allowed use for a > -/// getelementptr instruction of an array aggregate allocation. ?isFirstElt > -/// indicates whether Ptr is known to the start of the aggregate. > -void SROA::isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ?AllocaInfo &Info) { > - ?for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); > - ? ? ? I != E; ++I) { > - ? ?Instruction *User = cast(*I); > - ? ?switch (User->getOpcode()) { > - ? ?case Instruction::Load: ?break; > - ? ?case Instruction::Store: > - ? ? ?// Store is ok if storing INTO the pointer, not storing the pointer > - ? ? ?if (User->getOperand(0) == Ptr) return MarkUnsafe(Info); > - ? ? ?break; > - ? ?case Instruction::GetElementPtr: { > - ? ? ?GetElementPtrInst *GEP = cast(User); > - ? ? ?bool AreAllZeroIndices = isFirstElt; > - ? ? ?if (GEP->getNumOperands() > 1 && > - ? ? ? ? ?(!isa(GEP->getOperand(1)) || > - ? ? ? ? ? !cast(GEP->getOperand(1))->isZero())) > - ? ? ? ?// Using pointer arithmetic to navigate the array. > - ? ? ? ?return MarkUnsafe(Info); > - > - ? ? ?// Verify that any array subscripts are in range. > - ? ? ?for (gep_type_iterator GEPIt = gep_type_begin(GEP), > - ? ? ? ? ? E = gep_type_end(GEP); GEPIt != E; ++GEPIt) { > - ? ? ? ?// Ignore struct elements, no extra checking needed for these. > - ? ? ? ?if (isa(*GEPIt)) > - ? ? ? ? ?continue; > - > - ? ? ? ?// This GEP indexes an array. ?Verify that this is an in-range > - ? ? ? ?// constant integer. Specifically, consider A[0][i]. We cannot know that > - ? ? ? ?// the user isn't doing invalid things like allowing i to index an > - ? ? ? ?// out-of-range subscript that accesses A[1]. ?Because of this, we have > - ? ? ? ?// to reject SROA of any accesses into structs where any of the > - ? ? ? ?// components are variables. > - ? ? ? ?ConstantInt *IdxVal = dyn_cast(GEPIt.getOperand()); > - ? ? ? ?if (!IdxVal) return MarkUnsafe(Info); > - > - ? ? ? ?// Are all indices still zero? > - ? ? ? ?AreAllZeroIndices &= IdxVal->isZero(); > - > - ? ? ? ?if (const ArrayType *AT = dyn_cast(*GEPIt)) { > - ? ? ? ? ?if (IdxVal->getZExtValue() >= AT->getNumElements()) > - ? ? ? ? ? ?return MarkUnsafe(Info); > - ? ? ? ?} else if (const VectorType *VT = dyn_cast(*GEPIt)) { > - ? ? ? ? ?if (IdxVal->getZExtValue() >= VT->getNumElements()) > - ? ? ? ? ? ?return MarkUnsafe(Info); > - ? ? ? ?} > +/// DeleteDeadInstructions - Erase instructions on the DeadInstrs list, > +/// recursively including all their operands that become trivially dead. > +void SROA::DeleteDeadInstructions() { > + ?while (!DeadInsts.empty()) { > + ? ?Instruction *I = dyn_cast_or_null(DeadInsts.pop_back_val()); > + ? ?if (I == 0) > + ? ? ?continue; > + > + ? ?for (User::op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) > + ? ? ?if (Instruction *U = dyn_cast(*OI)) { > + ? ? ? ?// Zero out the operand and see if it becomes trivially dead. > + ? ? ? ?*OI = 0; > + ? ? ? ?if (isInstructionTriviallyDead(U)) > + ? ? ? ? ?DeadInsts.push_back(U); > ? ? ? } > - > - ? ? ?isSafeElementUse(GEP, AreAllZeroIndices, AI, Info); > - ? ? ?if (Info.isUnsafe) return; > - ? ? ?break; > - ? ?} > - ? ?case Instruction::BitCast: > - ? ? ?if (isFirstElt) { > - ? ? ? ?isSafeUseOfBitCastedAllocation(cast(User), AI, Info); > - ? ? ? ?if (Info.isUnsafe) return; > - ? ? ? ?break; > - ? ? ?} > - ? ? ?DEBUG(errs() << " ?Transformation preventing inst: " << *User << '\n'); > - ? ? ?return MarkUnsafe(Info); > - ? ?case Instruction::Call: > - ? ? ?if (MemIntrinsic *MI = dyn_cast(User)) { > - ? ? ? ?if (isFirstElt) { > - ? ? ? ? ?isSafeMemIntrinsicOnAllocation(MI, AI, I.getOperandNo(), Info); > - ? ? ? ? ?if (Info.isUnsafe) return; > - ? ? ? ? ?break; > - ? ? ? ?} > - ? ? ?} > - ? ? ?DEBUG(errs() << " ?Transformation preventing inst: " << *User << '\n'); > - ? ? ?return MarkUnsafe(Info); > - ? ?default: > - ? ? ?DEBUG(errs() << " ?Transformation preventing inst: " << *User << '\n'); > - ? ? ?return MarkUnsafe(Info); > - ? ?} > + > + ? ?I->eraseFromParent(); > ? } > - ?return; ?// All users look ok :) > ?} > - > + > ?/// AllUsersAreLoads - Return true if all users of this value are loads. > ?static bool AllUsersAreLoads(Value *Ptr) { > ? for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); > @@ -539,72 +409,116 @@ > ? return true; > ?} > > -/// isSafeUseOfAllocation - Check if this user is an allowed use for an > -/// aggregate allocation. > -void SROA::isSafeUseOfAllocation(Instruction *User, AllocaInst *AI, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? AllocaInfo &Info) { > - ?if (BitCastInst *C = dyn_cast(User)) > - ? ?return isSafeUseOfBitCastedAllocation(C, AI, Info); > - > - ?if (LoadInst *LI = dyn_cast(User)) > - ? ?if (!LI->isVolatile()) > - ? ? ?return;// Loads (returning a first class aggregrate) are always rewritable > - > - ?if (StoreInst *SI = dyn_cast(User)) > - ? ?if (!SI->isVolatile() && SI->getOperand(0) != AI) > - ? ? ?return;// Store is ok if storing INTO the pointer, not storing the pointer > - > - ?GetElementPtrInst *GEPI = dyn_cast(User); > - ?if (GEPI == 0) > - ? ?return MarkUnsafe(Info); > - > - ?gep_type_iterator I = gep_type_begin(GEPI), E = gep_type_end(GEPI); > +/// isSafeForScalarRepl - Check if instruction I is a safe use with regard to > +/// performing scalar replacement of alloca AI. ?The results are flagged in > +/// the Info parameter. ?Offset and ArrayOffset indicate the position within > +/// AI that is referenced by this instruction. > +void SROA::isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uint64_t ArrayOffset, AllocaInfo &Info) { > + ?for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI!=E; ++UI) { > + ? ?Instruction *User = cast(*UI); > > - ?// The GEP is not safe to transform if not of the form "GEP , 0, ". > - ?if (I == E || > - ? ? ?I.getOperand() != Constant::getNullValue(I.getOperand()->getType())) { > - ? ?return MarkUnsafe(Info); > + ? ?if (BitCastInst *BC = dyn_cast(User)) { > + ? ? ?isSafeForScalarRepl(BC, AI, Offset, ArrayOffset, Info); > + ? ?} else if (GetElementPtrInst *GEPI = dyn_cast(User)) { > + ? ? ?uint64_t GEPArrayOffset = ArrayOffset; > + ? ? ?uint64_t GEPOffset = Offset; > + ? ? ?isSafeGEP(GEPI, AI, GEPOffset, GEPArrayOffset, Info); > + ? ? ?if (!Info.isUnsafe) > + ? ? ? ?isSafeForScalarRepl(GEPI, AI, GEPOffset, GEPArrayOffset, Info); > + ? ?} else if (MemIntrinsic *MI = dyn_cast(UI)) { > + ? ? ?ConstantInt *Length = dyn_cast(MI->getLength()); > + ? ? ?if (Length) > + ? ? ? ?isSafeMemAccess(AI, Offset, ArrayOffset, Length->getZExtValue(), 0, > + ? ? ? ? ? ? ? ? ? ? ? ?UI.getOperandNo() == 1, Info); > + ? ? ?else > + ? ? ? ?MarkUnsafe(Info); > + ? ?} else if (LoadInst *LI = dyn_cast(User)) { > + ? ? ?if (!LI->isVolatile()) { > + ? ? ? ?const Type *LIType = LI->getType(); > + ? ? ? ?isSafeMemAccess(AI, Offset, ArrayOffset, TD->getTypeAllocSize(LIType), > + ? ? ? ? ? ? ? ? ? ? ? ?LIType, false, Info); > + ? ? ?} else > + ? ? ? ?MarkUnsafe(Info); > + ? ?} else if (StoreInst *SI = dyn_cast(User)) { > + ? ? ?// Store is ok if storing INTO the pointer, not storing the pointer > + ? ? ?if (!SI->isVolatile() && SI->getOperand(0) != I) { > + ? ? ? ?const Type *SIType = SI->getOperand(0)->getType(); > + ? ? ? ?isSafeMemAccess(AI, Offset, ArrayOffset, TD->getTypeAllocSize(SIType), > + ? ? ? ? ? ? ? ? ? ? ? ?SIType, true, Info); > + ? ? ?} else > + ? ? ? ?MarkUnsafe(Info); > + ? ?} else if (isa(UI)) { > + ? ? ?// If one user is DbgInfoIntrinsic then check if all users are > + ? ? ?// DbgInfoIntrinsics. > + ? ? ?if (OnlyUsedByDbgInfoIntrinsics(I)) { > + ? ? ? ?Info.needsCleanup = true; > + ? ? ? ?return; > + ? ? ?} > + ? ? ?MarkUnsafe(Info); > + ? ?} else { > + ? ? ?DEBUG(errs() << " ?Transformation preventing inst: " << *User << '\n'); > + ? ? ?MarkUnsafe(Info); > + ? ?} > + ? ?if (Info.isUnsafe) return; > ? } > +} > > - ?++I; > - ?if (I == E) return MarkUnsafe(Info); ?// ran out of GEP indices?? > +/// isSafeGEP - Check if a GEP instruction can be handled for scalar > +/// replacement. ?It is safe when all the indices are constant, in-bounds > +/// references, and when the resulting offset corresponds to an element within > +/// the alloca type. ?The results are flagged in the Info parameter. ?Upon > +/// return, Offset is adjusted as specified by the GEP indices. ?For the > +/// special case of a variable index to a 2-element array, ArrayOffset is set > +/// to the array element size. > +void SROA::isSafeGEP(GetElementPtrInst *GEPI, AllocaInst *AI, > + ? ? ? ? ? ? ? ? ? ? uint64_t &Offset, uint64_t &ArrayOffset, > + ? ? ? ? ? ? ? ? ? ? AllocaInfo &Info) { > + ?gep_type_iterator GEPIt = gep_type_begin(GEPI), E = gep_type_end(GEPI); > + ?if (GEPIt == E) > + ? ?return; > + > + ?// The first GEP index must be zero. > + ?if (!isa(GEPIt.getOperand()) || > + ? ? ?!cast(GEPIt.getOperand())->isZero()) > + ? ?return MarkUnsafe(Info); > + ?if (++GEPIt == E) > + ? ?return; > > - ?bool IsAllZeroIndices = true; > - > ? // If the first index is a non-constant index into an array, see if we can > ? // handle it as a special case. > - ?if (const ArrayType *AT = dyn_cast(*I)) { > - ? ?if (!isa(I.getOperand())) { > - ? ? ?IsAllZeroIndices = 0; > - ? ? ?uint64_t NumElements = AT->getNumElements(); > - > - ? ? ?// If this is an array index and the index is not constant, we cannot > - ? ? ?// promote... that is unless the array has exactly one or two elements in > - ? ? ?// it, in which case we CAN promote it, but we have to canonicalize this > - ? ? ?// out if this is the only problem. > - ? ? ?if ((NumElements == 1 || NumElements == 2) && > - ? ? ? ? ?AllUsersAreLoads(GEPI)) { > + ?const Type *ArrayEltTy = 0; > + ?if (ArrayOffset == 0 && Offset == 0) { > + ? ?if (const ArrayType *AT = dyn_cast(*GEPIt)) { > + ? ? ?if (!isa(GEPIt.getOperand())) { > + ? ? ? ?uint64_t NumElements = AT->getNumElements(); > + > + ? ? ? ?// If this is an array index and the index is not constant, we cannot > + ? ? ? ?// promote... that is unless the array has exactly one or two elements > + ? ? ? ?// in it, in which case we CAN promote it, but we have to canonicalize > + ? ? ? ?// this out if this is the only problem. > + ? ? ? ?if ((NumElements != 1 && NumElements != 2) || !AllUsersAreLoads(GEPI)) > + ? ? ? ? ?return MarkUnsafe(Info); > ? ? ? ? Info.needsCleanup = true; > - ? ? ? ?return; ?// Canonicalization required! > + ? ? ? ?ArrayOffset = TD->getTypeAllocSizeInBits(AT->getElementType()); > + ? ? ? ?ArrayEltTy = AT->getElementType(); > + ? ? ? ?++GEPIt; > ? ? ? } > - ? ? ?return MarkUnsafe(Info); > ? ? } > ? } > - > + > ? // Walk through the GEP type indices, checking the types that this indexes > ? // into. > - ?for (; I != E; ++I) { > + ?for (; GEPIt != E; ++GEPIt) { > ? ? // Ignore struct elements, no extra checking needed for these. > - ? ?if (isa(*I)) > + ? ?if (isa(*GEPIt)) > ? ? ? continue; > - > - ? ?ConstantInt *IdxVal = dyn_cast(I.getOperand()); > - ? ?if (!IdxVal) return MarkUnsafe(Info); > > - ? ?// Are all indices still zero? > - ? ?IsAllZeroIndices &= IdxVal->isZero(); > - > - ? ?if (const ArrayType *AT = dyn_cast(*I)) { > + ? ?ConstantInt *IdxVal = dyn_cast(GEPIt.getOperand()); > + ? ?if (!IdxVal) > + ? ? ?return MarkUnsafe(Info); > + > + ? ?if (const ArrayType *AT = dyn_cast(*GEPIt)) { > ? ? ? // This GEP indexes an array. ?Verify that this is an in-range constant > ? ? ? // integer. Specifically, consider A[0][i]. We cannot know that the user > ? ? ? // isn't doing invalid things like allowing i to index an out-of-range > @@ -612,147 +526,255 @@ > ? ? ? // of any accesses into structs where any of the components are variables. > ? ? ? if (IdxVal->getZExtValue() >= AT->getNumElements()) > ? ? ? ? return MarkUnsafe(Info); > - ? ?} else if (const VectorType *VT = dyn_cast(*I)) { > + ? ?} else { > + ? ? ?const VectorType *VT = dyn_cast(*GEPIt); > + ? ? ?assert(VT && "unexpected type in GEP type iterator"); > ? ? ? if (IdxVal->getZExtValue() >= VT->getNumElements()) > ? ? ? ? return MarkUnsafe(Info); > ? ? } > ? } > - > - ?// If there are any non-simple uses of this getelementptr, make sure to reject > - ?// them. > - ?return isSafeElementUse(GEPI, IsAllZeroIndices, AI, Info); > + > + ?// All the indices are safe. ?Now compute the offset due to this GEP and > + ?// check if the alloca has a component element at that offset. > + ?if (ArrayOffset == 0) { > + ? ?SmallVector Indices(GEPI->op_begin() + 1, GEPI->op_end()); > + ? ?Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(), > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &Indices[0], Indices.size()); > + ?} else { > + ? ?// Both array elements have the same type, so it suffices to check one of > + ? ?// them. ?Copy the GEP indices starting from the array index, but replace > + ? ?// that variable index with a constant zero. > + ? ?SmallVector Indices(GEPI->op_begin() + 2, GEPI->op_end()); > + ? ?Indices[0] = Constant::getNullValue(Type::getInt32Ty(GEPI->getContext())); > + ? ?const Type *ArrayEltPtr = PointerType::getUnqual(ArrayEltTy); > + ? ?Offset += TD->getIndexedOffset(ArrayEltPtr, &Indices[0], Indices.size()); > + ?} > + ?if (!TypeHasComponent(AI->getAllocatedType(), Offset, 0)) > + ? ?MarkUnsafe(Info); > +} > + > +/// isSafeMemAccess - Check if a load/store/memcpy operates on the entire AI > +/// alloca or has an offset and size that corresponds to a component element > +/// within it. ?The offset checked here may have been formed from a GEP with a > +/// pointer bitcasted to a different type. > +void SROA::isSafeMemAccess(AllocaInst *AI, uint64_t Offset, > + ? ? ? ? ? ? ? ? ? ? ? ? ? uint64_t ArrayOffset, uint64_t MemSize, > + ? ? ? ? ? ? ? ? ? ? ? ? ? const Type *MemOpType, bool isStore, > + ? ? ? ? ? ? ? ? ? ? ? ? ? AllocaInfo &Info) { > + ?// Check if this is a load/store of the entire alloca. > + ?if (Offset == 0 && ArrayOffset == 0 && > + ? ? ?MemSize == TD->getTypeAllocSize(AI->getAllocatedType())) { > + ? ?bool UsesAggregateType = (MemOpType == AI->getAllocatedType()); > + ? ?// This is safe for MemIntrinsics (where MemOpType is 0), integer types > + ? ?// (which are essentially the same as the MemIntrinsics, especially with > + ? ?// regard to copying padding between elements), or references using the > + ? ?// aggregate type of the alloca. > + ? ?if (!MemOpType || isa(MemOpType) || UsesAggregateType) { > + ? ? ?if (!UsesAggregateType) { > + ? ? ? ?if (isStore) > + ? ? ? ? ?Info.isMemCpyDst = true; > + ? ? ? ?else > + ? ? ? ? ?Info.isMemCpySrc = true; > + ? ? ?} > + ? ? ?return; > + ? ?} > + ?} > + ?// Check if the offset/size correspond to a component within the alloca type. > + ?const Type *T = AI->getAllocatedType(); > + ?if (TypeHasComponent(T, Offset, MemSize) && > + ? ? ?(ArrayOffset == 0 || TypeHasComponent(T, Offset + ArrayOffset, MemSize))) > + ? ?return; > + > + ?return MarkUnsafe(Info); > ?} > > -/// isSafeMemIntrinsicOnAllocation - Check if the specified memory > -/// intrinsic can be promoted by SROA. ?At this point, we know that the operand > -/// of the memintrinsic is a pointer to the beginning of the allocation. > -void SROA::isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned OpNo, AllocaInfo &Info) { > - ?// If not constant length, give up. > - ?ConstantInt *Length = dyn_cast(MI->getLength()); > - ?if (!Length) return MarkUnsafe(Info); > - > - ?// If not the whole aggregate, give up. > - ?if (Length->getZExtValue() != > - ? ? ?TD->getTypeAllocSize(AI->getType()->getElementType())) > - ? ?return MarkUnsafe(Info); > - > - ?// We only know about memcpy/memset/memmove. > - ?if (!isa(MI)) > - ? ?return MarkUnsafe(Info); > - > - ?// Otherwise, we can transform it. ?Determine whether this is a memcpy/set > - ?// into or out of the aggregate. > - ?if (OpNo == 1) > - ? ?Info.isMemCpyDst = true; > - ?else { > - ? ?assert(OpNo == 2); > - ? ?Info.isMemCpySrc = true; > +/// TypeHasComponent - Return true if T has a component type with the > +/// specified offset and size. ?If Size is zero, do not check the size. > +bool SROA::TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size) { > + ?const Type *EltTy; > + ?uint64_t EltSize; > + ?if (const StructType *ST = dyn_cast(T)) { > + ? ?const StructLayout *Layout = TD->getStructLayout(ST); > + ? ?unsigned EltIdx = Layout->getElementContainingOffset(Offset); > + ? ?EltTy = ST->getContainedType(EltIdx); > + ? ?EltSize = TD->getTypeAllocSize(EltTy); > + ? ?Offset -= Layout->getElementOffset(EltIdx); > + ?} else if (const ArrayType *AT = dyn_cast(T)) { > + ? ?EltTy = AT->getElementType(); > + ? ?EltSize = TD->getTypeAllocSize(EltTy); > + ? ?Offset %= EltSize; > + ?} else { > + ? ?return false; > ? } > + ?if (Offset == 0 && (Size == 0 || EltSize == Size)) > + ? ?return true; > + ?// Check if the component spans multiple elements. > + ?if (Offset + Size > EltSize) > + ? ?return false; > + ?return TypeHasComponent(EltTy, Offset, Size); > ?} > > -/// isSafeUseOfBitCastedAllocation - Check if all users of this bitcast > -/// from an alloca are safe for SROA of that alloca. > -void SROA::isSafeUseOfBitCastedAllocation(BitCastInst *BC, AllocaInst *AI, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?AllocaInfo &Info) { > - ?for (Value::use_iterator UI = BC->use_begin(), E = BC->use_end(); > - ? ? ? UI != E; ++UI) { > - ? ?if (BitCastInst *BCU = dyn_cast(UI)) { > - ? ? ?isSafeUseOfBitCastedAllocation(BCU, AI, Info); > - ? ?} else if (MemIntrinsic *MI = dyn_cast(UI)) { > - ? ? ?isSafeMemIntrinsicOnAllocation(MI, AI, UI.getOperandNo(), Info); > - ? ?} else if (StoreInst *SI = dyn_cast(UI)) { > - ? ? ?if (SI->isVolatile()) > - ? ? ? ?return MarkUnsafe(Info); > - > - ? ? ?// If storing the entire alloca in one chunk through a bitcasted pointer > - ? ? ?// to integer, we can transform it. ?This happens (for example) when you > - ? ? ?// cast a {i32,i32}* to i64* and store through it. ?This is similar to the > - ? ? ?// memcpy case and occurs in various "byval" cases and emulated memcpys. > - ? ? ?if (isa(SI->getOperand(0)->getType()) && > - ? ? ? ? ?TD->getTypeAllocSize(SI->getOperand(0)->getType()) == > - ? ? ? ? ?TD->getTypeAllocSize(AI->getType()->getElementType())) { > - ? ? ? ?Info.isMemCpyDst = true; > - ? ? ? ?continue; > - ? ? ?} > - ? ? ?return MarkUnsafe(Info); > - ? ?} else if (LoadInst *LI = dyn_cast(UI)) { > - ? ? ?if (LI->isVolatile()) > - ? ? ? ?return MarkUnsafe(Info); > +/// RewriteForScalarRepl - Alloca AI is being split into NewElts, so rewrite > +/// the instruction I, which references it, to use the separate elements. > +/// Offset indicates the position within AI that is referenced by this > +/// instruction. > +void SROA::RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SmallVector &NewElts) { > + ?for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI!=E; ++UI) { > + ? ?Instruction *User = cast(*UI); > > - ? ? ?// If loading the entire alloca in one chunk through a bitcasted pointer > - ? ? ?// to integer, we can transform it. ?This happens (for example) when you > - ? ? ?// cast a {i32,i32}* to i64* and load through it. ?This is similar to the > - ? ? ?// memcpy case and occurs in various "byval" cases and emulated memcpys. > - ? ? ?if (isa(LI->getType()) && > - ? ? ? ? ?TD->getTypeAllocSize(LI->getType()) == > - ? ? ? ? ?TD->getTypeAllocSize(AI->getType()->getElementType())) { > - ? ? ? ?Info.isMemCpySrc = true; > - ? ? ? ?continue; > + ? ?if (BitCastInst *BC = dyn_cast(User)) { > + ? ? ?RewriteBitCast(BC, AI, Offset, NewElts); > + ? ?} else if (GetElementPtrInst *GEPI = dyn_cast(User)) { > + ? ? ?RewriteGEP(GEPI, AI, Offset, NewElts); > + ? ?} else if (MemIntrinsic *MI = dyn_cast(User)) { > + ? ? ?ConstantInt *Length = dyn_cast(MI->getLength()); > + ? ? ?uint64_t MemSize = Length->getZExtValue(); > + ? ? ?if (Offset == 0 && > + ? ? ? ? ?MemSize == TD->getTypeAllocSize(AI->getAllocatedType())) > + ? ? ? ?RewriteMemIntrinUserOfAlloca(MI, I, AI, NewElts); > + ? ?} else if (LoadInst *LI = dyn_cast(User)) { > + ? ? ?const Type *LIType = LI->getType(); > + ? ? ?if (LIType == AI->getAllocatedType()) { > + ? ? ? ?// Replace: > + ? ? ? ?// ? %res = load { i32, i32 }* %alloc > + ? ? ? ?// with: